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

Accept promise as element type #13397

Merged
merged 14 commits into from Aug 16, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/react-dom/src/test-utils/ReactTestUtils.js
Expand Up @@ -11,7 +11,9 @@ import {findCurrentFiberUsingSlowPath} from 'react-reconciler/reflection';
import * as ReactInstanceMap from 'shared/ReactInstanceMap';
import {
ClassComponent,
ClassComponentLazy,
FunctionalComponent,
FunctionalComponentLazy,
HostComponent,
HostText,
} from 'shared/ReactTypeOfWork';
Expand Down Expand Up @@ -81,7 +83,9 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
node.tag === HostComponent ||
node.tag === HostText ||
node.tag === ClassComponent ||
node.tag === FunctionalComponent
node.tag === ClassComponentLazy ||
node.tag === FunctionalComponent ||
node.tag === FunctionalComponentLazy
) {
const publicInst = node.stateNode;
if (test(publicInst)) {
Expand Down
9 changes: 6 additions & 3 deletions packages/react-reconciler/src/ReactChildFiber.js
Expand Up @@ -23,6 +23,7 @@ import {
import {
FunctionalComponent,
ClassComponent,
ClassComponentLazy,
HostText,
HostPortal,
Fragment,
Expand Down Expand Up @@ -117,7 +118,7 @@ function coerceRef(
if (!didWarnAboutStringRefInStrictMode[componentName]) {
warningWithoutStack(
false,
'A string ref, "%s", has been found within a strict mode tree. ' +
'A string ref, "%s", has been found within a strict mode tree. ' +
'String refs are a source of potential bugs and should be avoided. ' +
'We recommend using createRef() instead.' +
'\n%s' +
Expand All @@ -137,7 +138,8 @@ function coerceRef(
if (owner) {
const ownerFiber = ((owner: any): Fiber);
invariant(
ownerFiber.tag === ClassComponent,
ownerFiber.tag === ClassComponent ||
ownerFiber.tag === ClassComponentLazy,
'Stateless function components cannot have refs.',
);
inst = ownerFiber.stateNode;
Expand Down Expand Up @@ -1307,7 +1309,8 @@ function ChildReconciler(shouldTrackSideEffects) {
// component, throw an error. If Fiber return types are disabled,
// we already threw above.
switch (returnFiber.tag) {
case ClassComponent: {
case ClassComponent:
case ClassComponentLazy: {
if (__DEV__) {
const instance = returnFiber.stateNode;
if (instance.render._isMockFunction) {
Expand Down
4 changes: 4 additions & 0 deletions packages/react-reconciler/src/ReactCurrentFiber.js
Expand Up @@ -11,7 +11,9 @@ import ReactSharedInternals from 'shared/ReactSharedInternals';
import {
IndeterminateComponent,
FunctionalComponent,
FunctionalComponentLazy,
ClassComponent,
ClassComponentLazy,
HostComponent,
Mode,
} from 'shared/ReactTypeOfWork';
Expand All @@ -28,7 +30,9 @@ function describeFiber(fiber: Fiber): string {
switch (fiber.tag) {
case IndeterminateComponent:
case FunctionalComponent:
case FunctionalComponentLazy:
case ClassComponent:
case ClassComponentLazy:
case HostComponent:
case Mode:
const owner = fiber._debugOwner;
Expand Down
128 changes: 78 additions & 50 deletions packages/react-reconciler/src/ReactFiber.js
Expand Up @@ -33,6 +33,9 @@ import {
ContextConsumer,
Profiler,
PlaceholderComponent,
FunctionalComponentLazy,
ClassComponentLazy,
ForwardRefLazy,
} from 'shared/ReactTypeOfWork';
import getComponentName from 'shared/getComponentName';

Expand Down Expand Up @@ -278,8 +281,31 @@ const createFiber = function(
return new FiberNode(tag, pendingProps, key, mode);
};

function shouldConstruct(Component) {
return !!(Component.prototype && Component.prototype.isReactComponent);
function shouldConstruct(Component: Function) {
const prototype = Component.prototype;
return (
typeof prototype === 'object' &&
prototype !== null &&
typeof prototype.isReactComponent === 'object' &&
prototype.isReactComponent !== null
);
}

export function reassignLazyComponentTag(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Slight preference for returning the tag and assigning it in the outer function to avoid an unnecessary Get since this will be inlined.

fiber: Fiber,
Component: Function,
): void {
if (typeof Component === 'function') {
fiber.tag = shouldConstruct(Component)
? ClassComponentLazy
: FunctionalComponentLazy;
} else if (
Component !== undefined &&
Component !== null &&
Component.$$typeof
) {
fiber.tag = ForwardRefLazy;
}
}

// This is used to create an alternate fiber to do work on.
Expand Down Expand Up @@ -390,15 +416,15 @@ export function createFiberFromElement(
let fiber;
const type = element.type;
const key = element.key;
let pendingProps = element.props;
const pendingProps = element.props;

let fiberTag;
if (typeof type === 'function') {
fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent;
} else if (typeof type === 'string') {
fiberTag = HostComponent;
} else {
switch (type) {
getTag: switch (type) {
case REACT_FRAGMENT_TYPE:
return createFiberFromFragment(
pendingProps.children,
Expand All @@ -419,9 +445,54 @@ export function createFiberFromElement(
case REACT_PLACEHOLDER_TYPE:
fiberTag = PlaceholderComponent;
break;
default:
fiberTag = getFiberTagFromObjectType(type, owner);
break;
default: {
if (typeof type === 'object' && type !== null) {
switch (type.$$typeof) {
case REACT_PROVIDER_TYPE:
fiberTag = ContextProvider;
break getTag;
case REACT_CONTEXT_TYPE:
// This is a consumer
fiberTag = ContextConsumer;
break getTag;
case REACT_FORWARD_REF_TYPE:
fiberTag = ForwardRef;
break getTag;
default: {
if (typeof type.then === 'function') {
fiberTag = IndeterminateComponent;
break getTag;
}
}
}
}
let info = '';
if (__DEV__) {
if (
type === undefined ||
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
"it's defined in, or you might have mixed up default and " +
'named imports.';
}
const ownerName = owner ? getComponentName(owner.type) : null;
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
}
invariant(
false,
'Element type is invalid: expected a string (for built-in ' +
'components) or a class/function (for composite components) ' +
'but got: %s.%s',
type == null ? type : typeof type,
info,
);
}
}
}

Expand All @@ -437,49 +508,6 @@ export function createFiberFromElement(
return fiber;
}

function getFiberTagFromObjectType(type, owner): TypeOfWork {
const $$typeof =
typeof type === 'object' && type !== null ? type.$$typeof : null;

switch ($$typeof) {
case REACT_PROVIDER_TYPE:
return ContextProvider;
case REACT_CONTEXT_TYPE:
// This is a consumer
return ContextConsumer;
case REACT_FORWARD_REF_TYPE:
return ForwardRef;
default: {
let info = '';
if (__DEV__) {
if (
type === undefined ||
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
"it's defined in, or you might have mixed up default and " +
'named imports.';
}
const ownerName = owner ? getComponentName(owner.type) : null;
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
}
invariant(
false,
'Element type is invalid: expected a string (for built-in ' +
'components) or a class/function (for composite components) ' +
'but got: %s.%s',
type == null ? type : typeof type,
info,
);
}
}
}

export function createFiberFromFragment(
elements: ReactFragment,
mode: TypeOfMode,
Expand Down