Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make host context use null as empty and only error in dev #25609

Merged
merged 1 commit into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 15 additions & 22 deletions packages/react-reconciler/src/ReactFiberHostContext.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,26 @@ import type {Container, HostContext} from './ReactFiberHostConfig';
import {getChildHostContext, getRootHostContext} from './ReactFiberHostConfig';
import {createCursor, push, pop} from './ReactFiberStack.new';

declare class NoContextT {}
const NO_CONTEXT: NoContextT = ({}: any);

const contextStackCursor: StackCursor<HostContext | NoContextT> = createCursor(
NO_CONTEXT,
);
const contextFiberStackCursor: StackCursor<Fiber | NoContextT> = createCursor(
NO_CONTEXT,
const contextStackCursor: StackCursor<HostContext | null> = createCursor(null);
const contextFiberStackCursor: StackCursor<Fiber | null> = createCursor(null);
const rootInstanceStackCursor: StackCursor<Container | null> = createCursor(
null,
);
const rootInstanceStackCursor: StackCursor<
Container | NoContextT,
> = createCursor(NO_CONTEXT);

function requiredContext<Value>(c: Value | NoContextT): Value {
if (c === NO_CONTEXT) {
throw new Error(
'Expected host context to exist. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}

function requiredContext<Value>(c: Value | null): Value {
if (__DEV__) {
if (c === null) {
console.error(
'Expected host context to exist. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}
}
return (c: any);
}

function getCurrentRootHostContainer(): null | Container {
const container = rootInstanceStackCursor.current;
return container === NO_CONTEXT ? null : ((container: any): Container);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is precious.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was busy!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it's fair, once a pattern is established it tends to spread.

return rootInstanceStackCursor.current;
}

function getRootHostContainer(): Container {
Expand All @@ -61,7 +54,7 @@ function pushHostContainer(fiber: Fiber, nextRootInstance: Container) {
// we'd have a different number of entries on the stack depending on
// whether getRootHostContext() throws somewhere in renderer code or not.
// So we push an empty value first. This lets us safely unwind on errors.
push(contextStackCursor, NO_CONTEXT, fiber);
push(contextStackCursor, null, fiber);
const nextRootContext = getRootHostContext(nextRootInstance);
// Now that we know this function doesn't throw, replace it.
pop(contextStackCursor, fiber);
Expand Down
37 changes: 15 additions & 22 deletions packages/react-reconciler/src/ReactFiberHostContext.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,26 @@ import type {Container, HostContext} from './ReactFiberHostConfig';
import {getChildHostContext, getRootHostContext} from './ReactFiberHostConfig';
import {createCursor, push, pop} from './ReactFiberStack.old';

declare class NoContextT {}
const NO_CONTEXT: NoContextT = ({}: any);

const contextStackCursor: StackCursor<HostContext | NoContextT> = createCursor(
NO_CONTEXT,
);
const contextFiberStackCursor: StackCursor<Fiber | NoContextT> = createCursor(
NO_CONTEXT,
const contextStackCursor: StackCursor<HostContext | null> = createCursor(null);
const contextFiberStackCursor: StackCursor<Fiber | null> = createCursor(null);
const rootInstanceStackCursor: StackCursor<Container | null> = createCursor(
null,
);
const rootInstanceStackCursor: StackCursor<
Container | NoContextT,
> = createCursor(NO_CONTEXT);

function requiredContext<Value>(c: Value | NoContextT): Value {
if (c === NO_CONTEXT) {
throw new Error(
'Expected host context to exist. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}

function requiredContext<Value>(c: Value | null): Value {
if (__DEV__) {
if (c === null) {
console.error(
'Expected host context to exist. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}
}
return (c: any);
}

function getCurrentRootHostContainer(): null | Container {
const container = rootInstanceStackCursor.current;
return container === NO_CONTEXT ? null : ((container: any): Container);
return rootInstanceStackCursor.current;
}

function getRootHostContainer(): Container {
Expand All @@ -61,7 +54,7 @@ function pushHostContainer(fiber: Fiber, nextRootInstance: Container) {
// we'd have a different number of entries on the stack depending on
// whether getRootHostContext() throws somewhere in renderer code or not.
// So we push an empty value first. This lets us safely unwind on errors.
push(contextStackCursor, NO_CONTEXT, fiber);
push(contextStackCursor, null, fiber);
const nextRootContext = getRootHostContext(nextRootInstance);
// Now that we know this function doesn't throw, replace it.
pop(contextStackCursor, fiber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,72 +30,10 @@ describe('ReactFiberHostContext', () => {

global.IS_REACT_ACT_ENVIRONMENT = true;

// @gate __DEV__
it('works with null host context', async () => {
let creates = 0;
const Renderer = ReactFiberReconciler({
prepareForCommit: function() {
return null;
},
resetAfterCommit: function() {},
getRootHostContext: function() {
return null;
},
getChildHostContext: function() {
return null;
},
shouldSetTextContent: function() {
return false;
},
createInstance: function() {
creates++;
},
finalizeInitialChildren: function() {
return null;
},
appendInitialChild: function() {
return null;
},
now: function() {
return 0;
},
appendChildToContainer: function() {
return null;
},
clearContainer: function() {},
getCurrentEventPriority: function() {
return DefaultEventPriority;
},
prepareRendererToRender: function() {},
resetRendererAfterRender: function() {},
supportsMutation: true,
requestPostPaintCallback: function() {},
});

const container = Renderer.createContainer(
/* root: */ null,
ConcurrentRoot,
null,
false,
'',
null,
);
act(() => {
Renderer.updateContainer(
<a>
<b />
</a>,
container,
/* parentComponent: */ null,
/* callback: */ null,
);
});
expect(creates).toBe(2);
});

// @gate __DEV__
it('should send the context to prepareForCommit and resetAfterCommit', () => {
const rootContext = {};
const childContext = {};
const Renderer = ReactFiberReconciler({
prepareForCommit: function(hostContext) {
expect(hostContext).toBe(rootContext);
Expand All @@ -105,10 +43,10 @@ describe('ReactFiberHostContext', () => {
expect(hostContext).toBe(rootContext);
},
getRootHostContext: function() {
return null;
return rootContext;
},
getChildHostContext: function() {
return null;
return childContext;
},
shouldSetTextContent: function() {
return false;
Expand Down