Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Detect Fiber types to avoid inlining constants
  • Loading branch information
gaearon authored and ljharb committed Aug 24, 2018
commit 4e91f04339a7b76875e15c501cdd3eec7e88ef08
40 changes: 18 additions & 22 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,10 @@ import {
ensureKeyOrUndefined,
} from 'enzyme-adapter-utils';
import findCurrentFiberUsingSlowPath from './findCurrentFiberUsingSlowPath';
import detectFiberTags from './detectFiberTags';

const HostRoot = 3;
const ClassComponent = 2;
const FragmentType = 10;
const FunctionalComponent = 1;
const HostPortal = 4;
const HostComponent = 5;
const HostText = 6;
const Mode = 11;
const ContextConsumerType = 12;
const ContextProviderType = 13;
const ForwardRefType = 14;
// Lazily populated if DOM is available.
let FiberTags = null;

function nodeAndSiblingsArray(nodeWithSibling) {
const array = [];
Expand Down Expand Up @@ -115,9 +107,9 @@ function toTree(vnode) {
// somewhere else. Should talk to sebastian about this perhaps
const node = findCurrentFiberUsingSlowPath(vnode);
switch (node.tag) {
case HostRoot: // 3
case FiberTags.HostRoot:
return childrenToTree(node.child);
case HostPortal: { // 4
case FiberTags.HostPortal: {
const {
stateNode: { containerInfo },
memoizedProps: children,
Expand All @@ -133,7 +125,7 @@ function toTree(vnode) {
rendered: childrenToTree(node.child),
};
}
case ClassComponent:
case FiberTags.ClassComponent:
return {
nodeType: 'class',
type: node.type,
Expand All @@ -143,7 +135,7 @@ function toTree(vnode) {
instance: node.stateNode,
rendered: childrenToTree(node.child),
};
case FunctionalComponent: // 1
case FiberTags.FunctionalComponent:
return {
nodeType: 'function',
type: node.type,
Expand All @@ -154,7 +146,7 @@ function toTree(vnode) {
rendered: childrenToTree(node.child),
};

case HostComponent: { // 5
case FiberTags.HostComponent: {
let renderedNodes = flatten(nodeAndSiblingsArray(node.child).map(toTree));
if (renderedNodes.length === 0) {
renderedNodes = [node.memoizedProps.children];
Expand All @@ -169,14 +161,14 @@ function toTree(vnode) {
rendered: renderedNodes,
};
}
case HostText: // 6
case FiberTags.HostText:
return node.memoizedProps;
case FragmentType: // 10
case Mode: // 11
case ContextProviderType: // 13
case ContextConsumerType: // 12
case FiberTags.Fragment:
case FiberTags.Mode:
case FiberTags.ContextProvider:
case FiberTags.ContextConsumer:
return childrenToTree(node.child);
case ForwardRefType: {
case FiberTags.ForwardRef: {
return {
nodeType: 'function',
type: node.type,
Expand Down Expand Up @@ -255,6 +247,10 @@ class ReactSixteenAdapter extends EnzymeAdapter {

createMountRenderer(options) {
assertDomAvailable('mount');
if (FiberTags === null) {
// Requires DOM.
FiberTags = detectFiberTags();
}
const { attachTo, hydrateIn } = options;
const domNode = hydrateIn || attachTo || global.document.createElement('div');
let instance = null;
Expand Down
63 changes: 63 additions & 0 deletions packages/enzyme-adapter-react-16/src/detectFiberTags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import ReactDOM from 'react-dom';

function getFiber(element) {
const container = global.document.createElement('div');
let inst = null;
class Tester extends React.Component {
render() {
inst = this;
return element;
}
}
ReactDOM.render(React.createElement(Tester), container);
return inst._reactInternalFiber.child;
}

module.exports = function detectFiberTags() {
const supportsMode = typeof React.StrictMode !== 'undefined';
const supportsContext = typeof React.createContext !== 'undefined';
const supportsForwardRef = typeof React.forwardRef !== 'undefined';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These assume you're not going to use a newer react minor with an older react-dom minor. If that's not an assumption we're comfortable making, I can add some try-catches and fall back.

Copy link
Member

Choose a reason for hiding this comment

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

I think that it's fine if things break with a mismatched react/react-dom - those have always had to match minor versions to work properly.


function Fn() {
return null;
}
// eslint-disable-next-line react/prefer-stateless-function
class Cls extends React.Component {
render() {
return null;
}
}
let Ctx = null;
let FwdRef = null;
if (supportsContext) {
Ctx = React.createContext();
}
if (supportsForwardRef) {
// React will warn if we don't have both arguments.
// eslint-disable-next-line no-unused-vars
FwdRef = React.forwardRef((props, ref) => null);
}

return {
HostRoot: getFiber('test').return.return.tag, // Go two levels above to find the root
ClassComponent: getFiber(React.createElement(Cls)).tag,
Fragment: getFiber([['nested']]).tag,
FunctionalComponent: getFiber(React.createElement(Fn)).tag,
HostPortal: getFiber(ReactDOM.createPortal(null, global.document.createElement('div'))).tag,
HostComponent: getFiber(React.createElement('span')).tag,
HostText: getFiber('text').tag,
Mode: supportsMode
? getFiber(React.createElement(React.StrictMode)).tag
: -1,
ContextConsumer: supportsContext
? getFiber(React.createElement(Ctx.Consumer, null, () => null)).tag
: -1,
ContextProvider: supportsContext
? getFiber(React.createElement(Ctx.Provider, { value: null })).tag
: -1,
ForwardRef: supportsForwardRef
? getFiber(React.createElement(FwdRef)).tag
: -1,
};
};