-
Notifications
You must be signed in to change notification settings - Fork 47k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fiber] Implement test renderer (#8628)
* ReactTestRenderer move current impl to stack dir * ReactTestRenderer on fiber: commence! * ReactTestRenderer: most non-ref/non-public-instance tests are passing * Move ReactTestFiberComponent functions from Renderer to Component file * test renderer: get rid of private root containers and root Maps * TestRenderer: switch impl based on ReactDOMFeatureFlag.useFiber * ReactTestRenderer: inline component creation * ReactTestRenderer: return to pristine original glory (+ Fiber for error order difference) * TestRendererFiber: use a simple class as TestComponentInstances * Add `getPublicInstance` to support TestRenderer `createNodeMock` * Rename files to end. Update for `mountContainer->createContainer` change * test renderer return same object to prevent unnecessary context pushing/popping * Fiber HostConfig add getPublicInstance. This should be the identity fn everywhere except the test renderer * appease flow * Initial cleanup from sleepy work * unstable_batchedUpdates * Stack test renderer: cache nodeMock to not call on unmount * add public instance type parameter to the reconciler * test renderer: set _nodeMock when mounted * More cleanup * Add test cases for root fragments and (maybe?) root text nodes * Fix the npm package build Explicitly require the Stack version by default. Add a separate entry point for Fiber. We don't add fiber.js to the package yet since it's considered internal until React 16. * Relax the ref type from Object to mixed This seems like the most straightforward way to support getPublicInstance for test renderer. * Remove accidental newline * test renderer: unify TestComponent and TestContainer, handle root updates * Remove string/number serialization attempts since Fiber ensures all textInstances are strings * Return full fragments in toJSON * Test Renderer remove TestComponent instances for simple objects * Update babylon for exact object type syntax * Use $$typeof because clarity > punching ducks. * Minor Flow annotation tweaks * Tweak style, types, and naming * Fix typo
- Loading branch information
Showing
24 changed files
with
630 additions
and
174 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
'use strict'; | ||
|
||
module.exports = require('./lib/ReactTestRendererFiber'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
'use strict'; | ||
|
||
module.exports = require('./lib/ReactTestRenderer'); | ||
module.exports = require('./lib/ReactTestRendererStack'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,157 +1,18 @@ | ||
/** | ||
* Copyright 2013-present, Facebook, Inc. | ||
* Copyright (c) 2013-present Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule ReactTestRenderer | ||
* @preventMunge | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var ReactComponentEnvironment = require('ReactComponentEnvironment'); | ||
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy'); | ||
var ReactEmptyComponent = require('ReactEmptyComponent'); | ||
var ReactMultiChild = require('ReactMultiChild'); | ||
var ReactHostComponent = require('ReactHostComponent'); | ||
var ReactTestMount = require('ReactTestMount'); | ||
var ReactTestReconcileTransaction = require('ReactTestReconcileTransaction'); | ||
var ReactUpdates = require('ReactUpdates'); | ||
var ReactTestTextComponent = require('ReactTestTextComponent'); | ||
var ReactTestEmptyComponent = require('ReactTestEmptyComponent'); | ||
var invariant = require('invariant'); | ||
const ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); | ||
|
||
import type { ReactElement } from 'ReactElementType'; | ||
import type { ReactInstance } from 'ReactInstanceType'; | ||
|
||
type ReactTestRendererJSON = { | ||
type: string, | ||
props: { [propName: string]: string }, | ||
children: null | Array<string | ReactTestRendererJSON>, | ||
$$typeof?: any | ||
} | ||
|
||
/** | ||
* Drill down (through composites and empty components) until we get a native or | ||
* native 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; | ||
} | ||
|
||
class ReactTestComponent { | ||
_currentElement: ReactElement; | ||
_renderedChildren: null | Object; | ||
_topLevelWrapper: null | ReactInstance; | ||
_hostContainerInfo: null | Object; | ||
|
||
constructor(element: ReactElement) { | ||
this._currentElement = element; | ||
this._renderedChildren = null; | ||
this._topLevelWrapper = null; | ||
this._hostContainerInfo = null; | ||
} | ||
|
||
mountComponent( | ||
transaction: ReactTestReconcileTransaction, | ||
nativeParent: null | ReactTestComponent, | ||
hostContainerInfo: Object, | ||
context: Object, | ||
) { | ||
var element = this._currentElement; | ||
this._hostContainerInfo = hostContainerInfo; | ||
// $FlowFixMe https://github.com/facebook/flow/issues/1805 | ||
this.mountChildren(element.props.children, transaction, context); | ||
} | ||
|
||
receiveComponent( | ||
nextElement: ReactElement, | ||
transaction: ReactTestReconcileTransaction, | ||
context: Object, | ||
) { | ||
this._currentElement = nextElement; | ||
// $FlowFixMe https://github.com/facebook/flow/issues/1805 | ||
this.updateChildren(nextElement.props.children, transaction, context); | ||
} | ||
|
||
getPublicInstance(): Object { | ||
var element = this._currentElement; | ||
var hostContainerInfo = this._hostContainerInfo; | ||
invariant( | ||
hostContainerInfo, | ||
'hostContainerInfo should be populated before ' + | ||
'getPublicInstance is called.' | ||
); | ||
return hostContainerInfo.createNodeMock(element); | ||
} | ||
|
||
toJSON(): ReactTestRendererJSON { | ||
// not using `children`, but I don't want to rewrite without destructuring | ||
// eslint-disable-next-line no-unused-vars | ||
var {children, ...props} = this._currentElement.props; | ||
var childrenJSON = []; | ||
for (var key in this._renderedChildren) { | ||
var inst = this._renderedChildren[key]; | ||
inst = getRenderedHostOrTextFromComponent(inst); | ||
var json = inst.toJSON(); | ||
if (json !== undefined) { | ||
childrenJSON.push(json); | ||
} | ||
} | ||
var object: ReactTestRendererJSON = { | ||
type: this._currentElement.type, | ||
props: props, | ||
children: childrenJSON.length ? childrenJSON : null, | ||
}; | ||
Object.defineProperty(object, '$$typeof', { | ||
value: Symbol.for('react.test.json'), | ||
}); | ||
return object; | ||
} | ||
|
||
getHostNode(): void {} | ||
unmountComponent(safely, skipLifecycle): void { | ||
// $FlowFixMe https://github.com/facebook/flow/issues/1805 | ||
this.unmountChildren(safely, skipLifecycle); | ||
} | ||
} | ||
|
||
Object.assign(ReactTestComponent.prototype, ReactMultiChild); | ||
|
||
// ============================================================================= | ||
|
||
ReactUpdates.injection.injectReconcileTransaction( | ||
ReactTestReconcileTransaction | ||
); | ||
ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy); | ||
|
||
ReactHostComponent.injection.injectGenericComponentClass(ReactTestComponent); | ||
ReactHostComponent.injection.injectTextComponentClass(ReactTestTextComponent); | ||
ReactEmptyComponent.injection.injectEmptyComponentFactory(function() { | ||
return new ReactTestEmptyComponent(); | ||
}); | ||
|
||
ReactComponentEnvironment.injection.injectEnvironment({ | ||
processChildrenUpdates: function() {}, | ||
replaceNodeWithMarkup: function() {}, | ||
}); | ||
|
||
var ReactTestRenderer = { | ||
create: ReactTestMount.render, | ||
/* eslint-disable camelcase */ | ||
unstable_batchedUpdates: ReactUpdates.batchedUpdates, | ||
/* eslint-enable camelcase */ | ||
}; | ||
|
||
module.exports = ReactTestRenderer; | ||
module.exports = ReactDOMFeatureFlags.useFiber | ||
? require('ReactTestRendererFiber') | ||
: require('ReactTestRendererStack'); |
Oops, something went wrong.