mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove Stack (part 4: remove Stack-only branches and types) (#10798)
* Remove findDOMNode injection and inline it * Remove Stack-only code in ReactGenericBatching * Remove Stack-only code branches
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
|
||||
/**
|
||||
@@ -24,7 +23,7 @@ var ReactCurrentOwner = {
|
||||
* @internal
|
||||
* @type {ReactComponent}
|
||||
*/
|
||||
current: (null: null | ReactInstance | Fiber),
|
||||
current: (null: null | Fiber),
|
||||
};
|
||||
|
||||
module.exports = ReactCurrentOwner;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
import type {ReactNodeList} from 'ReactTypes';
|
||||
|
||||
require('checkReact');
|
||||
@@ -28,6 +27,7 @@ var ReactInputSelection = require('ReactInputSelection');
|
||||
var ReactInstanceMap = require('ReactInstanceMap');
|
||||
var ReactPortal = require('ReactPortal');
|
||||
var ReactVersion = require('ReactVersion');
|
||||
var {ReactCurrentOwner} = require('ReactGlobalSharedState');
|
||||
var {injectInternals} = require('ReactFiberDevToolsHook');
|
||||
var {
|
||||
ELEMENT_NODE,
|
||||
@@ -38,7 +38,7 @@ var {
|
||||
} = require('HTMLNodeType');
|
||||
var {ROOT_ATTRIBUTE_NAME} = require('DOMProperty');
|
||||
|
||||
var findDOMNode = require('findDOMNode');
|
||||
var getComponentName = require('getComponentName');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
var {getChildNamespace} = DOMNamespaces;
|
||||
@@ -85,9 +85,6 @@ require('ReactDOMInjection');
|
||||
ReactControlledComponent.injection.injectFiberControlledHostComponent(
|
||||
ReactDOMFiberComponent,
|
||||
);
|
||||
findDOMNode._injectFiber(function(fiber: Fiber) {
|
||||
return DOMRenderer.findHostInstance(fiber);
|
||||
});
|
||||
|
||||
type DOMContainer =
|
||||
| (Element & {
|
||||
@@ -232,7 +229,7 @@ var DOMRenderer = ReactFiberReconciler({
|
||||
if (__DEV__) {
|
||||
// TODO: take namespace into account when validating.
|
||||
const hostContextDev = ((hostContext: any): HostContextDev);
|
||||
validateDOMNesting(type, null, null, hostContextDev.ancestorInfo);
|
||||
validateDOMNesting(type, null, hostContextDev.ancestorInfo);
|
||||
if (
|
||||
typeof props.children === 'string' ||
|
||||
typeof props.children === 'number'
|
||||
@@ -243,7 +240,7 @@ var DOMRenderer = ReactFiberReconciler({
|
||||
type,
|
||||
null,
|
||||
);
|
||||
validateDOMNesting(null, string, null, ownAncestorInfo);
|
||||
validateDOMNesting(null, string, ownAncestorInfo);
|
||||
}
|
||||
parentNamespace = hostContextDev.namespace;
|
||||
} else {
|
||||
@@ -298,7 +295,7 @@ var DOMRenderer = ReactFiberReconciler({
|
||||
type,
|
||||
null,
|
||||
);
|
||||
validateDOMNesting(null, string, null, ownAncestorInfo);
|
||||
validateDOMNesting(null, string, ownAncestorInfo);
|
||||
}
|
||||
}
|
||||
return diffProperties(
|
||||
@@ -365,7 +362,7 @@ var DOMRenderer = ReactFiberReconciler({
|
||||
): TextInstance {
|
||||
if (__DEV__) {
|
||||
const hostContextDev = ((hostContext: any): HostContextDev);
|
||||
validateDOMNesting(null, text, null, hostContextDev.ancestorInfo);
|
||||
validateDOMNesting(null, text, hostContextDev.ancestorInfo);
|
||||
}
|
||||
var textNode: TextInstance = createTextNode(text, rootContainerInstance);
|
||||
precacheFiberNode(internalInstanceHandle, textNode);
|
||||
@@ -675,6 +672,48 @@ function createPortal(
|
||||
var ReactDOMFiber = {
|
||||
createPortal,
|
||||
|
||||
findDOMNode(
|
||||
componentOrElement: Element | ?React$Component<any, any>,
|
||||
): null | Element | Text {
|
||||
if (__DEV__) {
|
||||
var owner = (ReactCurrentOwner.current: any);
|
||||
if (owner !== null) {
|
||||
var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
|
||||
warning(
|
||||
warnedAboutRefsInRender,
|
||||
'%s is accessing findDOMNode inside its render(). ' +
|
||||
'render() should be a pure function of props and state. It should ' +
|
||||
'never access something that requires stale data from the previous ' +
|
||||
'render, such as refs. Move this logic to componentDidMount and ' +
|
||||
'componentDidUpdate instead.',
|
||||
getComponentName(owner) || 'A component',
|
||||
);
|
||||
owner.stateNode._warnedAboutRefsInRender = true;
|
||||
}
|
||||
}
|
||||
if (componentOrElement == null) {
|
||||
return null;
|
||||
}
|
||||
if ((componentOrElement: any).nodeType === ELEMENT_NODE) {
|
||||
return (componentOrElement: any);
|
||||
}
|
||||
|
||||
var inst = ReactInstanceMap.get(componentOrElement);
|
||||
if (inst) {
|
||||
return DOMRenderer.findHostInstance(inst);
|
||||
}
|
||||
|
||||
if (typeof componentOrElement.render === 'function') {
|
||||
invariant(false, 'Unable to find node on an unmounted component.');
|
||||
} else {
|
||||
invariant(
|
||||
false,
|
||||
'Element appears to be neither ReactComponent nor DOMNode. Keys: %s',
|
||||
Object.keys(componentOrElement),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
hydrate(element: React$Node, container: DOMContainer, callback: ?Function) {
|
||||
// TODO: throw or warn if we couldn't hydrate?
|
||||
return renderSubtreeIntoContainer(null, element, container, true, callback);
|
||||
@@ -768,8 +807,6 @@ var ReactDOMFiber = {
|
||||
}
|
||||
},
|
||||
|
||||
findDOMNode: findDOMNode,
|
||||
|
||||
// Temporary alias since we already shipped React 16 RC with it.
|
||||
// TODO: remove in React 17.
|
||||
unstable_createPortal: createPortal,
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule ReactDOMComponentFlags
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ReactDOMComponentFlags = {
|
||||
hasCachedChildNodes: 1 << 0,
|
||||
};
|
||||
|
||||
module.exports = ReactDOMComponentFlags;
|
||||
@@ -9,116 +9,18 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var DOMProperty = require('DOMProperty');
|
||||
var ReactDOMComponentFlags = require('ReactDOMComponentFlags');
|
||||
var {HostComponent, HostText} = require('ReactTypeOfWork');
|
||||
var {ELEMENT_NODE, COMMENT_NODE} = require('HTMLNodeType');
|
||||
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
|
||||
var Flags = ReactDOMComponentFlags;
|
||||
|
||||
var randomKey = Math.random().toString(36).slice(2);
|
||||
|
||||
var internalInstanceKey = '__reactInternalInstance$' + randomKey;
|
||||
|
||||
var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
|
||||
|
||||
/**
|
||||
* Check if a given node should be cached.
|
||||
*/
|
||||
function shouldPrecacheNode(node, nodeID) {
|
||||
return (
|
||||
(node.nodeType === ELEMENT_NODE &&
|
||||
node.getAttribute(ATTR_NAME) === '' + nodeID) ||
|
||||
(node.nodeType === COMMENT_NODE &&
|
||||
node.nodeValue === ' react-text: ' + nodeID + ' ') ||
|
||||
(node.nodeType === COMMENT_NODE &&
|
||||
node.nodeValue === ' react-empty: ' + nodeID + ' ')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drill down (through composites and empty components) until we get a host or
|
||||
* host text component.
|
||||
*
|
||||
* This is pretty polymorphic but unavoidable with the current structure we have
|
||||
* for `_renderedChildren`.
|
||||
*/
|
||||
function getRenderedHostOrTextFromComponent(component) {
|
||||
var rendered;
|
||||
while ((rendered = component._renderedComponent)) {
|
||||
component = rendered;
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate `_hostNode` on the rendered host/text component with the given
|
||||
* DOM node. The passed `inst` can be a composite.
|
||||
*/
|
||||
function precacheNode(inst, node) {
|
||||
var hostInst = getRenderedHostOrTextFromComponent(inst);
|
||||
hostInst._hostNode = node;
|
||||
node[internalInstanceKey] = hostInst;
|
||||
}
|
||||
|
||||
function precacheFiberNode(hostInst, node) {
|
||||
node[internalInstanceKey] = hostInst;
|
||||
}
|
||||
|
||||
function uncacheNode(inst) {
|
||||
var node = inst._hostNode;
|
||||
if (node) {
|
||||
delete node[internalInstanceKey];
|
||||
inst._hostNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate `_hostNode` on each child of `inst`, assuming that the children
|
||||
* match up with the DOM (element) children of `node`.
|
||||
*
|
||||
* We cache entire levels at once to avoid an n^2 problem where we access the
|
||||
* children of a node sequentially and have to walk from the start to our target
|
||||
* node every time.
|
||||
*
|
||||
* Since we update `_renderedChildren` and the actual DOM at (slightly)
|
||||
* different times, we could race here and see a newer `_renderedChildren` than
|
||||
* the DOM nodes we see. To avoid this, ReactMultiChild calls
|
||||
* `prepareToManageChildren` before we change `_renderedChildren`, at which
|
||||
* time the container's child nodes are always cached (until it unmounts).
|
||||
*/
|
||||
function precacheChildNodes(inst, node) {
|
||||
if (inst._flags & Flags.hasCachedChildNodes) {
|
||||
return;
|
||||
}
|
||||
var children = inst._renderedChildren;
|
||||
var childNode = node.firstChild;
|
||||
outer: for (var name in children) {
|
||||
if (!children.hasOwnProperty(name)) {
|
||||
continue;
|
||||
}
|
||||
var childInst = children[name];
|
||||
var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
|
||||
if (childID === 0) {
|
||||
// We're currently unmounting this child in ReactMultiChild; skip it.
|
||||
continue;
|
||||
}
|
||||
// We assume the child nodes are in the same order as the child instances.
|
||||
for (; childNode !== null; childNode = childNode.nextSibling) {
|
||||
if (shouldPrecacheNode(childNode, childID)) {
|
||||
precacheNode(childInst, childNode);
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
// We reached the end of the DOM children without finding an ID match.
|
||||
invariant(false, 'Unable to find element with ID %s.', childID);
|
||||
}
|
||||
inst._flags |= Flags.hasCachedChildNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a DOM node, return the closest ReactDOMComponent or
|
||||
* ReactDOMTextComponent instance ancestor.
|
||||
@@ -149,9 +51,6 @@ function getClosestInstanceFromNode(node) {
|
||||
}
|
||||
for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
|
||||
closest = inst;
|
||||
if (parents.length) {
|
||||
precacheChildNodes(inst, node);
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
@@ -166,18 +65,11 @@ function getInstanceFromNode(node) {
|
||||
if (inst) {
|
||||
if (inst.tag === HostComponent || inst.tag === HostText) {
|
||||
return inst;
|
||||
} else if (inst._hostNode === node) {
|
||||
return inst;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
inst = getClosestInstanceFromNode(node);
|
||||
if (inst != null && inst._hostNode === node) {
|
||||
return inst;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,33 +85,7 @@ function getNodeFromInstance(inst) {
|
||||
|
||||
// Without this first invariant, passing a non-DOM-component triggers the next
|
||||
// invariant for a missing parent, which is super confusing.
|
||||
invariant(
|
||||
inst._hostNode !== undefined,
|
||||
'getNodeFromInstance: Invalid argument.',
|
||||
);
|
||||
|
||||
if (inst._hostNode) {
|
||||
return inst._hostNode;
|
||||
}
|
||||
|
||||
// Walk up the tree until we find an ancestor whose DOM node we have cached.
|
||||
var parents = [];
|
||||
while (!inst._hostNode) {
|
||||
parents.push(inst);
|
||||
invariant(
|
||||
inst._hostParent,
|
||||
'React DOM tree root should always have a node reference.',
|
||||
);
|
||||
inst = inst._hostParent;
|
||||
}
|
||||
|
||||
// Now parents contains each ancestor that does *not* have a cached native
|
||||
// node, and `inst` is the deepest ancestor that does.
|
||||
for (; parents.length; inst = parents.pop()) {
|
||||
precacheChildNodes(inst, inst._hostNode);
|
||||
}
|
||||
|
||||
return inst._hostNode;
|
||||
invariant(false, 'getNodeFromInstance: Invalid argument.');
|
||||
}
|
||||
|
||||
function getFiberCurrentPropsFromNode(node) {
|
||||
@@ -234,9 +100,6 @@ var ReactDOMComponentTree = {
|
||||
getClosestInstanceFromNode: getClosestInstanceFromNode,
|
||||
getInstanceFromNode: getInstanceFromNode,
|
||||
getNodeFromInstance: getNodeFromInstance,
|
||||
precacheChildNodes: precacheChildNodes,
|
||||
precacheNode: precacheNode,
|
||||
uncacheNode: uncacheNode,
|
||||
precacheFiberNode: precacheFiberNode,
|
||||
getFiberCurrentPropsFromNode,
|
||||
updateFiberProps,
|
||||
|
||||
@@ -31,22 +31,14 @@ function findRootContainerNode(inst) {
|
||||
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
|
||||
// traversal, but caching is difficult to do correctly without using a
|
||||
// mutation observer to listen for all DOM changes.
|
||||
if (typeof inst.tag === 'number') {
|
||||
while (inst.return) {
|
||||
inst = inst.return;
|
||||
}
|
||||
if (inst.tag !== HostRoot) {
|
||||
// This can happen if we're in a detached tree.
|
||||
return null;
|
||||
}
|
||||
return inst.stateNode.containerInfo;
|
||||
} else {
|
||||
while (inst._hostParent) {
|
||||
inst = inst._hostParent;
|
||||
}
|
||||
var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
|
||||
return rootNode.parentNode;
|
||||
while (inst.return) {
|
||||
inst = inst.return;
|
||||
}
|
||||
if (inst.tag !== HostRoot) {
|
||||
// This can happen if we're in a detached tree.
|
||||
return null;
|
||||
}
|
||||
return inst.stateNode.containerInfo;
|
||||
}
|
||||
|
||||
// Used to store ancestor hierarchy in top level callback
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
var ReactDOMFeatureFlags = {
|
||||
fiberAsyncScheduling: false,
|
||||
useFiber: true,
|
||||
};
|
||||
|
||||
module.exports = ReactDOMFeatureFlags;
|
||||
|
||||
@@ -23,17 +23,11 @@ describe('ReactDOMComponentTree', () => {
|
||||
}
|
||||
|
||||
function getTypeOf(instance) {
|
||||
if (typeof instance.tag === 'number') {
|
||||
return instance.type;
|
||||
}
|
||||
return instance._currentElement.type;
|
||||
return instance.type;
|
||||
}
|
||||
|
||||
function getTextOf(instance) {
|
||||
if (typeof instance.tag === 'number') {
|
||||
return instance.memoizedProps;
|
||||
}
|
||||
return instance._stringText;
|
||||
return instance.memoizedProps;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -34,7 +34,7 @@ import type {
|
||||
DispatchConfig,
|
||||
ReactSyntheticEvent,
|
||||
} from 'ReactSyntheticEventType';
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
import type {EventTypes, PluginModule} from 'PluginModuleType';
|
||||
|
||||
/**
|
||||
@@ -179,7 +179,7 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
|
||||
|
||||
extractEvents: function(
|
||||
topLevelType: TopLevelTypes,
|
||||
targetInst: ReactInstance,
|
||||
targetInst: Fiber,
|
||||
nativeEvent: MouseEvent,
|
||||
nativeEventTarget: EventTarget,
|
||||
): null | ReactSyntheticEvent {
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule findDOMNode
|
||||
* @flow
|
||||
*/
|
||||
|
||||
var ReactInstanceMap = require('ReactInstanceMap');
|
||||
var {ELEMENT_NODE} = require('HTMLNodeType');
|
||||
var {ReactCurrentOwner} = require('ReactGlobalSharedState');
|
||||
|
||||
var getComponentName = require('getComponentName');
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
if (__DEV__) {
|
||||
var warning = require('fbjs/lib/warning');
|
||||
}
|
||||
|
||||
let findFiber = function(arg) {
|
||||
invariant(false, 'Missing injection for fiber findDOMNode');
|
||||
};
|
||||
let findStack = function(arg) {
|
||||
invariant(false, 'Missing injection for stack findDOMNode');
|
||||
};
|
||||
|
||||
const findDOMNode = function(
|
||||
componentOrElement: Element | ?React$Component<any, any>,
|
||||
): null | Element | Text {
|
||||
if (__DEV__) {
|
||||
var owner = (ReactCurrentOwner.current: any);
|
||||
if (owner !== null) {
|
||||
var isFiber = typeof owner.tag === 'number';
|
||||
var warnedAboutRefsInRender = isFiber
|
||||
? owner.stateNode._warnedAboutRefsInRender
|
||||
: owner._warnedAboutRefsInRender;
|
||||
warning(
|
||||
warnedAboutRefsInRender,
|
||||
'%s is accessing findDOMNode inside its render(). ' +
|
||||
'render() should be a pure function of props and state. It should ' +
|
||||
'never access something that requires stale data from the previous ' +
|
||||
'render, such as refs. Move this logic to componentDidMount and ' +
|
||||
'componentDidUpdate instead.',
|
||||
getComponentName(owner) || 'A component',
|
||||
);
|
||||
if (isFiber) {
|
||||
owner.stateNode._warnedAboutRefsInRender = true;
|
||||
} else {
|
||||
owner._warnedAboutRefsInRender = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (componentOrElement == null) {
|
||||
return null;
|
||||
}
|
||||
if ((componentOrElement: any).nodeType === ELEMENT_NODE) {
|
||||
return (componentOrElement: any);
|
||||
}
|
||||
|
||||
var inst = ReactInstanceMap.get(componentOrElement);
|
||||
if (inst) {
|
||||
if (typeof inst.tag === 'number') {
|
||||
return findFiber(inst);
|
||||
} else {
|
||||
return findStack(inst);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof componentOrElement.render === 'function') {
|
||||
invariant(false, 'Unable to find node on an unmounted component.');
|
||||
} else {
|
||||
invariant(
|
||||
false,
|
||||
'Element appears to be neither ReactComponent nor DOMNode. Keys: %s',
|
||||
Object.keys(componentOrElement),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
findDOMNode._injectFiber = function(fn) {
|
||||
findFiber = fn;
|
||||
};
|
||||
findDOMNode._injectStack = function(fn) {
|
||||
findStack = fn;
|
||||
};
|
||||
|
||||
module.exports = findDOMNode;
|
||||
@@ -10,7 +10,6 @@
|
||||
'use strict';
|
||||
|
||||
var emptyFunction = require('fbjs/lib/emptyFunction');
|
||||
var getComponentName = require('getComponentName');
|
||||
|
||||
var validateDOMNesting = emptyFunction;
|
||||
|
||||
@@ -405,83 +404,9 @@ if (__DEV__) {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a ReactCompositeComponent instance, return a list of its recursive
|
||||
* owners, starting at the root and ending with the instance itself.
|
||||
*/
|
||||
var findOwnerStack = function(instance) {
|
||||
if (!instance) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var stack = [];
|
||||
do {
|
||||
stack.push(instance);
|
||||
} while ((instance = instance._currentElement._owner));
|
||||
stack.reverse();
|
||||
return stack;
|
||||
};
|
||||
|
||||
var getOwnerInfo = function(
|
||||
childInstance,
|
||||
childTag,
|
||||
ancestorInstance,
|
||||
ancestorTag,
|
||||
isParent,
|
||||
) {
|
||||
var childOwner = childInstance && childInstance._currentElement._owner;
|
||||
var ancestorOwner =
|
||||
ancestorInstance && ancestorInstance._currentElement._owner;
|
||||
|
||||
var childOwners = findOwnerStack(childOwner);
|
||||
var ancestorOwners = findOwnerStack(ancestorOwner);
|
||||
|
||||
var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
|
||||
var i;
|
||||
|
||||
var deepestCommon = -1;
|
||||
for (i = 0; i < minStackLen; i++) {
|
||||
if (childOwners[i] === ancestorOwners[i]) {
|
||||
deepestCommon = i;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var UNKNOWN = '(unknown)';
|
||||
var childOwnerNames = childOwners
|
||||
.slice(deepestCommon + 1)
|
||||
.map(inst => getComponentName(inst) || UNKNOWN);
|
||||
var ancestorOwnerNames = ancestorOwners
|
||||
.slice(deepestCommon + 1)
|
||||
.map(inst => getComponentName(inst) || UNKNOWN);
|
||||
var ownerInfo = []
|
||||
.concat(
|
||||
// If the parent and child instances have a common owner ancestor, start
|
||||
// with that -- otherwise we just start with the parent's owners.
|
||||
deepestCommon !== -1
|
||||
? getComponentName(childOwners[deepestCommon]) || UNKNOWN
|
||||
: [],
|
||||
ancestorOwnerNames,
|
||||
ancestorTag,
|
||||
// If we're warning about an invalid (non-parent) ancestry, add '...'
|
||||
isParent ? [] : ['...'],
|
||||
childOwnerNames,
|
||||
childTag,
|
||||
)
|
||||
.join(' > ');
|
||||
|
||||
return ownerInfo;
|
||||
};
|
||||
|
||||
var didWarn = {};
|
||||
|
||||
validateDOMNesting = function(
|
||||
childTag,
|
||||
childText,
|
||||
childInstance,
|
||||
ancestorInfo,
|
||||
) {
|
||||
validateDOMNesting = function(childTag, childText, ancestorInfo) {
|
||||
ancestorInfo = ancestorInfo || emptyAncestorInfo;
|
||||
var parentInfo = ancestorInfo.current;
|
||||
var parentTag = parentInfo && parentInfo.tag;
|
||||
@@ -505,24 +430,8 @@ if (__DEV__) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ancestorInstance = invalidParentOrAncestor.instance;
|
||||
var ancestorTag = invalidParentOrAncestor.tag;
|
||||
var addendum;
|
||||
|
||||
if (childInstance != null) {
|
||||
addendum =
|
||||
' See ' +
|
||||
getOwnerInfo(
|
||||
childInstance,
|
||||
childTag,
|
||||
ancestorInstance,
|
||||
ancestorTag,
|
||||
!!invalidParent,
|
||||
) +
|
||||
'.';
|
||||
} else {
|
||||
addendum = getCurrentFiberStackAddendum();
|
||||
}
|
||||
var addendum = getCurrentFiberStackAddendum();
|
||||
|
||||
var warnKey =
|
||||
!!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
|
||||
|
||||
@@ -15,7 +15,6 @@ var warnValidStyle = emptyFunction;
|
||||
|
||||
if (__DEV__) {
|
||||
var camelizeStyleName = require('fbjs/lib/camelizeStyleName');
|
||||
var getComponentName = require('getComponentName');
|
||||
var warning = require('fbjs/lib/warning');
|
||||
var {getCurrentFiberOwnerName} = require('ReactDebugCurrentFiber');
|
||||
|
||||
@@ -30,7 +29,7 @@ if (__DEV__) {
|
||||
var warnedForNaNValue = false;
|
||||
var warnedForInfinityValue = false;
|
||||
|
||||
var warnHyphenatedStyleName = function(name, owner) {
|
||||
var warnHyphenatedStyleName = function(name) {
|
||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||
return;
|
||||
}
|
||||
@@ -41,11 +40,11 @@ if (__DEV__) {
|
||||
'Unsupported style property %s. Did you mean %s?%s',
|
||||
name,
|
||||
camelizeStyleName(name),
|
||||
checkRenderMessage(owner),
|
||||
checkRenderMessage(),
|
||||
);
|
||||
};
|
||||
|
||||
var warnBadVendoredStyleName = function(name, owner) {
|
||||
var warnBadVendoredStyleName = function(name) {
|
||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||
return;
|
||||
}
|
||||
@@ -56,11 +55,11 @@ if (__DEV__) {
|
||||
'Unsupported vendor-prefixed style property %s. Did you mean %s?%s',
|
||||
name,
|
||||
name.charAt(0).toUpperCase() + name.slice(1),
|
||||
checkRenderMessage(owner),
|
||||
checkRenderMessage(),
|
||||
);
|
||||
};
|
||||
|
||||
var warnStyleValueWithSemicolon = function(name, value, owner) {
|
||||
var warnStyleValueWithSemicolon = function(name, value) {
|
||||
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
|
||||
return;
|
||||
}
|
||||
@@ -70,13 +69,13 @@ if (__DEV__) {
|
||||
false,
|
||||
"Style property values shouldn't contain a semicolon.%s " +
|
||||
'Try "%s: %s" instead.',
|
||||
checkRenderMessage(owner),
|
||||
checkRenderMessage(),
|
||||
name,
|
||||
value.replace(badStyleValueWithSemicolonPattern, ''),
|
||||
);
|
||||
};
|
||||
|
||||
var warnStyleValueIsNaN = function(name, value, owner) {
|
||||
var warnStyleValueIsNaN = function(name, value) {
|
||||
if (warnedForNaNValue) {
|
||||
return;
|
||||
}
|
||||
@@ -86,11 +85,11 @@ if (__DEV__) {
|
||||
false,
|
||||
'`NaN` is an invalid value for the `%s` css style property.%s',
|
||||
name,
|
||||
checkRenderMessage(owner),
|
||||
checkRenderMessage(),
|
||||
);
|
||||
};
|
||||
|
||||
var warnStyleValueIsInfinity = function(name, value, owner) {
|
||||
var warnStyleValueIsInfinity = function(name, value) {
|
||||
if (warnedForInfinityValue) {
|
||||
return;
|
||||
}
|
||||
@@ -100,21 +99,16 @@ if (__DEV__) {
|
||||
false,
|
||||
'`Infinity` is an invalid value for the `%s` css style property.%s',
|
||||
name,
|
||||
checkRenderMessage(owner),
|
||||
checkRenderMessage(),
|
||||
);
|
||||
};
|
||||
|
||||
var checkRenderMessage = function(owner) {
|
||||
var checkRenderMessage = function() {
|
||||
var ownerName;
|
||||
if (owner != null) {
|
||||
// Stack passes the owner manually all the way to CSSPropertyOperations.
|
||||
ownerName = getComponentName(owner);
|
||||
} else {
|
||||
// Fiber doesn't pass it but uses ReactDebugCurrentFiber to track it.
|
||||
// It is only enabled in development and tracks host components too.
|
||||
ownerName = getCurrentFiberOwnerName();
|
||||
// TODO: also report the stack.
|
||||
}
|
||||
// Fiber doesn't pass it but uses ReactDebugCurrentFiber to track it.
|
||||
// It is only enabled in development and tracks host components too.
|
||||
ownerName = getCurrentFiberOwnerName();
|
||||
// TODO: also report the stack.
|
||||
if (ownerName) {
|
||||
return '\n\nCheck the render method of `' + ownerName + '`.';
|
||||
}
|
||||
@@ -122,24 +116,19 @@ if (__DEV__) {
|
||||
};
|
||||
|
||||
warnValidStyle = function(name, value, component) {
|
||||
var owner;
|
||||
if (component) {
|
||||
// TODO: this only works with Stack. Seems like we need to add unit tests?
|
||||
owner = component._currentElement._owner;
|
||||
}
|
||||
if (name.indexOf('-') > -1) {
|
||||
warnHyphenatedStyleName(name, owner);
|
||||
warnHyphenatedStyleName(name);
|
||||
} else if (badVendoredStyleNamePattern.test(name)) {
|
||||
warnBadVendoredStyleName(name, owner);
|
||||
warnBadVendoredStyleName(name);
|
||||
} else if (badStyleValueWithSemicolonPattern.test(value)) {
|
||||
warnStyleValueWithSemicolon(name, value, owner);
|
||||
warnStyleValueWithSemicolon(name, value);
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
if (isNaN(value)) {
|
||||
warnStyleValueIsNaN(name, value, owner);
|
||||
warnStyleValueIsNaN(name, value);
|
||||
} else if (!isFinite(value)) {
|
||||
warnStyleValueIsInfinity(name, value, owner);
|
||||
warnStyleValueIsInfinity(name, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,35 +43,6 @@ function Event(suffix) {}
|
||||
* @class ReactTestUtils
|
||||
*/
|
||||
|
||||
function findAllInRenderedStackTreeInternal(inst, test) {
|
||||
if (!inst || !inst.getPublicInstance) {
|
||||
return [];
|
||||
}
|
||||
var publicInst = inst.getPublicInstance();
|
||||
var ret = test(publicInst) ? [publicInst] : [];
|
||||
var currentElement = inst._currentElement;
|
||||
if (ReactTestUtils.isDOMComponent(publicInst)) {
|
||||
var renderedChildren = inst._renderedChildren;
|
||||
var key;
|
||||
for (key in renderedChildren) {
|
||||
if (!renderedChildren.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
ret = ret.concat(
|
||||
findAllInRenderedStackTreeInternal(renderedChildren[key], test),
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
React.isValidElement(currentElement) &&
|
||||
typeof currentElement.type === 'function'
|
||||
) {
|
||||
ret = ret.concat(
|
||||
findAllInRenderedStackTreeInternal(inst._renderedComponent, test),
|
||||
);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function findAllInRenderedFiberTreeInternal(fiber, test) {
|
||||
if (!fiber) {
|
||||
return [];
|
||||
@@ -169,10 +140,7 @@ var ReactTestUtils = {
|
||||
return false;
|
||||
}
|
||||
var internalInstance = ReactInstanceMap.get(inst);
|
||||
var constructor = typeof internalInstance.tag === 'number'
|
||||
? internalInstance.type // Fiber reconciler
|
||||
: internalInstance._currentElement.type; // Stack reconciler
|
||||
|
||||
var constructor = internalInstance.type;
|
||||
return constructor === type;
|
||||
},
|
||||
|
||||
@@ -185,11 +153,7 @@ var ReactTestUtils = {
|
||||
'findAllInRenderedTree(...): instance must be a composite component',
|
||||
);
|
||||
var internalInstance = ReactInstanceMap.get(inst);
|
||||
if (internalInstance && typeof internalInstance.tag === 'number') {
|
||||
return findAllInRenderedFiberTreeInternal(internalInstance, test);
|
||||
} else {
|
||||
return findAllInRenderedStackTreeInternal(internalInstance, test);
|
||||
}
|
||||
return findAllInRenderedFiberTreeInternal(internalInstance, test);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,41 +14,10 @@ var invariant = require('fbjs/lib/invariant');
|
||||
var instanceCache = {};
|
||||
var instanceProps = {};
|
||||
|
||||
/**
|
||||
* Drill down (through composites and empty components) until we get a host or
|
||||
* host text component.
|
||||
*
|
||||
* This is pretty polymorphic but unavoidable with the current structure we have
|
||||
* for `_renderedChildren`.
|
||||
*/
|
||||
function getRenderedHostOrTextFromComponent(component) {
|
||||
var rendered;
|
||||
while ((rendered = component._renderedComponent)) {
|
||||
component = rendered;
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate `_hostNode` on the rendered host/text component with the given
|
||||
* DOM node. The passed `inst` can be a composite.
|
||||
*/
|
||||
function precacheNode(inst, tag) {
|
||||
var nativeInst = getRenderedHostOrTextFromComponent(inst);
|
||||
instanceCache[tag] = nativeInst;
|
||||
}
|
||||
|
||||
function precacheFiberNode(hostInst, tag) {
|
||||
instanceCache[tag] = hostInst;
|
||||
}
|
||||
|
||||
function uncacheNode(inst) {
|
||||
var tag = inst._rootNodeID;
|
||||
if (tag) {
|
||||
delete instanceCache[tag];
|
||||
}
|
||||
}
|
||||
|
||||
function uncacheFiberNode(tag) {
|
||||
delete instanceCache[tag];
|
||||
delete instanceProps[tag];
|
||||
@@ -77,9 +46,7 @@ var ReactNativeComponentTree = {
|
||||
getInstanceFromNode: getInstanceFromTag,
|
||||
getNodeFromInstance: getTagFromInstance,
|
||||
precacheFiberNode,
|
||||
precacheNode,
|
||||
uncacheFiberNode,
|
||||
uncacheNode,
|
||||
getFiberCurrentPropsFromNode,
|
||||
updateFiberProps,
|
||||
};
|
||||
|
||||
@@ -250,9 +250,7 @@ it('handles when a responder is unmounted while a touch sequence is in progress'
|
||||
if (responder === null) {
|
||||
return null;
|
||||
}
|
||||
const props = typeof responder.tag === 'number'
|
||||
? responder.memoizedProps
|
||||
: responder._currentElement.props;
|
||||
const props = responder.memoizedProps;
|
||||
return props ? props.id : null;
|
||||
}
|
||||
|
||||
@@ -342,9 +340,7 @@ it('handles events without target', () => {
|
||||
if (responder === null) {
|
||||
return null;
|
||||
}
|
||||
const props = typeof responder.tag === 'number'
|
||||
? responder.memoizedProps
|
||||
: responder._currentElement.props;
|
||||
const props = responder.memoizedProps;
|
||||
return props ? props.id : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
import type {ReactElement} from 'ReactElementType';
|
||||
import type {ReactCoroutine, ReactPortal, ReactYield} from 'ReactTypes';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {PriorityLevel} from 'ReactPriorityLevel';
|
||||
|
||||
var {REACT_COROUTINE_TYPE, REACT_YIELD_TYPE} = require('ReactCoroutine');
|
||||
@@ -120,20 +119,15 @@ function coerceRef(current: Fiber | null, element: ReactElement) {
|
||||
let mixedRef = element.ref;
|
||||
if (mixedRef !== null && typeof mixedRef !== 'function') {
|
||||
if (element._owner) {
|
||||
const owner: ?(Fiber | ReactInstance) = (element._owner: any);
|
||||
const owner: ?Fiber = (element._owner: any);
|
||||
let inst;
|
||||
if (owner) {
|
||||
if (typeof owner.tag === 'number') {
|
||||
const ownerFiber = ((owner: any): Fiber);
|
||||
invariant(
|
||||
ownerFiber.tag === ClassComponent,
|
||||
'Stateless function components cannot have refs.',
|
||||
);
|
||||
inst = ownerFiber.stateNode;
|
||||
} else {
|
||||
// Stack
|
||||
inst = (owner: any).getPublicInstance();
|
||||
}
|
||||
const ownerFiber = ((owner: any): Fiber);
|
||||
invariant(
|
||||
ownerFiber.tag === ClassComponent,
|
||||
'Stateless function components cannot have refs.',
|
||||
);
|
||||
inst = ownerFiber.stateNode;
|
||||
}
|
||||
invariant(
|
||||
inst,
|
||||
|
||||
@@ -29,8 +29,9 @@ function getCurrentFiberOwnerName(): string | null {
|
||||
if (fiber === null) {
|
||||
return null;
|
||||
}
|
||||
if (fiber._debugOwner != null) {
|
||||
return getComponentName(fiber._debugOwner);
|
||||
const owner = fiber._debugOwner;
|
||||
if (owner !== null && typeof owner !== 'undefined') {
|
||||
return getComponentName(owner);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
'use strict';
|
||||
|
||||
import type {ReactElement, Source} from 'ReactElementType';
|
||||
import type {ReactInstance, DebugID} from 'ReactInstanceType';
|
||||
import type {
|
||||
ReactCoroutine,
|
||||
ReactFragment,
|
||||
@@ -147,9 +146,9 @@ export type Fiber = {|
|
||||
// workInProgress : Fiber -> alternate The alternate used for reuse happens
|
||||
// to be the same as work in progress.
|
||||
// __DEV__ only
|
||||
_debugID?: DebugID,
|
||||
_debugID?: number,
|
||||
_debugSource?: Source | null,
|
||||
_debugOwner?: Fiber | ReactInstance | null, // Stack compatible
|
||||
_debugOwner?: Fiber | null,
|
||||
_debugIsCurrentlyTiming?: boolean,
|
||||
|};
|
||||
|
||||
@@ -349,7 +348,7 @@ function createFiberFromElementType(
|
||||
type: mixed,
|
||||
key: null | string,
|
||||
internalContextTag: TypeOfInternalContext,
|
||||
debugOwner: null | Fiber | ReactInstance,
|
||||
debugOwner: null | Fiber,
|
||||
): Fiber {
|
||||
let fiber;
|
||||
if (typeof type === 'function') {
|
||||
|
||||
@@ -25,7 +25,9 @@ var {
|
||||
} = require('ReactFiberContext');
|
||||
var {createFiberRoot} = require('ReactFiberRoot');
|
||||
var ReactFiberScheduler = require('ReactFiberScheduler');
|
||||
var ReactInstanceMap = require('ReactInstanceMap');
|
||||
var {HostComponent} = require('ReactTypeOfWork');
|
||||
var emptyObject = require('fbjs/lib/emptyObject');
|
||||
|
||||
if (__DEV__) {
|
||||
var warning = require('fbjs/lib/warning');
|
||||
@@ -39,8 +41,6 @@ var {
|
||||
findCurrentHostFiberWithNoPortals,
|
||||
} = require('ReactFiberTreeReflection');
|
||||
|
||||
var getContextForSubtree = require('getContextForSubtree');
|
||||
|
||||
export type Deadline = {
|
||||
timeRemaining: () => number,
|
||||
};
|
||||
@@ -178,12 +178,19 @@ export type Reconciler<C, I, TI> = {
|
||||
findHostInstanceWithNoPortals(component: Fiber): I | TI | null,
|
||||
};
|
||||
|
||||
getContextForSubtree._injectFiber(function(fiber: Fiber) {
|
||||
function getContextForSubtree(
|
||||
parentComponent: ?React$Component<any, any>,
|
||||
): Object {
|
||||
if (!parentComponent) {
|
||||
return emptyObject;
|
||||
}
|
||||
|
||||
const fiber = ReactInstanceMap.get(parentComponent);
|
||||
const parentContext = findCurrentUnmaskedContext(fiber);
|
||||
return isContextProvider(fiber)
|
||||
? processChildContext(fiber, parentContext)
|
||||
: parentContext;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
|
||||
config: HostConfig<T, P, I, TI, PI, C, CX, PL>,
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule ReactHostOperationHistoryHook
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {DebugID} from 'ReactInstanceType';
|
||||
|
||||
export type Operation = {instanceID: DebugID} & (
|
||||
| {type: 'mount', payload: string}
|
||||
| {type: 'insert child', payload: {toIndex: number, content: string}}
|
||||
| {type: 'move child', payload: {fromIndex: number, toIndex: number}}
|
||||
| {type: 'replace children', payload: string}
|
||||
| {type: 'replace text', payload: string}
|
||||
| {type: 'replace with', payload: string}
|
||||
| {type: 'update styles', payload: mixed /* Style Object */}
|
||||
| {type: 'update attribute', payload: {[name: string]: string}}
|
||||
| {type: 'remove attribute', payload: string});
|
||||
|
||||
// Trust the developer to only use this with a __DEV__ check
|
||||
var ReactHostOperationHistoryHook = ((null: any): typeof ReactHostOperationHistoryHook);
|
||||
|
||||
if (__DEV__) {
|
||||
var history: Array<Operation> = [];
|
||||
|
||||
ReactHostOperationHistoryHook = {
|
||||
onHostOperation(operation: Operation) {
|
||||
history.push(operation);
|
||||
},
|
||||
|
||||
clearHistory(): void {
|
||||
if (ReactHostOperationHistoryHook._preventClearing) {
|
||||
// Should only be used for tests.
|
||||
return;
|
||||
}
|
||||
|
||||
history = [];
|
||||
},
|
||||
|
||||
getHistory(): Array<Operation> {
|
||||
return history;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ReactHostOperationHistoryHook;
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule ReactInvalidSetStateWarningHook
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ReactInvalidSetStateWarningHook = {};
|
||||
|
||||
if (__DEV__) {
|
||||
var warning = require('fbjs/lib/warning');
|
||||
var processingChildContext = false;
|
||||
|
||||
var warnInvalidSetState = function() {
|
||||
warning(
|
||||
!processingChildContext,
|
||||
'setState(...): Cannot call setState() inside getChildContext()',
|
||||
);
|
||||
};
|
||||
|
||||
ReactInvalidSetStateWarningHook = {
|
||||
onBeginProcessingChildContext(): void {
|
||||
processingChildContext = true;
|
||||
},
|
||||
onEndProcessingChildContext(): void {
|
||||
processingChildContext = false;
|
||||
},
|
||||
onSetState(): void {
|
||||
warnInvalidSetState();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ReactInvalidSetStateWarningHook;
|
||||
@@ -12,21 +12,16 @@
|
||||
var {HostComponent} = require('ReactTypeOfWork');
|
||||
|
||||
function getParent(inst) {
|
||||
if (inst._hostParent !== undefined) {
|
||||
return inst._hostParent;
|
||||
}
|
||||
if (typeof inst.tag === 'number') {
|
||||
do {
|
||||
inst = inst.return;
|
||||
// TODO: If this is a HostRoot we might want to bail out.
|
||||
// That is depending on if we want nested subtrees (layers) to bubble
|
||||
// events to their parent. We could also go through parentNode on the
|
||||
// host node but that wouldn't work for React Native and doesn't let us
|
||||
// do the portal feature.
|
||||
} while (inst && inst.tag !== HostComponent);
|
||||
if (inst) {
|
||||
return inst;
|
||||
}
|
||||
do {
|
||||
inst = inst.return;
|
||||
// TODO: If this is a HostRoot we might want to bail out.
|
||||
// That is depending on if we want nested subtrees (layers) to bubble
|
||||
// events to their parent. We could also go through parentNode on the
|
||||
// host node but that wouldn't work for React Native and doesn't let us
|
||||
// do the portal feature.
|
||||
} while (inst && inst.tag !== HostComponent);
|
||||
if (inst) {
|
||||
return inst;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -122,43 +122,20 @@ var EventPluginHub = {
|
||||
|
||||
// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
|
||||
// live here; needs to be moved to a better place soon
|
||||
if (typeof inst.tag === 'number') {
|
||||
const stateNode = inst.stateNode;
|
||||
if (!stateNode) {
|
||||
// Work in progress (ex: onload events in incremental mode).
|
||||
return null;
|
||||
}
|
||||
const props = EventPluginUtils.getFiberCurrentPropsFromNode(stateNode);
|
||||
if (!props) {
|
||||
// Work in progress.
|
||||
return null;
|
||||
}
|
||||
listener = props[registrationName];
|
||||
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
const currentElement = inst._currentElement;
|
||||
if (
|
||||
typeof currentElement === 'string' ||
|
||||
typeof currentElement === 'number'
|
||||
) {
|
||||
// Text node, let it bubble through.
|
||||
return null;
|
||||
}
|
||||
if (!inst._rootNodeID) {
|
||||
// If the instance is already unmounted, we have no listeners.
|
||||
return null;
|
||||
}
|
||||
const props = currentElement.props;
|
||||
listener = props[registrationName];
|
||||
if (
|
||||
shouldPreventMouseEvent(registrationName, currentElement.type, props)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const stateNode = inst.stateNode;
|
||||
if (!stateNode) {
|
||||
// Work in progress (ex: onload events in incremental mode).
|
||||
return null;
|
||||
}
|
||||
const props = EventPluginUtils.getFiberCurrentPropsFromNode(stateNode);
|
||||
if (!props) {
|
||||
// Work in progress.
|
||||
return null;
|
||||
}
|
||||
listener = props[registrationName];
|
||||
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
invariant(
|
||||
!listener || typeof listener === 'function',
|
||||
'Expected `%s` listener to be a function, instead got a value of `%s` type.',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
import type {
|
||||
DispatchConfig,
|
||||
ReactSyntheticEvent,
|
||||
@@ -26,7 +26,7 @@ export type PluginModule<NativeEvent> = {
|
||||
eventTypes: EventTypes,
|
||||
extractEvents: (
|
||||
topLevelType: string,
|
||||
targetInst: ReactInstance,
|
||||
targetInst: Fiber,
|
||||
nativeTarget: NativeEvent,
|
||||
nativeEventTarget: EventTarget,
|
||||
) => null | ReactSyntheticEvent,
|
||||
|
||||
@@ -36,30 +36,20 @@ function restoreStateOfTarget(target) {
|
||||
// Unmounted
|
||||
return;
|
||||
}
|
||||
if (typeof internalInstance.tag === 'number') {
|
||||
invariant(
|
||||
fiberHostComponent &&
|
||||
typeof fiberHostComponent.restoreControlledState === 'function',
|
||||
'Fiber needs to be injected to handle a fiber target for controlled ' +
|
||||
'events. This error is likely caused by a bug in React. Please file an issue.',
|
||||
);
|
||||
const props = EventPluginUtils.getFiberCurrentPropsFromNode(
|
||||
internalInstance.stateNode,
|
||||
);
|
||||
fiberHostComponent.restoreControlledState(
|
||||
internalInstance.stateNode,
|
||||
internalInstance.type,
|
||||
props,
|
||||
);
|
||||
return;
|
||||
}
|
||||
invariant(
|
||||
typeof internalInstance.restoreControlledState === 'function',
|
||||
'The internal instance must be a React host component. ' +
|
||||
'This error is likely caused by a bug in React. Please file an issue.',
|
||||
fiberHostComponent &&
|
||||
typeof fiberHostComponent.restoreControlledState === 'function',
|
||||
'Fiber needs to be injected to handle a fiber target for controlled ' +
|
||||
'events. This error is likely caused by a bug in React. Please file an issue.',
|
||||
);
|
||||
const props = EventPluginUtils.getFiberCurrentPropsFromNode(
|
||||
internalInstance.stateNode,
|
||||
);
|
||||
fiberHostComponent.restoreControlledState(
|
||||
internalInstance.stateNode,
|
||||
internalInstance.type,
|
||||
props,
|
||||
);
|
||||
// If it is not a Fiber, we can just use dynamic dispatch.
|
||||
internalInstance.restoreControlledState();
|
||||
}
|
||||
|
||||
var ReactControlledComponent = {
|
||||
|
||||
@@ -11,30 +11,22 @@
|
||||
|
||||
var ReactControlledComponent = require('ReactControlledComponent');
|
||||
|
||||
// Used as a way to call batchedUpdates when we don't know if we're in a Fiber
|
||||
// or Stack context. Such as when we're dispatching events or if third party
|
||||
// Used as a way to call batchedUpdates when we don't have a reference to
|
||||
// the renderer. Such as when we're dispatching events or if third party
|
||||
// libraries need to call batchedUpdates. Eventually, this API will go away when
|
||||
// everything is batched by default. We'll then have a similar API to opt-out of
|
||||
// scheduled work and instead do synchronous work.
|
||||
|
||||
// Defaults
|
||||
var stackBatchedUpdates = function(fn, a, b, c, d, e) {
|
||||
return fn(a, b, c, d, e);
|
||||
};
|
||||
var fiberBatchedUpdates = function(fn, bookkeeping) {
|
||||
return fn(bookkeeping);
|
||||
};
|
||||
|
||||
function performFiberBatchedUpdates(fn, bookkeeping) {
|
||||
function batchedUpdates(fn, bookkeeping) {
|
||||
// If we have Fiber loaded, we need to wrap this in a batching call so that
|
||||
// Fiber can apply its default priority for this call.
|
||||
return fiberBatchedUpdates(fn, bookkeeping);
|
||||
}
|
||||
function batchedUpdates(fn, bookkeeping) {
|
||||
// We first perform work with the stack batching strategy, by passing our
|
||||
// indirection to it.
|
||||
return stackBatchedUpdates(performFiberBatchedUpdates, fn, bookkeeping);
|
||||
}
|
||||
|
||||
var isNestingBatched = false;
|
||||
function batchedUpdatesWithControlledComponents(fn, bookkeeping) {
|
||||
@@ -58,9 +50,6 @@ function batchedUpdatesWithControlledComponents(fn, bookkeeping) {
|
||||
}
|
||||
|
||||
var ReactGenericBatchingInjection = {
|
||||
injectStackBatchedUpdates: function(_batchedUpdates) {
|
||||
stackBatchedUpdates = _batchedUpdates;
|
||||
},
|
||||
injectFiberBatchedUpdates: function(_batchedUpdates) {
|
||||
fiberBatchedUpdates = _batchedUpdates;
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
|
||||
export type DispatchConfig = {
|
||||
dependencies: Array<string>,
|
||||
@@ -27,7 +27,7 @@ export type ReactSyntheticEvent = {
|
||||
dispatchConfig: DispatchConfig,
|
||||
getPooled: (
|
||||
dispatchConfig: DispatchConfig,
|
||||
targetInst: ReactInstance,
|
||||
targetInst: Fiber,
|
||||
nativeTarget: Event,
|
||||
nativeEventTarget: EventTarget,
|
||||
) => ReactSyntheticEvent,
|
||||
|
||||
+35
-26
@@ -9,6 +9,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var {HostComponent} = require('ReactTypeOfWork');
|
||||
|
||||
var EventPluginHub;
|
||||
var ResponderEventPlugin;
|
||||
|
||||
@@ -318,35 +320,37 @@ var PARENT_HOST_NODE = {};
|
||||
var CHILD_HOST_NODE = {};
|
||||
var CHILD_HOST_NODE2 = {};
|
||||
|
||||
// These intentionally look like Fibers. ReactTreeTraversal depends on their field names.
|
||||
// TODO: we could test this with regular DOM nodes (and real fibers) instead.
|
||||
var GRANDPARENT_INST = {
|
||||
_hostParent: null,
|
||||
_rootNodeID: '1',
|
||||
_hostNode: GRANDPARENT_HOST_NODE,
|
||||
_currentElement: {props: {}},
|
||||
return: null,
|
||||
tag: HostComponent,
|
||||
stateNode: GRANDPARENT_HOST_NODE,
|
||||
memoizedProps: {},
|
||||
};
|
||||
var PARENT_INST = {
|
||||
_hostParent: GRANDPARENT_INST,
|
||||
_rootNodeID: '2',
|
||||
_hostNode: PARENT_HOST_NODE,
|
||||
_currentElement: {props: {}},
|
||||
return: GRANDPARENT_INST,
|
||||
tag: HostComponent,
|
||||
stateNode: PARENT_HOST_NODE,
|
||||
memoizedProps: {},
|
||||
};
|
||||
var CHILD_INST = {
|
||||
_hostParent: PARENT_INST,
|
||||
_rootNodeID: '3',
|
||||
_hostNode: CHILD_HOST_NODE,
|
||||
_currentElement: {props: {}},
|
||||
return: PARENT_INST,
|
||||
tag: HostComponent,
|
||||
stateNode: CHILD_HOST_NODE,
|
||||
memoizedProps: {},
|
||||
};
|
||||
var CHILD_INST2 = {
|
||||
_hostParent: PARENT_INST,
|
||||
_rootNodeID: '4',
|
||||
_hostNode: CHILD_HOST_NODE2,
|
||||
_currentElement: {props: {}},
|
||||
return: PARENT_INST,
|
||||
tag: HostComponent,
|
||||
stateNode: CHILD_HOST_NODE2,
|
||||
memoizedProps: {},
|
||||
};
|
||||
|
||||
GRANDPARENT_HOST_NODE._reactInstance = GRANDPARENT_INST;
|
||||
PARENT_HOST_NODE._reactInstance = PARENT_INST;
|
||||
CHILD_HOST_NODE._reactInstance = CHILD_INST;
|
||||
CHILD_HOST_NODE2._reactInstance = CHILD_INST2;
|
||||
GRANDPARENT_HOST_NODE.testInstance = GRANDPARENT_INST;
|
||||
PARENT_HOST_NODE.testInstance = PARENT_INST;
|
||||
CHILD_HOST_NODE.testInstance = CHILD_INST;
|
||||
CHILD_HOST_NODE2.testInstance = CHILD_INST2;
|
||||
|
||||
var three = {
|
||||
grandParent: GRANDPARENT_HOST_NODE,
|
||||
@@ -361,19 +365,23 @@ var siblings = {
|
||||
};
|
||||
|
||||
function getInstanceFromNode(node) {
|
||||
return node._reactInstance;
|
||||
return node.testInstance;
|
||||
}
|
||||
|
||||
function getNodeFromInstance(inst) {
|
||||
return inst._hostNode;
|
||||
return inst.stateNode;
|
||||
}
|
||||
|
||||
function putListener(node, registrationName, handler) {
|
||||
node._currentElement.props[registrationName] = handler;
|
||||
function getFiberCurrentPropsFromNode(node) {
|
||||
return node.testInstance.memoizedProps;
|
||||
}
|
||||
|
||||
function deleteAllListeners(node) {
|
||||
node._currentElement.props = {};
|
||||
function putListener(instance, registrationName, handler) {
|
||||
instance.memoizedProps[registrationName] = handler;
|
||||
}
|
||||
|
||||
function deleteAllListeners(instance) {
|
||||
instance.memoizedProps = {};
|
||||
}
|
||||
|
||||
describe('ResponderEventPlugin', () => {
|
||||
@@ -398,6 +406,7 @@ describe('ResponderEventPlugin', () => {
|
||||
injectComponentTree({
|
||||
getInstanceFromNode,
|
||||
getNodeFromInstance,
|
||||
getFiberCurrentPropsFromNode,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule getContextForSubtree
|
||||
* @flow
|
||||
*/
|
||||
|
||||
const ReactInstanceMap = require('ReactInstanceMap');
|
||||
|
||||
const emptyObject = require('fbjs/lib/emptyObject');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
|
||||
let getContextFiber = function(arg) {
|
||||
invariant(false, 'Missing injection for fiber getContextForSubtree');
|
||||
};
|
||||
|
||||
function getContextForSubtree(
|
||||
parentComponent: ?React$Component<any, any>,
|
||||
): Object {
|
||||
if (!parentComponent) {
|
||||
return emptyObject;
|
||||
}
|
||||
|
||||
const instance = ReactInstanceMap.get(parentComponent);
|
||||
if (typeof instance.tag === 'number') {
|
||||
return getContextFiber(instance);
|
||||
} else {
|
||||
return instance._processChildContext(instance._context);
|
||||
}
|
||||
}
|
||||
|
||||
getContextForSubtree._injectFiber = function(fn) {
|
||||
getContextFiber = fn;
|
||||
};
|
||||
|
||||
module.exports = getContextForSubtree;
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule ReactInstanceType
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// TODO: delete this file.
|
||||
// It was only necessary for Stack.
|
||||
|
||||
import type {ReactElement} from 'ReactElementType';
|
||||
|
||||
export type DebugID = number;
|
||||
|
||||
export type ReactInstance = {
|
||||
mountComponent: any,
|
||||
unmountComponent: any,
|
||||
receiveComponent: any,
|
||||
getName: () => string,
|
||||
getPublicInstance: any,
|
||||
_currentElement: ReactElement,
|
||||
};
|
||||
@@ -10,27 +10,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {ReactInstance} from 'ReactInstanceType';
|
||||
import type {Fiber} from 'ReactFiber';
|
||||
|
||||
function getComponentName(
|
||||
instanceOrFiber: ReactInstance | Fiber,
|
||||
): string | null {
|
||||
if (typeof instanceOrFiber.getName === 'function') {
|
||||
// Stack reconciler
|
||||
const instance = ((instanceOrFiber: any): ReactInstance);
|
||||
return instance.getName();
|
||||
function getComponentName(fiber: Fiber): string | null {
|
||||
const {type} = fiber;
|
||||
if (typeof type === 'string') {
|
||||
return type;
|
||||
}
|
||||
if (typeof instanceOrFiber.tag === 'number') {
|
||||
// Fiber reconciler
|
||||
const fiber = ((instanceOrFiber: any): Fiber);
|
||||
const {type} = fiber;
|
||||
if (typeof type === 'string') {
|
||||
return type;
|
||||
}
|
||||
if (typeof type === 'function') {
|
||||
return type.displayName || type.name;
|
||||
}
|
||||
if (typeof type === 'function') {
|
||||
return type.displayName || type.name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user