mirror of
https://github.com/facebook/react.git
synced 2026-02-26 00:15:01 +00:00
* Use relative paths in packages/react * Use relative paths in packages/react-art * Use relative paths in packages/react-cs * Use relative paths in other packages * Fix as many issues as I can This uncovered an interesting problem where ./b from package/src/a would resolve to a different instantiation of package/src/b in Jest. Either this is a showstopper or we can solve it by completely fobbidding remaining /src/. * Fix all tests It seems we can't use relative requires in tests anymore. Otherwise Jest becomes confused between real file and symlink. https://github.com/facebook/jest/issues/3830 This seems bad... Except that we already *don't* want people to create tests that import individual source files. All existing cases of us doing so are actually TODOs waiting to be fixed. So perhaps this requirement isn't too bad because it makes bad code looks bad. Of course, if we go with this, we'll have to lint against relative requires in tests. It also makes moving things more painful. * Prettier * Remove @providesModule * Fix remaining Haste imports I missed earlier * Fix up paths to reflect new flat structure * Fix Flow * Fix CJS and UMD builds * Fix FB bundles * Fix RN bundles * Prettier * Fix lint * Fix warning printing and error codes * Fix buggy return * Fix lint and Flow * Use Yarn on CI * Unbreak Jest * Fix lint * Fix aliased originals getting included in DEV Shouldn't affect correctness (they were ignored) but fixes DEV size regression. * Record sizes * Fix weird version in package.json * Tweak bundle labels * Get rid of output option by introducing react-dom/server.node * Reconciler should depend on prop-types * Update sizes last time
157 lines
3.6 KiB
JavaScript
157 lines
3.6 KiB
JavaScript
/**
|
|
* 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.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var {HostComponent} = require('./ReactTypeOfWork');
|
|
|
|
function getParent(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;
|
|
}
|
|
|
|
/**
|
|
* Return the lowest common ancestor of A and B, or null if they are in
|
|
* different trees.
|
|
*/
|
|
function getLowestCommonAncestor(instA, instB) {
|
|
var depthA = 0;
|
|
for (var tempA = instA; tempA; tempA = getParent(tempA)) {
|
|
depthA++;
|
|
}
|
|
var depthB = 0;
|
|
for (var tempB = instB; tempB; tempB = getParent(tempB)) {
|
|
depthB++;
|
|
}
|
|
|
|
// If A is deeper, crawl up.
|
|
while (depthA - depthB > 0) {
|
|
instA = getParent(instA);
|
|
depthA--;
|
|
}
|
|
|
|
// If B is deeper, crawl up.
|
|
while (depthB - depthA > 0) {
|
|
instB = getParent(instB);
|
|
depthB--;
|
|
}
|
|
|
|
// Walk in lockstep until we find a match.
|
|
var depth = depthA;
|
|
while (depth--) {
|
|
if (instA === instB || instA === instB.alternate) {
|
|
return instA;
|
|
}
|
|
instA = getParent(instA);
|
|
instB = getParent(instB);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return if A is an ancestor of B.
|
|
*/
|
|
function isAncestor(instA, instB) {
|
|
while (instB) {
|
|
if (instA === instB || instA === instB.alternate) {
|
|
return true;
|
|
}
|
|
instB = getParent(instB);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return the parent instance of the passed-in instance.
|
|
*/
|
|
function getParentInstance(inst) {
|
|
return getParent(inst);
|
|
}
|
|
|
|
/**
|
|
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
|
|
*/
|
|
function traverseTwoPhase(inst, fn, arg) {
|
|
var path = [];
|
|
while (inst) {
|
|
path.push(inst);
|
|
inst = getParent(inst);
|
|
}
|
|
var i;
|
|
for (i = path.length; i-- > 0; ) {
|
|
fn(path[i], 'captured', arg);
|
|
}
|
|
for (i = 0; i < path.length; i++) {
|
|
fn(path[i], 'bubbled', arg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
|
|
* should would receive a `mouseEnter` or `mouseLeave` event.
|
|
*
|
|
* Does not invoke the callback on the nearest common ancestor because nothing
|
|
* "entered" or "left" that element.
|
|
*/
|
|
function traverseEnterLeave(from, to, fn, argFrom, argTo) {
|
|
const common = from && to ? getLowestCommonAncestor(from, to) : null;
|
|
const pathFrom = [];
|
|
while (true) {
|
|
if (!from) {
|
|
break;
|
|
}
|
|
if (from === common) {
|
|
break;
|
|
}
|
|
const alternate = from.alternate;
|
|
if (alternate !== null && alternate === common) {
|
|
break;
|
|
}
|
|
pathFrom.push(from);
|
|
from = getParent(from);
|
|
}
|
|
const pathTo = [];
|
|
while (true) {
|
|
if (!to) {
|
|
break;
|
|
}
|
|
if (to === common) {
|
|
break;
|
|
}
|
|
const alternate = to.alternate;
|
|
if (alternate !== null && alternate === common) {
|
|
break;
|
|
}
|
|
pathTo.push(to);
|
|
to = getParent(to);
|
|
}
|
|
for (let i = 0; i < pathFrom.length; i++) {
|
|
fn(pathFrom[i], 'bubbled', argFrom);
|
|
}
|
|
for (let i = pathTo.length; i-- > 0; ) {
|
|
fn(pathTo[i], 'captured', argTo);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
isAncestor: isAncestor,
|
|
getLowestCommonAncestor: getLowestCommonAncestor,
|
|
getParentInstance: getParentInstance,
|
|
traverseTwoPhase: traverseTwoPhase,
|
|
traverseEnterLeave: traverseEnterLeave,
|
|
};
|