/** * 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. */ 'use strict'; var {HostComponent, HostText} = require('shared/ReactTypeOfWork'); var invariant = require('fbjs/lib/invariant'); var randomKey = Math.random().toString(36).slice(2); var internalInstanceKey = '__reactInternalInstance$' + randomKey; var internalEventHandlersKey = '__reactEventHandlers$' + randomKey; function precacheFiberNode(hostInst, node) { node[internalInstanceKey] = hostInst; } /** * Given a DOM node, return the closest ReactDOMComponent or * ReactDOMTextComponent instance ancestor. */ function getClosestInstanceFromNode(node) { if (node[internalInstanceKey]) { return node[internalInstanceKey]; } // Walk up the tree until we find an ancestor whose instance we have cached. var parents = []; while (!node[internalInstanceKey]) { parents.push(node); if (node.parentNode) { node = node.parentNode; } else { // Top of the tree. This node must not be part of a React tree (or is // unmounted, potentially). return null; } } var closest; var inst = node[internalInstanceKey]; if (inst.tag === HostComponent || inst.tag === HostText) { // In Fiber, this will always be the deepest root. return inst; } for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) { closest = inst; } return closest; } /** * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent * instance, or null if the node was not rendered by this React. */ function getInstanceFromNode(node) { var inst = node[internalInstanceKey]; if (inst) { if (inst.tag === HostComponent || inst.tag === HostText) { return inst; } else { return null; } } return null; } /** * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding * DOM node. */ function getNodeFromInstance(inst) { if (inst.tag === HostComponent || inst.tag === HostText) { // In Fiber this, is just the state node right now. We assume it will be // a host component or host text. return inst.stateNode; } // Without this first invariant, passing a non-DOM-component triggers the next // invariant for a missing parent, which is super confusing. invariant(false, 'getNodeFromInstance: Invalid argument.'); } function getFiberCurrentPropsFromNode(node) { return node[internalEventHandlersKey] || null; } function updateFiberProps(node, props) { node[internalEventHandlersKey] = props; } var ReactDOMComponentTree = { getClosestInstanceFromNode: getClosestInstanceFromNode, getInstanceFromNode: getInstanceFromNode, getNodeFromInstance: getNodeFromInstance, precacheFiberNode: precacheFiberNode, getFiberCurrentPropsFromNode, updateFiberProps, }; module.exports = ReactDOMComponentTree;