@quilted/react-testing
Advanced tools
Comparing version 0.0.0-preview-20230111045215 to 0.0.0-preview-20230114092353
@@ -41,2 +41,3 @@ import type { ComponentType, LegacyRef } from 'react'; | ||
} | ||
export declare function findCurrentFiberUsingSlowPath(fiber: any): Fiber | null; | ||
//# sourceMappingURL=react.d.ts.map |
# @quilted/react-testing | ||
## 0.0.0-preview-20230111045215 | ||
## 0.0.0-preview-20230114092353 | ||
### Patch Changes | ||
- Add signal to react-testing root nodes | ||
- Looser React version restrictions | ||
## 0.5.23 | ||
### Patch Changes | ||
- [#474](https://github.com/lemonmade/quilt/pull/474) [`8890fad8`](https://github.com/lemonmade/quilt/commit/8890fad8d04efa95b362f4beaefcdbd51e65ba04) Thanks [@lemonmade](https://github.com/lemonmade)! - Looser React version restrictions | ||
## 0.5.22 | ||
@@ -10,0 +16,0 @@ |
{ | ||
"name": "@quilted/react-testing", | ||
"type": "module", | ||
"version": "0.0.0-preview-20230111045215", | ||
"version": "0.0.0-preview-20230114092353", | ||
"repository": { | ||
@@ -74,8 +74,6 @@ "type": "git", | ||
"dependencies": { | ||
"@types/react-test-renderer": "^17.0.0", | ||
"jest-matcher-utils": "^27.0.0", | ||
"react-reconciler": "^0.26.0", | ||
"react-test-renderer": "^17.0.0" | ||
"jest-matcher-utils": "^27.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/react-test-renderer": "^17.0.0", | ||
"@jest/globals": "^27.0.0", | ||
@@ -85,3 +83,4 @@ "expect": "^27.0.0", | ||
"react": "^17.0.0", | ||
"react-dom": "^17.0.0" | ||
"react-dom": "^17.0.0", | ||
"react-test-renderer": "^17.0.0" | ||
}, | ||
@@ -92,4 +91,5 @@ "peerDependencies": { | ||
"preact": "^10.11.0", | ||
"react": ">=17.0.0 <18.0.0", | ||
"react-dom": ">=17.0.0 <18.0.0" | ||
"react": "^17.0.0 || ^18.0.0", | ||
"react-dom": "^17.0.0 || ^18.0.0", | ||
"react-test-renderer": "^17.0.0 || ^18.0.0" | ||
}, | ||
@@ -111,2 +111,5 @@ "peerDependenciesMeta": { | ||
"optional": true | ||
}, | ||
"react-test-renderer": { | ||
"optional": true | ||
} | ||
@@ -113,0 +116,0 @@ }, |
@@ -8,8 +8,5 @@ import {render, unmountComponentAtNode} from 'react-dom'; | ||
import {Tag} from './shared/react'; | ||
import {Tag, findCurrentFiberUsingSlowPath} from './shared/react'; | ||
import type {Fiber} from './shared/react'; | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const {findCurrentFiberUsingSlowPath} = require('react-reconciler/reflection'); | ||
interface Context { | ||
@@ -52,3 +49,3 @@ element: HTMLDivElement; | ||
export function createNodeFromFiber(element: any, create: Create): Child { | ||
const fiber: Fiber = findCurrentFiberUsingSlowPath(element); | ||
const fiber = findCurrentFiberUsingSlowPath(element)!; | ||
@@ -55,0 +52,0 @@ if (fiber.tag === Tag.HostText) { |
@@ -45,1 +45,188 @@ import type {ComponentType, LegacyRef} from 'react'; | ||
} | ||
// Adapted from https://github.com/cfaester/enzyme-adapter-react-18/blob/87b97516f6cb942c9dad7a9813c0780d4795c1de/src/findCurrentFiberUsingSlowPath.ts#L43, | ||
// originally adapted from https://github.com/facebook/react/blob/b76103d66fdb7396cbfcc66a032b31a0cd8ad342/packages/react-reconciler/src/ReactFiberTreeReflection.js | ||
const Placement = 0b0000000000000000000000010; | ||
const Hydrating = 0b0000000000001000000000000; | ||
const NoFlags = 0b0000000000000000000000000; | ||
export function findCurrentFiberUsingSlowPath(fiber: any): Fiber | null { | ||
const alternate = fiber.alternate; | ||
if (!alternate) { | ||
// If there is no alternate, then we only need to check if it is mounted. | ||
const nearestMounted = getNearestMountedFiber(fiber); | ||
if (nearestMounted === null) { | ||
throw new Error('Unable to find node on an unmounted component.'); | ||
} | ||
if (nearestMounted !== fiber) { | ||
return null; | ||
} | ||
return fiber; | ||
} | ||
// If we have two possible branches, we'll walk backwards up to the root | ||
// to see what path the root points to. On the way we may hit one of the | ||
// special cases and we'll deal with them. | ||
let a = fiber; | ||
let b = alternate; | ||
// eslint-disable-next-line no-constant-condition | ||
while (true) { | ||
const parentA = a.return; | ||
if (parentA === null) { | ||
// We're at the root. | ||
break; | ||
} | ||
const parentB = parentA.alternate; | ||
if (parentB === null) { | ||
// There is no alternate. This is an unusual case. Currently, it only | ||
// happens when a Suspense component is hidden. An extra fragment fiber | ||
// is inserted in between the Suspense fiber and its children. Skip | ||
// over this extra fragment fiber and proceed to the next parent. | ||
const nextParent = parentA.return; | ||
if (nextParent !== null) { | ||
a = b = nextParent; | ||
continue; | ||
} | ||
// If there's no parent, we're at the root. | ||
break; | ||
} | ||
// If both copies of the parent fiber point to the same child, we can | ||
// assume that the child is current. This happens when we bailout on low | ||
// priority: the bailed out fiber's child reuses the current child. | ||
if (parentA.child === parentB.child) { | ||
let child = parentA.child; | ||
while (child) { | ||
if (child === a) { | ||
// We've determined that A is the current branch. | ||
// assertIsMounted(parentA); | ||
return fiber; | ||
} | ||
if (child === b) { | ||
// We've determined that B is the current branch. | ||
// assertIsMounted(parentA); | ||
return alternate; | ||
} | ||
child = child.sibling; | ||
} | ||
// We should never have an alternate for any mounting node. So the only | ||
// way this could possibly happen is if this was unmounted, if at all. | ||
throw new Error('Unable to find node on an unmounted component.'); | ||
} | ||
if (a.return !== b.return) { | ||
// The return pointer of A and the return pointer of B point to different | ||
// fibers. We assume that return pointers never criss-cross, so A must | ||
// belong to the child set of A.return, and B must belong to the child | ||
// set of B.return. | ||
a = parentA; | ||
b = parentB; | ||
} else { | ||
// The return pointers point to the same fiber. We'll have to use the | ||
// default, slow path: scan the child sets of each parent alternate to see | ||
// which child belongs to which set. | ||
// | ||
// Search parent A's child set | ||
let didFindChild = false; | ||
let child = parentA.child; | ||
while (child) { | ||
if (child === a) { | ||
didFindChild = true; | ||
a = parentA; | ||
b = parentB; | ||
break; | ||
} | ||
if (child === b) { | ||
didFindChild = true; | ||
b = parentA; | ||
a = parentB; | ||
break; | ||
} | ||
child = child.sibling; | ||
} | ||
if (!didFindChild) { | ||
// Search parent B's child set | ||
child = parentB.child; | ||
while (child) { | ||
if (child === a) { | ||
didFindChild = true; | ||
a = parentB; | ||
b = parentA; | ||
break; | ||
} | ||
if (child === b) { | ||
didFindChild = true; | ||
b = parentB; | ||
a = parentA; | ||
break; | ||
} | ||
child = child.sibling; | ||
} | ||
if (!didFindChild) { | ||
throw new Error( | ||
'Child was not found in either parent set. This indicates a bug ' + | ||
'in React related to the return pointer. Please file an issue.', | ||
); | ||
} | ||
} | ||
} | ||
if (a.alternate !== b) { | ||
throw new Error( | ||
"Return fibers should always be each others' alternates. " + | ||
'This error is likely caused by a bug in React. Please file an issue.', | ||
); | ||
} | ||
} | ||
// If the root is not a host container, we're in a disconnected tree. I.e. | ||
// unmounted. | ||
if (a.tag !== Tag.HostRoot) { | ||
throw new Error('Unable to find node on an unmounted component.'); | ||
} | ||
if (a.stateNode.current === a) { | ||
// We've determined that A is the current branch. | ||
return fiber; | ||
} | ||
// Otherwise B has to be current branch. | ||
return alternate; | ||
} | ||
function getNearestMountedFiber(fiber: any) { | ||
let node = fiber; | ||
let nearestMounted = fiber; | ||
if (!fiber.alternate) { | ||
// If there is no alternate, this might be a new tree that isn't inserted | ||
// yet. If it is, then it will have a pending insertion effect on it. | ||
let nextNode = node; | ||
do { | ||
node = nextNode; | ||
if ((node.flags & (Placement | Hydrating)) !== NoFlags) { | ||
// This is an insertion or in-progress hydration. The nearest possible | ||
// mounted fiber is the parent but we need to continue to figure out | ||
// if that one is still mounted. | ||
nearestMounted = node.return; | ||
} | ||
nextNode = node.return; | ||
} while (nextNode); | ||
} else { | ||
while (node.return) { | ||
node = node.return; | ||
} | ||
} | ||
if (node.tag === Tag.HostRoot) { | ||
// TODO: Check if this was a nested HostRoot when used with | ||
// renderContainerIntoSubtree. | ||
return nearestMounted; | ||
} | ||
// If we didn't hit the root, that means that we're in an disconnected tree | ||
// that has been unmounted. | ||
return null; | ||
} |
@@ -47,3 +47,3 @@ import { | ||
props: testInstance.props, | ||
type: testInstance.type, | ||
type: testInstance.type as any, | ||
children, | ||
@@ -50,0 +50,0 @@ instance: testInstance.instance, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
334955
7
5097
7
+ Addedreact@18.3.1(transitive)
+ Addedreact-dom@18.3.1(transitive)
+ Addedreact-is@18.3.1(transitive)
+ Addedreact-test-renderer@18.3.1(transitive)
+ Addedscheduler@0.23.2(transitive)
- Removed@types/react-test-renderer@^17.0.0
- Removedreact-reconciler@^0.26.0
- Removedreact-test-renderer@^17.0.0
- Removed@types/prop-types@15.7.13(transitive)
- Removed@types/react@17.0.83(transitive)
- Removed@types/react-test-renderer@17.0.9(transitive)
- Removed@types/scheduler@0.16.8(transitive)
- Removedcsstype@3.1.3(transitive)
- Removedreact@17.0.2(transitive)
- Removedreact-dom@17.0.2(transitive)
- Removedreact-reconciler@0.26.2(transitive)
- Removedreact-test-renderer@17.0.2(transitive)
- Removedscheduler@0.20.2(transitive)