@samitouri / QOS-React-2 / commits / aad0970192

Remove Stack (part 1, safe: unused files and tests) (#10794)

* Remove Fiber Jest project * Remove Stack reconciler and ReactDOMStack code * Fix tests depending on Stack internals * Fix Flow

Dan Abramov committed Sep 27, 2017 at 15:15 UTC aad09701929fc03c4d997af8a6e1bed0d3f4ac3a
64 files changed +71 -9438
package.json
+35 -4
@@ -108,9 +108,40 @@
108 "version-check": "node ./scripts/tasks/version-check.js"
109 },
110 "jest": {
111 - "projects": [
112 - "<rootDir>/scripts/jest/stack.config.json",
113 - "<rootDir>/scripts/jest/fiber.config.json"
114 - ]
111 + "modulePathIgnorePatterns": [
112 + "/.module-cache/",
113 + "<rootDir>/build/",
114 + "<rootDir>/scripts/rollup/shims/",
115 + "<rootDir>/scripts/bench/"
116 + ],
117 + "transform": {
118 + ".*": "./scripts/jest/preprocessor.js"
119 + },
120 + "setupFiles": [
121 + "./scripts/jest/setup.js",
122 + "./scripts/jest/environment.js"
123 + ],
124 + "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js",
125 + "testRegex": "/__tests__/.*(\\.js|coffee|ts)$",
126 + "moduleFileExtensions": [
127 + "js",
128 + "json",
129 + "node",
130 + "coffee",
131 + "ts"
132 + ],
133 + "roots": [
134 + "<rootDir>/eslint-rules",
135 + "<rootDir>/mocks",
136 + "<rootDir>/scripts",
137 + "<rootDir>/src",
138 + "node_modules/fbjs"
139 + ],
140 + "collectCoverageFrom": [
141 + "src/**/*.js",
142 + "!src/__mocks__/vendor/third_party/*.js",
143 + "!src/test/*.js"
144 + ],
145 + "timers": "fake"
146 }
147 }
scripts/jest/fiber.config.json deleted
-38
@@ -1,38 +0,0 @@
1 -{
2 - "modulePathIgnorePatterns": [
3 - "/.module-cache/",
4 - "<rootDir>/build/",
5 - "<rootDir>/scripts/rollup/shims/",
6 - "<rootDir>/scripts/bench/"
7 - ],
8 - "rootDir": "../../",
9 - "transform": {
10 - ".*": "./scripts/jest/preprocessor.js"
11 - },
12 - "setupFiles": [
13 - "./scripts/jest/fiber.setup.js",
14 - "./scripts/jest/environment.js"
15 - ],
16 - "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js",
17 - "testRegex": "/__tests__/.*(\\.js|coffee|ts)$",
18 - "moduleFileExtensions": [
19 - "js",
20 - "json",
21 - "node",
22 - "coffee",
23 - "ts"
24 - ],
25 - "roots": [
26 - "<rootDir>/eslint-rules",
27 - "<rootDir>/mocks",
28 - "<rootDir>/scripts",
29 - "<rootDir>/src",
30 - "node_modules/fbjs"
31 - ],
32 - "collectCoverageFrom": [
33 - "src/**/*.js",
34 - "!src/__mocks__/vendor/third_party/*.js",
35 - "!src/test/*.js"
36 - ],
37 - "timers": "fake"
38 -}
scripts/jest/setup.js renamed
-6
@@ -2,12 +2,6 @@
2
3 // We want to globally mock this but jest doesn't let us do that by default
4 // for a file that already exists. So we have to explicitly mock it.
5 -jest.mock('ReactDOMFeatureFlags', () => {
6 - const flags = require.requireActual('ReactDOMFeatureFlags');
7 - return Object.assign({}, flags, {
8 - useFiber: true,
9 - });
10 -});
5 jest.mock('ReactFeatureFlags', () => {
6 const flags = require.requireActual('ReactFeatureFlags');
7 return Object.assign({}, flags, {
scripts/jest/stack.config.json deleted
-38
@@ -1,38 +0,0 @@
1 -{
2 - "modulePathIgnorePatterns": [
3 - "/.module-cache/",
4 - "<rootDir>/build/",
5 - "<rootDir>/scripts/rollup/shims/",
6 - "<rootDir>/scripts/bench/"
7 - ],
8 - "rootDir": "../../",
9 - "transform": {
10 - ".*": "./scripts/jest/preprocessor.js"
11 - },
12 - "setupFiles": [
13 - "./scripts/jest/stack.setup.js",
14 - "./scripts/jest/environment.js"
15 - ],
16 - "setupTestFrameworkScriptFile": "./scripts/jest/test-framework-setup.js",
17 - "testRegex": "/__tests__/.*(\\.js|coffee|ts)$",
18 - "moduleFileExtensions": [
19 - "js",
20 - "json",
21 - "node",
22 - "coffee",
23 - "ts"
24 - ],
25 - "roots": [
26 - "<rootDir>/eslint-rules",
27 - "<rootDir>/mocks",
28 - "<rootDir>/scripts",
29 - "<rootDir>/src",
30 - "node_modules/fbjs"
31 - ],
32 - "collectCoverageFrom": [
33 - "src/**/*.js",
34 - "!src/__mocks__/vendor/third_party/*.js",
35 - "!src/test/*.js"
36 - ],
37 - "timers": "fake"
38 -}
scripts/jest/stack.setup.js deleted
-14
@@ -1,14 +0,0 @@
1 -'use strict';
2 -
3 -// We want to globally mock this but jest doesn't let us do that by default
4 -// for a file that already exists. So we have to explicitly mock it.
5 -jest.mock('ReactDOMFeatureFlags', () => {
6 - const flags = require.requireActual('ReactDOMFeatureFlags');
7 - return Object.assign({}, flags, {
8 - useFiber: false,
9 - });
10 -});
11 -
12 -// Error logging varies between Fiber and Stack;
13 -// Rather than fork dozens of tests, mock the error-logging file by default.
14 -jest.mock('ReactFiberErrorLogger');
scripts/rollup/packaging.js
+1 -1
@@ -25,7 +25,7 @@ const facebookWWWSrcDependencies = [
25 // these files need to be copied to the react-native build
26 const reactNativeSrcDependencies = [
27 // TODO: copy this to RN repository and delete from React
28 - 'src/renderers/shared/stack/PooledClass.js',
28 + 'src/renderers/native/PooledClass.js',
29 'src/renderers/shared/fiber/isomorphic/ReactTypes.js',
30 'src/renderers/native/ReactNativeTypes.js',
31 ];
src/node_modules/react-dom/index.js
+1 -6
@@ -6,9 +6,4 @@
6
7 'use strict';
8
9 -var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
10 -var useFiber = ReactDOMFeatureFlags.useFiber;
11 -
12 -module.exports = useFiber
13 - ? require('ReactDOMFiberEntry')
14 - : require('ReactDOMStackEntry');
9 +module.exports = require('ReactDOMFiberEntry');
src/node_modules/react-dom/server.browser.js
+1 -6
@@ -6,9 +6,4 @@
6
7 'use strict';
8
9 -var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
10 -var useFiber = ReactDOMFeatureFlags.useFiber;
11 -
12 -module.exports = useFiber
13 - ? require('ReactDOMServerBrowserEntry')
14 - : require('ReactDOMServerStackEntry');
9 +module.exports = require('ReactDOMServerBrowserEntry');
src/node_modules/react-dom/server.js
+1 -6
@@ -6,9 +6,4 @@
6
7 'use strict';
8
9 -var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
10 -var useFiber = ReactDOMFeatureFlags.useFiber;
11 -
12 -module.exports = useFiber
13 - ? require('ReactDOMServerNodeEntry')
14 - : require('ReactDOMServerStackEntry');
9 +module.exports = require('ReactDOMServerNodeEntry');
src/renderers/__tests__/refs-test.js
-85
@@ -306,91 +306,6 @@ describe('ref swapping', () => {
306 });
307 });
308
309 -describe('string refs between fiber and stack', () => {
310 - beforeEach(() => {
311 - jest.resetModules();
312 - React = require('react');
313 - ReactTestUtils = require('react-dom/test-utils');
314 - });
315 -
316 - it('attaches, detaches from fiber component with stack layer', () => {
317 - const ReactCurrentOwner = require('ReactCurrentOwner');
318 -
319 - const ReactDOMStack = require('ReactDOMStackEntry');
320 - const ReactDOMFiber = require('ReactDOMFiberEntry');
321 - const ReactInstanceMap = require('ReactInstanceMap');
322 - let layerMounted = false;
323 - class A extends React.Component {
324 - render() {
325 - return <div />;
326 - }
327 - componentDidMount() {
328 - // ReactLayeredComponentMixin sets ReactCurrentOwner manually
329 - ReactCurrentOwner.current = ReactInstanceMap.get(this);
330 - const span = <span ref="span" />;
331 - ReactCurrentOwner.current = null;
332 -
333 - ReactDOMStack.unstable_renderSubtreeIntoContainer(
334 - this,
335 - span,
336 - (this._container = document.createElement('div')),
337 - () => {
338 - expect(this.refs.span.nodeName).toBe('SPAN');
339 - layerMounted = true;
340 - },
341 - );
342 - }
343 - componentWillUnmount() {
344 - ReactDOMStack.unmountComponentAtNode(this._container);
345 - }
346 - }
347 - const container = document.createElement('div');
348 - const a = ReactDOMFiber.render(<A />, container);
349 - expect(a.refs.span).toBeTruthy();
350 - ReactDOMFiber.unmountComponentAtNode(container);
351 - expect(a.refs.span).toBe(undefined);
352 - expect(layerMounted).toBe(true);
353 - });
354 -
355 - it('attaches, detaches from stack component with fiber layer', () => {
356 - const ReactCurrentOwner = require('ReactCurrentOwner');
357 - const ReactDOM = require('ReactDOMStackEntry');
358 - const ReactDOMFiber = require('ReactDOMFiberEntry');
359 - const ReactInstanceMap = require('ReactInstanceMap');
360 - let layerMounted = false;
361 - class A extends React.Component {
362 - render() {
363 - return <div />;
364 - }
365 - componentDidMount() {
366 - // ReactLayeredComponentMixin sets ReactCurrentOwner manually
367 - ReactCurrentOwner.current = ReactInstanceMap.get(this);
368 - const span = <span ref="span" />;
369 - ReactCurrentOwner.current = null;
370 -
371 - ReactDOMFiber.unstable_renderSubtreeIntoContainer(
372 - this,
373 - span,
374 - (this._container = document.createElement('div')),
375 - () => {
376 - expect(this.refs.span.nodeName).toBe('SPAN');
377 - layerMounted = true;
378 - },
379 - );
380 - }
381 - componentWillUnmount() {
382 - ReactDOMFiber.unmountComponentAtNode(this._container);
383 - }
384 - }
385 - const container = document.createElement('div');
386 - const a = ReactDOM.render(<A />, container);
387 - expect(a.refs.span).toBeTruthy();
388 - ReactDOM.unmountComponentAtNode(container);
389 - expect(a.refs.span).toBe(undefined);
390 - expect(layerMounted).toBe(true);
391 - });
392 -});
393 -
309 describe('root level refs', () => {
310 it('attaches and detaches root refs', () => {
311 var ReactDOM = require('react-dom');
src/renderers/dom/ReactDOMServerStackEntry.js deleted
-35
@@ -1,35 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMServerStackEntry
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactServerRendering = require('ReactServerRendering');
13 -var ReactVersion = require('ReactVersion');
14 -
15 -require('ReactDOMInjection');
16 -require('ReactDOMStackInjection');
17 -
18 -var ReactDOMServerStack = {
19 - renderToString: ReactServerRendering.renderToString,
20 - renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,
21 - version: ReactVersion,
22 -};
23 -
24 -if (__DEV__) {
25 - var ReactInstrumentation = require('ReactInstrumentation');
26 - var ReactDOMUnknownPropertyHook = require('ReactDOMUnknownPropertyHook');
27 - var ReactDOMNullInputValuePropHook = require('ReactDOMNullInputValuePropHook');
28 - var ReactDOMInvalidARIAHook = require('ReactDOMInvalidARIAHook');
29 -
30 - ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook);
31 - ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook);
32 - ReactInstrumentation.debugTool.addHook(ReactDOMInvalidARIAHook);
33 -}
34 -
35 -module.exports = ReactDOMServerStack;
src/renderers/dom/ReactDOMStackEntry.js deleted
-168
@@ -1,168 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMStackEntry
8 - */
9 -
10 -/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
11 -
12 -'use strict';
13 -
14 -require('checkReact');
15 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
16 -var ReactGenericBatching = require('ReactGenericBatching');
17 -var ReactMount = require('ReactMount');
18 -var ReactUpdates = require('ReactUpdates');
19 -var ReactReconciler = require('ReactReconciler');
20 -var ReactVersion = require('ReactVersion');
21 -
22 -var findDOMNode = require('findDOMNode');
23 -var getHostComponentFromComposite = require('getHostComponentFromComposite');
24 -
25 -if (__DEV__) {
26 - var warning = require('fbjs/lib/warning');
27 -}
28 -
29 -require('ReactDOMInjection');
30 -require('ReactDOMClientInjection');
31 -require('ReactDOMStackInjection');
32 -
33 -var ReactDOMStack = {
34 - findDOMNode: findDOMNode,
35 - render: ReactMount.render,
36 - unmountComponentAtNode: ReactMount.unmountComponentAtNode,
37 - version: ReactVersion,
38 -
39 - /* eslint-disable camelcase */
40 - unstable_batchedUpdates: ReactGenericBatching.batchedUpdates,
41 - unstable_renderSubtreeIntoContainer: ReactMount.renderSubtreeIntoContainer,
42 - /* eslint-enable camelcase */
43 -
44 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
45 - // For TapEventPlugin which is popular in open source
46 - EventPluginHub: require('EventPluginHub'),
47 - // Used by test-utils
48 - EventPluginRegistry: require('EventPluginRegistry'),
49 - EventPropagators: require('EventPropagators'),
50 - ReactControlledComponent: require('ReactControlledComponent'),
51 - ReactDOMComponentTree,
52 - ReactDOMEventListener: require('ReactDOMEventListener'),
53 - ReactUpdates: ReactUpdates,
54 - },
55 -};
56 -
57 -// Inject the runtime into a devtools global hook regardless of browser.
58 -// Allows for debugging when the hook is injected on the page.
59 -if (
60 - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
61 - typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function'
62 -) {
63 - __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
64 - ComponentTree: {
65 - getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
66 - getNodeFromInstance: function(inst) {
67 - // inst is an internal instance (but could be a composite)
68 - if (inst._renderedComponent) {
69 - inst = getHostComponentFromComposite(inst);
70 - }
71 - if (inst) {
72 - return ReactDOMComponentTree.getNodeFromInstance(inst);
73 - } else {
74 - return null;
75 - }
76 - },
77 - },
78 - Mount: ReactMount,
79 - Reconciler: ReactReconciler,
80 - rendererPackageName: 'react-dom',
81 - });
82 -}
83 -
84 -if (__DEV__) {
85 - var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
86 - if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
87 - // First check if devtools is not installed
88 - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
89 - // If we're in Chrome or Firefox, provide a download link if not installed.
90 - if (
91 - (navigator.userAgent.indexOf('Chrome') > -1 &&
92 - navigator.userAgent.indexOf('Edge') === -1) ||
93 - navigator.userAgent.indexOf('Firefox') > -1
94 - ) {
95 - // Firefox does not have the issue with devtools loaded over file://
96 - var showFileUrlMessage =
97 - window.location.protocol.indexOf('http') === -1 &&
98 - navigator.userAgent.indexOf('Firefox') === -1;
99 - console.debug(
100 - 'Download the React DevTools ' +
101 - (showFileUrlMessage
102 - ? 'and use an HTTP server (instead of a file: URL) '
103 - : '') +
104 - 'for a better development experience: ' +
105 - 'https://fb.me/react-devtools',
106 - );
107 - }
108 - }
109 -
110 - var testFunc = function testFn() {};
111 - warning(
112 - (testFunc.name || testFunc.toString()).indexOf('testFn') !== -1,
113 - "It looks like you're using a minified copy of the development build " +
114 - 'of React. When deploying React apps to production, make sure to use ' +
115 - 'the production build which skips development warnings and is faster. ' +
116 - 'See https://fb.me/react-minification for more details.',
117 - );
118 -
119 - // If we're in IE8, check to see if we are in compatibility mode and provide
120 - // information on preventing compatibility mode
121 - var ieCompatibilityMode =
122 - document.documentMode && document.documentMode < 8;
123 -
124 - warning(
125 - !ieCompatibilityMode,
126 - 'Internet Explorer is running in compatibility mode; please add the ' +
127 - 'following tag to your HTML to prevent this from happening: ' +
128 - '<meta http-equiv="X-UA-Compatible" content="IE=edge" />',
129 - );
130 -
131 - var expectedFeatures = [
132 - // shims
133 - Array.isArray,
134 - Array.prototype.every,
135 - Array.prototype.forEach,
136 - Array.prototype.indexOf,
137 - Array.prototype.map,
138 - Date.now,
139 - Function.prototype.bind,
140 - Object.keys,
141 - String.prototype.trim,
142 - ];
143 -
144 - for (var i = 0; i < expectedFeatures.length; i++) {
145 - if (!expectedFeatures[i]) {
146 - warning(
147 - false,
148 - 'One or more ES5 shims expected by React are not available: ' +
149 - 'https://fb.me/react-warning-polyfills',
150 - );
151 - break;
152 - }
153 - }
154 - }
155 -}
156 -
157 -if (__DEV__) {
158 - var ReactInstrumentation = require('ReactInstrumentation');
159 - var ReactDOMUnknownPropertyHook = require('ReactDOMUnknownPropertyHook');
160 - var ReactDOMNullInputValuePropHook = require('ReactDOMNullInputValuePropHook');
161 - var ReactDOMInvalidARIAHook = require('ReactDOMInvalidARIAHook');
162 -
163 - ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook);
164 - ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook);
165 - ReactInstrumentation.debugTool.addHook(ReactDOMInvalidARIAHook);
166 -}
167 -
168 -module.exports = ReactDOMStack;
src/renderers/dom/shared/__tests__/ReactServerRendering-test.js
+3 -58
@@ -13,8 +13,6 @@ var ExecutionEnvironment;
13 var React;
14 var ReactDOM;
15 var ReactDOMServer;
16 -var ReactMarkupChecksum;
17 -var ReactReconcileTransaction;
16 var ReactTestUtils;
17 var PropTypes;
18
@@ -29,8 +27,6 @@ describe('ReactDOMServer', () => {
27 React = require('react');
28 ReactDOM = require('react-dom');
29 ReactTestUtils = require('react-dom/test-utils');
32 - ReactMarkupChecksum = require('ReactMarkupChecksum');
33 - ReactReconcileTransaction = require('ReactReconcileTransaction');
30 PropTypes = require('prop-types');
31
32 ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
@@ -47,16 +43,7 @@ describe('ReactDOMServer', () => {
43 var response = ReactDOMServer.renderToString(<span>hello world</span>);
44 expect(response).toMatch(
45 new RegExp(
50 - '<span ' +
51 - ROOT_ATTRIBUTE_NAME +
52 - '=""' +
53 - (ReactDOMFeatureFlags.useFiber
54 - ? ''
55 - : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
56 - (ReactDOMFeatureFlags.useFiber
57 - ? ''
58 - : ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="[^"]+"') +
59 - '>hello world</span>',
46 + '<span ' + ROOT_ATTRIBUTE_NAME + '=""' + '>hello world</span>',
47 ),
48 );
49 });
@@ -64,18 +51,7 @@ describe('ReactDOMServer', () => {
51 it('should generate simple markup for self-closing tags', () => {
52 var response = ReactDOMServer.renderToString(<img />);
53 expect(response).toMatch(
67 - new RegExp(
68 - '<img ' +
69 - ROOT_ATTRIBUTE_NAME +
70 - '=""' +
71 - (ReactDOMFeatureFlags.useFiber
72 - ? ''
73 - : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
74 - (ReactDOMFeatureFlags.useFiber
75 - ? ''
76 - : ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="[^"]+"') +
77 - '/>',
78 - ),
54 + new RegExp('<img ' + ROOT_ATTRIBUTE_NAME + '=""' + '/>'),
55 );
56 });
57
@@ -83,16 +59,7 @@ describe('ReactDOMServer', () => {
59 var response = ReactDOMServer.renderToString(<img data-attr=">" />);
60 expect(response).toMatch(
61 new RegExp(
86 - '<img data-attr="&gt;" ' +
87 - ROOT_ATTRIBUTE_NAME +
88 - '=""' +
89 - (ReactDOMFeatureFlags.useFiber
90 - ? ''
91 - : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
92 - (ReactDOMFeatureFlags.useFiber
93 - ? ''
94 - : ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="[^"]+"') +
95 - '/>',
62 + '<img data-attr="&gt;" ' + ROOT_ATTRIBUTE_NAME + '=""' + '/>',
63 ),
64 );
65 });
@@ -133,17 +100,8 @@ describe('ReactDOMServer', () => {
100 '<div ' +
101 ROOT_ATTRIBUTE_NAME +
102 '=""' +
136 - (ReactDOMFeatureFlags.useFiber
137 - ? ''
138 - : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
139 - (ReactDOMFeatureFlags.useFiber
140 - ? ''
141 - : ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="[^"]+"') +
103 '>' +
104 '<span' +
144 - (ReactDOMFeatureFlags.useFiber
145 - ? ''
146 - : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
105 '>' +
106 (ReactDOMFeatureFlags.useFiber
107 ? 'My name is <!-- -->child'
@@ -210,9 +168,6 @@ describe('ReactDOMServer', () => {
168 (ReactDOMFeatureFlags.useFiber
169 ? ''
170 : ' ' + ID_ATTRIBUTE_NAME + '="[^"]*"') +
213 - (ReactDOMFeatureFlags.useFiber
214 - ? ''
215 - : ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="[^"]+"') +
171 '>' +
172 (ReactDOMFeatureFlags.useFiber
173 ? 'Component name: <!-- -->TestComponent'
@@ -576,11 +531,6 @@ describe('ReactDOMServer', () => {
531 return <div>{this.state.text}</div>;
532 }
533 }
579 -
580 - ReactReconcileTransaction.prototype.perform = function() {
581 - // We shouldn't ever be calling this on the server
582 - throw new Error('Browser reconcile transaction should not be used');
583 - };
534 var markup = ReactDOMServer.renderToString(<Component />);
535 expect(markup).toContain('hello, world');
536 });
@@ -600,11 +550,6 @@ describe('ReactDOMServer', () => {
550 return <div>{this.state.text}</div>;
551 }
552 }
603 -
604 - ReactReconcileTransaction.prototype.perform = function() {
605 - // We shouldn't ever be calling this on the server
606 - throw new Error('Browser reconcile transaction should not be used');
607 - };
553 var markup = ReactDOMServer.renderToString(<Component />);
554 expect(markup).toContain('hello, world');
555 });
src/renderers/dom/stack/client/DOMChildrenOperations.js deleted
-248
@@ -1,248 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule DOMChildrenOperations
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMLazyTree = require('DOMLazyTree');
13 -var Danger = require('Danger');
14 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
15 -var ReactInstrumentation = require('ReactInstrumentation');
16 -
17 -var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction');
18 -var setInnerHTML = require('setInnerHTML');
19 -var setTextContent = require('setTextContent');
20 -
21 -function getNodeAfter(parentNode, node) {
22 - // Special case for text components, which return [open, close] comments
23 - // from getHostNode.
24 - if (Array.isArray(node)) {
25 - node = node[1];
26 - }
27 - return node ? node.nextSibling : parentNode.firstChild;
28 -}
29 -
30 -/**
31 - * Inserts `childNode` as a child of `parentNode` at the `index`.
32 - *
33 - * @param {DOMElement} parentNode Parent node in which to insert.
34 - * @param {DOMElement} childNode Child node to insert.
35 - * @param {number} index Index at which to insert the child.
36 - * @internal
37 - */
38 -var insertChildAt = createMicrosoftUnsafeLocalFunction(function(
39 - parentNode,
40 - childNode,
41 - referenceNode,
42 -) {
43 - // We rely exclusively on `insertBefore(node, null)` instead of also using
44 - // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
45 - // we are careful to use `null`.)
46 - parentNode.insertBefore(childNode, referenceNode);
47 -});
48 -
49 -function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
50 - DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);
51 -}
52 -
53 -function moveChild(parentNode, childNode, referenceNode) {
54 - if (Array.isArray(childNode)) {
55 - moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);
56 - } else {
57 - insertChildAt(parentNode, childNode, referenceNode);
58 - }
59 -}
60 -
61 -function removeChild(parentNode, childNode) {
62 - if (Array.isArray(childNode)) {
63 - var closingComment = childNode[1];
64 - childNode = childNode[0];
65 - removeDelimitedText(parentNode, childNode, closingComment);
66 - parentNode.removeChild(closingComment);
67 - }
68 - parentNode.removeChild(childNode);
69 -}
70 -
71 -function moveDelimitedText(
72 - parentNode,
73 - openingComment,
74 - closingComment,
75 - referenceNode,
76 -) {
77 - var node = openingComment;
78 - while (true) {
79 - var nextNode = node.nextSibling;
80 - insertChildAt(parentNode, node, referenceNode);
81 - if (node === closingComment) {
82 - break;
83 - }
84 - node = nextNode;
85 - }
86 -}
87 -
88 -function removeDelimitedText(parentNode, startNode, closingComment) {
89 - while (true) {
90 - var node = startNode.nextSibling;
91 - if (node === closingComment) {
92 - // The closing comment is removed by ReactMultiChild.
93 - break;
94 - } else {
95 - parentNode.removeChild(node);
96 - }
97 - }
98 -}
99 -
100 -function replaceDelimitedText(openingComment, closingComment, stringText) {
101 - var parentNode = openingComment.parentNode;
102 - var nodeAfterComment = openingComment.nextSibling;
103 - if (nodeAfterComment === closingComment) {
104 - // There are no text nodes between the opening and closing comments; insert
105 - // a new one if stringText isn't empty.
106 - if (stringText) {
107 - insertChildAt(
108 - parentNode,
109 - document.createTextNode(stringText),
110 - nodeAfterComment,
111 - );
112 - }
113 - } else {
114 - if (stringText) {
115 - // Set the text content of the first node after the opening comment, and
116 - // remove all following nodes up until the closing comment.
117 - setTextContent(nodeAfterComment, stringText);
118 - removeDelimitedText(parentNode, nodeAfterComment, closingComment);
119 - } else {
120 - removeDelimitedText(parentNode, openingComment, closingComment);
121 - }
122 - }
123 -
124 - if (__DEV__) {
125 - ReactInstrumentation.debugTool.onHostOperation({
126 - instanceID: ReactDOMComponentTree.getInstanceFromNode(openingComment)
127 - ._debugID,
128 - type: 'replace text',
129 - payload: stringText,
130 - });
131 - }
132 -}
133 -
134 -var dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;
135 -if (__DEV__) {
136 - dangerouslyReplaceNodeWithMarkup = function(oldChild, markup, prevInstance) {
137 - Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);
138 - if (prevInstance._debugID !== 0) {
139 - ReactInstrumentation.debugTool.onHostOperation({
140 - instanceID: prevInstance._debugID,
141 - type: 'replace with',
142 - payload: markup.toString(),
143 - });
144 - } else {
145 - var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);
146 - if (nextInstance._debugID !== 0) {
147 - ReactInstrumentation.debugTool.onHostOperation({
148 - instanceID: nextInstance._debugID,
149 - type: 'mount',
150 - payload: markup.toString(),
151 - });
152 - }
153 - }
154 - };
155 -}
156 -
157 -/**
158 - * Operations for updating with DOM children.
159 - */
160 -var DOMChildrenOperations = {
161 - dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,
162 -
163 - replaceDelimitedText: replaceDelimitedText,
164 -
165 - /**
166 - * Updates a component's children by processing a series of updates. The
167 - * update configurations are each expected to have a `parentNode` property.
168 - *
169 - * @param {array<object>} updates List of update configurations.
170 - * @internal
171 - */
172 - processUpdates: function(parentNode, updates) {
173 - if (__DEV__) {
174 - var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(
175 - parentNode,
176 - )._debugID;
177 - }
178 -
179 - for (var k = 0; k < updates.length; k++) {
180 - var update = updates[k];
181 - switch (update.type) {
182 - case 'INSERT_MARKUP':
183 - insertLazyTreeChildAt(
184 - parentNode,
185 - update.content,
186 - getNodeAfter(parentNode, update.afterNode),
187 - );
188 - if (__DEV__) {
189 - ReactInstrumentation.debugTool.onHostOperation({
190 - instanceID: parentNodeDebugID,
191 - type: 'insert child',
192 - payload: {
193 - toIndex: update.toIndex,
194 - content: update.content.toString(),
195 - },
196 - });
197 - }
198 - break;
199 - case 'MOVE_EXISTING':
200 - moveChild(
201 - parentNode,
202 - update.fromNode,
203 - getNodeAfter(parentNode, update.afterNode),
204 - );
205 - if (__DEV__) {
206 - ReactInstrumentation.debugTool.onHostOperation({
207 - instanceID: parentNodeDebugID,
208 - type: 'move child',
209 - payload: {fromIndex: update.fromIndex, toIndex: update.toIndex},
210 - });
211 - }
212 - break;
213 - case 'SET_MARKUP':
214 - setInnerHTML(parentNode, update.content);
215 - if (__DEV__) {
216 - ReactInstrumentation.debugTool.onHostOperation({
217 - instanceID: parentNodeDebugID,
218 - type: 'replace children',
219 - payload: update.content.toString(),
220 - });
221 - }
222 - break;
223 - case 'TEXT_CONTENT':
224 - setTextContent(parentNode, update.content);
225 - if (__DEV__) {
226 - ReactInstrumentation.debugTool.onHostOperation({
227 - instanceID: parentNodeDebugID,
228 - type: 'replace text',
229 - payload: update.content.toString(),
230 - });
231 - }
232 - break;
233 - case 'REMOVE_NODE':
234 - removeChild(parentNode, update.fromNode);
235 - if (__DEV__) {
236 - ReactInstrumentation.debugTool.onHostOperation({
237 - instanceID: parentNodeDebugID,
238 - type: 'remove child',
239 - payload: {fromIndex: update.fromIndex},
240 - });
241 - }
242 - break;
243 - }
244 - }
245 - },
246 -};
247 -
248 -module.exports = DOMChildrenOperations;
src/renderers/dom/stack/client/DOMLazyTree.js deleted
-128
@@ -1,128 +0,0 @@
1 -/**
2 - * Copyright (c) 2015-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule DOMLazyTree
8 - */
9 -
10 -'use strict';
11 -
12 -var Namespaces = require('DOMNamespaces').Namespaces;
13 -var setInnerHTML = require('setInnerHTML');
14 -var {DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE} = require('HTMLNodeType');
15 -var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction');
16 -var setTextContent = require('setTextContent');
17 -
18 -/**
19 - * In IE (8-11) and Edge, appending nodes with no children is dramatically
20 - * faster than appending a full subtree, so we essentially queue up the
21 - * .appendChild calls here and apply them so each node is added to its parent
22 - * before any children are added.
23 - *
24 - * In other browsers, doing so is slower or neutral compared to the other order
25 - * (in Firefox, twice as slow) so we only do this inversion in IE.
26 - *
27 - * See https://github.com/sophiebits/innerhtml-vs-createelement-vs-clonenode.
28 - */
29 -var enableLazy =
30 - (typeof document !== 'undefined' &&
31 - typeof document.documentMode === 'number') ||
32 - (typeof navigator !== 'undefined' &&
33 - typeof navigator.userAgent === 'string' &&
34 - /\bEdge\/\d/.test(navigator.userAgent));
35 -
36 -function insertTreeChildren(tree) {
37 - if (!enableLazy) {
38 - return;
39 - }
40 - var node = tree.node;
41 - var children = tree.children;
42 - if (children.length) {
43 - for (var i = 0; i < children.length; i++) {
44 - insertTreeBefore(node, children[i], null);
45 - }
46 - } else if (tree.html != null) {
47 - setInnerHTML(node, tree.html);
48 - } else if (tree.text != null) {
49 - setTextContent(node, tree.text);
50 - }
51 -}
52 -
53 -var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function(
54 - parentNode,
55 - tree,
56 - referenceNode,
57 -) {
58 - // DocumentFragments aren't actually part of the DOM after insertion so
59 - // appending children won't update the DOM. We need to ensure the fragment
60 - // is properly populated first, breaking out of our lazy approach for just
61 - // this level. Also, some <object> plugins (like Flash Player) will read
62 - // <param> nodes immediately upon insertion into the DOM, so <object>
63 - // must also be populated prior to insertion into the DOM.
64 - if (
65 - tree.node.nodeType === DOCUMENT_FRAGMENT_NODE ||
66 - (tree.node.nodeType === ELEMENT_NODE &&
67 - tree.node.nodeName.toLowerCase() === 'object' &&
68 - (tree.node.namespaceURI == null ||
69 - tree.node.namespaceURI === Namespaces.html))
70 - ) {
71 - insertTreeChildren(tree);
72 - parentNode.insertBefore(tree.node, referenceNode);
73 - } else {
74 - parentNode.insertBefore(tree.node, referenceNode);
75 - insertTreeChildren(tree);
76 - }
77 -});
78 -
79 -function replaceChildWithTree(oldNode, newTree) {
80 - oldNode.parentNode.replaceChild(newTree.node, oldNode);
81 - insertTreeChildren(newTree);
82 -}
83 -
84 -function queueChild(parentTree, childTree) {
85 - if (enableLazy) {
86 - parentTree.children.push(childTree);
87 - } else {
88 - parentTree.node.appendChild(childTree.node);
89 - }
90 -}
91 -
92 -function queueHTML(tree, html) {
93 - if (enableLazy) {
94 - tree.html = html;
95 - } else {
96 - setInnerHTML(tree.node, html);
97 - }
98 -}
99 -
100 -function queueText(tree, text) {
101 - if (enableLazy) {
102 - tree.text = text;
103 - } else {
104 - setTextContent(tree.node, text);
105 - }
106 -}
107 -
108 -function toString() {
109 - return this.node.nodeName;
110 -}
111 -
112 -function DOMLazyTree(node) {
113 - return {
114 - node: node,
115 - children: [],
116 - html: null,
117 - text: null,
118 - toString,
119 - };
120 -}
121 -
122 -DOMLazyTree.insertTreeBefore = insertTreeBefore;
123 -DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
124 -DOMLazyTree.queueChild = queueChild;
125 -DOMLazyTree.queueHTML = queueHTML;
126 -DOMLazyTree.queueText = queueText;
127 -
128 -module.exports = DOMLazyTree;
src/renderers/dom/stack/client/Danger.js deleted
-54
@@ -1,54 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule Danger
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMLazyTree = require('DOMLazyTree');
13 -var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
14 -
15 -var createNodesFromMarkup = require('fbjs/lib/createNodesFromMarkup');
16 -var emptyFunction = require('fbjs/lib/emptyFunction');
17 -var invariant = require('fbjs/lib/invariant');
18 -
19 -var Danger = {
20 - /**
21 - * Replaces a node with a string of markup at its current position within its
22 - * parent. The markup must render into a single root node.
23 - *
24 - * @param {DOMElement} oldChild Child node to replace.
25 - * @param {string} markup Markup to render in place of the child node.
26 - * @internal
27 - */
28 - dangerouslyReplaceNodeWithMarkup: function(oldChild, markup) {
29 - invariant(
30 - ExecutionEnvironment.canUseDOM,
31 - 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' +
32 - 'worker thread. Make sure `window` and `document` are available ' +
33 - 'globally before requiring React when unit testing or use ' +
34 - 'ReactDOMServer.renderToString() for server rendering.',
35 - );
36 - invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.');
37 - invariant(
38 - oldChild.nodeName !== 'HTML',
39 - 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' +
40 - '<html> node. This is because browser quirks make this unreliable ' +
41 - 'and/or slow. If you want to render to the root you must use ' +
42 - 'server rendering. See ReactDOMServer.renderToString().',
43 - );
44 -
45 - if (typeof markup === 'string') {
46 - var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
47 - oldChild.parentNode.replaceChild(newChild, oldChild);
48 - } else {
49 - DOMLazyTree.replaceChildWithTree(oldChild, markup);
50 - }
51 - },
52 -};
53 -
54 -module.exports = Danger;
src/renderers/dom/stack/client/ReactComponentBrowserEnvironment.js deleted
-26
@@ -1,26 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactComponentBrowserEnvironment
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMChildrenOperations = require('DOMChildrenOperations');
13 -var ReactDOMIDOperations = require('ReactDOMIDOperations');
14 -
15 -/**
16 - * Abstracts away all functionality of the reconciler that requires knowledge of
17 - * the browser context. TODO: These callers should be refactored to avoid the
18 - * need for this injection.
19 - */
20 -var ReactComponentBrowserEnvironment = {
21 - processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,
22 -
23 - replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,
24 -};
25 -
26 -module.exports = ReactComponentBrowserEnvironment;
src/renderers/dom/stack/client/ReactDOMComponent.js deleted
-1195
@@ -1,1195 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var AutoFocusUtils = require('AutoFocusUtils');
13 -var CSSPropertyOperations = require('CSSPropertyOperations');
14 -var DOMLazyTree = require('DOMLazyTree');
15 -var Namespaces = require('DOMNamespaces').Namespaces;
16 -var DOMMarkupOperations = require('DOMMarkupOperations');
17 -var DOMProperty = require('DOMProperty');
18 -var DOMPropertyOperations = require('DOMPropertyOperations');
19 -var EventPluginRegistry = require('EventPluginRegistry');
20 -var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
21 -var ReactDOMComponentFlags = require('ReactDOMComponentFlags');
22 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
23 -var ReactDOMInput = require('ReactDOMInput');
24 -var ReactDOMOption = require('ReactDOMOption');
25 -var ReactDOMSelect = require('ReactDOMSelect');
26 -var ReactDOMTextarea = require('ReactDOMTextarea');
27 -var ReactInstrumentation = require('ReactInstrumentation');
28 -var ReactMultiChild = require('ReactMultiChild');
29 -var ReactServerRenderingTransaction = require('ReactServerRenderingTransaction');
30 -var {DOCUMENT_FRAGMENT_NODE} = require('HTMLNodeType');
31 -
32 -var dangerousStyleValue = require('dangerousStyleValue');
33 -var emptyFunction = require('fbjs/lib/emptyFunction');
34 -var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
35 -var hyphenateStyleName = require('fbjs/lib/hyphenateStyleName');
36 -var inputValueTracking = require('inputValueTracking');
37 -var invariant = require('fbjs/lib/invariant');
38 -var isCustomComponent = require('isCustomComponent');
39 -var memoizeStringOnly = require('fbjs/lib/memoizeStringOnly');
40 -var omittedCloseTags = require('omittedCloseTags');
41 -var validateDOMNesting = require('validateDOMNesting');
42 -var voidElementTags = require('voidElementTags');
43 -var warnValidStyle = require('warnValidStyle');
44 -
45 -if (__DEV__) {
46 - var warning = require('fbjs/lib/warning');
47 -}
48 -
49 -var didWarnShadyDOM = false;
50 -
51 -var Flags = ReactDOMComponentFlags;
52 -var getNode = ReactDOMComponentTree.getNodeFromInstance;
53 -var listenTo = ReactBrowserEventEmitter.listenTo;
54 -var registrationNameModules = EventPluginRegistry.registrationNameModules;
55 -
56 -// For quickly matching children type, to test if can be treated as content.
57 -var CONTENT_TYPES = {string: true, number: true};
58 -
59 -var STYLE = 'style';
60 -var HTML = '__html';
61 -
62 -function getDeclarationErrorAddendum(internalInstance) {
63 - if (internalInstance) {
64 - var owner = internalInstance._currentElement._owner || null;
65 - if (owner) {
66 - var name = owner.getName();
67 - if (name) {
68 - return '\n\nThis DOM node was rendered by `' + name + '`.';
69 - }
70 - }
71 - }
72 - return '';
73 -}
74 -
75 -/**
76 - * @param {object} component
77 - * @param {?object} props
78 - */
79 -function assertValidProps(component, props) {
80 - if (!props) {
81 - return;
82 - }
83 - // Note the use of `==` which checks for null or undefined.
84 - if (voidElementTags[component._tag]) {
85 - invariant(
86 - props.children == null && props.dangerouslySetInnerHTML == null,
87 - '%s is a void element tag and must neither have `children` nor ' +
88 - 'use `dangerouslySetInnerHTML`.%s',
89 - component._tag,
90 - getDeclarationErrorAddendum(component),
91 - );
92 - }
93 - if (props.dangerouslySetInnerHTML != null) {
94 - invariant(
95 - props.children == null,
96 - 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
97 - );
98 - invariant(
99 - typeof props.dangerouslySetInnerHTML === 'object' &&
100 - HTML in props.dangerouslySetInnerHTML,
101 - '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
102 - 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' +
103 - 'for more information.',
104 - );
105 - }
106 - if (__DEV__) {
107 - warning(
108 - props.suppressContentEditableWarning ||
109 - !props.contentEditable ||
110 - props.children == null,
111 - 'A component is `contentEditable` and contains `children` managed by ' +
112 - 'React. It is now your responsibility to guarantee that none of ' +
113 - 'those nodes are unexpectedly modified or duplicated. This is ' +
114 - 'probably not intentional.',
115 - );
116 - }
117 - invariant(
118 - props.style == null || typeof props.style === 'object',
119 - 'The `style` prop expects a mapping from style properties to values, ' +
120 - "not a string. For example, style={{marginRight: spacing + 'em'}} when " +
121 - 'using JSX.%s',
122 - getDeclarationErrorAddendum(component),
123 - );
124 -}
125 -
126 -function ensureListeningTo(inst, registrationName, transaction) {
127 - if (transaction instanceof ReactServerRenderingTransaction) {
128 - return;
129 - }
130 - var containerInfo = inst._hostContainerInfo;
131 - var isDocumentFragment =
132 - containerInfo._node &&
133 - containerInfo._node.nodeType === DOCUMENT_FRAGMENT_NODE;
134 - var doc = isDocumentFragment
135 - ? containerInfo._node
136 - : containerInfo._ownerDocument;
137 - listenTo(registrationName, doc);
138 -}
139 -
140 -function inputPostMount() {
141 - var inst = this;
142 - ReactDOMInput.postMountWrapper(inst);
143 -}
144 -
145 -function textareaPostMount() {
146 - var inst = this;
147 - ReactDOMTextarea.postMountWrapper(inst);
148 -}
149 -
150 -function optionPostMount() {
151 - var inst = this;
152 - ReactDOMOption.postMountWrapper(inst);
153 -}
154 -
155 -var processStyleName = memoizeStringOnly(function(styleName) {
156 - return hyphenateStyleName(styleName);
157 -});
158 -
159 -function createMarkupForStyles(styles, component) {
160 - var serialized = '';
161 - var delimiter = '';
162 - for (var styleName in styles) {
163 - if (!styles.hasOwnProperty(styleName)) {
164 - continue;
165 - }
166 - var isCustomProperty = styleName.indexOf('--') === 0;
167 - var styleValue = styles[styleName];
168 - if (__DEV__) {
169 - if (!isCustomProperty) {
170 - warnValidStyle(styleName, styleValue, component);
171 - }
172 - }
173 - if (styleValue != null) {
174 - serialized += delimiter + processStyleName(styleName) + ':';
175 - serialized += dangerousStyleValue(
176 - styleName,
177 - styleValue,
178 - isCustomProperty,
179 - );
180 -
181 - delimiter = ';';
182 - }
183 - }
184 - return serialized || null;
185 -}
186 -
187 -var setAndValidateContentChildDev = emptyFunction;
188 -if (__DEV__) {
189 - setAndValidateContentChildDev = function(content) {
190 - var hasExistingContent = this._contentDebugID != null;
191 - var debugID = this._debugID;
192 - // This ID represents the inlined child that has no backing instance:
193 - var contentDebugID = -debugID;
194 -
195 - if (content == null) {
196 - if (hasExistingContent) {
197 - ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
198 - }
199 - this._contentDebugID = null;
200 - return;
201 - }
202 -
203 - validateDOMNesting(null, '' + content, this, this._ancestorInfo);
204 - this._contentDebugID = contentDebugID;
205 - if (hasExistingContent) {
206 - ReactInstrumentation.debugTool.onBeforeUpdateComponent(
207 - contentDebugID,
208 - content,
209 - );
210 - ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);
211 - } else {
212 - ReactInstrumentation.debugTool.onBeforeMountComponent(
213 - contentDebugID,
214 - content,
215 - debugID,
216 - );
217 - ReactInstrumentation.debugTool.onMountComponent(contentDebugID);
218 - ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);
219 - }
220 - };
221 -}
222 -
223 -// There are so many media events, it makes sense to just
224 -// maintain a list rather than create a `trapBubbledEvent` for each
225 -var mediaEvents = {
226 - topAbort: 'abort',
227 - topCanPlay: 'canplay',
228 - topCanPlayThrough: 'canplaythrough',
229 - topDurationChange: 'durationchange',
230 - topEmptied: 'emptied',
231 - topEncrypted: 'encrypted',
232 - topEnded: 'ended',
233 - topError: 'error',
234 - topLoadedData: 'loadeddata',
235 - topLoadedMetadata: 'loadedmetadata',
236 - topLoadStart: 'loadstart',
237 - topPause: 'pause',
238 - topPlay: 'play',
239 - topPlaying: 'playing',
240 - topProgress: 'progress',
241 - topRateChange: 'ratechange',
242 - topSeeked: 'seeked',
243 - topSeeking: 'seeking',
244 - topStalled: 'stalled',
245 - topSuspend: 'suspend',
246 - topTimeUpdate: 'timeupdate',
247 - topVolumeChange: 'volumechange',
248 - topWaiting: 'waiting',
249 -};
250 -
251 -function trackInputValue() {
252 - inputValueTracking.track(getNode(this));
253 -}
254 -
255 -function trapClickOnNonInteractiveElement() {
256 - // Mobile Safari does not fire properly bubble click events on
257 - // non-interactive elements, which means delegated click listeners do not
258 - // fire. The workaround for this bug involves attaching an empty click
259 - // listener on the target node.
260 - // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
261 - // Just set it using the onclick property so that we don't have to manage any
262 - // bookkeeping for it. Not sure if we need to clear it when the listener is
263 - // removed.
264 - // TODO: Only do this for the relevant Safaris maybe?
265 - var node = getNode(this);
266 - node.onclick = emptyFunction;
267 -}
268 -
269 -function trapBubbledEventsLocal() {
270 - var inst = this;
271 - // If a component renders to null or if another component fatals and causes
272 - // the state of the tree to be corrupted, `node` here can be null.
273 - invariant(inst._rootNodeID, 'Must be mounted to trap events');
274 - var node = getNode(inst);
275 - invariant(node, 'trapBubbledEvent(...): Requires node to be rendered.');
276 -
277 - switch (inst._tag) {
278 - case 'iframe':
279 - case 'object':
280 - inst._wrapperState.listeners = [
281 - ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node),
282 - ];
283 - break;
284 - case 'video':
285 - case 'audio':
286 - inst._wrapperState.listeners = [];
287 - // Create listener for each media event
288 - for (var event in mediaEvents) {
289 - if (mediaEvents.hasOwnProperty(event)) {
290 - inst._wrapperState.listeners.push(
291 - ReactBrowserEventEmitter.trapBubbledEvent(
292 - event,
293 - mediaEvents[event],
294 - node,
295 - ),
296 - );
297 - }
298 - }
299 - break;
300 - case 'source':
301 - inst._wrapperState.listeners = [
302 - ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node),
303 - ];
304 - break;
305 - case 'img':
306 - case 'image':
307 - inst._wrapperState.listeners = [
308 - ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node),
309 - ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node),
310 - ];
311 - break;
312 - case 'form':
313 - inst._wrapperState.listeners = [
314 - ReactBrowserEventEmitter.trapBubbledEvent('topReset', 'reset', node),
315 - ReactBrowserEventEmitter.trapBubbledEvent('topSubmit', 'submit', node),
316 - ];
317 - break;
318 - case 'input':
319 - case 'select':
320 - case 'textarea':
321 - inst._wrapperState.listeners = [
322 - ReactBrowserEventEmitter.trapBubbledEvent(
323 - 'topInvalid',
324 - 'invalid',
325 - node,
326 - ),
327 - ];
328 - break;
329 - case 'details':
330 - inst._wrapperState.listeners = [
331 - ReactBrowserEventEmitter.trapBubbledEvent('topToggle', 'toggle', node),
332 - ];
333 - break;
334 - }
335 -}
336 -
337 -function postUpdateSelectWrapper() {
338 - ReactDOMSelect.postUpdateWrapper(this);
339 -}
340 -
341 -var newlineEatingTags = {
342 - listing: true,
343 - pre: true,
344 - textarea: true,
345 -};
346 -
347 -// We accept any tag to be rendered but since this gets injected into arbitrary
348 -// HTML, we want to make sure that it's a safe tag.
349 -// http://www.w3.org/TR/REC-xml/#NT-Name
350 -
351 -var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
352 -var validatedTagCache = {};
353 -
354 -function validateDangerousTag(tag) {
355 - if (!validatedTagCache.hasOwnProperty(tag)) {
356 - invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag);
357 - validatedTagCache[tag] = true;
358 - }
359 -}
360 -
361 -var globalIdCounter = 1;
362 -var warnedUnknownTags = {
363 - // Chrome is the only major browser not shipping <time>. But as of July
364 - // 2017 it intends to ship it due to widespread usage. We intentionally
365 - // *don't* warn for <time> even if it's unrecognized by Chrome because
366 - // it soon will be, and many apps have been using it anyway.
367 - time: true,
368 -};
369 -
370 -/**
371 - * Creates a new React class that is idempotent and capable of containing other
372 - * React components. It accepts event listeners and DOM properties that are
373 - * valid according to `DOMProperty`.
374 - *
375 - * - Event listeners: `onClick`, `onMouseDown`, etc.
376 - * - DOM properties: `className`, `name`, `title`, etc.
377 - *
378 - * The `style` property functions differently from the DOM API. It accepts an
379 - * object mapping of style properties to values.
380 - *
381 - * @constructor ReactDOMComponent
382 - * @extends ReactMultiChild
383 - */
384 -function ReactDOMComponent(element) {
385 - var tag = element.type;
386 - this._currentElement = element;
387 - this._tag = tag.toLowerCase();
388 - this._namespaceURI = null;
389 - this._renderedChildren = null;
390 - this._hostNode = null;
391 - this._hostParent = null;
392 - this._rootNodeID = 0;
393 - this._domID = 0;
394 - this._hostContainerInfo = null;
395 - this._wrapperState = null;
396 - this._topLevelWrapper = null;
397 - this._flags = 0;
398 - if (__DEV__) {
399 - this._ancestorInfo = null;
400 - setAndValidateContentChildDev.call(this, null);
401 - }
402 -}
403 -
404 -ReactDOMComponent.displayName = 'ReactDOMComponent';
405 -
406 -ReactDOMComponent.Mixin = {
407 - /**
408 - * Generates root tag markup then recurses. This method has side effects and
409 - * is not idempotent.
410 - *
411 - * @internal
412 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
413 - * @param {?ReactDOMComponent} the parent component instance
414 - * @param {?object} info about the host container
415 - * @param {object} context
416 - * @return {string} The computed markup.
417 - */
418 - mountComponent: function(
419 - transaction,
420 - hostParent,
421 - hostContainerInfo,
422 - context,
423 - ) {
424 - this._rootNodeID = globalIdCounter++;
425 - this._domID = hostContainerInfo._idCounter++;
426 - this._hostParent = hostParent;
427 - this._hostContainerInfo = hostContainerInfo;
428 -
429 - var props = this._currentElement.props;
430 -
431 - switch (this._tag) {
432 - case 'audio':
433 - case 'form':
434 - case 'iframe':
435 - case 'img':
436 - case 'image':
437 - case 'link':
438 - case 'object':
439 - case 'source':
440 - case 'video':
441 - case 'details':
442 - this._wrapperState = {
443 - listeners: null,
444 - };
445 - transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
446 - break;
447 - case 'input':
448 - ReactDOMInput.mountWrapper(this, props, hostParent);
449 - props = ReactDOMInput.getHostProps(this, props);
450 - transaction.getReactMountReady().enqueue(trackInputValue, this);
451 - transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
452 - // For controlled components we always need to ensure we're listening
453 - // to onChange. Even if there is no listener.
454 - ensureListeningTo(this, 'onChange', transaction);
455 - break;
456 - case 'option':
457 - ReactDOMOption.mountWrapper(this, props, hostParent);
458 - props = ReactDOMOption.getHostProps(this, props);
459 - break;
460 - case 'select':
461 - ReactDOMSelect.mountWrapper(this, props, hostParent);
462 - props = ReactDOMSelect.getHostProps(this, props);
463 - transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
464 - // For controlled components we always need to ensure we're listening
465 - // to onChange. Even if there is no listener.
466 - ensureListeningTo(this, 'onChange', transaction);
467 - break;
468 - case 'textarea':
469 - ReactDOMTextarea.mountWrapper(this, props, hostParent);
470 - props = ReactDOMTextarea.getHostProps(this, props);
471 - transaction.getReactMountReady().enqueue(trackInputValue, this);
472 - transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
473 - // For controlled components we always need to ensure we're listening
474 - // to onChange. Even if there is no listener.
475 - ensureListeningTo(this, 'onChange', transaction);
476 - break;
477 - }
478 -
479 - assertValidProps(this, props);
480 -
481 - // We create tags in the namespace of their parent container, except HTML
482 - // tags get no namespace.
483 - var namespaceURI;
484 - var parentTag;
485 - if (hostParent != null) {
486 - namespaceURI = hostParent._namespaceURI;
487 - parentTag = hostParent._tag;
488 - } else if (hostContainerInfo._tag) {
489 - namespaceURI = hostContainerInfo._namespaceURI;
490 - parentTag = hostContainerInfo._tag;
491 - }
492 - if (
493 - namespaceURI == null ||
494 - (namespaceURI === Namespaces.svg && parentTag === 'foreignobject')
495 - ) {
496 - namespaceURI = Namespaces.html;
497 - }
498 - if (__DEV__) {
499 - var isCustomComponentTag = isCustomComponent(this._tag, props);
500 - }
501 - if (namespaceURI === Namespaces.html) {
502 - if (__DEV__) {
503 - warning(
504 - isCustomComponentTag || this._tag === this._currentElement.type,
505 - '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' +
506 - 'in React.',
507 - this._currentElement.type,
508 - );
509 - }
510 - if (this._tag === 'svg') {
511 - namespaceURI = Namespaces.svg;
512 - } else if (this._tag === 'math') {
513 - namespaceURI = Namespaces.mathml;
514 - }
515 - }
516 - this._namespaceURI = namespaceURI;
517 -
518 - if (__DEV__) {
519 - var parentInfo;
520 - if (hostParent != null) {
521 - parentInfo = hostParent._ancestorInfo;
522 - } else if (hostContainerInfo._tag) {
523 - parentInfo = hostContainerInfo._ancestorInfo;
524 - }
525 - if (parentInfo) {
526 - // parentInfo should always be present except for the top-level
527 - // component when server rendering
528 - validateDOMNesting(this._tag, null, this, parentInfo);
529 - }
530 - this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(
531 - parentInfo,
532 - this._tag,
533 - this,
534 - );
535 - }
536 -
537 - var mountImage;
538 - var type = this._currentElement.type;
539 - if (transaction.useCreateElement) {
540 - var ownerDocument = hostContainerInfo._ownerDocument;
541 - var el;
542 - if (namespaceURI === Namespaces.html) {
543 - if (this._tag === 'script') {
544 - // Create the script via .innerHTML so its "parser-inserted" flag is
545 - // set to true and it does not execute
546 - var div = ownerDocument.createElement('div');
547 - div.innerHTML = `<${type}></${type}>`;
548 - el = div.removeChild(div.firstChild);
549 - } else if (typeof props.is === 'string') {
550 - el = ownerDocument.createElement(type, {is: props.is});
551 - } else {
552 - // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
553 - // See discussion in https://github.com/facebook/react/pull/6896
554 - // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
555 - el = ownerDocument.createElement(type);
556 - }
557 - } else {
558 - el = ownerDocument.createElementNS(namespaceURI, type);
559 - }
560 - if (__DEV__) {
561 - if (isCustomComponentTag && !didWarnShadyDOM && el.shadyRoot) {
562 - var owner = this._currentElement._owner;
563 - var name = (owner && owner.getName()) || 'A component';
564 - warning(
565 - false,
566 - '%s is using shady DOM. Using shady DOM with React can ' +
567 - 'cause things to break subtly.',
568 - name,
569 - );
570 - didWarnShadyDOM = true;
571 - }
572 - if (this._namespaceURI === Namespaces.html) {
573 - if (
574 - !isCustomComponentTag &&
575 - Object.prototype.toString.call(el) ===
576 - '[object HTMLUnknownElement]' &&
577 - !Object.prototype.hasOwnProperty.call(warnedUnknownTags, this._tag)
578 - ) {
579 - warnedUnknownTags[this._tag] = true;
580 - warning(
581 - false,
582 - 'The tag <%s> is unrecognized in this browser. ' +
583 - 'If you meant to render a React component, start its name with ' +
584 - 'an uppercase letter.',
585 - this._tag,
586 - );
587 - }
588 - }
589 - }
590 - ReactDOMComponentTree.precacheNode(this, el);
591 - this._flags |= Flags.hasCachedChildNodes;
592 - if (!this._hostParent) {
593 - DOMPropertyOperations.setAttributeForRoot(el);
594 - }
595 - this._updateDOMProperties(null, props, transaction, isCustomComponentTag);
596 - var lazyTree = DOMLazyTree(el);
597 - this._createInitialChildren(transaction, props, context, lazyTree);
598 - mountImage = lazyTree;
599 - } else {
600 - validateDangerousTag(this._tag);
601 - var tagOpen = this._createOpenTagMarkupAndPutListeners(
602 - transaction,
603 - props,
604 - );
605 - var tagContent = this._createContentMarkup(transaction, props, context);
606 - if (!tagContent && omittedCloseTags[this._tag]) {
607 - mountImage = tagOpen + '/>';
608 - } else {
609 - mountImage = tagOpen + '>' + tagContent + '</' + type + '>';
610 - }
611 - }
612 -
613 - switch (this._tag) {
614 - case 'input':
615 - transaction.getReactMountReady().enqueue(inputPostMount, this);
616 - if (props.autoFocus) {
617 - transaction
618 - .getReactMountReady()
619 - .enqueue(AutoFocusUtils.focusDOMComponent, this);
620 - }
621 - break;
622 - case 'textarea':
623 - transaction.getReactMountReady().enqueue(textareaPostMount, this);
624 - if (props.autoFocus) {
625 - transaction
626 - .getReactMountReady()
627 - .enqueue(AutoFocusUtils.focusDOMComponent, this);
628 - }
629 - break;
630 - case 'select':
631 - if (props.autoFocus) {
632 - transaction
633 - .getReactMountReady()
634 - .enqueue(AutoFocusUtils.focusDOMComponent, this);
635 - }
636 - break;
637 - case 'button':
638 - if (props.autoFocus) {
639 - transaction
640 - .getReactMountReady()
641 - .enqueue(AutoFocusUtils.focusDOMComponent, this);
642 - }
643 - break;
644 - case 'option':
645 - transaction.getReactMountReady().enqueue(optionPostMount, this);
646 - break;
647 - default:
648 - if (typeof props.onClick === 'function') {
649 - transaction
650 - .getReactMountReady()
651 - .enqueue(trapClickOnNonInteractiveElement, this);
652 - }
653 - break;
654 - }
655 -
656 - return mountImage;
657 - },
658 -
659 - /**
660 - * Creates markup for the open tag and all attributes.
661 - *
662 - * This method has side effects because events get registered.
663 - *
664 - * Iterating over object properties is faster than iterating over arrays.
665 - * @see http://jsperf.com/obj-vs-arr-iteration
666 - *
667 - * @private
668 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
669 - * @param {object} props
670 - * @return {string} Markup of opening tag.
671 - */
672 - _createOpenTagMarkupAndPutListeners: function(transaction, props) {
673 - var ret = '<' + this._currentElement.type;
674 -
675 - for (var propKey in props) {
676 - if (!props.hasOwnProperty(propKey)) {
677 - continue;
678 - }
679 - var propValue = props[propKey];
680 - if (propValue == null) {
681 - continue;
682 - }
683 - if (registrationNameModules.hasOwnProperty(propKey)) {
684 - if (propValue) {
685 - ensureListeningTo(this, propKey, transaction);
686 - }
687 - } else {
688 - if (propKey === STYLE) {
689 - if (propValue) {
690 - if (__DEV__) {
691 - Object.freeze(propValue);
692 - }
693 - }
694 - propValue = createMarkupForStyles(propValue, this);
695 - }
696 - var markup = null;
697 - if (this._tag != null && isCustomComponent(this._tag, props)) {
698 - if (!DOMProperty.isReservedProp(propKey)) {
699 - markup = DOMMarkupOperations.createMarkupForCustomAttribute(
700 - propKey,
701 - propValue,
702 - );
703 - }
704 - } else {
705 - markup = DOMMarkupOperations.createMarkupForProperty(
706 - propKey,
707 - propValue,
708 - );
709 - }
710 - if (markup) {
711 - ret += ' ' + markup;
712 - }
713 - }
714 - }
715 -
716 - // For static pages, no need to put React ID and checksum. Saves lots of
717 - // bytes.
718 - if (transaction.renderToStaticMarkup) {
719 - return ret;
720 - }
721 -
722 - if (!this._hostParent) {
723 - ret += ' ' + DOMMarkupOperations.createMarkupForRoot();
724 - }
725 - ret += ' ' + DOMMarkupOperations.createMarkupForID(this._domID);
726 - return ret;
727 - },
728 -
729 - /**
730 - * Creates markup for the content between the tags.
731 - *
732 - * @private
733 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
734 - * @param {object} props
735 - * @param {object} context
736 - * @return {string} Content markup.
737 - */
738 - _createContentMarkup: function(transaction, props, context) {
739 - var ret = '';
740 -
741 - // Intentional use of != to avoid catching zero/false.
742 - var innerHTML = props.dangerouslySetInnerHTML;
743 - if (innerHTML != null) {
744 - if (innerHTML.__html != null) {
745 - ret = innerHTML.__html;
746 - }
747 - } else {
748 - var contentToUse = CONTENT_TYPES[typeof props.children]
749 - ? props.children
750 - : null;
751 - var childrenToUse = contentToUse != null ? null : props.children;
752 - if (contentToUse != null) {
753 - // TODO: Validate that text is allowed as a child of this node
754 - ret = escapeTextContentForBrowser(contentToUse);
755 - if (__DEV__) {
756 - setAndValidateContentChildDev.call(this, contentToUse);
757 - }
758 - } else if (childrenToUse != null) {
759 - var mountImages = this.mountChildren(
760 - childrenToUse,
761 - transaction,
762 - context,
763 - );
764 - ret = mountImages.join('');
765 - }
766 - }
767 - if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
768 - // text/html ignores the first character in these tags if it's a newline
769 - // Prefer to break application/xml over text/html (for now) by adding
770 - // a newline specifically to get eaten by the parser. (Alternately for
771 - // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
772 - // \r is normalized out by HTMLTextAreaElement#value.)
773 - // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
774 - // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
775 - // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
776 - // See: Parsing of "textarea" "listing" and "pre" elements
777 - // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
778 - return '\n' + ret;
779 - } else {
780 - return ret;
781 - }
782 - },
783 -
784 - _createInitialChildren: function(transaction, props, context, lazyTree) {
785 - // Intentional use of != to avoid catching zero/false.
786 - var innerHTML = props.dangerouslySetInnerHTML;
787 - if (innerHTML != null) {
788 - const innerHTMLContent = innerHTML.__html;
789 - if (innerHTMLContent != null && innerHTMLContent !== '') {
790 - DOMLazyTree.queueHTML(lazyTree, innerHTMLContent);
791 - }
792 - } else {
793 - var contentToUse = CONTENT_TYPES[typeof props.children]
794 - ? props.children
795 - : null;
796 - var childrenToUse = contentToUse != null ? null : props.children;
797 - // TODO: Validate that text is allowed as a child of this node
798 - if (contentToUse != null) {
799 - // Avoid setting textContent when the text is empty. In IE11 setting
800 - // textContent on a text area will cause the placeholder to not
801 - // show within the textarea until it has been focused and blurred again.
802 - // https://github.com/facebook/react/issues/6731#issuecomment-254874553
803 - if (contentToUse !== '') {
804 - if (__DEV__) {
805 - setAndValidateContentChildDev.call(this, contentToUse);
806 - }
807 - DOMLazyTree.queueText(lazyTree, contentToUse);
808 - }
809 - } else if (childrenToUse != null) {
810 - var mountImages = this.mountChildren(
811 - childrenToUse,
812 - transaction,
813 - context,
814 - );
815 - for (var i = 0; i < mountImages.length; i++) {
816 - DOMLazyTree.queueChild(lazyTree, mountImages[i]);
817 - }
818 - }
819 - }
820 - },
821 -
822 - /**
823 - * Receives a next element and updates the component.
824 - *
825 - * @internal
826 - * @param {ReactElement} nextElement
827 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
828 - * @param {object} context
829 - */
830 - receiveComponent: function(nextElement, transaction, context) {
831 - var prevElement = this._currentElement;
832 - this._currentElement = nextElement;
833 - this.updateComponent(transaction, prevElement, nextElement, context);
834 - },
835 -
836 - /**
837 - * Updates a DOM component after it has already been allocated and
838 - * attached to the DOM. Reconciles the root DOM node, then recurses.
839 - *
840 - * @param {ReactReconcileTransaction} transaction
841 - * @param {ReactElement} prevElement
842 - * @param {ReactElement} nextElement
843 - * @internal
844 - * @overridable
845 - */
846 - updateComponent: function(transaction, prevElement, nextElement, context) {
847 - var lastProps = prevElement.props;
848 - var nextProps = this._currentElement.props;
849 -
850 - switch (this._tag) {
851 - case 'input':
852 - lastProps = ReactDOMInput.getHostProps(this, lastProps);
853 - nextProps = ReactDOMInput.getHostProps(this, nextProps);
854 - break;
855 - case 'option':
856 - lastProps = ReactDOMOption.getHostProps(this, lastProps);
857 - nextProps = ReactDOMOption.getHostProps(this, nextProps);
858 - break;
859 - case 'select':
860 - lastProps = ReactDOMSelect.getHostProps(this, lastProps);
861 - nextProps = ReactDOMSelect.getHostProps(this, nextProps);
862 - break;
863 - case 'textarea':
864 - lastProps = ReactDOMTextarea.getHostProps(this, lastProps);
865 - nextProps = ReactDOMTextarea.getHostProps(this, nextProps);
866 - break;
867 - default:
868 - if (
869 - typeof lastProps.onClick !== 'function' &&
870 - typeof nextProps.onClick === 'function'
871 - ) {
872 - transaction
873 - .getReactMountReady()
874 - .enqueue(trapClickOnNonInteractiveElement, this);
875 - }
876 - break;
877 - }
878 -
879 - assertValidProps(this, nextProps);
880 - var isCustomComponentTag = isCustomComponent(this._tag, nextProps);
881 - this._updateDOMProperties(
882 - lastProps,
883 - nextProps,
884 - transaction,
885 - isCustomComponentTag,
886 - );
887 - this._updateDOMChildren(lastProps, nextProps, transaction, context);
888 -
889 - switch (this._tag) {
890 - case 'input':
891 - // Update the wrapper around inputs *after* updating props. This has to
892 - // happen after `_updateDOMProperties`. Otherwise HTML5 input validations
893 - // raise warnings and prevent the new value from being assigned.
894 - ReactDOMInput.updateWrapper(this);
895 - // We also check that we haven't missed a value update, such as a
896 - // Radio group shifting the checked value to another named radio input.
897 - inputValueTracking.updateValueIfChanged(getNode(this));
898 - break;
899 - case 'textarea':
900 - ReactDOMTextarea.updateWrapper(this);
901 - break;
902 - case 'select':
903 - // <select> value update needs to occur after <option> children
904 - // reconciliation
905 - transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
906 - break;
907 - }
908 - },
909 -
910 - /**
911 - * Reconciles the properties by detecting differences in property values and
912 - * updating the DOM as necessary. This function is probably the single most
913 - * critical path for performance optimization.
914 - *
915 - * TODO: Benchmark whether checking for changed values in memory actually
916 - * improves performance (especially statically positioned elements).
917 - * TODO: Benchmark the effects of putting this at the top since 99% of props
918 - * do not change for a given reconciliation.
919 - * TODO: Benchmark areas that can be improved with caching.
920 - *
921 - * @private
922 - * @param {object} lastProps
923 - * @param {object} nextProps
924 - * @param {?DOMElement} node
925 - */
926 - _updateDOMProperties: function(
927 - lastProps,
928 - nextProps,
929 - transaction,
930 - isCustomComponentTag,
931 - ) {
932 - var propKey;
933 - var styleName;
934 - var styleUpdates;
935 - for (propKey in lastProps) {
936 - if (
937 - nextProps.hasOwnProperty(propKey) ||
938 - !lastProps.hasOwnProperty(propKey) ||
939 - lastProps[propKey] == null
940 - ) {
941 - continue;
942 - }
943 - if (propKey === STYLE) {
944 - var lastStyle = lastProps[STYLE];
945 - for (styleName in lastStyle) {
946 - if (lastStyle.hasOwnProperty(styleName)) {
947 - styleUpdates = styleUpdates || {};
948 - styleUpdates[styleName] = '';
949 - }
950 - }
951 - } else if (registrationNameModules.hasOwnProperty(propKey)) {
952 - // Do nothing for event names.
953 - } else if (!DOMProperty.isReservedProp(propKey)) {
954 - if (isCustomComponent(this._tag, lastProps)) {
955 - DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);
956 - } else {
957 - DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);
958 - }
959 - }
960 - }
961 - for (propKey in nextProps) {
962 - var nextProp = nextProps[propKey];
963 - var lastProp = lastProps != null ? lastProps[propKey] : undefined;
964 - if (
965 - !nextProps.hasOwnProperty(propKey) ||
966 - nextProp === lastProp ||
967 - (nextProp == null && lastProp == null)
968 - ) {
969 - continue;
970 - }
971 - if (propKey === STYLE) {
972 - if (nextProp) {
973 - if (__DEV__) {
974 - Object.freeze(nextProp);
975 - }
976 - }
977 - if (lastProp) {
978 - // Unset styles on `lastProp` but not on `nextProp`.
979 - for (styleName in lastProp) {
980 - if (
981 - lastProp.hasOwnProperty(styleName) &&
982 - (!nextProp || !nextProp.hasOwnProperty(styleName))
983 - ) {
984 - styleUpdates = styleUpdates || {};
985 - styleUpdates[styleName] = '';
986 - }
987 - }
988 - // Update styles that changed since `lastProp`.
989 - for (styleName in nextProp) {
990 - if (
991 - nextProp.hasOwnProperty(styleName) &&
992 - lastProp[styleName] !== nextProp[styleName]
993 - ) {
994 - styleUpdates = styleUpdates || {};
995 - styleUpdates[styleName] = nextProp[styleName];
996 - }
997 - }
998 - } else {
999 - // Relies on `updateStylesByID` not mutating `styleUpdates`.
1000 - styleUpdates = nextProp;
1001 - }
1002 - } else if (registrationNameModules.hasOwnProperty(propKey)) {
1003 - if (nextProp) {
1004 - ensureListeningTo(this, propKey, transaction);
1005 - }
1006 - } else if (isCustomComponentTag) {
1007 - if (!DOMProperty.isReservedProp(propKey)) {
1008 - DOMPropertyOperations.setValueForAttribute(
1009 - getNode(this),
1010 - propKey,
1011 - nextProp,
1012 - );
1013 - }
1014 - } else if (!DOMProperty.isReservedProp(propKey)) {
1015 - var node = getNode(this);
1016 - // If we're updating to null or undefined, we should remove the property
1017 - // from the DOM node instead of inadvertently setting to a string. This
1018 - // brings us in line with the same behavior we have on initial render.
1019 - if (nextProp != null) {
1020 - DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
1021 - } else {
1022 - DOMPropertyOperations.deleteValueForProperty(node, propKey);
1023 - }
1024 - }
1025 - }
1026 - if (styleUpdates) {
1027 - if (__DEV__) {
1028 - ReactInstrumentation.debugTool.onHostOperation({
1029 - instanceID: this._debugID,
1030 - type: 'update styles',
1031 - payload: styleUpdates,
1032 - });
1033 - }
1034 - CSSPropertyOperations.setValueForStyles(
1035 - getNode(this),
1036 - styleUpdates,
1037 - this,
1038 - );
1039 - }
1040 - },
1041 -
1042 - /**
1043 - * Reconciles the children with the various properties that affect the
1044 - * children content.
1045 - *
1046 - * @param {object} lastProps
1047 - * @param {object} nextProps
1048 - * @param {ReactReconcileTransaction} transaction
1049 - * @param {object} context
1050 - */
1051 - _updateDOMChildren: function(lastProps, nextProps, transaction, context) {
1052 - var lastContent = CONTENT_TYPES[typeof lastProps.children]
1053 - ? lastProps.children
1054 - : null;
1055 - var nextContent = CONTENT_TYPES[typeof nextProps.children]
1056 - ? nextProps.children
1057 - : null;
1058 -
1059 - var lastHtml =
1060 - lastProps.dangerouslySetInnerHTML &&
1061 - lastProps.dangerouslySetInnerHTML.__html;
1062 - var nextHtml =
1063 - nextProps.dangerouslySetInnerHTML &&
1064 - nextProps.dangerouslySetInnerHTML.__html;
1065 -
1066 - // Note the use of `!=` which checks for null or undefined.
1067 - var lastChildren = lastContent != null ? null : lastProps.children;
1068 - var nextChildren = nextContent != null ? null : nextProps.children;
1069 -
1070 - // If we're switching from children to content/html or vice versa, remove
1071 - // the old content
1072 - var lastHasContentOrHtml = lastContent != null || lastHtml != null;
1073 - var nextHasContentOrHtml = nextContent != null || nextHtml != null;
1074 - if (lastChildren != null && nextChildren == null) {
1075 - this.updateChildren(null, transaction, context);
1076 - } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
1077 - this.updateTextContent('');
1078 - if (__DEV__) {
1079 - ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
1080 - }
1081 - }
1082 -
1083 - if (nextContent != null) {
1084 - if (lastContent !== nextContent) {
1085 - this.updateTextContent('' + nextContent);
1086 - if (__DEV__) {
1087 - setAndValidateContentChildDev.call(this, nextContent);
1088 - }
1089 - }
1090 - } else if (nextHtml != null) {
1091 - if (lastHtml !== nextHtml) {
1092 - this.updateMarkup('' + nextHtml);
1093 - }
1094 - if (__DEV__) {
1095 - ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
1096 - }
1097 - } else if (nextChildren != null) {
1098 - if (__DEV__) {
1099 - setAndValidateContentChildDev.call(this, null);
1100 - }
1101 -
1102 - this.updateChildren(nextChildren, transaction, context);
1103 - }
1104 - },
1105 -
1106 - getHostNode: function() {
1107 - return getNode(this);
1108 - },
1109 -
1110 - /**
1111 - * Destroys all event registrations for this instance. Does not remove from
1112 - * the DOM. That must be done by the parent.
1113 - *
1114 - * @internal
1115 - */
1116 - unmountComponent: function(safely, skipLifecycle) {
1117 - switch (this._tag) {
1118 - case 'audio':
1119 - case 'form':
1120 - case 'iframe':
1121 - case 'img':
1122 - case 'image':
1123 - case 'link':
1124 - case 'object':
1125 - case 'source':
1126 - case 'video':
1127 - var listeners = this._wrapperState.listeners;
1128 - if (listeners) {
1129 - for (var i = 0; i < listeners.length; i++) {
1130 - listeners[i].remove();
1131 - }
1132 - }
1133 - break;
1134 - case 'input':
1135 - case 'textarea':
1136 - inputValueTracking.stopTracking(getNode(this));
1137 - break;
1138 - case 'html':
1139 - case 'head':
1140 - case 'body':
1141 - /**
1142 - * Components like <html> <head> and <body> can't be removed or added
1143 - * easily in a cross-browser way, however it's valuable to be able to
1144 - * take advantage of React's reconciliation for styling and <title>
1145 - * management. So we just document it and throw in dangerous cases.
1146 - */
1147 - invariant(
1148 - false,
1149 - '<%s> tried to unmount. Because of cross-browser quirks it is ' +
1150 - 'impossible to unmount some top-level components (eg <html>, ' +
1151 - '<head>, and <body>) reliably and efficiently. To fix this, have a ' +
1152 - 'single top-level component that never unmounts render these ' +
1153 - 'elements.',
1154 - this._tag,
1155 - );
1156 - break;
1157 - }
1158 -
1159 - this.unmountChildren(safely, skipLifecycle);
1160 - ReactDOMComponentTree.uncacheNode(this);
1161 - this._rootNodeID = 0;
1162 - this._domID = 0;
1163 - this._wrapperState = null;
1164 -
1165 - if (__DEV__) {
1166 - setAndValidateContentChildDev.call(this, null);
1167 - }
1168 - },
1169 -
1170 - restoreControlledState: function() {
1171 - switch (this._tag) {
1172 - case 'input':
1173 - ReactDOMInput.restoreControlledState(this);
1174 - return;
1175 - case 'textarea':
1176 - ReactDOMTextarea.restoreControlledState(this);
1177 - return;
1178 - case 'select':
1179 - ReactDOMSelect.restoreControlledState(this);
1180 - return;
1181 - }
1182 - },
1183 -
1184 - getPublicInstance: function() {
1185 - return getNode(this);
1186 - },
1187 -};
1188 -
1189 -Object.assign(
1190 - ReactDOMComponent.prototype,
1191 - ReactDOMComponent.Mixin,
1192 - ReactMultiChild,
1193 -);
1194 -
1195 -module.exports = ReactDOMComponent;
src/renderers/dom/stack/client/ReactDOMContainerInfo.js deleted
-34
@@ -1,34 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMContainerInfo
8 - */
9 -
10 -'use strict';
11 -
12 -var validateDOMNesting = require('validateDOMNesting');
13 -var {DOCUMENT_NODE} = require('HTMLNodeType');
14 -
15 -function ReactDOMContainerInfo(topLevelWrapper, node) {
16 - var info = {
17 - _topLevelWrapper: topLevelWrapper,
18 - _idCounter: 1,
19 - _ownerDocument: node
20 - ? node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument
21 - : null,
22 - _node: node,
23 - _tag: node ? node.nodeName.toLowerCase() : null,
24 - _namespaceURI: node ? node.namespaceURI : null,
25 - };
26 - if (__DEV__) {
27 - info._ancestorInfo = node
28 - ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null)
29 - : null;
30 - }
31 - return info;
32 -}
33 -
34 -module.exports = ReactDOMContainerInfo;
src/renderers/dom/stack/client/ReactDOMEmptyComponent.js deleted
-61
@@ -1,61 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMEmptyComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMLazyTree = require('DOMLazyTree');
13 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
14 -
15 -var ReactDOMEmptyComponent = function(instantiate) {
16 - // ReactCompositeComponent uses this:
17 - this._currentElement = null;
18 - // ReactDOMComponentTree uses these:
19 - this._hostNode = null;
20 - this._hostParent = null;
21 - this._hostContainerInfo = null;
22 - this._domID = 0;
23 -};
24 -Object.assign(ReactDOMEmptyComponent.prototype, {
25 - mountComponent: function(
26 - transaction,
27 - hostParent,
28 - hostContainerInfo,
29 - context,
30 - ) {
31 - var domID = hostContainerInfo._idCounter++;
32 - this._domID = domID;
33 - this._hostParent = hostParent;
34 - this._hostContainerInfo = hostContainerInfo;
35 -
36 - var nodeValue = ' react-empty: ' + this._domID + ' ';
37 - if (transaction.useCreateElement) {
38 - var ownerDocument = hostContainerInfo._ownerDocument;
39 - var node = ownerDocument.createComment(nodeValue);
40 - ReactDOMComponentTree.precacheNode(this, node);
41 - return DOMLazyTree(node);
42 - } else {
43 - if (transaction.renderToStaticMarkup) {
44 - // Normally we'd insert a comment node, but since this is a situation
45 - // where React won't take over (static pages), we can simply return
46 - // nothing.
47 - return '';
48 - }
49 - return '<!--' + nodeValue + '-->';
50 - }
51 - },
52 - receiveComponent: function() {},
53 - getHostNode: function() {
54 - return ReactDOMComponentTree.getNodeFromInstance(this);
55 - },
56 - unmountComponent: function() {
57 - ReactDOMComponentTree.uncacheNode(this);
58 - },
59 -});
60 -
61 -module.exports = ReactDOMEmptyComponent;
src/renderers/dom/stack/client/ReactDOMIDOperations.js deleted
-31
@@ -1,31 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMIDOperations
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMChildrenOperations = require('DOMChildrenOperations');
13 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
14 -
15 -/**
16 - * Operations used to process updates to DOM nodes.
17 - */
18 -var ReactDOMIDOperations = {
19 - /**
20 - * Updates a component's children by processing a series of updates.
21 - *
22 - * @param {array<object>} updates List of update configurations.
23 - * @internal
24 - */
25 - dangerouslyProcessChildrenUpdates: function(parentInst, updates) {
26 - var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);
27 - DOMChildrenOperations.processUpdates(node, updates);
28 - },
29 -};
30 -
31 -module.exports = ReactDOMIDOperations;
src/renderers/dom/stack/client/ReactDOMStackInjection.js deleted
-52
@@ -1,52 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMStackInjection
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactComponentEnvironment = require('ReactComponentEnvironment');
13 -var ReactComponentBrowserEnvironment = require('ReactComponentBrowserEnvironment');
14 -var ReactDOMComponent = require('ReactDOMComponent');
15 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
16 -var ReactDOMEmptyComponent = require('ReactDOMEmptyComponent');
17 -var ReactDOMTextComponent = require('ReactDOMTextComponent');
18 -var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
19 -var ReactEmptyComponent = require('ReactEmptyComponent');
20 -var ReactGenericBatching = require('ReactGenericBatching');
21 -var ReactHostComponent = require('ReactHostComponent');
22 -var ReactReconcileTransaction = require('ReactReconcileTransaction');
23 -var ReactUpdates = require('ReactUpdates');
24 -
25 -var findDOMNode = require('findDOMNode');
26 -var getHostComponentFromComposite = require('getHostComponentFromComposite');
27 -
28 -ReactGenericBatching.injection.injectStackBatchedUpdates(
29 - ReactUpdates.batchedUpdates,
30 -);
31 -
32 -ReactHostComponent.injection.injectGenericComponentClass(ReactDOMComponent);
33 -
34 -ReactHostComponent.injection.injectTextComponentClass(ReactDOMTextComponent);
35 -
36 -ReactEmptyComponent.injection.injectEmptyComponentFactory(function(
37 - instantiate,
38 -) {
39 - return new ReactDOMEmptyComponent(instantiate);
40 -});
41 -
42 -ReactUpdates.injection.injectReconcileTransaction(ReactReconcileTransaction);
43 -ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);
44 -
45 -ReactComponentEnvironment.injection.injectEnvironment(
46 - ReactComponentBrowserEnvironment,
47 -);
48 -
49 -findDOMNode._injectStack(function(inst) {
50 - inst = getHostComponentFromComposite(inst);
51 - return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;
52 -});
src/renderers/dom/stack/client/ReactDOMTextComponent.js deleted
-185
@@ -1,185 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMTextComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMChildrenOperations = require('DOMChildrenOperations');
13 -var DOMLazyTree = require('DOMLazyTree');
14 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
15 -var {COMMENT_NODE} = require('HTMLNodeType');
16 -
17 -var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
18 -var invariant = require('fbjs/lib/invariant');
19 -var validateDOMNesting = require('validateDOMNesting');
20 -
21 -/**
22 - * Text nodes violate a couple assumptions that React makes about components:
23 - *
24 - * - When mounting text into the DOM, adjacent text nodes are merged.
25 - * - Text nodes cannot be assigned a React root ID.
26 - *
27 - * This component is used to wrap strings between comment nodes so that they
28 - * can undergo the same reconciliation that is applied to elements.
29 - *
30 - * TODO: Investigate representing React components in the DOM with text nodes.
31 - *
32 - * @class ReactDOMTextComponent
33 - * @extends ReactComponent
34 - * @internal
35 - */
36 -var ReactDOMTextComponent = function(text) {
37 - // TODO: This is really a ReactText (ReactNode), not a ReactElement
38 - this._currentElement = text;
39 - this._stringText = '' + text;
40 - // ReactDOMComponentTree uses these:
41 - this._hostNode = null;
42 - this._hostParent = null;
43 -
44 - // Properties
45 - this._domID = 0;
46 - this._mountIndex = 0;
47 - this._closingComment = null;
48 - this._commentNodes = null;
49 -};
50 -
51 -Object.assign(ReactDOMTextComponent.prototype, {
52 - /**
53 - * Creates the markup for this text node. This node is not intended to have
54 - * any features besides containing text content.
55 - *
56 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
57 - * @return {string} Markup for this text node.
58 - * @internal
59 - */
60 - mountComponent: function(
61 - transaction,
62 - hostParent,
63 - hostContainerInfo,
64 - context,
65 - ) {
66 - if (__DEV__) {
67 - var parentInfo;
68 - if (hostParent != null) {
69 - parentInfo = hostParent._ancestorInfo;
70 - } else if (hostContainerInfo != null) {
71 - parentInfo = hostContainerInfo._ancestorInfo;
72 - }
73 - if (parentInfo) {
74 - // parentInfo should always be present except for the top-level
75 - // component when server rendering
76 - validateDOMNesting(null, this._stringText, this, parentInfo);
77 - }
78 - }
79 -
80 - var domID = hostContainerInfo._idCounter++;
81 - var openingValue = ' react-text: ' + domID + ' ';
82 - var closingValue = ' /react-text ';
83 - this._domID = domID;
84 - this._hostParent = hostParent;
85 - if (transaction.useCreateElement) {
86 - var ownerDocument = hostContainerInfo._ownerDocument;
87 - var openingComment = ownerDocument.createComment(openingValue);
88 - var closingComment = ownerDocument.createComment(closingValue);
89 - var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());
90 - DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));
91 - if (this._stringText) {
92 - DOMLazyTree.queueChild(
93 - lazyTree,
94 - DOMLazyTree(ownerDocument.createTextNode(this._stringText)),
95 - );
96 - }
97 - DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));
98 - ReactDOMComponentTree.precacheNode(this, openingComment);
99 - this._closingComment = closingComment;
100 - return lazyTree;
101 - } else {
102 - var escapedText = escapeTextContentForBrowser(this._stringText);
103 -
104 - if (transaction.renderToStaticMarkup) {
105 - // Normally we'd wrap this between comment nodes for the reasons stated
106 - // above, but since this is a situation where React won't take over
107 - // (static pages), we can simply return the text as it is.
108 - return escapedText;
109 - }
110 -
111 - return (
112 - '<!--' +
113 - openingValue +
114 - '-->' +
115 - escapedText +
116 - '<!--' +
117 - closingValue +
118 - '-->'
119 - );
120 - }
121 - },
122 -
123 - /**
124 - * Updates this component by updating the text content.
125 - *
126 - * @param {ReactText} nextText The next text content
127 - * @param {ReactReconcileTransaction} transaction
128 - * @internal
129 - */
130 - receiveComponent: function(nextText, transaction) {
131 - if (nextText !== this._currentElement) {
132 - this._currentElement = nextText;
133 - var nextStringText = '' + nextText;
134 - if (nextStringText !== this._stringText) {
135 - // TODO: Save this as pending props and use performUpdateIfNecessary
136 - // and/or updateComponent to do the actual update for consistency with
137 - // other component types?
138 - this._stringText = nextStringText;
139 - var commentNodes = this.getHostNode();
140 - DOMChildrenOperations.replaceDelimitedText(
141 - commentNodes[0],
142 - commentNodes[1],
143 - nextStringText,
144 - );
145 - }
146 - }
147 - },
148 -
149 - getHostNode: function() {
150 - var hostNode = this._commentNodes;
151 - if (hostNode) {
152 - return hostNode;
153 - }
154 - if (!this._closingComment) {
155 - var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);
156 - var node = openingComment.nextSibling;
157 - while (true) {
158 - invariant(
159 - node != null,
160 - 'Missing closing comment for text component %s',
161 - this._domID,
162 - );
163 - if (
164 - node.nodeType === COMMENT_NODE &&
165 - node.nodeValue === ' /react-text '
166 - ) {
167 - this._closingComment = node;
168 - break;
169 - }
170 - node = node.nextSibling;
171 - }
172 - }
173 - hostNode = [this._hostNode, this._closingComment];
174 - this._commentNodes = hostNode;
175 - return hostNode;
176 - },
177 -
178 - unmountComponent: function() {
179 - this._closingComment = null;
180 - this._commentNodes = null;
181 - ReactDOMComponentTree.uncacheNode(this);
182 - },
183 -});
184 -
185 -module.exports = ReactDOMTextComponent;
src/renderers/dom/stack/client/ReactMount.js deleted
-778
@@ -1,778 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactMount
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMLazyTree = require('DOMLazyTree');
13 -var DOMProperty = require('DOMProperty');
14 -var React = require('react');
15 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
16 -var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
17 -var ReactInstanceMap = require('ReactInstanceMap');
18 -var ReactInstrumentation = require('ReactInstrumentation');
19 -var ReactMarkupChecksum = require('ReactMarkupChecksum');
20 -var ReactReconciler = require('ReactReconciler');
21 -var ReactUpdateQueue = require('ReactUpdateQueue');
22 -var ReactUpdates = require('ReactUpdates');
23 -var {ReactCurrentOwner} = require('ReactGlobalSharedState');
24 -
25 -var getContextForSubtree = require('getContextForSubtree');
26 -var instantiateReactComponent = require('instantiateReactComponent');
27 -var invariant = require('fbjs/lib/invariant');
28 -var setInnerHTML = require('setInnerHTML');
29 -var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
30 -var warning = require('fbjs/lib/warning');
31 -var validateCallback = require('validateCallback');
32 -var {
33 - DOCUMENT_NODE,
34 - ELEMENT_NODE,
35 - DOCUMENT_FRAGMENT_NODE,
36 -} = require('HTMLNodeType');
37 -
38 -var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
39 -var ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;
40 -
41 -var instancesByReactRootID = {};
42 -
43 -/**
44 - * Finds the index of the first character
45 - * that's not common between the two given strings.
46 - *
47 - * @return {number} the index of the character where the strings diverge
48 - */
49 -function firstDifferenceIndex(string1, string2) {
50 - var minLen = Math.min(string1.length, string2.length);
51 - for (var i = 0; i < minLen; i++) {
52 - if (string1.charAt(i) !== string2.charAt(i)) {
53 - return i;
54 - }
55 - }
56 - return string1.length === string2.length ? -1 : minLen;
57 -}
58 -
59 -/**
60 - * @param {DOMElement|DOMDocument} container DOM element that may contain
61 - * a React component
62 - * @return {?*} DOM element that may have the reactRoot ID, or null.
63 - */
64 -function getReactRootElementInContainer(container) {
65 - if (!container) {
66 - return null;
67 - }
68 -
69 - if (container.nodeType === DOCUMENT_NODE) {
70 - return container.documentElement;
71 - } else {
72 - return container.firstChild;
73 - }
74 -}
75 -
76 -function internalGetID(node) {
77 - // If node is something like a window, document, or text node, none of
78 - // which support attributes or a .getAttribute method, gracefully return
79 - // the empty string, as if the attribute were missing.
80 - return (node.getAttribute && node.getAttribute(ATTR_NAME)) || '';
81 -}
82 -
83 -/**
84 - * Mounts this component and inserts it into the DOM.
85 - *
86 - * @param {ReactComponent} wrapperInstance The instance to mount.
87 - * @param {DOMElement} container DOM element to mount into.
88 - * @param {ReactReconcileTransaction} transaction
89 - * @param {boolean} shouldReuseMarkup If true, do not insert markup
90 - */
91 -function mountComponentIntoNode(
92 - wrapperInstance,
93 - container,
94 - transaction,
95 - shouldReuseMarkup,
96 - context,
97 -) {
98 - var markup = ReactReconciler.mountComponent(
99 - wrapperInstance,
100 - transaction,
101 - null,
102 - ReactDOMContainerInfo(wrapperInstance, container),
103 - context,
104 - 0 /* parentDebugID */,
105 - );
106 -
107 - wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
108 - ReactMount._mountImageIntoNode(
109 - markup,
110 - container,
111 - wrapperInstance,
112 - shouldReuseMarkup,
113 - transaction,
114 - );
115 -}
116 -
117 -/**
118 - * Batched mount.
119 - *
120 - * @param {ReactComponent} componentInstance The instance to mount.
121 - * @param {DOMElement} container DOM element to mount into.
122 - * @param {boolean} shouldReuseMarkup If true, do not insert markup
123 - */
124 -function batchedMountComponentIntoNode(
125 - componentInstance,
126 - container,
127 - shouldReuseMarkup,
128 - context,
129 -) {
130 - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
131 - /* useCreateElement */
132 - !shouldReuseMarkup,
133 - );
134 - transaction.perform(
135 - mountComponentIntoNode,
136 - null,
137 - componentInstance,
138 - container,
139 - transaction,
140 - shouldReuseMarkup,
141 - context,
142 - );
143 - ReactUpdates.ReactReconcileTransaction.release(transaction);
144 -}
145 -
146 -/**
147 - * Unmounts a component and removes it from the DOM.
148 - *
149 - * @param {ReactComponent} instance React component instance.
150 - * @param {DOMElement} container DOM element to unmount from.
151 - * @final
152 - * @internal
153 - * @see {ReactMount.unmountComponentAtNode}
154 - */
155 -function unmountComponentFromNode(instance, container) {
156 - if (__DEV__) {
157 - ReactInstrumentation.debugTool.onBeginFlush();
158 - }
159 - ReactReconciler.unmountComponent(
160 - instance,
161 - false /* safely */,
162 - false /* skipLifecycle */,
163 - );
164 - if (__DEV__) {
165 - ReactInstrumentation.debugTool.onEndFlush();
166 - }
167 -
168 - if (container.nodeType === DOCUMENT_NODE) {
169 - container = container.documentElement;
170 - }
171 -
172 - // http://jsperf.com/emptying-a-node
173 - while (container.lastChild) {
174 - container.removeChild(container.lastChild);
175 - }
176 -}
177 -
178 -/**
179 - * True if the supplied DOM node has a direct React-rendered child that is
180 - * not a React root element. Useful for warning in `render`,
181 - * `unmountComponentAtNode`, etc.
182 - *
183 - * @param {?DOMElement} node The candidate DOM node.
184 - * @return {boolean} True if the DOM element contains a direct child that was
185 - * rendered by React but is not a root element.
186 - * @internal
187 - */
188 -function hasNonRootReactChild(container) {
189 - var rootEl = getReactRootElementInContainer(container);
190 - if (rootEl) {
191 - var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);
192 - return !!(inst && inst._hostParent);
193 - }
194 -}
195 -
196 -/**
197 - * True if the supplied DOM node is a React DOM element and
198 - * it has been rendered by another copy of React.
199 - *
200 - * @param {?DOMElement} node The candidate DOM node.
201 - * @return {boolean} True if the DOM has been rendered by another copy of React
202 - * @internal
203 - */
204 -function nodeIsRenderedByOtherInstance(container) {
205 - var rootEl = getReactRootElementInContainer(container);
206 - return !!(rootEl &&
207 - isReactNode(rootEl) &&
208 - !ReactDOMComponentTree.getInstanceFromNode(rootEl));
209 -}
210 -
211 -/**
212 - * True if the supplied DOM node is a valid node element.
213 - *
214 - * @param {?DOMElement} node The candidate DOM node.
215 - * @return {boolean} True if the DOM is a valid DOM node.
216 - * @internal
217 - */
218 -function isValidContainer(node) {
219 - return !!(node &&
220 - (node.nodeType === ELEMENT_NODE ||
221 - node.nodeType === DOCUMENT_NODE ||
222 - node.nodeType === DOCUMENT_FRAGMENT_NODE));
223 -}
224 -
225 -/**
226 - * True if the supplied DOM node is a valid React node element.
227 - *
228 - * @param {?DOMElement} node The candidate DOM node.
229 - * @return {boolean} True if the DOM is a valid React DOM node.
230 - * @internal
231 - */
232 -function isReactNode(node) {
233 - return (
234 - isValidContainer(node) &&
235 - (node.hasAttribute(ROOT_ATTR_NAME) || node.hasAttribute(ATTR_NAME))
236 - );
237 -}
238 -
239 -function getHostRootInstanceInContainer(container) {
240 - var rootEl = getReactRootElementInContainer(container);
241 - var prevHostInstance =
242 - rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);
243 - return prevHostInstance && !prevHostInstance._hostParent
244 - ? prevHostInstance
245 - : null;
246 -}
247 -
248 -function getTopLevelWrapperInContainer(container) {
249 - var root = getHostRootInstanceInContainer(container);
250 - return root ? root._hostContainerInfo._topLevelWrapper : null;
251 -}
252 -
253 -/**
254 - * Temporary (?) hack so that we can store all top-level pending updates on
255 - * composites instead of having to worry about different types of components
256 - * here.
257 - */
258 -var topLevelRootCounter = 1;
259 -var TopLevelWrapper = function() {
260 - this.rootID = topLevelRootCounter++;
261 -};
262 -TopLevelWrapper.prototype.isReactComponent = {};
263 -if (__DEV__) {
264 - TopLevelWrapper.displayName = 'TopLevelWrapper';
265 -}
266 -TopLevelWrapper.prototype.render = function() {
267 - return this.props.child;
268 -};
269 -TopLevelWrapper.isReactTopLevelWrapper = true;
270 -
271 -/**
272 - * Mounting is the process of initializing a React component by creating its
273 - * representative DOM elements and inserting them into a supplied `container`.
274 - * Any prior content inside `container` is destroyed in the process.
275 - *
276 - * ReactMount.render(
277 - * component,
278 - * document.getElementById('container')
279 - * );
280 - *
281 - * <div id="container"> <-- Supplied `container`.
282 - * <div data-reactid=".3"> <-- Rendered reactRoot of React
283 - * // ... component.
284 - * </div>
285 - * </div>
286 - *
287 - * Inside of `container`, the first element rendered is the "reactRoot".
288 - */
289 -var ReactMount = {
290 - TopLevelWrapper: TopLevelWrapper,
291 -
292 - /**
293 - * Used by devtools. The keys are not important.
294 - */
295 - _instancesByReactRootID: instancesByReactRootID,
296 -
297 - /**
298 - * This is a hook provided to support rendering React components while
299 - * ensuring that the apparent scroll position of its `container` does not
300 - * change.
301 - *
302 - * @param {DOMElement} container The `container` being rendered into.
303 - * @param {function} renderCallback This must be called once to do the render.
304 - */
305 - scrollMonitor: function(container, renderCallback) {
306 - renderCallback();
307 - },
308 -
309 - /**
310 - * Take a component that's already mounted into the DOM and replace its props
311 - * @param {ReactComponent} prevComponent component instance already in the DOM
312 - * @param {ReactElement} nextElement component instance to render
313 - * @param {DOMElement} container container to render into
314 - * @param {?function} callback function triggered on completion
315 - */
316 - _updateRootComponent: function(
317 - prevComponent,
318 - nextElement,
319 - nextContext,
320 - container,
321 - callback,
322 - ) {
323 - ReactMount.scrollMonitor(container, function() {
324 - ReactUpdateQueue.enqueueElementInternal(
325 - prevComponent,
326 - nextElement,
327 - nextContext,
328 - );
329 - if (callback) {
330 - ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
331 - }
332 - });
333 -
334 - return prevComponent;
335 - },
336 -
337 - /**
338 - * Render a new component into the DOM. Hooked by hooks!
339 - *
340 - * @param {ReactElement} nextElement element to render
341 - * @param {DOMElement} container container to render into
342 - * @param {boolean} shouldReuseMarkup if we should skip the markup insertion
343 - * @return {ReactComponent} nextComponent
344 - */
345 - _renderNewRootComponent: function(
346 - nextElement,
347 - container,
348 - shouldReuseMarkup,
349 - context,
350 - callback,
351 - ) {
352 - // Various parts of our code (such as ReactCompositeComponent's
353 - // _renderValidatedComponent) assume that calls to render aren't nested;
354 - // verify that that's the case.
355 - warning(
356 - ReactCurrentOwner.current == null,
357 - '_renderNewRootComponent(): Render methods should be a pure function ' +
358 - 'of props and state; triggering nested component updates from ' +
359 - 'render is not allowed. If necessary, trigger nested updates in ' +
360 - 'componentDidUpdate.\n\nCheck the render method of %s.',
361 - (ReactCurrentOwner.current && ReactCurrentOwner.current.getName()) ||
362 - 'ReactCompositeComponent',
363 - );
364 -
365 - invariant(
366 - isValidContainer(container),
367 - '_registerComponent(...): Target container is not a DOM element.',
368 - );
369 -
370 - var componentInstance = instantiateReactComponent(nextElement, false);
371 -
372 - if (callback) {
373 - componentInstance._pendingCallbacks = [
374 - function() {
375 - validateCallback(callback);
376 - callback.call(
377 - componentInstance._renderedComponent.getPublicInstance(),
378 - );
379 - },
380 - ];
381 - }
382 -
383 - // The initial render is synchronous but any updates that happen during
384 - // rendering, in componentWillMount or componentDidMount, will be batched
385 - // according to the current batching strategy.
386 -
387 - ReactUpdates.batchedUpdates(
388 - batchedMountComponentIntoNode,
389 - componentInstance,
390 - container,
391 - shouldReuseMarkup,
392 - context,
393 - );
394 -
395 - var wrapperID = componentInstance._instance.rootID;
396 - instancesByReactRootID[wrapperID] = componentInstance;
397 -
398 - return componentInstance;
399 - },
400 -
401 - /**
402 - * Renders a React component into the DOM in the supplied `container`.
403 - *
404 - * If the React component was previously rendered into `container`, this will
405 - * perform an update on it and only mutate the DOM as necessary to reflect the
406 - * latest React component.
407 - *
408 - * @param {ReactComponent} parentComponent The conceptual parent of this render tree.
409 - * @param {ReactElement} nextElement Component element to render.
410 - * @param {DOMElement} container DOM element to render into.
411 - * @param {?function} callback function triggered on completion
412 - * @return {ReactComponent} Component instance rendered in `container`.
413 - */
414 - renderSubtreeIntoContainer: function(
415 - parentComponent,
416 - nextElement,
417 - container,
418 - callback,
419 - ) {
420 - invariant(
421 - parentComponent != null && ReactInstanceMap.has(parentComponent),
422 - 'parentComponent must be a valid React Component',
423 - );
424 - return ReactMount._renderSubtreeIntoContainer(
425 - parentComponent,
426 - nextElement,
427 - container,
428 - callback,
429 - );
430 - },
431 -
432 - _renderSubtreeIntoContainer: function(
433 - parentComponent,
434 - nextElement,
435 - container,
436 - callback,
437 - ) {
438 - callback = callback === undefined ? null : callback;
439 - if (__DEV__) {
440 - warning(
441 - callback === null || typeof callback === 'function',
442 - 'render(...): Expected the last optional `callback` argument to be a ' +
443 - 'function. Instead received: %s.',
444 - '' + callback,
445 - );
446 - }
447 - if (!React.isValidElement(nextElement)) {
448 - if (typeof nextElement === 'string') {
449 - invariant(
450 - false,
451 - 'ReactDOM.render(): Invalid component element. Instead of ' +
452 - "passing a string like 'div', pass " +
453 - "React.createElement('div') or <div />.",
454 - );
455 - } else if (typeof nextElement === 'function') {
456 - invariant(
457 - false,
458 - 'ReactDOM.render(): Invalid component element. Instead of ' +
459 - 'passing a class like Foo, pass React.createElement(Foo) ' +
460 - 'or <Foo />.',
461 - );
462 - } else if (
463 - nextElement != null &&
464 - typeof nextElement.props !== 'undefined'
465 - ) {
466 - // Check if it quacks like an element
467 - invariant(
468 - false,
469 - 'ReactDOM.render(): Invalid component element. This may be ' +
470 - 'caused by unintentionally loading two independent copies ' +
471 - 'of React.',
472 - );
473 - } else {
474 - invariant(false, 'ReactDOM.render(): Invalid component element.');
475 - }
476 - }
477 -
478 - warning(
479 - !container ||
480 - !container.tagName ||
481 - container.tagName.toUpperCase() !== 'BODY',
482 - 'render(): Rendering components directly into document.body is ' +
483 - 'discouraged, since its children are often manipulated by third-party ' +
484 - 'scripts and browser extensions. This may lead to subtle ' +
485 - 'reconciliation issues. Try rendering into a container element created ' +
486 - 'for your app.',
487 - );
488 -
489 - var nextWrappedElement = React.createElement(TopLevelWrapper, {
490 - child: nextElement,
491 - });
492 -
493 - var nextContext = getContextForSubtree(parentComponent);
494 - var prevComponent = getTopLevelWrapperInContainer(container);
495 -
496 - if (prevComponent) {
497 - var prevWrappedElement = prevComponent._currentElement;
498 - var prevElement = prevWrappedElement.props.child;
499 - if (shouldUpdateReactComponent(prevElement, nextElement)) {
500 - var publicInst = prevComponent._renderedComponent.getPublicInstance();
501 - var updatedCallback =
502 - callback &&
503 - function() {
504 - validateCallback(callback);
505 - callback.call(publicInst);
506 - };
507 - ReactMount._updateRootComponent(
508 - prevComponent,
509 - nextWrappedElement,
510 - nextContext,
511 - container,
512 - updatedCallback,
513 - );
514 - return publicInst;
515 - } else {
516 - ReactMount.unmountComponentAtNode(container);
517 - }
518 - }
519 -
520 - var reactRootElement = getReactRootElementInContainer(container);
521 - var containerHasReactMarkup =
522 - reactRootElement && !!internalGetID(reactRootElement);
523 - var containerHasNonRootReactChild = hasNonRootReactChild(container);
524 -
525 - if (__DEV__) {
526 - warning(
527 - !containerHasNonRootReactChild,
528 - 'render(...): Replacing React-rendered children with a new root ' +
529 - 'component. If you intended to update the children of this node, ' +
530 - 'you should instead have the existing children update their state ' +
531 - 'and render the new components instead of calling ReactDOM.render.',
532 - );
533 -
534 - if (!containerHasReactMarkup || reactRootElement.nextSibling) {
535 - var rootElementSibling = reactRootElement;
536 - while (rootElementSibling) {
537 - if (internalGetID(rootElementSibling)) {
538 - warning(
539 - false,
540 - 'render(): Target node has markup rendered by React, but there ' +
541 - 'are unrelated nodes as well. This is most commonly caused by ' +
542 - 'white-space inserted around server-rendered markup.',
543 - );
544 - break;
545 - }
546 - rootElementSibling = rootElementSibling.nextSibling;
547 - }
548 - }
549 - }
550 -
551 - var shouldReuseMarkup =
552 - containerHasReactMarkup &&
553 - !prevComponent &&
554 - !containerHasNonRootReactChild;
555 - var component = ReactMount._renderNewRootComponent(
556 - nextWrappedElement,
557 - container,
558 - shouldReuseMarkup,
559 - nextContext,
560 - callback,
561 - )._renderedComponent.getPublicInstance();
562 - return component;
563 - },
564 -
565 - /**
566 - * Renders a React component into the DOM in the supplied `container`.
567 - * See https://facebook.github.io/react/docs/react-dom.html#render
568 - *
569 - * If the React component was previously rendered into `container`, this will
570 - * perform an update on it and only mutate the DOM as necessary to reflect the
571 - * latest React component.
572 - *
573 - * @param {ReactElement} nextElement Component element to render.
574 - * @param {DOMElement} container DOM element to render into.
575 - * @param {?function} callback function triggered on completion
576 - * @return {ReactComponent} Component instance rendered in `container`.
577 - */
578 - render: function(nextElement, container, callback) {
579 - return ReactMount._renderSubtreeIntoContainer(
580 - null,
581 - nextElement,
582 - container,
583 - callback,
584 - );
585 - },
586 -
587 - /**
588 - * Unmounts and destroys the React component rendered in the `container`.
589 - * See https://facebook.github.io/react/docs/react-dom.html#unmountcomponentatnode
590 - *
591 - * @param {DOMElement} container DOM element containing a React component.
592 - * @return {boolean} True if a component was found in and unmounted from
593 - * `container`
594 - */
595 - unmountComponentAtNode: function(container) {
596 - // Various parts of our code (such as ReactCompositeComponent's
597 - // _renderValidatedComponent) assume that calls to render aren't nested;
598 - // verify that that's the case. (Strictly speaking, unmounting won't cause a
599 - // render but we still don't expect to be in a render call here.)
600 - warning(
601 - ReactCurrentOwner.current == null,
602 - 'unmountComponentAtNode(): Render methods should be a pure function ' +
603 - 'of props and state; triggering nested component updates from render ' +
604 - 'is not allowed. If necessary, trigger nested updates in ' +
605 - 'componentDidUpdate.\n\nCheck the render method of %s.',
606 - (ReactCurrentOwner.current && ReactCurrentOwner.current.getName()) ||
607 - 'ReactCompositeComponent',
608 - );
609 -
610 - invariant(
611 - isValidContainer(container),
612 - 'unmountComponentAtNode(...): Target container is not a DOM element.',
613 - );
614 -
615 - if (__DEV__) {
616 - warning(
617 - !nodeIsRenderedByOtherInstance(container),
618 - "unmountComponentAtNode(): The node you're attempting to unmount " +
619 - 'was rendered by another copy of React.',
620 - );
621 - }
622 -
623 - var prevComponent = getTopLevelWrapperInContainer(container);
624 - if (!prevComponent) {
625 - // Check if the node being unmounted was rendered by React, but isn't a
626 - // root node.
627 - var containerHasNonRootReactChild = hasNonRootReactChild(container);
628 -
629 - // Check if the container itself is a React root node.
630 - var isContainerReactRoot =
631 - container.nodeType === ELEMENT_NODE &&
632 - container.hasAttribute(ROOT_ATTR_NAME);
633 -
634 - if (__DEV__) {
635 - warning(
636 - !containerHasNonRootReactChild,
637 - "unmountComponentAtNode(): The node you're attempting to unmount " +
638 - 'was rendered by React and is not a top-level container. %s',
639 - isContainerReactRoot
640 - ? 'You may have accidentally passed in a React root node instead ' +
641 - 'of its container.'
642 - : 'Instead, have the parent component update its state and ' +
643 - 'rerender in order to remove this component.',
644 - );
645 - }
646 -
647 - return false;
648 - }
649 - delete instancesByReactRootID[prevComponent._instance.rootID];
650 - ReactUpdates.batchedUpdates(
651 - unmountComponentFromNode,
652 - prevComponent,
653 - container,
654 - );
655 - return true;
656 - },
657 -
658 - _mountImageIntoNode: function(
659 - markup,
660 - container,
661 - instance,
662 - shouldReuseMarkup,
663 - transaction,
664 - ) {
665 - invariant(
666 - isValidContainer(container),
667 - 'mountComponentIntoNode(...): Target container is not valid.',
668 - );
669 -
670 - if (shouldReuseMarkup) {
671 - var rootElement = getReactRootElementInContainer(container);
672 - if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {
673 - ReactDOMComponentTree.precacheNode(instance, rootElement);
674 - return;
675 - } else {
676 - var checksum = rootElement.getAttribute(
677 - ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
678 - );
679 - rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
680 -
681 - var rootMarkup = rootElement.outerHTML;
682 - rootElement.setAttribute(
683 - ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
684 - checksum,
685 - );
686 -
687 - var normalizedMarkup = markup;
688 - if (__DEV__) {
689 - // because rootMarkup is retrieved from the DOM, various normalizations
690 - // will have occurred which will not be present in `markup`. Here,
691 - // insert markup into a <div> or <iframe> depending on the container
692 - // type to perform the same normalizations before comparing.
693 - var normalizer;
694 - if (container.nodeType === ELEMENT_NODE) {
695 - normalizer = document.createElement('div');
696 - normalizer.innerHTML = markup;
697 - normalizedMarkup = normalizer.innerHTML;
698 - } else {
699 - normalizer = document.createElement('iframe');
700 - document.body.appendChild(normalizer);
701 - normalizer.contentDocument.write(markup);
702 - normalizedMarkup =
703 - normalizer.contentDocument.documentElement.outerHTML;
704 - document.body.removeChild(normalizer);
705 - }
706 - }
707 -
708 - var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);
709 - var difference =
710 - ' (client) ' +
711 - normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) +
712 - '\n (server) ' +
713 - rootMarkup.substring(diffIndex - 20, diffIndex + 20);
714 -
715 - invariant(
716 - container.nodeType !== DOCUMENT_NODE,
717 - "You're trying to render a component to the document using " +
718 - 'server rendering but the checksum was invalid. This usually ' +
719 - 'means you rendered a different component type or props on ' +
720 - 'the client from the one on the server, or your render() ' +
721 - 'methods are impure. React cannot handle this case due to ' +
722 - 'cross-browser quirks by rendering at the document root. You ' +
723 - 'should look for environment dependent code in your components ' +
724 - 'and ensure the props are the same client and server side:\n%s',
725 - difference,
726 - );
727 -
728 - if (__DEV__) {
729 - warning(
730 - false,
731 - 'React attempted to reuse markup in a container but the ' +
732 - 'checksum was invalid. This generally means that you are ' +
733 - 'using server rendering and the markup generated on the ' +
734 - 'server was not what the client was expecting. React injected ' +
735 - 'new markup to compensate which works but you have lost many ' +
736 - 'of the benefits of server rendering. Instead, figure out ' +
737 - 'why the markup being generated is different on the client ' +
738 - 'or server:\n%s',
739 - difference,
740 - );
741 - }
742 - }
743 - }
744 -
745 - invariant(
746 - container.nodeType !== DOCUMENT_NODE,
747 - "You're trying to render a component to the document but " +
748 - "you didn't use server rendering. We can't do this " +
749 - 'without using server rendering due to cross-browser quirks. ' +
750 - 'See ReactDOMServer.renderToString() for server rendering.',
751 - );
752 -
753 - if (transaction.useCreateElement) {
754 - while (container.lastChild) {
755 - container.removeChild(container.lastChild);
756 - }
757 - DOMLazyTree.insertTreeBefore(container, markup, null);
758 - } else {
759 - setInnerHTML(container, markup);
760 - ReactDOMComponentTree.precacheNode(instance, container.firstChild);
761 - }
762 -
763 - if (__DEV__) {
764 - var hostNode = ReactDOMComponentTree.getInstanceFromNode(
765 - container.firstChild,
766 - );
767 - if (hostNode._debugID !== 0) {
768 - ReactInstrumentation.debugTool.onHostOperation({
769 - instanceID: hostNode._debugID,
770 - type: 'mount',
771 - payload: markup.toString(),
772 - });
773 - }
774 - }
775 - },
776 -};
777 -
778 -module.exports = ReactMount;
src/renderers/dom/stack/client/ReactReconcileTransaction.js deleted
-178
@@ -1,178 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactReconcileTransaction
8 - */
9 -
10 -'use strict';
11 -
12 -var CallbackQueue = require('CallbackQueue');
13 -var PooledClass = require('PooledClass');
14 -var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
15 -var ReactInputSelection = require('ReactInputSelection');
16 -var ReactInstrumentation = require('ReactInstrumentation');
17 -var Transaction = require('Transaction');
18 -var ReactUpdateQueue = require('ReactUpdateQueue');
19 -
20 -/**
21 - * Ensures that, when possible, the selection range (currently selected text
22 - * input) is not disturbed by performing the transaction.
23 - */
24 -var SELECTION_RESTORATION = {
25 - /**
26 - * @return {Selection} Selection information.
27 - */
28 - initialize: ReactInputSelection.getSelectionInformation,
29 - /**
30 - * @param {Selection} sel Selection information returned from `initialize`.
31 - */
32 - close: ReactInputSelection.restoreSelection,
33 -};
34 -
35 -/**
36 - * Suppresses events (blur/focus) that could be inadvertently dispatched due to
37 - * high level DOM manipulations (like temporarily removing a text input from the
38 - * DOM).
39 - */
40 -var EVENT_SUPPRESSION = {
41 - /**
42 - * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
43 - * the reconciliation.
44 - */
45 - initialize: function() {
46 - var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
47 - ReactBrowserEventEmitter.setEnabled(false);
48 - return currentlyEnabled;
49 - },
50 -
51 - /**
52 - * @param {boolean} previouslyEnabled Enabled status of
53 - * `ReactBrowserEventEmitter` before the reconciliation occurred. `close`
54 - * restores the previous value.
55 - */
56 - close: function(previouslyEnabled) {
57 - ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
58 - },
59 -};
60 -
61 -/**
62 - * Provides a queue for collecting `componentDidMount` and
63 - * `componentDidUpdate` callbacks during the transaction.
64 - */
65 -var ON_DOM_READY_QUEUEING = {
66 - /**
67 - * Initializes the internal `onDOMReady` queue.
68 - */
69 - initialize: function() {
70 - this.reactMountReady.reset();
71 - },
72 -
73 - /**
74 - * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
75 - */
76 - close: function() {
77 - this.reactMountReady.notifyAll();
78 - },
79 -};
80 -
81 -/**
82 - * Executed within the scope of the `Transaction` instance. Consider these as
83 - * being member methods, but with an implied ordering while being isolated from
84 - * each other.
85 - */
86 -var TRANSACTION_WRAPPERS = [
87 - SELECTION_RESTORATION,
88 - EVENT_SUPPRESSION,
89 - ON_DOM_READY_QUEUEING,
90 -];
91 -
92 -if (__DEV__) {
93 - TRANSACTION_WRAPPERS.push({
94 - initialize: ReactInstrumentation.debugTool.onBeginFlush,
95 - close: ReactInstrumentation.debugTool.onEndFlush,
96 - });
97 -}
98 -
99 -/**
100 - * Currently:
101 - * - The order that these are listed in the transaction is critical:
102 - * - Suppresses events.
103 - * - Restores selection range.
104 - *
105 - * Future:
106 - * - Restore document/overflow scroll positions that were unintentionally
107 - * modified via DOM insertions above the top viewport boundary.
108 - * - Implement/integrate with customized constraint based layout system and keep
109 - * track of which dimensions must be remeasured.
110 - *
111 - * @class ReactReconcileTransaction
112 - */
113 -function ReactReconcileTransaction(useCreateElement) {
114 - this.reinitializeTransaction();
115 - // Only server-side rendering really needs this option (see
116 - // `ReactServerRendering`), but server-side uses
117 - // `ReactServerRenderingTransaction` instead. This option is here so that it's
118 - // accessible and defaults to false when `ReactDOMComponent` and
119 - // `ReactDOMTextComponent` checks it in `mountComponent`.`
120 - this.renderToStaticMarkup = false;
121 - this.reactMountReady = CallbackQueue.getPooled();
122 - this.useCreateElement = useCreateElement;
123 -}
124 -
125 -var Mixin = {
126 - /**
127 - * @see Transaction
128 - * @abstract
129 - * @final
130 - * @return {array<object>} List of operation wrap procedures.
131 - * TODO: convert to array<TransactionWrapper>
132 - */
133 - getTransactionWrappers: function() {
134 - return TRANSACTION_WRAPPERS;
135 - },
136 -
137 - /**
138 - * @return {object} The queue to collect `onDOMReady` callbacks with.
139 - */
140 - getReactMountReady: function() {
141 - return this.reactMountReady;
142 - },
143 -
144 - /**
145 - * @return {object} The queue to collect React async events.
146 - */
147 - getUpdateQueue: function() {
148 - return ReactUpdateQueue;
149 - },
150 -
151 - /**
152 - * Save current transaction state -- if the return value from this method is
153 - * passed to `rollback`, the transaction will be reset to that state.
154 - */
155 - checkpoint: function() {
156 - // reactMountReady is the our only stateful wrapper
157 - return this.reactMountReady.checkpoint();
158 - },
159 -
160 - rollback: function(checkpoint) {
161 - this.reactMountReady.rollback(checkpoint);
162 - },
163 -
164 - /**
165 - * `PooledClass` looks for this, and will invoke this before allowing this
166 - * instance to be reused.
167 - */
168 - destructor: function() {
169 - CallbackQueue.release(this.reactMountReady);
170 - this.reactMountReady = null;
171 - },
172 -};
173 -
174 -Object.assign(ReactReconcileTransaction.prototype, Transaction, Mixin);
175 -
176 -PooledClass.addPoolingTo(ReactReconcileTransaction);
177 -
178 -module.exports = ReactReconcileTransaction;
src/renderers/dom/stack/client/wrappers/ReactDOMInput.js deleted
-337
@@ -1,337 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMInput
8 - */
9 -
10 -'use strict';
11 -
12 -var DOMPropertyOperations = require('DOMPropertyOperations');
13 -var ReactControlledValuePropTypes = require('ReactControlledValuePropTypes');
14 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
15 -
16 -var invariant = require('fbjs/lib/invariant');
17 -var warning = require('fbjs/lib/warning');
18 -
19 -if (__DEV__) {
20 - var {
21 - getStackAddendumByID,
22 - } = require('ReactGlobalSharedState').ReactComponentTreeHook;
23 -}
24 -
25 -var didWarnValueDefaultValue = false;
26 -var didWarnCheckedDefaultChecked = false;
27 -var didWarnControlledToUncontrolled = false;
28 -var didWarnUncontrolledToControlled = false;
29 -
30 -function isControlled(props) {
31 - var usesChecked = props.type === 'checkbox' || props.type === 'radio';
32 - return usesChecked ? props.checked != null : props.value != null;
33 -}
34 -
35 -/**
36 - * Implements an <input> host component that allows setting these optional
37 - * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
38 - *
39 - * If `checked` or `value` are not supplied (or null/undefined), user actions
40 - * that affect the checked state or value will trigger updates to the element.
41 - *
42 - * If they are supplied (and not null/undefined), the rendered element will not
43 - * trigger updates to the element. Instead, the props must change in order for
44 - * the rendered element to be updated.
45 - *
46 - * The rendered element will be initialized as unchecked (or `defaultChecked`)
47 - * with an empty value (or `defaultValue`).
48 - *
49 - * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
50 - */
51 -var ReactDOMInput = {
52 - getHostProps: function(inst, props) {
53 - var value = props.value;
54 - var checked = props.checked;
55 -
56 - var hostProps = Object.assign(
57 - {
58 - // Make sure we set .type before any other properties (setting .value
59 - // before .type means .value is lost in IE11 and below)
60 - type: undefined,
61 - // Make sure we set .step before .value (setting .value before .step
62 - // means .value is rounded on mount, based upon step precision)
63 - step: undefined,
64 - // Make sure we set .min & .max before .value (to ensure proper order
65 - // in corner cases such as min or max deriving from value, e.g. Issue #7170)
66 - min: undefined,
67 - max: undefined,
68 - },
69 - props,
70 - {
71 - defaultChecked: undefined,
72 - defaultValue: undefined,
73 - value: value != null ? value : inst._wrapperState.initialValue,
74 - checked: checked != null ? checked : inst._wrapperState.initialChecked,
75 - },
76 - );
77 -
78 - return hostProps;
79 - },
80 -
81 - mountWrapper: function(inst, props) {
82 - if (__DEV__) {
83 - var owner = inst._currentElement._owner;
84 - ReactControlledValuePropTypes.checkPropTypes('input', props, () =>
85 - getStackAddendumByID(inst._debugID),
86 - );
87 -
88 - if (
89 - props.checked !== undefined &&
90 - props.defaultChecked !== undefined &&
91 - !didWarnCheckedDefaultChecked
92 - ) {
93 - warning(
94 - false,
95 - '%s contains an input of type %s with both checked and defaultChecked props. ' +
96 - 'Input elements must be either controlled or uncontrolled ' +
97 - '(specify either the checked prop, or the defaultChecked prop, but not ' +
98 - 'both). Decide between using a controlled or uncontrolled input ' +
99 - 'element and remove one of these props. More info: ' +
100 - 'https://fb.me/react-controlled-components',
101 - (owner && owner.getName()) || 'A component',
102 - props.type,
103 - );
104 - didWarnCheckedDefaultChecked = true;
105 - }
106 - if (
107 - props.value !== undefined &&
108 - props.defaultValue !== undefined &&
109 - !didWarnValueDefaultValue
110 - ) {
111 - warning(
112 - false,
113 - '%s contains an input of type %s with both value and defaultValue props. ' +
114 - 'Input elements must be either controlled or uncontrolled ' +
115 - '(specify either the value prop, or the defaultValue prop, but not ' +
116 - 'both). Decide between using a controlled or uncontrolled input ' +
117 - 'element and remove one of these props. More info: ' +
118 - 'https://fb.me/react-controlled-components',
119 - (owner && owner.getName()) || 'A component',
120 - props.type,
121 - );
122 - didWarnValueDefaultValue = true;
123 - }
124 - }
125 -
126 - var defaultValue = props.defaultValue;
127 - inst._wrapperState = {
128 - initialChecked: props.checked != null
129 - ? props.checked
130 - : props.defaultChecked,
131 - initialValue: props.value != null ? props.value : defaultValue,
132 - listeners: null,
133 - controlled: isControlled(props),
134 - };
135 - },
136 -
137 - updateWrapper: function(inst) {
138 - var props = inst._currentElement.props;
139 -
140 - if (__DEV__) {
141 - var controlled = isControlled(props);
142 -
143 - if (
144 - !inst._wrapperState.controlled &&
145 - controlled &&
146 - !didWarnUncontrolledToControlled
147 - ) {
148 - warning(
149 - false,
150 - 'A component is changing an uncontrolled input of type %s to be controlled. ' +
151 - 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' +
152 - 'Decide between using a controlled or uncontrolled input ' +
153 - 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s',
154 - props.type,
155 - getStackAddendumByID(inst._debugID),
156 - );
157 - didWarnUncontrolledToControlled = true;
158 - }
159 - if (
160 - inst._wrapperState.controlled &&
161 - !controlled &&
162 - !didWarnControlledToUncontrolled
163 - ) {
164 - warning(
165 - false,
166 - 'A component is changing a controlled input of type %s to be uncontrolled. ' +
167 - 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' +
168 - 'Decide between using a controlled or uncontrolled input ' +
169 - 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s',
170 - props.type,
171 - getStackAddendumByID(inst._debugID),
172 - );
173 - didWarnControlledToUncontrolled = true;
174 - }
175 - }
176 -
177 - var checked = props.checked;
178 - if (checked != null) {
179 - DOMPropertyOperations.setValueForProperty(
180 - ReactDOMComponentTree.getNodeFromInstance(inst),
181 - 'checked',
182 - checked || false,
183 - );
184 - }
185 -
186 - var node = ReactDOMComponentTree.getNodeFromInstance(inst);
187 - var value = props.value;
188 - if (value != null) {
189 - if (value === 0 && node.value === '') {
190 - node.value = '0';
191 - // Note: IE9 reports a number inputs as 'text', so check props instead.
192 - } else if (props.type === 'number') {
193 - // Simulate `input.valueAsNumber`. IE9 does not support it
194 - var valueAsNumber = parseFloat(node.value, 10) || 0;
195 -
196 - if (
197 - // eslint-disable-next-line
198 - value != valueAsNumber ||
199 - // eslint-disable-next-line
200 - (value == valueAsNumber && node.value != value)
201 - ) {
202 - // Cast `value` to a string to ensure the value is set correctly. While
203 - // browsers typically do this as necessary, jsdom doesn't.
204 - node.value = '' + value;
205 - }
206 - } else if (node.value !== '' + value) {
207 - // Cast `value` to a string to ensure the value is set correctly. While
208 - // browsers typically do this as necessary, jsdom doesn't.
209 - node.value = '' + value;
210 - }
211 - } else {
212 - if (props.value == null && props.defaultValue != null) {
213 - // In Chrome, assigning defaultValue to certain input types triggers input validation.
214 - // For number inputs, the display value loses trailing decimal points. For email inputs,
215 - // Chrome raises "The specified value <x> is not a valid email address".
216 - //
217 - // Here we check to see if the defaultValue has actually changed, avoiding these problems
218 - // when the user is inputting text
219 - //
220 - // https://github.com/facebook/react/issues/7253
221 - if (node.defaultValue !== '' + props.defaultValue) {
222 - node.defaultValue = '' + props.defaultValue;
223 - }
224 - }
225 - if (props.checked == null && props.defaultChecked != null) {
226 - node.defaultChecked = !!props.defaultChecked;
227 - }
228 - }
229 - },
230 -
231 - postMountWrapper: function(inst) {
232 - var props = inst._currentElement.props;
233 -
234 - // This is in postMount because we need access to the DOM node, which is not
235 - // available until after the component has mounted.
236 - var node = ReactDOMComponentTree.getNodeFromInstance(inst);
237 -
238 - // Detach value from defaultValue. We won't do anything if we're working on
239 - // submit or reset inputs as those values & defaultValues are linked. They
240 - // are not resetable nodes so this operation doesn't matter and actually
241 - // removes browser-default values (eg "Submit Query") when no value is
242 - // provided.
243 -
244 - switch (props.type) {
245 - case 'submit':
246 - case 'reset':
247 - break;
248 - case 'color':
249 - case 'date':
250 - case 'datetime':
251 - case 'datetime-local':
252 - case 'month':
253 - case 'time':
254 - case 'week':
255 - // This fixes the no-show issue on iOS Safari and Android Chrome:
256 - // https://github.com/facebook/react/issues/7233
257 - node.value = '';
258 - node.value = node.defaultValue;
259 - break;
260 - default:
261 - node.value = node.value;
262 - break;
263 - }
264 -
265 - // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
266 - // this is needed to work around a chrome bug where setting defaultChecked
267 - // will sometimes influence the value of checked (even after detachment).
268 - // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
269 - // We need to temporarily unset name to avoid disrupting radio button groups.
270 - var name = node.name;
271 - if (name !== '') {
272 - node.name = '';
273 - }
274 - node.defaultChecked = !node.defaultChecked;
275 - node.defaultChecked = !node.defaultChecked;
276 - if (name !== '') {
277 - node.name = name;
278 - }
279 - },
280 -
281 - restoreControlledState: function(inst) {
282 - if (inst._rootNodeID) {
283 - // DOM component is still mounted; update
284 - ReactDOMInput.updateWrapper(inst);
285 - }
286 - var props = inst._currentElement.props;
287 - updateNamedCousins(inst, props);
288 - },
289 -};
290 -
291 -function updateNamedCousins(thisInstance, props) {
292 - var name = props.name;
293 - if (props.type === 'radio' && name != null) {
294 - var rootNode = ReactDOMComponentTree.getNodeFromInstance(thisInstance);
295 - var queryRoot = rootNode;
296 -
297 - while (queryRoot.parentNode) {
298 - queryRoot = queryRoot.parentNode;
299 - }
300 -
301 - // If `rootNode.form` was non-null, then we could try `form.elements`,
302 - // but that sometimes behaves strangely in IE8. We could also try using
303 - // `form.getElementsByName`, but that will only return direct children
304 - // and won't include inputs that use the HTML5 `form=` attribute. Since
305 - // the input might not even be in a form. It might not even be in the
306 - // document. Let's just use the local `querySelectorAll` to ensure we don't
307 - // miss anything.
308 - var group = queryRoot.querySelectorAll(
309 - 'input[name=' + JSON.stringify('' + name) + '][type="radio"]',
310 - );
311 -
312 - for (var i = 0; i < group.length; i++) {
313 - var otherNode = group[i];
314 - if (otherNode === rootNode || otherNode.form !== rootNode.form) {
315 - continue;
316 - }
317 - // This will throw if radio buttons rendered by different copies of React
318 - // and the same name are rendered into the same form (same as #1939).
319 - // That's probably okay; we don't support it just as we don't support
320 - // mixing React radio buttons with non-React ones.
321 - var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
322 - invariant(
323 - otherInstance,
324 - 'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
325 - 'same `name` is not supported.',
326 - );
327 - // If this is a controlled radio button group, forcing the input that
328 - // was previously checked to update will cause it to be come re-checked
329 - // as appropriate.
330 - if (otherInstance._rootNodeID) {
331 - ReactDOMInput.updateWrapper(otherInstance);
332 - }
333 - }
334 - }
335 -}
336 -
337 -module.exports = ReactDOMInput;
src/renderers/dom/stack/client/wrappers/ReactDOMOption.js deleted
-128
@@ -1,128 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMOption
8 - */
9 -
10 -'use strict';
11 -
12 -var React = require('react');
13 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
14 -var ReactDOMSelect = require('ReactDOMSelect');
15 -
16 -var warning = require('fbjs/lib/warning');
17 -var didWarnInvalidOptionChildren = false;
18 -
19 -function flattenChildren(children) {
20 - var content = '';
21 -
22 - // Flatten children and warn if they aren't strings or numbers;
23 - // invalid types are ignored.
24 - React.Children.forEach(children, function(child) {
25 - if (child == null) {
26 - return;
27 - }
28 - if (typeof child === 'string' || typeof child === 'number') {
29 - content += child;
30 - } else if (!didWarnInvalidOptionChildren) {
31 - didWarnInvalidOptionChildren = true;
32 - warning(
33 - false,
34 - 'Only strings and numbers are supported as <option> children.',
35 - );
36 - }
37 - });
38 -
39 - return content;
40 -}
41 -
42 -/**
43 - * Implements an <option> host component that warns when `selected` is set.
44 - */
45 -var ReactDOMOption = {
46 - mountWrapper: function(inst, props, hostParent) {
47 - // TODO (yungsters): Remove support for `selected` in <option>.
48 - if (__DEV__) {
49 - warning(
50 - props.selected == null,
51 - 'Use the `defaultValue` or `value` props on <select> instead of ' +
52 - 'setting `selected` on <option>.',
53 - );
54 - }
55 -
56 - // Look up whether this option is 'selected'
57 - var selectValue = null;
58 - if (hostParent != null) {
59 - var selectParent = hostParent;
60 -
61 - if (selectParent._tag === 'optgroup') {
62 - selectParent = selectParent._hostParent;
63 - }
64 -
65 - if (selectParent != null && selectParent._tag === 'select') {
66 - selectValue = ReactDOMSelect.getSelectValueContext(selectParent);
67 - }
68 - }
69 -
70 - // If the value is null (e.g., no specified value or after initial mount)
71 - // or missing (e.g., for <datalist>), we don't change props.selected
72 - var selected = null;
73 - if (selectValue != null) {
74 - var value;
75 - if (props.value != null) {
76 - value = props.value + '';
77 - } else {
78 - value = flattenChildren(props.children);
79 - }
80 - selected = false;
81 - if (Array.isArray(selectValue)) {
82 - // multiple
83 - for (var i = 0; i < selectValue.length; i++) {
84 - if ('' + selectValue[i] === value) {
85 - selected = true;
86 - break;
87 - }
88 - }
89 - } else {
90 - selected = '' + selectValue === value;
91 - }
92 - }
93 -
94 - inst._wrapperState = {selected: selected};
95 - },
96 -
97 - postMountWrapper: function(inst) {
98 - // value="" should make a value attribute (#6219)
99 - var props = inst._currentElement.props;
100 - if (props.value != null) {
101 - var node = ReactDOMComponentTree.getNodeFromInstance(inst);
102 - node.setAttribute('value', props.value);
103 - }
104 - },
105 -
106 - getHostProps: function(inst, props) {
107 - var hostProps = Object.assign(
108 - {selected: undefined, children: undefined},
109 - props,
110 - );
111 -
112 - // Read state only from initial mount because <select> updates value
113 - // manually; we need the initial state only for server rendering
114 - if (inst._wrapperState.selected != null) {
115 - hostProps.selected = inst._wrapperState.selected;
116 - }
117 -
118 - var content = flattenChildren(props.children);
119 -
120 - if (content) {
121 - hostProps.children = content;
122 - }
123 -
124 - return hostProps;
125 - },
126 -};
127 -
128 -module.exports = ReactDOMOption;
src/renderers/dom/stack/client/wrappers/ReactDOMSelect.js deleted
-203
@@ -1,203 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMSelect
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactControlledValuePropTypes = require('ReactControlledValuePropTypes');
13 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
14 -
15 -var warning = require('fbjs/lib/warning');
16 -
17 -if (__DEV__) {
18 - var {
19 - getStackAddendumByID,
20 - } = require('ReactGlobalSharedState').ReactComponentTreeHook;
21 -}
22 -
23 -var didWarnValueDefaultValue = false;
24 -
25 -function getDeclarationErrorAddendum(owner) {
26 - if (owner) {
27 - var name = owner.getName();
28 - if (name) {
29 - return '\n\nCheck the render method of `' + name + '`.';
30 - }
31 - }
32 - return '';
33 -}
34 -
35 -var valuePropNames = ['value', 'defaultValue'];
36 -
37 -/**
38 - * Validation function for `value` and `defaultValue`.
39 - * @private
40 - */
41 -function checkSelectPropTypes(inst, props) {
42 - var owner = inst._currentElement._owner;
43 - ReactControlledValuePropTypes.checkPropTypes('select', props, () =>
44 - getStackAddendumByID(inst._debugID),
45 - );
46 -
47 - for (var i = 0; i < valuePropNames.length; i++) {
48 - var propName = valuePropNames[i];
49 - if (props[propName] == null) {
50 - continue;
51 - }
52 - var isArray = Array.isArray(props[propName]);
53 - if (props.multiple && !isArray) {
54 - warning(
55 - false,
56 - 'The `%s` prop supplied to <select> must be an array if ' +
57 - '`multiple` is true.%s',
58 - propName,
59 - getDeclarationErrorAddendum(owner),
60 - );
61 - } else if (!props.multiple && isArray) {
62 - warning(
63 - false,
64 - 'The `%s` prop supplied to <select> must be a scalar ' +
65 - 'value if `multiple` is false.%s',
66 - propName,
67 - getDeclarationErrorAddendum(owner),
68 - );
69 - }
70 - }
71 -}
72 -
73 -/**
74 - * @param {ReactDOMComponent} inst
75 - * @param {boolean} multiple
76 - * @param {*} propValue A stringable (with `multiple`, a list of stringables).
77 - * @private
78 - */
79 -function updateOptions(inst, multiple, propValue) {
80 - var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;
81 -
82 - if (multiple) {
83 - let selectedValue = {};
84 - for (let i = 0; i < propValue.length; i++) {
85 - // Prefix to avoid chaos with special keys.
86 - selectedValue['$' + propValue[i]] = true;
87 - }
88 - for (let i = 0; i < options.length; i++) {
89 - var selected = selectedValue.hasOwnProperty('$' + options[i].value);
90 - if (options[i].selected !== selected) {
91 - options[i].selected = selected;
92 - }
93 - }
94 - } else {
95 - // Do not set `select.value` as exact behavior isn't consistent across all
96 - // browsers for all cases.
97 - let selectedValue = '' + propValue;
98 - for (let i = 0; i < options.length; i++) {
99 - if (options[i].value === selectedValue) {
100 - options[i].selected = true;
101 - return;
102 - }
103 - }
104 - if (options.length) {
105 - options[0].selected = true;
106 - }
107 - }
108 -}
109 -
110 -/**
111 - * Implements a <select> host component that allows optionally setting the
112 - * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
113 - * stringable. If `multiple` is true, the prop must be an array of stringables.
114 - *
115 - * If `value` is not supplied (or null/undefined), user actions that change the
116 - * selected option will trigger updates to the rendered options.
117 - *
118 - * If it is supplied (and not null/undefined), the rendered options will not
119 - * update in response to user actions. Instead, the `value` prop must change in
120 - * order for the rendered options to update.
121 - *
122 - * If `defaultValue` is provided, any options with the supplied values will be
123 - * selected.
124 - */
125 -var ReactDOMSelect = {
126 - getHostProps: function(inst, props) {
127 - return Object.assign({}, props, {
128 - value: undefined,
129 - });
130 - },
131 -
132 - mountWrapper: function(inst, props) {
133 - if (__DEV__) {
134 - checkSelectPropTypes(inst, props);
135 - }
136 -
137 - var value = props.value;
138 - inst._wrapperState = {
139 - initialValue: value != null ? value : props.defaultValue,
140 - listeners: null,
141 - wasMultiple: !!props.multiple,
142 - };
143 -
144 - if (
145 - props.value !== undefined &&
146 - props.defaultValue !== undefined &&
147 - !didWarnValueDefaultValue
148 - ) {
149 - warning(
150 - false,
151 - 'Select elements must be either controlled or uncontrolled ' +
152 - '(specify either the value prop, or the defaultValue prop, but not ' +
153 - 'both). Decide between using a controlled or uncontrolled select ' +
154 - 'element and remove one of these props. More info: ' +
155 - 'https://fb.me/react-controlled-components',
156 - );
157 - didWarnValueDefaultValue = true;
158 - }
159 - },
160 -
161 - getSelectValueContext: function(inst) {
162 - // ReactDOMOption looks at this initial value so the initial generated
163 - // markup has correct `selected` attributes
164 - return inst._wrapperState.initialValue;
165 - },
166 -
167 - postUpdateWrapper: function(inst) {
168 - var props = inst._currentElement.props;
169 -
170 - // After the initial mount, we control selected-ness manually so don't pass
171 - // this value down
172 - inst._wrapperState.initialValue = undefined;
173 -
174 - var wasMultiple = inst._wrapperState.wasMultiple;
175 - inst._wrapperState.wasMultiple = !!props.multiple;
176 -
177 - var value = props.value;
178 - if (value != null) {
179 - updateOptions(inst, !!props.multiple, value);
180 - } else if (wasMultiple !== !!props.multiple) {
181 - // For simplicity, reapply `defaultValue` if `multiple` is toggled.
182 - if (props.defaultValue != null) {
183 - updateOptions(inst, !!props.multiple, props.defaultValue);
184 - } else {
185 - // Revert the select back to its default unselected state.
186 - updateOptions(inst, !!props.multiple, props.multiple ? [] : '');
187 - }
188 - }
189 - },
190 -
191 - restoreControlledState: function(inst) {
192 - if (inst._rootNodeID) {
193 - var props = inst._currentElement.props;
194 - var value = props.value;
195 -
196 - if (value != null) {
197 - updateOptions(inst, !!props.multiple, value);
198 - }
199 - }
200 - },
201 -};
202 -
203 -module.exports = ReactDOMSelect;
src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js deleted
-173
@@ -1,173 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDOMTextarea
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactControlledValuePropTypes = require('ReactControlledValuePropTypes');
13 -var ReactDOMComponentTree = require('ReactDOMComponentTree');
14 -
15 -var invariant = require('fbjs/lib/invariant');
16 -var warning = require('fbjs/lib/warning');
17 -
18 -if (__DEV__) {
19 - var {
20 - getStackAddendumByID,
21 - } = require('ReactGlobalSharedState').ReactComponentTreeHook;
22 -}
23 -
24 -var didWarnValDefaultVal = false;
25 -
26 -/**
27 - * Implements a <textarea> host component that allows setting `value`, and
28 - * `defaultValue`. This differs from the traditional DOM API because value is
29 - * usually set as PCDATA children.
30 - *
31 - * If `value` is not supplied (or null/undefined), user actions that affect the
32 - * value will trigger updates to the element.
33 - *
34 - * If `value` is supplied (and not null/undefined), the rendered element will
35 - * not trigger updates to the element. Instead, the `value` prop must change in
36 - * order for the rendered element to be updated.
37 - *
38 - * The rendered element will be initialized with an empty value, the prop
39 - * `defaultValue` if specified, or the children content (deprecated).
40 - */
41 -var ReactDOMTextarea = {
42 - getHostProps: function(inst, props) {
43 - invariant(
44 - props.dangerouslySetInnerHTML == null,
45 - '`dangerouslySetInnerHTML` does not make sense on <textarea>.',
46 - );
47 -
48 - // Always set children to the same thing. In IE9, the selection range will
49 - // get reset if `textContent` is mutated. We could add a check in setTextContent
50 - // to only set the value if/when the value differs from the node value (which would
51 - // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
52 - // solution. The value can be a boolean or object so that's why it's forced
53 - // to be a string.
54 - var hostProps = Object.assign({}, props, {
55 - value: undefined,
56 - defaultValue: undefined,
57 - children: '' + inst._wrapperState.initialValue,
58 - });
59 -
60 - return hostProps;
61 - },
62 -
63 - mountWrapper: function(inst, props) {
64 - if (__DEV__) {
65 - ReactControlledValuePropTypes.checkPropTypes('textarea', props, () =>
66 - getStackAddendumByID(inst._debugID),
67 - );
68 - if (
69 - props.value !== undefined &&
70 - props.defaultValue !== undefined &&
71 - !didWarnValDefaultVal
72 - ) {
73 - warning(
74 - false,
75 - 'Textarea elements must be either controlled or uncontrolled ' +
76 - '(specify either the value prop, or the defaultValue prop, but not ' +
77 - 'both). Decide between using a controlled or uncontrolled textarea ' +
78 - 'and remove one of these props. More info: ' +
79 - 'https://fb.me/react-controlled-components',
80 - );
81 - didWarnValDefaultVal = true;
82 - }
83 - }
84 -
85 - var value = props.value;
86 - var initialValue = value;
87 -
88 - // Only bother fetching default value if we're going to use it
89 - if (value == null) {
90 - var defaultValue = props.defaultValue;
91 - // TODO (yungsters): Remove support for children content in <textarea>.
92 - var children = props.children;
93 - if (children != null) {
94 - if (__DEV__) {
95 - warning(
96 - false,
97 - 'Use the `defaultValue` or `value` props instead of setting ' +
98 - 'children on <textarea>.',
99 - );
100 - }
101 - invariant(
102 - defaultValue == null,
103 - 'If you supply `defaultValue` on a <textarea>, do not pass children.',
104 - );
105 - if (Array.isArray(children)) {
106 - invariant(
107 - children.length <= 1,
108 - '<textarea> can only have at most one child.',
109 - );
110 - children = children[0];
111 - }
112 -
113 - defaultValue = '' + children;
114 - }
115 - if (defaultValue == null) {
116 - defaultValue = '';
117 - }
118 - initialValue = defaultValue;
119 - }
120 -
121 - inst._wrapperState = {
122 - initialValue: '' + initialValue,
123 - listeners: null,
124 - };
125 - },
126 -
127 - updateWrapper: function(inst) {
128 - var props = inst._currentElement.props;
129 -
130 - var node = ReactDOMComponentTree.getNodeFromInstance(inst);
131 - var value = props.value;
132 - if (value != null) {
133 - // Cast `value` to a string to ensure the value is set correctly. While
134 - // browsers typically do this as necessary, jsdom doesn't.
135 - var newValue = '' + value;
136 -
137 - // To avoid side effects (such as losing text selection), only set value if changed
138 - if (newValue !== node.value) {
139 - node.value = newValue;
140 - }
141 - if (props.defaultValue == null) {
142 - node.defaultValue = newValue;
143 - }
144 - }
145 - if (props.defaultValue != null) {
146 - node.defaultValue = props.defaultValue;
147 - }
148 - },
149 -
150 - postMountWrapper: function(inst) {
151 - // This is in postMount because we need access to the DOM node, which is not
152 - // available until after the component has mounted.
153 - var node = ReactDOMComponentTree.getNodeFromInstance(inst);
154 - var textContent = node.textContent;
155 -
156 - // Only set node.value if textContent is equal to the expected
157 - // initial value. In IE10/IE11 there is a bug where the placeholder attribute
158 - // will populate textContent as well.
159 - // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
160 - if (textContent === inst._wrapperState.initialValue) {
161 - node.value = textContent;
162 - }
163 - },
164 -
165 - restoreControlledState: function(inst) {
166 - if (inst._rootNodeID) {
167 - // DOM component is still mounted; update
168 - ReactDOMTextarea.updateWrapper(inst);
169 - }
170 - },
171 -};
172 -
173 -module.exports = ReactDOMTextarea;
src/renderers/dom/stack/server/ReactMarkupChecksum.js deleted
-53
@@ -1,53 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactMarkupChecksum
8 - */
9 -
10 -'use strict';
11 -
12 -var adler32 = require('adler32');
13 -
14 -var TAG_END = /\/?>/;
15 -var COMMENT_START = /^<\!\-\-/;
16 -
17 -var ReactMarkupChecksum = {
18 - CHECKSUM_ATTR_NAME: 'data-react-checksum',
19 -
20 - /**
21 - * @param {string} markup Markup string
22 - * @return {string} Markup string with checksum attribute attached
23 - */
24 - addChecksumToMarkup: function(markup) {
25 - var checksum = adler32(markup);
26 -
27 - // Add checksum (handle both parent tags, comments and self-closing tags)
28 - if (COMMENT_START.test(markup)) {
29 - return markup;
30 - } else {
31 - return markup.replace(
32 - TAG_END,
33 - ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '"$&',
34 - );
35 - }
36 - },
37 -
38 - /**
39 - * @param {string} markup to use
40 - * @param {DOMElement} element root React element
41 - * @returns {boolean} whether or not the markup is the same
42 - */
43 - canReuseMarkup: function(markup, element) {
44 - var existingChecksum = element.getAttribute(
45 - ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
46 - );
47 - existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
48 - var markupChecksum = adler32(markup);
49 - return markupChecksum === existingChecksum;
50 - },
51 -};
52 -
53 -module.exports = ReactMarkupChecksum;
src/renderers/dom/stack/server/ReactServerBatchingStrategy.js deleted
-20
@@ -1,20 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactServerBatchingStrategy
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactServerBatchingStrategy = {
13 - isBatchingUpdates: false,
14 - batchedUpdates: function(callback) {
15 - // Don't do anything here. During the server rendering we don't want to
16 - // schedule any updates. We will simply ignore them.
17 - },
18 -};
19 -
20 -module.exports = ReactServerBatchingStrategy;
src/renderers/dom/stack/server/ReactServerRendering.js deleted
-102
@@ -1,102 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactServerRendering
8 - */
9 -'use strict';
10 -
11 -var React = require('react');
12 -var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
13 -var ReactInstrumentation = require('ReactInstrumentation');
14 -var ReactMarkupChecksum = require('ReactMarkupChecksum');
15 -var ReactReconciler = require('ReactReconciler');
16 -var ReactServerBatchingStrategy = require('ReactServerBatchingStrategy');
17 -var ReactServerRenderingTransaction = require('ReactServerRenderingTransaction');
18 -var ReactUpdates = require('ReactUpdates');
19 -
20 -var emptyObject = require('fbjs/lib/emptyObject');
21 -var instantiateReactComponent = require('instantiateReactComponent');
22 -var invariant = require('fbjs/lib/invariant');
23 -
24 -var pendingTransactions = 0;
25 -
26 -/**
27 - * @param {ReactElement} element
28 - * @param {boolean} makeStaticMarkup
29 - * @return {string} the HTML markup
30 - */
31 -function renderToStringImpl(element, makeStaticMarkup) {
32 - var transaction;
33 - var previousBatchingStrategy;
34 - try {
35 - previousBatchingStrategy = ReactUpdates.injection.getBatchingStrategy();
36 - ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);
37 -
38 - transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);
39 -
40 - pendingTransactions++;
41 -
42 - return transaction.perform(function() {
43 - var componentInstance = instantiateReactComponent(element, true);
44 - var markup = ReactReconciler.mountComponent(
45 - componentInstance,
46 - transaction,
47 - null,
48 - ReactDOMContainerInfo(),
49 - emptyObject,
50 - 0 /* parentDebugID */,
51 - );
52 - if (__DEV__) {
53 - ReactInstrumentation.debugTool.onUnmountComponent(
54 - componentInstance._debugID,
55 - );
56 - }
57 - if (!makeStaticMarkup) {
58 - markup = ReactMarkupChecksum.addChecksumToMarkup(markup);
59 - }
60 - return markup;
61 - }, null);
62 - } finally {
63 - pendingTransactions--;
64 - ReactServerRenderingTransaction.release(transaction);
65 - // Revert to the DOM batching strategy since these two renderers
66 - // currently share these stateful modules.
67 - if (!pendingTransactions) {
68 - ReactUpdates.injection.injectBatchingStrategy(previousBatchingStrategy);
69 - }
70 - }
71 -}
72 -
73 -/**
74 - * Render a ReactElement to its initial HTML. This should only be used on the
75 - * server.
76 - * See https://facebook.github.io/react/docs/react-dom-server.html#rendertostring
77 - */
78 -function renderToString(element) {
79 - invariant(
80 - React.isValidElement(element),
81 - 'renderToString(): Invalid component element.',
82 - );
83 - return renderToStringImpl(element, false);
84 -}
85 -
86 -/**
87 - * Similar to renderToString, except this doesn't create extra DOM attributes
88 - * such as data-react-id that React uses internally.
89 - * See https://facebook.github.io/react/docs/react-dom-server.html#rendertostaticmarkup
90 - */
91 -function renderToStaticMarkup(element) {
92 - invariant(
93 - React.isValidElement(element),
94 - 'renderToStaticMarkup(): Invalid component element.',
95 - );
96 - return renderToStringImpl(element, true);
97 -}
98 -
99 -module.exports = {
100 - renderToString: renderToString,
101 - renderToStaticMarkup: renderToStaticMarkup,
102 -};
src/renderers/dom/stack/server/ReactServerRenderingTransaction.js deleted
-86
@@ -1,86 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactServerRenderingTransaction
8 - */
9 -
10 -'use strict';
11 -
12 -var PooledClass = require('PooledClass');
13 -var Transaction = require('Transaction');
14 -var ReactInstrumentation = require('ReactInstrumentation');
15 -var ReactServerUpdateQueue = require('ReactServerUpdateQueue');
16 -
17 -/**
18 - * Executed within the scope of the `Transaction` instance. Consider these as
19 - * being member methods, but with an implied ordering while being isolated from
20 - * each other.
21 - */
22 -var TRANSACTION_WRAPPERS = [];
23 -
24 -if (__DEV__) {
25 - TRANSACTION_WRAPPERS.push({
26 - initialize: ReactInstrumentation.debugTool.onBeginFlush,
27 - close: ReactInstrumentation.debugTool.onEndFlush,
28 - });
29 -}
30 -
31 -var noopCallbackQueue = {
32 - enqueue: function() {},
33 -};
34 -
35 -/**
36 - * @class ReactServerRenderingTransaction
37 - * @param {boolean} renderToStaticMarkup
38 - */
39 -function ReactServerRenderingTransaction(renderToStaticMarkup) {
40 - this.reinitializeTransaction();
41 - this.renderToStaticMarkup = renderToStaticMarkup;
42 - this.useCreateElement = false;
43 - this.updateQueue = new ReactServerUpdateQueue(this);
44 -}
45 -
46 -var Mixin = {
47 - /**
48 - * @see Transaction
49 - * @abstract
50 - * @final
51 - * @return {array} Empty list of operation wrap procedures.
52 - */
53 - getTransactionWrappers: function() {
54 - return TRANSACTION_WRAPPERS;
55 - },
56 -
57 - /**
58 - * @return {object} The queue to collect `onDOMReady` callbacks with.
59 - */
60 - getReactMountReady: function() {
61 - return noopCallbackQueue;
62 - },
63 -
64 - /**
65 - * @return {object} The queue to collect React async events.
66 - */
67 - getUpdateQueue: function() {
68 - return this.updateQueue;
69 - },
70 -
71 - /**
72 - * `PooledClass` looks for this, and will invoke this before allowing this
73 - * instance to be reused.
74 - */
75 - destructor: function() {},
76 -
77 - checkpoint: function() {},
78 -
79 - rollback: function() {},
80 -};
81 -
82 -Object.assign(ReactServerRenderingTransaction.prototype, Transaction, Mixin);
83 -
84 -PooledClass.addPoolingTo(ReactServerRenderingTransaction);
85 -
86 -module.exports = ReactServerRenderingTransaction;
src/renderers/dom/stack/server/ReactServerUpdateQueue.js deleted
-150
@@ -1,150 +0,0 @@
1 -/**
2 - * Copyright (c) 2015-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactServerUpdateQueue
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var ReactUpdateQueue = require('ReactUpdateQueue');
14 -
15 -var warning = require('fbjs/lib/warning');
16 -
17 -import type {Transaction} from 'Transaction';
18 -
19 -function warnNoop(
20 - publicInstance: React$Component<any, any>,
21 - callerName: string,
22 -) {
23 - if (__DEV__) {
24 - var constructor = publicInstance.constructor;
25 - warning(
26 - false,
27 - '%s(...): Can only update a mounting component. ' +
28 - 'This usually means you called %s() outside componentWillMount() on the server. ' +
29 - 'This is a no-op.\n\nPlease check the code for the %s component.',
30 - callerName,
31 - callerName,
32 - (constructor && (constructor.displayName || constructor.name)) ||
33 - 'ReactClass',
34 - );
35 - }
36 -}
37 -
38 -/**
39 - * This is the update queue used for server rendering.
40 - * It delegates to ReactUpdateQueue while server rendering is in progress and
41 - * switches to ReactNoopUpdateQueue after the transaction has completed.
42 - * @class ReactServerUpdateQueue
43 - * @param {Transaction} transaction
44 - */
45 -class ReactServerUpdateQueue {
46 - transaction: Transaction;
47 -
48 - constructor(transaction: Transaction) {
49 - this.transaction = transaction;
50 - }
51 -
52 - /**
53 - * Checks whether or not this composite component is mounted.
54 - * @param {ReactClass} publicInstance The instance we want to test.
55 - * @return {boolean} True if mounted, false otherwise.
56 - * @protected
57 - * @final
58 - */
59 - isMounted(publicInstance: React$Component<any, any>): boolean {
60 - return false;
61 - }
62 -
63 - /**
64 - * Forces an update. This should only be invoked when it is known with
65 - * certainty that we are **not** in a DOM transaction.
66 - *
67 - * You may want to call this when you know that some deeper aspect of the
68 - * component's state has changed but `setState` was not called.
69 - *
70 - * This will not invoke `shouldComponentUpdate`, but it will invoke
71 - * `componentWillUpdate` and `componentDidUpdate`.
72 - *
73 - * @param {ReactClass} publicInstance The instance that should rerender.
74 - * @param {?function} callback Called after component is updated.
75 - * @param {?string} callerName Name of the calling function in the public API.
76 - * @internal
77 - */
78 - enqueueForceUpdate(
79 - publicInstance: React$Component<any, any>,
80 - callback?: Function,
81 - callerName?: string,
82 - ) {
83 - if (this.transaction.isInTransaction()) {
84 - ReactUpdateQueue.enqueueForceUpdate(publicInstance, callback, callerName);
85 - } else {
86 - warnNoop(publicInstance, 'forceUpdate');
87 - }
88 - }
89 -
90 - /**
91 - * Replaces all of the state. Always use this or `setState` to mutate state.
92 - * You should treat `this.state` as immutable.
93 - *
94 - * There is no guarantee that `this.state` will be immediately updated, so
95 - * accessing `this.state` after calling this method may return the old value.
96 - *
97 - * @param {ReactClass} publicInstance The instance that should rerender.
98 - * @param {object|function} completeState Next state.
99 - * @param {?function} callback Called after component is updated.
100 - * @param {?string} Name of the calling function in the public API.
101 - * @internal
102 - */
103 - enqueueReplaceState(
104 - publicInstance: React$Component<any, any>,
105 - completeState: Object | Function,
106 - callback?: Function,
107 - callerName?: string,
108 - ) {
109 - if (this.transaction.isInTransaction()) {
110 - ReactUpdateQueue.enqueueReplaceState(
111 - publicInstance,
112 - completeState,
113 - callback,
114 - callerName,
115 - );
116 - } else {
117 - warnNoop(publicInstance, 'replaceState');
118 - }
119 - }
120 -
121 - /**
122 - * Sets a subset of the state. This only exists because _pendingState is
123 - * internal. This provides a merging strategy that is not available to deep
124 - * properties which is confusing. TODO: Expose pendingState or don't use it
125 - * during the merge.
126 - *
127 - * @param {ReactClass} publicInstance The instance that should rerender.
128 - * @param {object|function} partialState Next partial state to be merged with state.
129 - * @internal
130 - */
131 - enqueueSetState(
132 - publicInstance: React$Component<any, any>,
133 - partialState: Object | Function,
134 - callback?: Function,
135 - callerName?: string,
136 - ) {
137 - if (this.transaction.isInTransaction()) {
138 - ReactUpdateQueue.enqueueSetState(
139 - publicInstance,
140 - partialState,
141 - callback,
142 - callerName,
143 - );
144 - } else {
145 - warnNoop(publicInstance, 'setState');
146 - }
147 - }
148 -}
149 -
150 -module.exports = ReactServerUpdateQueue;
src/renderers/native/PooledClass.js renamed
src/renderers/native/__tests__/PooledClass-test.js renamed
src/renderers/shared/shared/shouldUpdateReactComponent.js deleted
-43
@@ -1,43 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule shouldUpdateReactComponent
8 - */
9 -
10 -'use strict';
11 -
12 -/**
13 - * Given a `prevElement` and `nextElement`, determines if the existing
14 - * instance should be updated as opposed to being destroyed or replaced by a new
15 - * instance. Both arguments are elements. This ensures that this logic can
16 - * operate on stateless trees without any backing instance.
17 - *
18 - * @param {?object} prevElement
19 - * @param {?object} nextElement
20 - * @return {boolean} True if the existing instance should be updated.
21 - * @protected
22 - */
23 -function shouldUpdateReactComponent(prevElement, nextElement) {
24 - var prevEmpty = prevElement === null || prevElement === false;
25 - var nextEmpty = nextElement === null || nextElement === false;
26 - if (prevEmpty || nextEmpty) {
27 - return prevEmpty === nextEmpty;
28 - }
29 -
30 - var prevType = typeof prevElement;
31 - var nextType = typeof nextElement;
32 - if (prevType === 'string' || prevType === 'number') {
33 - return nextType === 'string' || nextType === 'number';
34 - } else {
35 - return (
36 - nextType === 'object' &&
37 - prevElement.type === nextElement.type &&
38 - prevElement.key === nextElement.key
39 - );
40 - }
41 -}
42 -
43 -module.exports = shouldUpdateReactComponent;
src/renderers/shared/stack/reconciler/CallbackQueue.js deleted
-106
@@ -1,106 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule CallbackQueue
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var PooledClass = require('PooledClass');
14 -
15 -var invariant = require('fbjs/lib/invariant');
16 -var validateCallback = require('validateCallback');
17 -
18 -/**
19 - * A specialized pseudo-event module to help keep track of components waiting to
20 - * be notified when their DOM representations are available for use.
21 - *
22 - * This implements `PooledClass`, so you should never need to instantiate this.
23 - * Instead, use `CallbackQueue.getPooled()`.
24 - *
25 - * @class CallbackQueue
26 - * @implements PooledClass
27 - * @internal
28 - */
29 -class CallbackQueue<T> {
30 - _callbacks: ?Array<() => void>;
31 - _contexts: ?Array<T>;
32 -
33 - constructor() {
34 - this._callbacks = null;
35 - this._contexts = null;
36 - }
37 -
38 - /**
39 - * Enqueues a callback to be invoked when `notifyAll` is invoked.
40 - *
41 - * @param {function} callback Invoked when `notifyAll` is invoked.
42 - * @param {?object} context Context to call `callback` with.
43 - * @internal
44 - */
45 - enqueue(callback: () => void, context: T) {
46 - this._callbacks = this._callbacks || [];
47 - this._callbacks.push(callback);
48 - this._contexts = this._contexts || [];
49 - this._contexts.push(context);
50 - }
51 -
52 - /**
53 - * Invokes all enqueued callbacks and clears the queue. This is invoked after
54 - * the DOM representation of a component has been created or updated.
55 - *
56 - * @internal
57 - */
58 - notifyAll() {
59 - var callbacks = this._callbacks;
60 - var contexts = this._contexts;
61 - if (callbacks && contexts) {
62 - invariant(
63 - callbacks.length === contexts.length,
64 - 'Mismatched list of contexts in callback queue',
65 - );
66 - this._callbacks = null;
67 - this._contexts = null;
68 - for (var i = 0; i < callbacks.length; i++) {
69 - validateCallback(callbacks[i]);
70 - callbacks[i].call(contexts[i]);
71 - }
72 - callbacks.length = 0;
73 - contexts.length = 0;
74 - }
75 - }
76 -
77 - checkpoint() {
78 - return this._callbacks ? this._callbacks.length : 0;
79 - }
80 -
81 - rollback(len: number) {
82 - if (this._callbacks && this._contexts) {
83 - this._callbacks.length = len;
84 - this._contexts.length = len;
85 - }
86 - }
87 -
88 - /**
89 - * Resets the internal queue.
90 - *
91 - * @internal
92 - */
93 - reset() {
94 - this._callbacks = null;
95 - this._contexts = null;
96 - }
97 -
98 - /**
99 - * `PooledClass` looks for this.
100 - */
101 - destructor() {
102 - this.reset();
103 - }
104 -}
105 -
106 -module.exports = PooledClass.addPoolingTo(CallbackQueue);
src/renderers/shared/stack/reconciler/KeyEscapeUtils.js deleted
-63
@@ -1,63 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule KeyEscapeUtils
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var emptyFunction = require('fbjs/lib/emptyFunction');
14 -
15 -/**
16 - * Escape and wrap key so it is safe to use as a reactid
17 - *
18 - * @param {string} key to be escaped.
19 - * @return {string} the escaped key.
20 - */
21 -function escape(key: string): string {
22 - var escapeRegex = /[=:]/g;
23 - var escaperLookup = {
24 - '=': '=0',
25 - ':': '=2',
26 - };
27 - var escapedString = ('' + key).replace(escapeRegex, function(match) {
28 - return escaperLookup[match];
29 - });
30 -
31 - return '$' + escapedString;
32 -}
33 -
34 -var unescapeInDev = emptyFunction;
35 -if (__DEV__) {
36 - /**
37 - * Unescape and unwrap key for human-readable display
38 - *
39 - * @param {string} key to unescape.
40 - * @return {string} the unescaped key.
41 - */
42 - unescapeInDev = function(key: string): string {
43 - var unescapeRegex = /(=0|=2)/g;
44 - var unescaperLookup = {
45 - '=0': '=',
46 - '=2': ':',
47 - };
48 - var keySubstring = key[0] === '.' && key[1] === '$'
49 - ? key.substring(2)
50 - : key.substring(1);
51 -
52 - return ('' + keySubstring).replace(unescapeRegex, function(match) {
53 - return unescaperLookup[match];
54 - });
55 - };
56 -}
57 -
58 -var KeyEscapeUtils = {
59 - escape: escape,
60 - unescapeInDev: unescapeInDev,
61 -};
62 -
63 -module.exports = KeyEscapeUtils;
src/renderers/shared/stack/reconciler/ReactChildReconciler.js deleted
-212
@@ -1,212 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactChildReconciler
8 - */
9 -
10 -'use strict';
11 -
12 -var KeyEscapeUtils = require('KeyEscapeUtils');
13 -var ReactReconciler = require('ReactReconciler');
14 -
15 -var instantiateReactComponent = require('instantiateReactComponent');
16 -var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
17 -var traverseStackChildren = require('traverseStackChildren');
18 -
19 -if (__DEV__) {
20 - var warning = require('fbjs/lib/warning');
21 -}
22 -
23 -var ReactComponentTreeHook;
24 -
25 -if (
26 - typeof process !== 'undefined' &&
27 - process.env &&
28 - process.env.NODE_ENV === 'test'
29 -) {
30 - // Temporary hack.
31 - // Inline requires don't work well with Jest:
32 - // https://github.com/facebook/react/issues/7240
33 - // Remove the inline requires when we don't need them anymore:
34 - // https://github.com/facebook/react/pull/7178
35 - ReactComponentTreeHook = require('ReactGlobalSharedState')
36 - .ReactComponentTreeHook;
37 -}
38 -
39 -function instantiateChild(childInstances, child, name, selfDebugID) {
40 - // We found a component instance.
41 - var keyUnique = childInstances[name] === undefined;
42 - if (__DEV__) {
43 - if (!ReactComponentTreeHook) {
44 - ReactComponentTreeHook = require('ReactGlobalSharedState')
45 - .ReactComponentTreeHook;
46 - }
47 - if (!keyUnique) {
48 - warning(
49 - false,
50 - 'flattenChildren(...): ' +
51 - 'Encountered two children with the same key, `%s`. ' +
52 - 'Keys should be unique so that components maintain their identity ' +
53 - 'across updates. Non-unique keys may cause children to be ' +
54 - 'duplicated and/or omitted — the behavior is unsupported and ' +
55 - 'could change in a future version.%s',
56 - KeyEscapeUtils.unescapeInDev(name),
57 - ReactComponentTreeHook.getStackAddendumByID(selfDebugID),
58 - );
59 - }
60 - }
61 - if (child != null && keyUnique) {
62 - childInstances[name] = instantiateReactComponent(child, true);
63 - }
64 -}
65 -
66 -/**
67 - * ReactChildReconciler provides helpers for initializing or updating a set of
68 - * children. Its output is suitable for passing it onto ReactMultiChild which
69 - * does diffed reordering and insertion.
70 - */
71 -var ReactChildReconciler = {
72 - /**
73 - * Generates a "mount image" for each of the supplied children. In the case
74 - * of `ReactDOMComponent`, a mount image is a string of markup.
75 - *
76 - * @param {?object} nestedChildNodes Nested child maps.
77 - * @return {?object} A set of child instances.
78 - * @internal
79 - */
80 - instantiateChildren: function(
81 - nestedChildNodes,
82 - transaction,
83 - context,
84 - selfDebugID, // 0 in production and for roots
85 - ) {
86 - if (nestedChildNodes == null) {
87 - return null;
88 - }
89 - var childInstances = {};
90 -
91 - if (__DEV__) {
92 - traverseStackChildren(
93 - nestedChildNodes,
94 - (childInsts, child, name) =>
95 - instantiateChild(childInsts, child, name, selfDebugID),
96 - childInstances,
97 - );
98 - } else {
99 - traverseStackChildren(nestedChildNodes, instantiateChild, childInstances);
100 - }
101 - return childInstances;
102 - },
103 -
104 - /**
105 - * Updates the rendered children and returns a new set of children.
106 - *
107 - * @param {?object} prevChildren Previously initialized set of children.
108 - * @param {?object} nextChildren Flat child element maps.
109 - * @param {ReactReconcileTransaction} transaction
110 - * @param {object} context
111 - * @return {?object} A new set of child instances.
112 - * @internal
113 - */
114 - updateChildren: function(
115 - prevChildren,
116 - nextChildren,
117 - mountImages,
118 - removedNodes,
119 - transaction,
120 - hostParent,
121 - hostContainerInfo,
122 - context,
123 - selfDebugID, // 0 in production and for roots
124 - ) {
125 - // We currently don't have a way to track moves here but if we use iterators
126 - // instead of for..in we can zip the iterators and check if an item has
127 - // moved.
128 - // TODO: If nothing has changed, return the prevChildren object so that we
129 - // can quickly bailout if nothing has changed.
130 - if (!nextChildren && !prevChildren) {
131 - return;
132 - }
133 - var name;
134 - var prevChild;
135 - for (name in nextChildren) {
136 - if (!nextChildren.hasOwnProperty(name)) {
137 - continue;
138 - }
139 - prevChild = prevChildren && prevChildren[name];
140 - var prevElement = prevChild && prevChild._currentElement;
141 - var nextElement = nextChildren[name];
142 - if (
143 - prevChild != null &&
144 - shouldUpdateReactComponent(prevElement, nextElement)
145 - ) {
146 - ReactReconciler.receiveComponent(
147 - prevChild,
148 - nextElement,
149 - transaction,
150 - context,
151 - );
152 - nextChildren[name] = prevChild;
153 - } else {
154 - // The child must be instantiated before it's mounted.
155 - var nextChildInstance = instantiateReactComponent(nextElement, true);
156 - nextChildren[name] = nextChildInstance;
157 - // Creating mount image now ensures refs are resolved in right order
158 - // (see https://github.com/facebook/react/pull/7101 for explanation).
159 - var nextChildMountImage = ReactReconciler.mountComponent(
160 - nextChildInstance,
161 - transaction,
162 - hostParent,
163 - hostContainerInfo,
164 - context,
165 - selfDebugID,
166 - );
167 - mountImages.push(nextChildMountImage);
168 - if (prevChild) {
169 - removedNodes[name] = ReactReconciler.getHostNode(prevChild);
170 - ReactReconciler.unmountComponent(
171 - prevChild,
172 - false /* safely */,
173 - false /* skipLifecycle */,
174 - );
175 - }
176 - }
177 - }
178 - // Unmount children that are no longer present.
179 - for (name in prevChildren) {
180 - if (
181 - prevChildren.hasOwnProperty(name) &&
182 - !(nextChildren && nextChildren.hasOwnProperty(name))
183 - ) {
184 - prevChild = prevChildren[name];
185 - removedNodes[name] = ReactReconciler.getHostNode(prevChild);
186 - ReactReconciler.unmountComponent(
187 - prevChild,
188 - false /* safely */,
189 - false /* skipLifecycle */,
190 - );
191 - }
192 - }
193 - },
194 -
195 - /**
196 - * Unmounts all rendered children. This should be used to clean up children
197 - * when this component is unmounted.
198 - *
199 - * @param {?object} renderedChildren Previously initialized set of children.
200 - * @internal
201 - */
202 - unmountChildren: function(renderedChildren, safely, skipLifecycle) {
203 - for (var name in renderedChildren) {
204 - if (renderedChildren.hasOwnProperty(name)) {
205 - var renderedChild = renderedChildren[name];
206 - ReactReconciler.unmountComponent(renderedChild, safely, skipLifecycle);
207 - }
208 - }
209 - },
210 -};
211 -
212 -module.exports = ReactChildReconciler;
src/renderers/shared/stack/reconciler/ReactComponentEnvironment.js deleted
-53
@@ -1,53 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactComponentEnvironment
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var invariant = require('fbjs/lib/invariant');
14 -
15 -type ReplaceNodeWithMarkup = (node: HTMLElement, markup: string) => void;
16 -type ProcessChildrenUpdates = (instance: mixed, updates: mixed) => void;
17 -
18 -type Environment = {
19 - replaceNodeWithMarkup: ReplaceNodeWithMarkup,
20 - processChildrenUpdates: ProcessChildrenUpdates,
21 -};
22 -
23 -var injected = false;
24 -
25 -var ReactComponentEnvironment = {
26 - /**
27 - * Optionally injectable hook for swapping out mount images in the middle of
28 - * the tree.
29 - */
30 - replaceNodeWithMarkup: (null: ?ReplaceNodeWithMarkup),
31 -
32 - /**
33 - * Optionally injectable hook for processing a queue of child updates. Will
34 - * later move into MultiChildComponents.
35 - */
36 - processChildrenUpdates: (null: ?ReplaceNodeWithMarkup),
37 -
38 - injection: {
39 - injectEnvironment: function(environment: Environment) {
40 - invariant(
41 - !injected,
42 - 'ReactCompositeComponent: injectEnvironment() can only be called once.',
43 - );
44 - ReactComponentEnvironment.replaceNodeWithMarkup =
45 - environment.replaceNodeWithMarkup;
46 - ReactComponentEnvironment.processChildrenUpdates =
47 - environment.processChildrenUpdates;
48 - injected = true;
49 - },
50 - },
51 -};
52 -
53 -module.exports = ReactComponentEnvironment;
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js deleted
-1347
@@ -1,1347 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactCompositeComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var React = require('react');
13 -var ReactComponentEnvironment = require('ReactComponentEnvironment');
14 -var ReactCompositeComponentTypes = require('ReactCompositeComponentTypes');
15 -var ReactErrorUtils = require('ReactErrorUtils');
16 -var ReactInstanceMap = require('ReactInstanceMap');
17 -var ReactInstrumentation = require('ReactInstrumentation');
18 -var ReactNodeTypes = require('ReactNodeTypes');
19 -var ReactReconciler = require('ReactReconciler');
20 -var {ReactCurrentOwner} = require('ReactGlobalSharedState');
21 -
22 -if (__DEV__) {
23 - var {ReactDebugCurrentFrame} = require('ReactGlobalSharedState');
24 - var ReactDebugCurrentStack = require('ReactDebugCurrentStack');
25 - var warning = require('fbjs/lib/warning');
26 - var warningAboutMissingGetChildContext = {};
27 -}
28 -
29 -var checkPropTypes = require('prop-types/checkPropTypes');
30 -var emptyObject = require('fbjs/lib/emptyObject');
31 -var invariant = require('fbjs/lib/invariant');
32 -var shallowEqual = require('fbjs/lib/shallowEqual');
33 -var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
34 -
35 -function StatelessComponent(Component) {}
36 -StatelessComponent.prototype.render = function() {
37 - var Component = ReactInstanceMap.get(this)._currentElement.type;
38 - var element = Component(this.props, this.context, this.updater);
39 - return element;
40 -};
41 -
42 -function shouldConstruct(Component) {
43 - return !!(Component.prototype && Component.prototype.isReactComponent);
44 -}
45 -
46 -function isPureComponent(Component) {
47 - return !!(Component.prototype && Component.prototype.isPureReactComponent);
48 -}
49 -
50 -// Separated into a function to contain deoptimizations caused by try/finally.
51 -function measureLifeCyclePerf(fn, debugID, timerType) {
52 - if (debugID === 0) {
53 - // Top-level wrappers (see ReactMount) and empty components (see
54 - // ReactDOMEmptyComponent) are invisible to hooks and devtools.
55 - // Both are implementation details that should go away in the future.
56 - return fn();
57 - }
58 -
59 - ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);
60 - try {
61 - return fn();
62 - } finally {
63 - ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);
64 - }
65 -}
66 -
67 -/**
68 - * ------------------ The Life-Cycle of a Composite Component ------------------
69 - *
70 - * - constructor: Initialization of state. The instance is now retained.
71 - * - componentWillMount
72 - * - render
73 - * - [children's constructors]
74 - * - [children's componentWillMount and render]
75 - * - [children's componentDidMount]
76 - * - componentDidMount
77 - *
78 - * Update Phases:
79 - * - componentWillReceiveProps (only called if parent updated)
80 - * - shouldComponentUpdate
81 - * - componentWillUpdate
82 - * - render
83 - * - [children's constructors or receive props phases]
84 - * - componentDidUpdate
85 - *
86 - * - componentWillUnmount
87 - * - [children's componentWillUnmount]
88 - * - [children destroyed]
89 - * - (destroyed): The instance is now blank, released by React and ready for GC.
90 - *
91 - * -----------------------------------------------------------------------------
92 - */
93 -
94 -/**
95 - * An incrementing ID assigned to each component when it is mounted. This is
96 - * used to enforce the order in which `ReactUpdates` updates dirty components.
97 - *
98 - * @private
99 - */
100 -var nextMountID = 1;
101 -
102 -/**
103 - * @lends {ReactCompositeComponent.prototype}
104 - */
105 -var ReactCompositeComponent = {
106 - /**
107 - * Base constructor for all composite component.
108 - *
109 - * @param {ReactElement} element
110 - * @final
111 - * @internal
112 - */
113 - construct: function(element) {
114 - this._currentElement = element;
115 - this._rootNodeID = 0;
116 - this._compositeType = null;
117 - this._instance = null;
118 - this._hostParent = null;
119 - this._hostContainerInfo = null;
120 -
121 - // See ReactUpdateQueue
122 - this._updateBatchNumber = null;
123 - this._pendingElement = null;
124 - this._pendingStateQueue = null;
125 - this._pendingReplaceState = false;
126 - this._pendingForceUpdate = false;
127 -
128 - this._renderedNodeType = null;
129 - this._renderedComponent = null;
130 - this._context = null;
131 - this._mountOrder = 0;
132 - this._topLevelWrapper = null;
133 -
134 - // See ReactUpdates and ReactUpdateQueue.
135 - this._pendingCallbacks = null;
136 -
137 - // ComponentWillUnmount shall only be called once
138 - this._calledComponentWillUnmount = false;
139 -
140 - if (__DEV__) {
141 - this._warnedAboutRefsInRender = false;
142 - }
143 - },
144 -
145 - /**
146 - * Initializes the component, renders markup, and registers event listeners.
147 - *
148 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
149 - * @param {?object} hostParent
150 - * @param {?object} hostContainerInfo
151 - * @param {?object} context
152 - * @return {?string} Rendered markup to be inserted into the DOM.
153 - * @final
154 - * @internal
155 - */
156 - mountComponent: function(
157 - transaction,
158 - hostParent,
159 - hostContainerInfo,
160 - context,
161 - ) {
162 - this._context = context;
163 - this._mountOrder = nextMountID++;
164 - this._hostParent = hostParent;
165 - this._hostContainerInfo = hostContainerInfo;
166 -
167 - var publicProps = this._currentElement.props;
168 - var publicContext = this._processContext(context);
169 -
170 - var Component = this._currentElement.type;
171 -
172 - var updateQueue = transaction.getUpdateQueue();
173 -
174 - // Initialize the public class
175 - var doConstruct = shouldConstruct(Component);
176 - var inst = this._constructComponent(
177 - doConstruct,
178 - publicProps,
179 - publicContext,
180 - updateQueue,
181 - );
182 - var renderedElement;
183 -
184 - // Support functional components
185 - if (!doConstruct && (inst == null || inst.render == null)) {
186 - renderedElement = inst;
187 - if (__DEV__) {
188 - warning(
189 - !Component.childContextTypes,
190 - '%s(...): childContextTypes cannot be defined on a functional component.',
191 - Component.displayName || Component.name || 'Component',
192 - );
193 - }
194 - invariant(
195 - inst === null || inst === false || React.isValidElement(inst),
196 - '%s(...): A valid React element (or null) must be returned. You may have ' +
197 - 'returned undefined, an array or some other invalid object.',
198 - Component.displayName || Component.name || 'Component',
199 - );
200 - inst = new StatelessComponent(Component);
201 - this._compositeType = ReactCompositeComponentTypes.StatelessFunctional;
202 - } else {
203 - if (isPureComponent(Component)) {
204 - this._compositeType = ReactCompositeComponentTypes.PureClass;
205 - } else {
206 - this._compositeType = ReactCompositeComponentTypes.ImpureClass;
207 - }
208 - }
209 -
210 - if (__DEV__) {
211 - // This will throw later in _renderValidatedComponent, but add an early
212 - // warning now to help debugging
213 - if (inst.render == null) {
214 - warning(
215 - false,
216 - '%s(...): No `render` method found on the returned component ' +
217 - 'instance: you may have forgotten to define `render`.',
218 - Component.displayName || Component.name || 'Component',
219 - );
220 - }
221 -
222 - var propsMutated = inst.props !== publicProps;
223 - var componentName =
224 - Component.displayName || Component.name || 'Component';
225 -
226 - warning(
227 - inst.props === undefined || !propsMutated,
228 - '%s(...): When calling super() in `%s`, make sure to pass ' +
229 - "up the same props that your component's constructor was passed.",
230 - componentName,
231 - componentName,
232 - );
233 - }
234 -
235 - // These should be set up in the constructor, but as a convenience for
236 - // simpler class abstractions, we set them up after the fact.
237 - inst.props = publicProps;
238 - inst.context = publicContext;
239 - inst.refs = emptyObject;
240 - inst.updater = updateQueue;
241 -
242 - this._instance = inst;
243 -
244 - // Store a reference from the instance back to the internal representation
245 - ReactInstanceMap.set(inst, this);
246 -
247 - if (__DEV__) {
248 - // Since plain JS classes are defined without any special initialization
249 - // logic, we can not catch common errors early. Therefore, we have to
250 - // catch them here, at initialization time, instead.
251 - warning(
252 - !inst.getInitialState ||
253 - inst.getInitialState.isReactClassApproved ||
254 - inst.state,
255 - 'getInitialState was defined on %s, a plain JavaScript class. ' +
256 - 'This is only supported for classes created using React.createClass. ' +
257 - 'Did you mean to define a state property instead?',
258 - this.getName() || 'a component',
259 - );
260 - warning(
261 - !inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved,
262 - 'getDefaultProps was defined on %s, a plain JavaScript class. ' +
263 - 'This is only supported for classes created using React.createClass. ' +
264 - 'Use a static property to define defaultProps instead.',
265 - this.getName() || 'a component',
266 - );
267 - warning(
268 - !inst.propTypes,
269 - 'propTypes was defined as an instance property on %s. Use a static ' +
270 - 'property to define propTypes instead.',
271 - this.getName() || 'a component',
272 - );
273 - warning(
274 - !inst.contextTypes,
275 - 'contextTypes was defined as an instance property on %s. Use a ' +
276 - 'static property to define contextTypes instead.',
277 - this.getName() || 'a component',
278 - );
279 - warning(
280 - typeof inst.componentShouldUpdate !== 'function',
281 - '%s has a method called ' +
282 - 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
283 - 'The name is phrased as a question because the function is ' +
284 - 'expected to return a value.',
285 - this.getName() || 'A component',
286 - );
287 - warning(
288 - typeof inst.componentDidUnmount !== 'function',
289 - '%s has a method called ' +
290 - 'componentDidUnmount(). But there is no such lifecycle method. ' +
291 - 'Did you mean componentWillUnmount()?',
292 - this.getName() || 'A component',
293 - );
294 - warning(
295 - typeof inst.componentWillRecieveProps !== 'function',
296 - '%s has a method called ' +
297 - 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
298 - this.getName() || 'A component',
299 - );
300 - if (
301 - isPureComponent(Component) &&
302 - typeof inst.shouldComponentUpdate !== 'undefined'
303 - ) {
304 - warning(
305 - false,
306 - '%s has a method called shouldComponentUpdate(). ' +
307 - 'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
308 - 'Please extend React.Component if shouldComponentUpdate is used.',
309 - this.getName() || 'A pure component',
310 - );
311 - }
312 - warning(
313 - !inst.defaultProps,
314 - 'Setting defaultProps as an instance property on %s is not supported and will be ignored.' +
315 - ' Instead, define defaultProps as a static property on %s.',
316 - this.getName() || 'a component',
317 - this.getName() || 'a component',
318 - );
319 - }
320 -
321 - var initialState = inst.state;
322 - if (initialState === undefined) {
323 - inst.state = initialState = null;
324 - }
325 - invariant(
326 - typeof initialState === 'object' && !Array.isArray(initialState),
327 - '%s.state: must be set to an object or null',
328 - this.getName() || 'ReactCompositeComponent',
329 - );
330 -
331 - this._pendingStateQueue = null;
332 - this._pendingReplaceState = false;
333 - this._pendingForceUpdate = false;
334 -
335 - if (inst.componentWillMount) {
336 - if (__DEV__) {
337 - measureLifeCyclePerf(
338 - () => inst.componentWillMount(),
339 - this._debugID,
340 - 'componentWillMount',
341 - );
342 - } else {
343 - inst.componentWillMount();
344 - }
345 - // When mounting, calls to `setState` by `componentWillMount` will set
346 - // `this._pendingStateQueue` without triggering a re-render.
347 - if (this._pendingStateQueue) {
348 - inst.state = this._processPendingState(inst.props, inst.context);
349 - }
350 - }
351 -
352 - var markup;
353 - if (inst.componentDidCatch) {
354 - markup = this.performInitialMountWithErrorHandling(
355 - renderedElement,
356 - hostParent,
357 - hostContainerInfo,
358 - transaction,
359 - context,
360 - );
361 - } else {
362 - markup = this.performInitialMount(
363 - renderedElement,
364 - hostParent,
365 - hostContainerInfo,
366 - transaction,
367 - context,
368 - );
369 - }
370 -
371 - if (inst.componentDidMount) {
372 - if (__DEV__) {
373 - transaction.getReactMountReady().enqueue(() => {
374 - measureLifeCyclePerf(
375 - () => inst.componentDidMount(),
376 - this._debugID,
377 - 'componentDidMount',
378 - );
379 - });
380 - } else {
381 - transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
382 - }
383 - }
384 -
385 - // setState callbacks during willMount should end up here
386 - const callbacks = this._pendingCallbacks;
387 - if (callbacks) {
388 - this._pendingCallbacks = null;
389 - for (let i = 0; i < callbacks.length; i++) {
390 - transaction.getReactMountReady().enqueue(callbacks[i], inst);
391 - }
392 - }
393 -
394 - return markup;
395 - },
396 -
397 - _constructComponent: function(
398 - doConstruct,
399 - publicProps,
400 - publicContext,
401 - updateQueue,
402 - ) {
403 - if (__DEV__ && !doConstruct) {
404 - ReactCurrentOwner.current = this;
405 - ReactDebugCurrentFrame.getCurrentStack =
406 - ReactDebugCurrentStack.getStackAddendum;
407 - try {
408 - return this._constructComponentWithoutOwner(
409 - doConstruct,
410 - publicProps,
411 - publicContext,
412 - updateQueue,
413 - );
414 - } finally {
415 - ReactCurrentOwner.current = null;
416 - ReactDebugCurrentFrame.getCurrentStack = null;
417 - }
418 - } else {
419 - return this._constructComponentWithoutOwner(
420 - doConstruct,
421 - publicProps,
422 - publicContext,
423 - updateQueue,
424 - );
425 - }
426 - },
427 -
428 - _constructComponentWithoutOwner: function(
429 - doConstruct,
430 - publicProps,
431 - publicContext,
432 - updateQueue,
433 - ) {
434 - var Component = this._currentElement.type;
435 -
436 - if (doConstruct) {
437 - if (__DEV__) {
438 - return measureLifeCyclePerf(
439 - () => new Component(publicProps, publicContext, updateQueue),
440 - this._debugID,
441 - 'ctor',
442 - );
443 - } else {
444 - return new Component(publicProps, publicContext, updateQueue);
445 - }
446 - }
447 -
448 - // This can still be an instance in case of factory components
449 - // but we'll count this as time spent rendering as the more common case.
450 - if (__DEV__) {
451 - return measureLifeCyclePerf(
452 - () => Component(publicProps, publicContext, updateQueue),
453 - this._debugID,
454 - 'render',
455 - );
456 - } else {
457 - return Component(publicProps, publicContext, updateQueue);
458 - }
459 - },
460 -
461 - performInitialMountWithErrorHandling: function(
462 - renderedElement,
463 - hostParent,
464 - hostContainerInfo,
465 - transaction,
466 - context,
467 - ) {
468 - var markup;
469 - var checkpoint = transaction.checkpoint();
470 - try {
471 - markup = this.performInitialMount(
472 - renderedElement,
473 - hostParent,
474 - hostContainerInfo,
475 - transaction,
476 - context,
477 - );
478 - } catch (e) {
479 - // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
480 - transaction.rollback(checkpoint);
481 - this._instance.componentDidCatch(e);
482 - if (this._pendingStateQueue) {
483 - this._instance.state = this._processPendingState(
484 - this._instance.props,
485 - this._instance.context,
486 - );
487 - }
488 - checkpoint = transaction.checkpoint();
489 - this._renderedComponent.unmountComponent(
490 - true /* safely */,
491 - // Don't call componentWillUnmount() because they never fully mounted:
492 - true /* skipLifecyle */,
493 - );
494 - transaction.rollback(checkpoint);
495 -
496 - // Try again - we've informed the component about the error, so they can render an error message this time.
497 - // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
498 - markup = this.performInitialMount(
499 - renderedElement,
500 - hostParent,
501 - hostContainerInfo,
502 - transaction,
503 - context,
504 - );
505 - }
506 - return markup;
507 - },
508 -
509 - performInitialMount: function(
510 - renderedElement,
511 - hostParent,
512 - hostContainerInfo,
513 - transaction,
514 - context,
515 - ) {
516 - // If not a stateless component, we now render
517 - if (renderedElement === undefined) {
518 - renderedElement = this._renderValidatedComponent();
519 - }
520 -
521 - var nodeType = ReactNodeTypes.getType(renderedElement);
522 - this._renderedNodeType = nodeType;
523 - var child = this._instantiateReactComponent(
524 - renderedElement,
525 - nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */,
526 - );
527 - this._renderedComponent = child;
528 -
529 - var debugID = 0;
530 - if (__DEV__) {
531 - debugID = this._debugID;
532 - }
533 -
534 - var markup = ReactReconciler.mountComponent(
535 - child,
536 - transaction,
537 - hostParent,
538 - hostContainerInfo,
539 - this._processChildContext(context),
540 - debugID,
541 - );
542 -
543 - if (__DEV__) {
544 - if (debugID !== 0) {
545 - var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
546 - ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
547 - }
548 - }
549 -
550 - return markup;
551 - },
552 -
553 - getHostNode: function() {
554 - return ReactReconciler.getHostNode(this._renderedComponent);
555 - },
556 -
557 - /**
558 - * Releases any resources allocated by `mountComponent`.
559 - *
560 - * @final
561 - * @internal
562 - */
563 - unmountComponent: function(safely, skipLifecycle) {
564 - if (!this._renderedComponent) {
565 - return;
566 - }
567 -
568 - var inst = this._instance;
569 -
570 - if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
571 - inst._calledComponentWillUnmount = true;
572 -
573 - if (safely) {
574 - if (!skipLifecycle) {
575 - var name = this.getName() + '.componentWillUnmount()';
576 - ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(
577 - name,
578 - inst.componentWillUnmount,
579 - inst,
580 - );
581 - }
582 - } else {
583 - if (__DEV__) {
584 - measureLifeCyclePerf(
585 - () => inst.componentWillUnmount(),
586 - this._debugID,
587 - 'componentWillUnmount',
588 - );
589 - } else {
590 - inst.componentWillUnmount();
591 - }
592 - }
593 - }
594 -
595 - if (this._renderedComponent) {
596 - ReactReconciler.unmountComponent(
597 - this._renderedComponent,
598 - safely,
599 - skipLifecycle,
600 - );
601 - this._renderedNodeType = null;
602 - this._renderedComponent = null;
603 - this._instance = null;
604 - }
605 -
606 - // Reset pending fields
607 - // Even if this component is scheduled for another update in ReactUpdates,
608 - // it would still be ignored because these fields are reset.
609 - this._pendingStateQueue = null;
610 - this._pendingReplaceState = false;
611 - this._pendingForceUpdate = false;
612 - this._pendingCallbacks = null;
613 - this._pendingElement = null;
614 -
615 - // These fields do not really need to be reset since this object is no
616 - // longer accessible.
617 - this._context = null;
618 - this._rootNodeID = 0;
619 - this._topLevelWrapper = null;
620 -
621 - // Delete the reference from the instance to this internal representation
622 - // which allow the internals to be properly cleaned up even if the user
623 - // leaks a reference to the public instance.
624 - ReactInstanceMap.remove(inst);
625 -
626 - // Some existing components rely on inst.props even after they've been
627 - // destroyed (in event handlers).
628 - // TODO: inst.props = null;
629 - // TODO: inst.state = null;
630 - // TODO: inst.context = null;
631 - },
632 -
633 - /**
634 - * Filters the context object to only contain keys specified in
635 - * `contextTypes`
636 - *
637 - * @param {object} context
638 - * @return {?object}
639 - * @private
640 - */
641 - _maskContext: function(context) {
642 - var Component = this._currentElement.type;
643 - var contextTypes = Component.contextTypes;
644 - if (!contextTypes) {
645 - return emptyObject;
646 - }
647 - var maskedContext = {};
648 - for (var contextName in contextTypes) {
649 - maskedContext[contextName] = context[contextName];
650 - }
651 - return maskedContext;
652 - },
653 -
654 - /**
655 - * Filters the context object to only contain keys specified in
656 - * `contextTypes`, and asserts that they are valid.
657 - *
658 - * @param {object} context
659 - * @return {?object}
660 - * @private
661 - */
662 - _processContext: function(context) {
663 - var maskedContext = this._maskContext(context);
664 - if (__DEV__) {
665 - var Component = this._currentElement.type;
666 - if (Component.contextTypes) {
667 - this._checkContextTypes(
668 - Component.contextTypes,
669 - maskedContext,
670 - 'context',
671 - );
672 - }
673 - }
674 - return maskedContext;
675 - },
676 -
677 - /**
678 - * @param {object} currentContext
679 - * @return {object}
680 - * @private
681 - */
682 - _processChildContext: function(currentContext) {
683 - var Component = this._currentElement.type;
684 - var inst = this._instance;
685 - var childContext;
686 -
687 - if (typeof inst.getChildContext === 'function') {
688 - if (__DEV__) {
689 - ReactInstrumentation.debugTool.onBeginProcessingChildContext();
690 - try {
691 - childContext = inst.getChildContext();
692 - } finally {
693 - ReactInstrumentation.debugTool.onEndProcessingChildContext();
694 - }
695 - } else {
696 - childContext = inst.getChildContext();
697 - }
698 -
699 - invariant(
700 - typeof Component.childContextTypes === 'object',
701 - '%s.getChildContext(): childContextTypes must be defined in order to ' +
702 - 'use getChildContext().',
703 - this.getName() || 'ReactCompositeComponent',
704 - );
705 - if (__DEV__) {
706 - this._checkContextTypes(
707 - Component.childContextTypes,
708 - childContext,
709 - 'child context',
710 - );
711 - }
712 - for (var name in childContext) {
713 - invariant(
714 - name in Component.childContextTypes,
715 - '%s.getChildContext(): key "%s" is not defined in childContextTypes.',
716 - this.getName() || 'ReactCompositeComponent',
717 - name,
718 - );
719 - }
720 - return Object.assign({}, currentContext, childContext);
721 - } else {
722 - if (__DEV__) {
723 - const componentName = this.getName();
724 -
725 - if (!warningAboutMissingGetChildContext[componentName]) {
726 - warningAboutMissingGetChildContext[componentName] = true;
727 - warning(
728 - !Component.childContextTypes,
729 - '%s.childContextTypes is specified but there is no getChildContext() method ' +
730 - 'on the instance. You can either define getChildContext() on %s or remove ' +
731 - 'childContextTypes from it.',
732 - componentName,
733 - componentName,
734 - );
735 - }
736 - }
737 - }
738 - return currentContext;
739 - },
740 -
741 - /**
742 - * Assert that the context types are valid
743 - *
744 - * @param {object} typeSpecs Map of context field to a ReactPropType
745 - * @param {object} values Runtime values that need to be type-checked
746 - * @param {string} location e.g. "prop", "context", "child context"
747 - * @private
748 - */
749 - _checkContextTypes: function(typeSpecs, values, location: string) {
750 - if (__DEV__) {
751 - ReactDebugCurrentStack.current = this._debugID;
752 - checkPropTypes(
753 - typeSpecs,
754 - values,
755 - location,
756 - this.getName(),
757 - ReactDebugCurrentStack.getStackAddendum,
758 - );
759 - ReactDebugCurrentStack.current = null;
760 - }
761 - },
762 -
763 - receiveComponent: function(nextElement, transaction, nextContext) {
764 - var prevElement = this._currentElement;
765 - var prevContext = this._context;
766 -
767 - this._pendingElement = null;
768 -
769 - this.updateComponent(
770 - transaction,
771 - prevElement,
772 - nextElement,
773 - prevContext,
774 - nextContext,
775 - );
776 - },
777 -
778 - /**
779 - * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
780 - * is set, update the component.
781 - *
782 - * @param {ReactReconcileTransaction} transaction
783 - * @internal
784 - */
785 - performUpdateIfNecessary: function(transaction) {
786 - if (this._pendingElement != null) {
787 - ReactReconciler.receiveComponent(
788 - this,
789 - this._pendingElement,
790 - transaction,
791 - this._context,
792 - );
793 - } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
794 - this.updateComponent(
795 - transaction,
796 - this._currentElement,
797 - this._currentElement,
798 - this._context,
799 - this._context,
800 - );
801 - } else {
802 - var callbacks = this._pendingCallbacks;
803 - this._pendingCallbacks = null;
804 - if (callbacks) {
805 - for (var j = 0; j < callbacks.length; j++) {
806 - transaction
807 - .getReactMountReady()
808 - .enqueue(callbacks[j], this.getPublicInstance());
809 - }
810 - }
811 - this._updateBatchNumber = null;
812 - }
813 - },
814 -
815 - /**
816 - * Perform an update to a mounted component. The componentWillReceiveProps and
817 - * shouldComponentUpdate methods are called, then (assuming the update isn't
818 - * skipped) the remaining update lifecycle methods are called and the DOM
819 - * representation is updated.
820 - *
821 - * By default, this implements React's rendering and reconciliation algorithm.
822 - * Sophisticated clients may wish to override this.
823 - *
824 - * @param {ReactReconcileTransaction} transaction
825 - * @param {ReactElement} prevParentElement
826 - * @param {ReactElement} nextParentElement
827 - * @internal
828 - * @overridable
829 - */
830 - updateComponent: function(
831 - transaction,
832 - prevParentElement,
833 - nextParentElement,
834 - prevUnmaskedContext,
835 - nextUnmaskedContext,
836 - ) {
837 - var inst = this._instance;
838 - invariant(
839 - inst != null,
840 - 'Attempted to update component `%s` that has already been unmounted ' +
841 - '(or failed to mount).',
842 - this.getName() || 'ReactCompositeComponent',
843 - );
844 -
845 - var willReceive = false;
846 - var nextContext;
847 -
848 - // Determine if the context has changed or not
849 - if (this._context === nextUnmaskedContext) {
850 - nextContext = inst.context;
851 - } else {
852 - nextContext = this._processContext(nextUnmaskedContext);
853 - willReceive = true;
854 - }
855 -
856 - var prevProps = prevParentElement.props;
857 - var nextProps = nextParentElement.props;
858 -
859 - // Not a simple state update but a props update
860 - if (prevParentElement !== nextParentElement) {
861 - willReceive = true;
862 - }
863 -
864 - // An update here will schedule an update but immediately set
865 - // _pendingStateQueue which will ensure that any state updates gets
866 - // immediately reconciled instead of waiting for the next batch.
867 - if (willReceive && inst.componentWillReceiveProps) {
868 - const beforeState = inst.state;
869 - if (__DEV__) {
870 - measureLifeCyclePerf(
871 - () => inst.componentWillReceiveProps(nextProps, nextContext),
872 - this._debugID,
873 - 'componentWillReceiveProps',
874 - );
875 - } else {
876 - inst.componentWillReceiveProps(nextProps, nextContext);
877 - }
878 - const afterState = inst.state;
879 - if (beforeState !== afterState) {
880 - inst.state = beforeState;
881 - inst.updater.enqueueReplaceState(inst, afterState);
882 - if (__DEV__) {
883 - warning(
884 - false,
885 - '%s.componentWillReceiveProps(): Assigning directly to ' +
886 - "this.state is deprecated (except inside a component's " +
887 - 'constructor). Use setState instead.',
888 - this.getName() || 'ReactCompositeComponent',
889 - );
890 - }
891 - }
892 - }
893 -
894 - // If updating happens to enqueue any new updates, we shouldn't execute new
895 - // callbacks until the next render happens, so stash the callbacks first.
896 - var callbacks = this._pendingCallbacks;
897 - this._pendingCallbacks = null;
898 -
899 - var nextState = this._processPendingState(nextProps, nextContext);
900 - var shouldUpdate = true;
901 - if (!this._pendingForceUpdate) {
902 - var prevState = inst.state;
903 - shouldUpdate = willReceive || nextState !== prevState;
904 - if (inst.shouldComponentUpdate) {
905 - if (__DEV__) {
906 - shouldUpdate = measureLifeCyclePerf(
907 - () => inst.shouldComponentUpdate(nextProps, nextState, nextContext),
908 - this._debugID,
909 - 'shouldComponentUpdate',
910 - );
911 - } else {
912 - shouldUpdate = inst.shouldComponentUpdate(
913 - nextProps,
914 - nextState,
915 - nextContext,
916 - );
917 - }
918 - } else {
919 - if (this._compositeType === ReactCompositeComponentTypes.PureClass) {
920 - shouldUpdate =
921 - !shallowEqual(prevProps, nextProps) ||
922 - !shallowEqual(inst.state, nextState);
923 - }
924 - }
925 - }
926 -
927 - if (__DEV__) {
928 - warning(
929 - shouldUpdate !== undefined,
930 - '%s.shouldComponentUpdate(): Returned undefined instead of a ' +
931 - 'boolean value. Make sure to return true or false.',
932 - this.getName() || 'ReactCompositeComponent',
933 - );
934 - }
935 -
936 - this._updateBatchNumber = null;
937 - if (shouldUpdate) {
938 - this._pendingForceUpdate = false;
939 - // Will set `this.props`, `this.state` and `this.context`.
940 - this._performComponentUpdate(
941 - nextParentElement,
942 - nextProps,
943 - nextState,
944 - nextContext,
945 - transaction,
946 - nextUnmaskedContext,
947 - );
948 - } else {
949 - // If it's determined that a component should not update, we still want
950 - // to set props and state but we shortcut the rest of the update.
951 - this._currentElement = nextParentElement;
952 - this._context = nextUnmaskedContext;
953 - inst.props = nextProps;
954 - inst.state = nextState;
955 - inst.context = nextContext;
956 - }
957 -
958 - if (callbacks) {
959 - for (var j = 0; j < callbacks.length; j++) {
960 - transaction
961 - .getReactMountReady()
962 - .enqueue(callbacks[j], this.getPublicInstance());
963 - }
964 - }
965 - },
966 -
967 - _processPendingState: function(props, context) {
968 - var inst = this._instance;
969 - var queue = this._pendingStateQueue;
970 - var replace = this._pendingReplaceState;
971 - this._pendingReplaceState = false;
972 - this._pendingStateQueue = null;
973 -
974 - if (!queue) {
975 - return inst.state;
976 - }
977 -
978 - if (replace && queue.length === 1) {
979 - return queue[0];
980 - }
981 -
982 - var nextState = replace ? queue[0] : inst.state;
983 - var dontMutate = true;
984 - for (var i = replace ? 1 : 0; i < queue.length; i++) {
985 - var partial = queue[i];
986 - let partialState = typeof partial === 'function'
987 - ? partial.call(inst, nextState, props, context)
988 - : partial;
989 - if (partialState) {
990 - if (dontMutate) {
991 - dontMutate = false;
992 - nextState = Object.assign({}, nextState, partialState);
993 - } else {
994 - Object.assign(nextState, partialState);
995 - }
996 - }
997 - }
998 -
999 - return nextState;
1000 - },
1001 -
1002 - /**
1003 - * Merges new props and state, notifies delegate methods of update and
1004 - * performs update.
1005 - *
1006 - * @param {ReactElement} nextElement Next element
1007 - * @param {object} nextProps Next public object to set as properties.
1008 - * @param {?object} nextState Next object to set as state.
1009 - * @param {?object} nextContext Next public object to set as context.
1010 - * @param {ReactReconcileTransaction} transaction
1011 - * @param {?object} unmaskedContext
1012 - * @private
1013 - */
1014 - _performComponentUpdate: function(
1015 - nextElement,
1016 - nextProps,
1017 - nextState,
1018 - nextContext,
1019 - transaction,
1020 - unmaskedContext,
1021 - ) {
1022 - var inst = this._instance;
1023 -
1024 - var hasComponentDidUpdate = !!inst.componentDidUpdate;
1025 - var prevProps;
1026 - var prevState;
1027 - if (hasComponentDidUpdate) {
1028 - prevProps = inst.props;
1029 - prevState = inst.state;
1030 - }
1031 -
1032 - if (inst.componentWillUpdate) {
1033 - if (__DEV__) {
1034 - measureLifeCyclePerf(
1035 - () => inst.componentWillUpdate(nextProps, nextState, nextContext),
1036 - this._debugID,
1037 - 'componentWillUpdate',
1038 - );
1039 - } else {
1040 - inst.componentWillUpdate(nextProps, nextState, nextContext);
1041 - }
1042 - }
1043 -
1044 - this._currentElement = nextElement;
1045 - this._context = unmaskedContext;
1046 - inst.props = nextProps;
1047 - inst.state = nextState;
1048 - inst.context = nextContext;
1049 -
1050 - if (inst.componentDidCatch) {
1051 - this._updateRenderedComponentWithErrorHandling(
1052 - transaction,
1053 - unmaskedContext,
1054 - );
1055 - } else {
1056 - this._updateRenderedComponent(transaction, unmaskedContext);
1057 - }
1058 -
1059 - if (hasComponentDidUpdate) {
1060 - if (__DEV__) {
1061 - transaction.getReactMountReady().enqueue(() => {
1062 - measureLifeCyclePerf(
1063 - inst.componentDidUpdate.bind(inst, prevProps, prevState),
1064 - this._debugID,
1065 - 'componentDidUpdate',
1066 - );
1067 - });
1068 - } else {
1069 - transaction
1070 - .getReactMountReady()
1071 - .enqueue(
1072 - inst.componentDidUpdate.bind(inst, prevProps, prevState),
1073 - inst,
1074 - );
1075 - }
1076 - }
1077 - },
1078 -
1079 - /**
1080 - * Call the component's `render` method and update the DOM accordingly.
1081 - *
1082 - * @param {ReactReconcileTransaction} transaction
1083 - * @internal
1084 - */
1085 - _updateRenderedComponentWithErrorHandling: function(transaction, context) {
1086 - var checkpoint = transaction.checkpoint();
1087 - try {
1088 - this._updateRenderedComponent(transaction, context);
1089 - } catch (e) {
1090 - // Roll back to checkpoint, handle error (which may add items to the transaction),
1091 - // and take a new checkpoint
1092 - transaction.rollback(checkpoint);
1093 - this._instance.componentDidCatch(e);
1094 - if (this._pendingStateQueue) {
1095 - this._instance.state = this._processPendingState(
1096 - this._instance.props,
1097 - this._instance.context,
1098 - );
1099 - }
1100 - checkpoint = transaction.checkpoint();
1101 -
1102 - // Gracefully update to a clean state
1103 - this._updateRenderedComponentWithNextElement(
1104 - transaction,
1105 - context,
1106 - null,
1107 - true /* safely */,
1108 - );
1109 -
1110 - // Try again - we've informed the component about the error, so they can render an error message this time.
1111 - // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
1112 - this._updateRenderedComponent(transaction, context);
1113 - }
1114 - },
1115 -
1116 - /**
1117 - * Call the component's `render` method and update the DOM accordingly.
1118 - *
1119 - * @param {ReactReconcileTransaction} transaction
1120 - * @internal
1121 - */
1122 - _updateRenderedComponent: function(transaction, context) {
1123 - var nextRenderedElement = this._renderValidatedComponent();
1124 - this._updateRenderedComponentWithNextElement(
1125 - transaction,
1126 - context,
1127 - nextRenderedElement,
1128 - false /* safely */,
1129 - );
1130 - },
1131 -
1132 - /**
1133 - * Call the component's `render` method and update the DOM accordingly.
1134 - *
1135 - * @param {ReactReconcileTransaction} transaction
1136 - * @internal
1137 - */
1138 - _updateRenderedComponentWithNextElement: function(
1139 - transaction,
1140 - context,
1141 - nextRenderedElement,
1142 - safely,
1143 - ) {
1144 - var prevComponentInstance = this._renderedComponent;
1145 - var prevRenderedElement = prevComponentInstance._currentElement;
1146 -
1147 - var debugID = 0;
1148 - if (__DEV__) {
1149 - debugID = this._debugID;
1150 - }
1151 -
1152 - if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
1153 - ReactReconciler.receiveComponent(
1154 - prevComponentInstance,
1155 - nextRenderedElement,
1156 - transaction,
1157 - this._processChildContext(context),
1158 - );
1159 - } else {
1160 - var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);
1161 - var nodeType = ReactNodeTypes.getType(nextRenderedElement);
1162 - this._renderedNodeType = nodeType;
1163 - var child = this._instantiateReactComponent(
1164 - nextRenderedElement,
1165 - nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */,
1166 - );
1167 - this._renderedComponent = child;
1168 -
1169 - var nextMarkup = ReactReconciler.mountComponent(
1170 - child,
1171 - transaction,
1172 - this._hostParent,
1173 - this._hostContainerInfo,
1174 - this._processChildContext(context),
1175 - debugID,
1176 - );
1177 -
1178 - ReactReconciler.unmountComponent(
1179 - prevComponentInstance,
1180 - safely,
1181 - false /* skipLifecycle */,
1182 - );
1183 -
1184 - if (__DEV__) {
1185 - if (debugID !== 0) {
1186 - var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
1187 - ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
1188 - }
1189 - }
1190 -
1191 - this._replaceNodeWithMarkup(
1192 - oldHostNode,
1193 - nextMarkup,
1194 - prevComponentInstance,
1195 - );
1196 - }
1197 - },
1198 -
1199 - /**
1200 - * Overridden in shallow rendering.
1201 - *
1202 - * @protected
1203 - */
1204 - _replaceNodeWithMarkup: function(oldHostNode, nextMarkup, prevInstance) {
1205 - ReactComponentEnvironment.replaceNodeWithMarkup(
1206 - oldHostNode,
1207 - nextMarkup,
1208 - prevInstance,
1209 - );
1210 - },
1211 -
1212 - /**
1213 - * @protected
1214 - */
1215 - _renderValidatedComponentWithoutOwnerOrContext: function() {
1216 - var inst = this._instance;
1217 - var renderedElement;
1218 -
1219 - if (__DEV__) {
1220 - renderedElement = measureLifeCyclePerf(
1221 - () => inst.render(),
1222 - this._debugID,
1223 - 'render',
1224 - );
1225 - } else {
1226 - renderedElement = inst.render();
1227 - }
1228 -
1229 - if (__DEV__) {
1230 - // We allow auto-mocks to proceed as if they're returning null.
1231 - if (renderedElement === undefined && inst.render._isMockFunction) {
1232 - // This is probably bad practice. Consider warning here and
1233 - // deprecating this convenience.
1234 - renderedElement = null;
1235 - }
1236 - }
1237 -
1238 - return renderedElement;
1239 - },
1240 -
1241 - /**
1242 - * @private
1243 - */
1244 - _renderValidatedComponent: function() {
1245 - var renderedElement;
1246 - if (
1247 - __DEV__ ||
1248 - this._compositeType !== ReactCompositeComponentTypes.StatelessFunctional
1249 - ) {
1250 - ReactCurrentOwner.current = this;
1251 - if (__DEV__) {
1252 - ReactDebugCurrentFrame.getCurrentStack =
1253 - ReactDebugCurrentStack.getStackAddendum;
1254 - }
1255 - try {
1256 - renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();
1257 - } finally {
1258 - ReactCurrentOwner.current = null;
1259 - if (__DEV__) {
1260 - ReactDebugCurrentFrame.getCurrentStack = null;
1261 - }
1262 - }
1263 - } else {
1264 - renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();
1265 - }
1266 - invariant(
1267 - // TODO: An `isValidNode` function would probably be more appropriate
1268 - renderedElement === null ||
1269 - renderedElement === false ||
1270 - React.isValidElement(renderedElement),
1271 - '%s.render(): A valid React element (or null) must be returned. You may have ' +
1272 - 'returned undefined, an array or some other invalid object.',
1273 - this.getName() || 'ReactCompositeComponent',
1274 - );
1275 -
1276 - return renderedElement;
1277 - },
1278 -
1279 - /**
1280 - * Lazily allocates the refs object and stores `component` as `ref`.
1281 - *
1282 - * @param {string} ref Reference name.
1283 - * @param {component} component Component to store as `ref`.
1284 - * @final
1285 - * @private
1286 - */
1287 - attachRef: function(ref, component) {
1288 - var inst = this.getPublicInstance();
1289 - invariant(inst != null, 'Stateless function components cannot have refs.');
1290 - var publicComponentInstance = component.getPublicInstance();
1291 - var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
1292 - refs[ref] = publicComponentInstance;
1293 - },
1294 -
1295 - /**
1296 - * Detaches a reference name.
1297 - *
1298 - * @param {string} ref Name to dereference.
1299 - * @final
1300 - * @private
1301 - */
1302 - detachRef: function(ref) {
1303 - var refs = this.getPublicInstance().refs;
1304 - delete refs[ref];
1305 - },
1306 -
1307 - /**
1308 - * Get a text description of the component that can be used to identify it
1309 - * in error messages.
1310 - * @return {string} The name or null.
1311 - * @internal
1312 - */
1313 - getName: function() {
1314 - var type = this._currentElement.type;
1315 - var constructor = this._instance && this._instance.constructor;
1316 - return (
1317 - type.displayName ||
1318 - (constructor && constructor.displayName) ||
1319 - type.name ||
1320 - (constructor && constructor.name) ||
1321 - null
1322 - );
1323 - },
1324 -
1325 - /**
1326 - * Get the publicly accessible representation of this component - i.e. what
1327 - * is exposed by refs and returned by render. Can be null for stateless
1328 - * components.
1329 - *
1330 - * @return {ReactComponent} the public component instance.
1331 - * @internal
1332 - */
1333 - getPublicInstance: function() {
1334 - var inst = this._instance;
1335 - if (
1336 - this._compositeType === ReactCompositeComponentTypes.StatelessFunctional
1337 - ) {
1338 - return null;
1339 - }
1340 - return inst;
1341 - },
1342 -
1343 - // Stub
1344 - _instantiateReactComponent: null,
1345 -};
1346 -
1347 -module.exports = ReactCompositeComponent;
src/renderers/shared/stack/reconciler/ReactCompositeComponentTypes.js deleted
-17
@@ -1,17 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactCompositeComponentTypes
8 - * @flow
9 - */
10 -
11 -export type CompositeComponentTypes = 0 | 1 | 2;
12 -
13 -module.exports = {
14 - ImpureClass: 0,
15 - PureClass: 1,
16 - StatelessFunctional: 2,
17 -};
src/renderers/shared/stack/reconciler/ReactDebugCurrentStack.js deleted
-36
@@ -1,36 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDebugCurrentStack
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -import type {DebugID} from 'ReactInstanceType';
14 -
15 -const ReactDebugCurrentStack = {};
16 -
17 -if (__DEV__) {
18 - var {ReactComponentTreeHook} = require('ReactGlobalSharedState');
19 - var {getStackAddendumByID, getCurrentStackAddendum} = ReactComponentTreeHook;
20 -
21 - // Component that is being worked on
22 - ReactDebugCurrentStack.current = (null: DebugID | null);
23 -
24 - ReactDebugCurrentStack.getStackAddendum = function(): string | null {
25 - let stack = null;
26 - const current = ReactDebugCurrentStack.current;
27 - if (current !== null) {
28 - stack = getStackAddendumByID(current);
29 - } else {
30 - stack = getCurrentStackAddendum();
31 - }
32 - return stack;
33 - };
34 -}
35 -
36 -module.exports = ReactDebugCurrentStack;
src/renderers/shared/stack/reconciler/ReactDefaultBatchingStrategy.js deleted
-64
@@ -1,64 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactDefaultBatchingStrategy
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactUpdates = require('ReactUpdates');
13 -var Transaction = require('Transaction');
14 -
15 -var emptyFunction = require('fbjs/lib/emptyFunction');
16 -
17 -var RESET_BATCHED_UPDATES = {
18 - initialize: emptyFunction,
19 - close: function() {
20 - ReactDefaultBatchingStrategy.isBatchingUpdates = false;
21 - },
22 -};
23 -
24 -var FLUSH_BATCHED_UPDATES = {
25 - initialize: emptyFunction,
26 - close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates),
27 -};
28 -
29 -var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
30 -
31 -function ReactDefaultBatchingStrategyTransaction() {
32 - this.reinitializeTransaction();
33 -}
34 -
35 -Object.assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction, {
36 - getTransactionWrappers: function() {
37 - return TRANSACTION_WRAPPERS;
38 - },
39 -});
40 -
41 -var transaction = new ReactDefaultBatchingStrategyTransaction();
42 -
43 -var ReactDefaultBatchingStrategy = {
44 - isBatchingUpdates: false,
45 -
46 - /**
47 - * Call the provided function in a context within which calls to `setState`
48 - * and friends are batched such that components aren't updated unnecessarily.
49 - */
50 - batchedUpdates: function(callback, a, b, c, d, e) {
51 - var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
52 -
53 - ReactDefaultBatchingStrategy.isBatchingUpdates = true;
54 -
55 - // The code is written this way to avoid extra allocations
56 - if (alreadyBatchingUpdates) {
57 - return callback(a, b, c, d, e);
58 - } else {
59 - return transaction.perform(callback, null, a, b, c, d, e);
60 - }
61 - },
62 -};
63 -
64 -module.exports = ReactDefaultBatchingStrategy;
src/renderers/shared/stack/reconciler/ReactEmptyComponent.js deleted
-28
@@ -1,28 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactEmptyComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var emptyComponentFactory;
13 -
14 -var ReactEmptyComponentInjection = {
15 - injectEmptyComponentFactory: function(factory) {
16 - emptyComponentFactory = factory;
17 - },
18 -};
19 -
20 -var ReactEmptyComponent = {
21 - create: function(instantiate) {
22 - return emptyComponentFactory(instantiate);
23 - },
24 -};
25 -
26 -ReactEmptyComponent.injection = ReactEmptyComponentInjection;
27 -
28 -module.exports = ReactEmptyComponent;
src/renderers/shared/stack/reconciler/ReactHostComponent.js deleted
-68
@@ -1,68 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactHostComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var invariant = require('fbjs/lib/invariant');
13 -
14 -var genericComponentClass = null;
15 -var textComponentClass = null;
16 -
17 -var ReactHostComponentInjection = {
18 - // This accepts a class that receives the tag string. This is a catch all
19 - // that can render any kind of tag.
20 - injectGenericComponentClass: function(componentClass) {
21 - genericComponentClass = componentClass;
22 - },
23 - // This accepts a text component class that takes the text string to be
24 - // rendered as props.
25 - injectTextComponentClass: function(componentClass) {
26 - textComponentClass = componentClass;
27 - },
28 -};
29 -
30 -/**
31 - * Get a host internal component class for a specific tag.
32 - *
33 - * @param {ReactElement} element The element to create.
34 - * @return {function} The internal class constructor function.
35 - */
36 -function createInternalComponent(element) {
37 - invariant(
38 - genericComponentClass,
39 - 'There is no registered component for the tag %s',
40 - element.type,
41 - );
42 - return new genericComponentClass(element);
43 -}
44 -
45 -/**
46 - * @param {ReactText} text
47 - * @return {ReactComponent}
48 - */
49 -function createInstanceForText(text) {
50 - return new textComponentClass(text);
51 -}
52 -
53 -/**
54 - * @param {ReactComponent} component
55 - * @return {boolean}
56 - */
57 -function isTextComponent(component) {
58 - return component instanceof textComponentClass;
59 -}
60 -
61 -var ReactHostComponent = {
62 - createInternalComponent: createInternalComponent,
63 - createInstanceForText: createInstanceForText,
64 - isTextComponent: isTextComponent,
65 - injection: ReactHostComponentInjection,
66 -};
67 -
68 -module.exports = ReactHostComponent;
src/renderers/shared/stack/reconciler/ReactInstanceType.js deleted
-47
@@ -1,47 +0,0 @@
1 -/**
2 - * Copyright (c) 2016-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactInstanceType
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -import type {ReactElement} from 'ReactElementType';
14 -import type {CompositeComponentTypes} from 'ReactCompositeComponentTypes';
15 -
16 -export type DebugID = number;
17 -
18 -export type ReactInstance = {
19 - // Shared
20 - mountComponent: any,
21 - unmountComponent: any,
22 - receiveComponent: any,
23 - getName: () => string,
24 - getPublicInstance: any,
25 - _currentElement: ReactElement,
26 -
27 - // ReactCompositeComponent
28 - performInitialMountWithErrorHandling: any,
29 - performInitialMount: any,
30 - getHostNode: any,
31 - performUpdateIfNecessary: any,
32 - updateComponent: any,
33 - attachRef: (ref: string, component: ReactInstance) => void,
34 - detachRef: (ref: string) => void,
35 - _rootNodeID: number,
36 - _compositeType: CompositeComponentTypes,
37 -
38 - // ReactDOMComponent
39 - _tag: string,
40 -
41 - // instantiateReactComponent
42 - _mountIndex: number,
43 - _mountImage: any,
44 - // __DEV__
45 - _debugID: DebugID,
46 - _warnedAboutRefsInRender: boolean,
47 -};
src/renderers/shared/stack/reconciler/ReactMultiChild.js deleted
-544
@@ -1,544 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactMultiChild
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactComponentEnvironment = require('ReactComponentEnvironment');
13 -var ReactInstanceMap = require('ReactInstanceMap');
14 -var ReactInstrumentation = require('ReactInstrumentation');
15 -
16 -var ReactReconciler = require('ReactReconciler');
17 -var ReactChildReconciler = require('ReactChildReconciler');
18 -var {ReactCurrentOwner} = require('ReactGlobalSharedState');
19 -if (__DEV__) {
20 - var {ReactDebugCurrentFrame} = require('ReactGlobalSharedState');
21 - var ReactDebugCurrentStack = require('ReactDebugCurrentStack');
22 -}
23 -
24 -var emptyFunction = require('fbjs/lib/emptyFunction');
25 -var flattenStackChildren = require('flattenStackChildren');
26 -var invariant = require('fbjs/lib/invariant');
27 -
28 -/**
29 - * Make an update for markup to be rendered and inserted at a supplied index.
30 - *
31 - * @param {string} markup Markup that renders into an element.
32 - * @param {number} toIndex Destination index.
33 - * @private
34 - */
35 -function makeInsertMarkup(markup, afterNode, toIndex) {
36 - // NOTE: Null values reduce hidden classes.
37 - return {
38 - type: 'INSERT_MARKUP',
39 - content: markup,
40 - fromIndex: null,
41 - fromNode: null,
42 - toIndex: toIndex,
43 - afterNode: afterNode,
44 - };
45 -}
46 -
47 -/**
48 - * Make an update for moving an existing element to another index.
49 - *
50 - * @param {number} fromIndex Source index of the existing element.
51 - * @param {number} toIndex Destination index of the element.
52 - * @private
53 - */
54 -function makeMove(child, afterNode, toIndex) {
55 - // NOTE: Null values reduce hidden classes.
56 - return {
57 - type: 'MOVE_EXISTING',
58 - content: null,
59 - fromIndex: child._mountIndex,
60 - fromNode: ReactReconciler.getHostNode(child),
61 - toIndex: toIndex,
62 - afterNode: afterNode,
63 - };
64 -}
65 -
66 -/**
67 - * Make an update for removing an element at an index.
68 - *
69 - * @param {number} fromIndex Index of the element to remove.
70 - * @private
71 - */
72 -function makeRemove(child, node) {
73 - // NOTE: Null values reduce hidden classes.
74 - return {
75 - type: 'REMOVE_NODE',
76 - content: null,
77 - fromIndex: child._mountIndex,
78 - fromNode: node,
79 - toIndex: null,
80 - afterNode: null,
81 - };
82 -}
83 -
84 -/**
85 - * Make an update for setting the markup of a node.
86 - *
87 - * @param {string} markup Markup that renders into an element.
88 - * @private
89 - */
90 -function makeSetMarkup(markup) {
91 - // NOTE: Null values reduce hidden classes.
92 - return {
93 - type: 'SET_MARKUP',
94 - content: markup,
95 - fromIndex: null,
96 - fromNode: null,
97 - toIndex: null,
98 - afterNode: null,
99 - };
100 -}
101 -
102 -/**
103 - * Make an update for setting the text content.
104 - *
105 - * @param {string} textContent Text content to set.
106 - * @private
107 - */
108 -function makeTextContent(textContent) {
109 - // NOTE: Null values reduce hidden classes.
110 - return {
111 - type: 'TEXT_CONTENT',
112 - content: textContent,
113 - fromIndex: null,
114 - fromNode: null,
115 - toIndex: null,
116 - afterNode: null,
117 - };
118 -}
119 -
120 -/**
121 - * Push an update, if any, onto the queue. Creates a new queue if none is
122 - * passed and always returns the queue. Mutative.
123 - */
124 -function enqueue(queue, update) {
125 - if (update) {
126 - queue = queue || [];
127 - queue.push(update);
128 - }
129 - return queue;
130 -}
131 -
132 -/**
133 - * Processes any enqueued updates.
134 - *
135 - * @private
136 - */
137 -function processQueue(inst, updateQueue) {
138 - ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);
139 -}
140 -
141 -var setChildrenForInstrumentation = emptyFunction;
142 -if (__DEV__) {
143 - var getDebugID = function(inst) {
144 - if (!inst._debugID) {
145 - // Check for ART-like instances. TODO: This is silly/gross.
146 - var internal;
147 - if ((internal = ReactInstanceMap.get(inst))) {
148 - inst = internal;
149 - }
150 - }
151 - return inst._debugID;
152 - };
153 - setChildrenForInstrumentation = function(children) {
154 - var debugID = getDebugID(this);
155 - // TODO: React Native empty components are also multichild.
156 - // This means they still get into this method but don't have _debugID.
157 - if (debugID !== 0) {
158 - ReactInstrumentation.debugTool.onSetChildren(
159 - debugID,
160 - children
161 - ? Object.keys(children).map(key => children[key]._debugID)
162 - : [],
163 - );
164 - }
165 - };
166 -}
167 -
168 -/**
169 - * Provides common functionality for components that must reconcile multiple
170 - * children. This is used by `ReactDOMComponent` to mount, update, and
171 - * unmount child components.
172 - */
173 -var ReactMultiChild = {
174 - _reconcilerInstantiateChildren: function(
175 - nestedChildren,
176 - transaction,
177 - context,
178 - ) {
179 - if (__DEV__) {
180 - var selfDebugID = getDebugID(this);
181 - if (this._currentElement) {
182 - try {
183 - ReactCurrentOwner.current = this._currentElement._owner;
184 - ReactDebugCurrentFrame.getCurrentStack =
185 - ReactDebugCurrentStack.getStackAddendum;
186 - return ReactChildReconciler.instantiateChildren(
187 - nestedChildren,
188 - transaction,
189 - context,
190 - selfDebugID,
191 - );
192 - } finally {
193 - ReactCurrentOwner.current = null;
194 - ReactDebugCurrentFrame.getCurrentStack = null;
195 - }
196 - }
197 - }
198 - return ReactChildReconciler.instantiateChildren(
199 - nestedChildren,
200 - transaction,
201 - context,
202 - );
203 - },
204 -
205 - _reconcilerUpdateChildren: function(
206 - prevChildren,
207 - nextNestedChildrenElements,
208 - mountImages,
209 - removedNodes,
210 - transaction,
211 - context,
212 - ) {
213 - var nextChildren;
214 - var selfDebugID = 0;
215 - if (__DEV__) {
216 - selfDebugID = getDebugID(this);
217 - if (this._currentElement) {
218 - try {
219 - ReactCurrentOwner.current = this._currentElement._owner;
220 - ReactDebugCurrentFrame.getCurrentStack =
221 - ReactDebugCurrentStack.getStackAddendum;
222 - nextChildren = flattenStackChildren(
223 - nextNestedChildrenElements,
224 - selfDebugID,
225 - );
226 - } finally {
227 - ReactCurrentOwner.current = null;
228 - ReactDebugCurrentFrame.getCurrentStack = null;
229 - }
230 - ReactChildReconciler.updateChildren(
231 - prevChildren,
232 - nextChildren,
233 - mountImages,
234 - removedNodes,
235 - transaction,
236 - this,
237 - this._hostContainerInfo,
238 - context,
239 - selfDebugID,
240 - );
241 - return nextChildren;
242 - }
243 - }
244 - nextChildren = flattenStackChildren(
245 - nextNestedChildrenElements,
246 - selfDebugID,
247 - );
248 - ReactChildReconciler.updateChildren(
249 - prevChildren,
250 - nextChildren,
251 - mountImages,
252 - removedNodes,
253 - transaction,
254 - this,
255 - this._hostContainerInfo,
256 - context,
257 - selfDebugID,
258 - );
259 - return nextChildren;
260 - },
261 -
262 - /**
263 - * Generates a "mount image" for each of the supplied children. In the case
264 - * of `ReactDOMComponent`, a mount image is a string of markup.
265 - *
266 - * @param {?object} nestedChildren Nested child maps.
267 - * @return {array} An array of mounted representations.
268 - * @internal
269 - */
270 - mountChildren: function(nestedChildren, transaction, context) {
271 - var children = this._reconcilerInstantiateChildren(
272 - nestedChildren,
273 - transaction,
274 - context,
275 - );
276 - this._renderedChildren = children;
277 -
278 - var mountImages = [];
279 - var index = 0;
280 - for (var name in children) {
281 - if (children.hasOwnProperty(name)) {
282 - var child = children[name];
283 - var selfDebugID = 0;
284 - if (__DEV__) {
285 - selfDebugID = getDebugID(this);
286 - }
287 - var mountImage = ReactReconciler.mountComponent(
288 - child,
289 - transaction,
290 - this,
291 - this._hostContainerInfo,
292 - context,
293 - selfDebugID,
294 - );
295 - child._mountIndex = index++;
296 - mountImages.push(mountImage);
297 - }
298 - }
299 -
300 - if (__DEV__) {
301 - setChildrenForInstrumentation.call(this, children);
302 - }
303 -
304 - return mountImages;
305 - },
306 -
307 - /**
308 - * Replaces any rendered children with a text content string.
309 - *
310 - * @param {string} nextContent String of content.
311 - * @internal
312 - */
313 - updateTextContent: function(nextContent) {
314 - var prevChildren = this._renderedChildren;
315 - // Remove any rendered children.
316 - ReactChildReconciler.unmountChildren(
317 - prevChildren,
318 - false /* safely */,
319 - false /* skipLifecycle */,
320 - );
321 - for (var name in prevChildren) {
322 - if (prevChildren.hasOwnProperty(name)) {
323 - invariant(false, 'updateTextContent called on non-empty component.');
324 - }
325 - }
326 - // Set new text content.
327 - var updates = [makeTextContent(nextContent)];
328 - processQueue(this, updates);
329 - },
330 -
331 - /**
332 - * Replaces any rendered children with a markup string.
333 - *
334 - * @param {string} nextMarkup String of markup.
335 - * @internal
336 - */
337 - updateMarkup: function(nextMarkup) {
338 - var prevChildren = this._renderedChildren;
339 - // Remove any rendered children.
340 - ReactChildReconciler.unmountChildren(
341 - prevChildren,
342 - false /* safely */,
343 - false /* skipLifecycle */,
344 - );
345 - for (var name in prevChildren) {
346 - if (prevChildren.hasOwnProperty(name)) {
347 - invariant(false, 'updateTextContent called on non-empty component.');
348 - }
349 - }
350 - var updates = [makeSetMarkup(nextMarkup)];
351 - processQueue(this, updates);
352 - },
353 -
354 - /**
355 - * Updates the rendered children with new children.
356 - *
357 - * @param {?object} nextNestedChildrenElements Nested child element maps.
358 - * @param {ReactReconcileTransaction} transaction
359 - * @internal
360 - */
361 - updateChildren: function(nextNestedChildrenElements, transaction, context) {
362 - // Hook used by React ART
363 - this._updateChildren(nextNestedChildrenElements, transaction, context);
364 - },
365 -
366 - /**
367 - * @param {?object} nextNestedChildrenElements Nested child element maps.
368 - * @param {ReactReconcileTransaction} transaction
369 - * @final
370 - * @protected
371 - */
372 - _updateChildren: function(nextNestedChildrenElements, transaction, context) {
373 - var prevChildren = this._renderedChildren;
374 - var removedNodes = {};
375 - var mountImages = [];
376 - var nextChildren = this._reconcilerUpdateChildren(
377 - prevChildren,
378 - nextNestedChildrenElements,
379 - mountImages,
380 - removedNodes,
381 - transaction,
382 - context,
383 - );
384 - if (!nextChildren && !prevChildren) {
385 - return;
386 - }
387 - var updates = null;
388 - var name;
389 - // `nextIndex` will increment for each child in `nextChildren`, but
390 - // `lastIndex` will be the last index visited in `prevChildren`.
391 - var nextIndex = 0;
392 - var lastIndex = 0;
393 - // `nextMountIndex` will increment for each newly mounted child.
394 - var nextMountIndex = 0;
395 - var lastPlacedNode = null;
396 - for (name in nextChildren) {
397 - if (!nextChildren.hasOwnProperty(name)) {
398 - continue;
399 - }
400 - var prevChild = prevChildren && prevChildren[name];
401 - var nextChild = nextChildren[name];
402 - if (prevChild === nextChild) {
403 - updates = enqueue(
404 - updates,
405 - this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex),
406 - );
407 - lastIndex = Math.max(prevChild._mountIndex, lastIndex);
408 - prevChild._mountIndex = nextIndex;
409 - } else {
410 - if (prevChild) {
411 - // Update `lastIndex` before `_mountIndex` gets unset by unmounting.
412 - lastIndex = Math.max(prevChild._mountIndex, lastIndex);
413 - // The `removedNodes` loop below will actually remove the child.
414 - }
415 - // The child must be instantiated before it's mounted.
416 - updates = enqueue(
417 - updates,
418 - this._mountChildAtIndex(
419 - nextChild,
420 - mountImages[nextMountIndex],
421 - lastPlacedNode,
422 - nextIndex,
423 - transaction,
424 - context,
425 - ),
426 - );
427 - nextMountIndex++;
428 - }
429 - nextIndex++;
430 - lastPlacedNode = ReactReconciler.getHostNode(nextChild);
431 - }
432 - // Remove children that are no longer present.
433 - for (name in removedNodes) {
434 - if (removedNodes.hasOwnProperty(name)) {
435 - updates = enqueue(
436 - updates,
437 - this._unmountChild(prevChildren[name], removedNodes[name]),
438 - );
439 - }
440 - }
441 - if (updates) {
442 - processQueue(this, updates);
443 - }
444 - this._renderedChildren = nextChildren;
445 -
446 - if (__DEV__) {
447 - setChildrenForInstrumentation.call(this, nextChildren);
448 - }
449 - },
450 -
451 - /**
452 - * Unmounts all rendered children. This should be used to clean up children
453 - * when this component is unmounted. It does not actually perform any
454 - * backend operations.
455 - *
456 - * @internal
457 - */
458 - unmountChildren: function(safely, skipLifecycle) {
459 - var renderedChildren = this._renderedChildren;
460 - ReactChildReconciler.unmountChildren(
461 - renderedChildren,
462 - safely,
463 - skipLifecycle,
464 - );
465 - this._renderedChildren = null;
466 - },
467 -
468 - /**
469 - * Moves a child component to the supplied index.
470 - *
471 - * @param {ReactComponent} child Component to move.
472 - * @param {number} toIndex Destination index of the element.
473 - * @param {number} lastIndex Last index visited of the siblings of `child`.
474 - * @protected
475 - */
476 - moveChild: function(child, afterNode, toIndex, lastIndex) {
477 - // If the index of `child` is less than `lastIndex`, then it needs to
478 - // be moved. Otherwise, we do not need to move it because a child will be
479 - // inserted or moved before `child`.
480 - if (child._mountIndex < lastIndex) {
481 - return makeMove(child, afterNode, toIndex);
482 - }
483 - },
484 -
485 - /**
486 - * Creates a child component.
487 - *
488 - * @param {ReactComponent} child Component to create.
489 - * @param {string} mountImage Markup to insert.
490 - * @protected
491 - */
492 - createChild: function(child, afterNode, mountImage) {
493 - return makeInsertMarkup(mountImage, afterNode, child._mountIndex);
494 - },
495 -
496 - /**
497 - * Removes a child component.
498 - *
499 - * @param {ReactComponent} child Child to remove.
500 - * @protected
501 - */
502 - removeChild: function(child, node) {
503 - return makeRemove(child, node);
504 - },
505 -
506 - /**
507 - * Mounts a child with the supplied name.
508 - *
509 - * NOTE: This is part of `updateChildren` and is here for readability.
510 - *
511 - * @param {ReactComponent} child Component to mount.
512 - * @param {string} name Name of the child.
513 - * @param {number} index Index at which to insert the child.
514 - * @param {ReactReconcileTransaction} transaction
515 - * @private
516 - */
517 - _mountChildAtIndex: function(
518 - child,
519 - mountImage,
520 - afterNode,
521 - index,
522 - transaction,
523 - context,
524 - ) {
525 - child._mountIndex = index;
526 - return this.createChild(child, afterNode, mountImage);
527 - },
528 -
529 - /**
530 - * Unmounts a rendered child.
531 - *
532 - * NOTE: This is part of `updateChildren` and is here for readability.
533 - *
534 - * @param {ReactComponent} child Component to unmount.
535 - * @private
536 - */
537 - _unmountChild: function(child, node) {
538 - var update = this.removeChild(child, node);
539 - child._mountIndex = null;
540 - return update;
541 - },
542 -};
543 -
544 -module.exports = ReactMultiChild;
src/renderers/shared/stack/reconciler/ReactMultiChildUpdateTypes.js deleted
-23
@@ -1,23 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactMultiChildUpdateTypes
8 - */
9 -
10 -'use strict';
11 -
12 -/**
13 - * When a component's children are updated, a series of update configuration
14 - * objects are created in order to batch and serialize the required changes.
15 - *
16 - * Enumerates all the possible types of update configurations.
17 - */
18 -export type ReactMultiChildUpdateTypes =
19 - | 'INSERT_MARKUP'
20 - | 'MOVE_EXISTING'
21 - | 'REMOVE_NODE'
22 - | 'SET_MARKUP'
23 - | 'TEXT_CONTENT';
src/renderers/shared/stack/reconciler/ReactNodeTypes.js deleted
-38
@@ -1,38 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactNodeTypes
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -type ReactNodeType = 0 | 1 | 2;
14 -
15 -var React = require('react');
16 -
17 -var invariant = require('fbjs/lib/invariant');
18 -
19 -var ReactNodeTypes = {
20 - HOST: 0,
21 - COMPOSITE: 1,
22 - EMPTY: 2,
23 -
24 - getType: function(node: React$Element<any>): ReactNodeType {
25 - if (node === null || node === false) {
26 - return ReactNodeTypes.EMPTY;
27 - } else if (React.isValidElement(node)) {
28 - if (typeof node.type === 'function') {
29 - return ReactNodeTypes.COMPOSITE;
30 - } else {
31 - return ReactNodeTypes.HOST;
32 - }
33 - }
34 - invariant(false, 'Unexpected node: %s', node);
35 - },
36 -};
37 -
38 -module.exports = ReactNodeTypes;
src/renderers/shared/stack/reconciler/ReactOwner.js deleted
-133
@@ -1,133 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactOwner
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var {ClassComponent} = require('ReactTypeOfWork');
14 -
15 -var emptyObject = require('fbjs/lib/emptyObject');
16 -var invariant = require('fbjs/lib/invariant');
17 -
18 -import type {Fiber} from 'ReactFiber';
19 -import type {ReactInstance} from 'ReactInstanceType';
20 -
21 -/**
22 - * @param {?object} object
23 - * @return {boolean} True if `object` is a valid owner.
24 - * @final
25 - */
26 -function isValidOwner(object: any): boolean {
27 - return !!(object &&
28 - typeof object.attachRef === 'function' &&
29 - typeof object.detachRef === 'function');
30 -}
31 -
32 -/**
33 - * ReactOwners are capable of storing references to owned components.
34 - *
35 - * All components are capable of //being// referenced by owner components, but
36 - * only ReactOwner components are capable of //referencing// owned components.
37 - * The named reference is known as a "ref".
38 - *
39 - * Refs are available when mounted and updated during reconciliation.
40 - *
41 - * var MyComponent = React.createClass({
42 - * render: function() {
43 - * return (
44 - * <div onClick={this.handleClick}>
45 - * <CustomComponent ref="custom" />
46 - * </div>
47 - * );
48 - * },
49 - * handleClick: function() {
50 - * this.refs.custom.handleClick();
51 - * },
52 - * componentDidMount: function() {
53 - * this.refs.custom.initialize();
54 - * }
55 - * });
56 - *
57 - * Refs should rarely be used. When refs are used, they should only be done to
58 - * control data that is not handled by React's data flow.
59 - *
60 - * @class ReactOwner
61 - */
62 -var ReactOwner = {
63 - /**
64 - * Adds a component by ref to an owner component.
65 - *
66 - * @param {ReactComponent} component Component to reference.
67 - * @param {string} ref Name by which to refer to the component.
68 - * @param {ReactOwner} owner Component on which to record the ref.
69 - * @final
70 - * @internal
71 - */
72 - addComponentAsRefTo: function(
73 - component: ReactInstance,
74 - ref: string,
75 - owner: ReactInstance | Fiber,
76 - ): void {
77 - if (owner && (owner: any).tag === ClassComponent) {
78 - const inst = (owner: any).stateNode;
79 - const refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
80 - refs[ref] = component.getPublicInstance();
81 - } else {
82 - invariant(
83 - isValidOwner(owner),
84 - 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might ' +
85 - "be adding a ref to a component that was not created inside a component's " +
86 - '`render` method, or you have multiple copies of React loaded ' +
87 - '(details: https://fb.me/react-refs-must-have-owner).',
88 - );
89 - (owner: any).attachRef(ref, component);
90 - }
91 - },
92 -
93 - /**
94 - * Removes a component by ref from an owner component.
95 - *
96 - * @param {ReactComponent} component Component to dereference.
97 - * @param {string} ref Name of the ref to remove.
98 - * @param {ReactOwner} owner Component on which the ref is recorded.
99 - * @final
100 - * @internal
101 - */
102 - removeComponentAsRefFrom: function(
103 - component: ReactInstance,
104 - ref: string,
105 - owner: ReactInstance | Fiber,
106 - ): void {
107 - if (owner && (owner: any).tag === ClassComponent) {
108 - const inst = (owner: any).stateNode;
109 - if (inst && inst.refs[ref] === component.getPublicInstance()) {
110 - delete inst.refs[ref];
111 - }
112 - } else {
113 - invariant(
114 - isValidOwner(owner),
115 - 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might ' +
116 - "be removing a ref to a component that was not created inside a component's " +
117 - '`render` method, or you have multiple copies of React loaded ' +
118 - '(details: https://fb.me/react-refs-must-have-owner).',
119 - );
120 - var ownerPublicInstance = (owner: any).getPublicInstance();
121 - // Check that `component`'s owner is still alive and that `component` is still the current ref
122 - // because we do not want to detach the ref if another component stole it.
123 - if (
124 - ownerPublicInstance &&
125 - ownerPublicInstance.refs[ref] === component.getPublicInstance()
126 - ) {
127 - (owner: any).detachRef(ref);
128 - }
129 - }
130 - },
131 -};
132 -
133 -module.exports = ReactOwner;
src/renderers/shared/stack/reconciler/ReactReconciler.js deleted
-223
@@ -1,223 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactReconciler
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactRef = require('ReactRef');
13 -var ReactInstrumentation = require('ReactInstrumentation');
14 -
15 -if (__DEV__) {
16 - var warning = require('fbjs/lib/warning');
17 -}
18 -
19 -/**
20 - * Helper to call ReactRef.attachRefs with this composite component, split out
21 - * to avoid allocations in the transaction mount-ready queue.
22 - */
23 -function attachRefs() {
24 - ReactRef.attachRefs(this, this._currentElement);
25 -}
26 -
27 -var ReactReconciler = {
28 - /**
29 - * Initializes the component, renders markup, and registers event listeners.
30 - *
31 - * @param {ReactComponent} internalInstance
32 - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
33 - * @param {?object} hostParent the containing host component instance
34 - * @param {?object} hostContainerInfo info about the host container
35 - * @return {?string} Rendered markup to be inserted into the DOM.
36 - * @final
37 - * @internal
38 - */
39 - mountComponent: function(
40 - internalInstance,
41 - transaction,
42 - hostParent,
43 - hostContainerInfo,
44 - context,
45 - parentDebugID, // 0 in production and for roots
46 - ) {
47 - if (__DEV__) {
48 - if (internalInstance._debugID !== 0) {
49 - ReactInstrumentation.debugTool.onBeforeMountComponent(
50 - internalInstance._debugID,
51 - internalInstance._currentElement,
52 - parentDebugID,
53 - );
54 - }
55 - }
56 - var markup = internalInstance.mountComponent(
57 - transaction,
58 - hostParent,
59 - hostContainerInfo,
60 - context,
61 - parentDebugID,
62 - );
63 - if (
64 - internalInstance._currentElement &&
65 - internalInstance._currentElement.ref != null
66 - ) {
67 - transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
68 - }
69 - if (__DEV__) {
70 - if (internalInstance._debugID !== 0) {
71 - ReactInstrumentation.debugTool.onMountComponent(
72 - internalInstance._debugID,
73 - );
74 - }
75 - }
76 - return markup;
77 - },
78 -
79 - /**
80 - * Returns a value that can be passed to
81 - * ReactComponentEnvironment.replaceNodeWithMarkup.
82 - */
83 - getHostNode: function(internalInstance) {
84 - return internalInstance.getHostNode();
85 - },
86 -
87 - /**
88 - * Releases any resources allocated by `mountComponent`.
89 - *
90 - * @final
91 - * @internal
92 - */
93 - unmountComponent: function(internalInstance, safely, skipLifecycle) {
94 - if (__DEV__) {
95 - if (internalInstance._debugID !== 0) {
96 - ReactInstrumentation.debugTool.onBeforeUnmountComponent(
97 - internalInstance._debugID,
98 - );
99 - }
100 - }
101 - ReactRef.detachRefs(internalInstance, internalInstance._currentElement);
102 - internalInstance.unmountComponent(safely, skipLifecycle);
103 - if (__DEV__) {
104 - if (internalInstance._debugID !== 0) {
105 - ReactInstrumentation.debugTool.onUnmountComponent(
106 - internalInstance._debugID,
107 - );
108 - }
109 - }
110 - },
111 -
112 - /**
113 - * Update a component using a new element.
114 - *
115 - * @param {ReactComponent} internalInstance
116 - * @param {ReactElement} nextElement
117 - * @param {ReactReconcileTransaction} transaction
118 - * @param {object} context
119 - * @internal
120 - */
121 - receiveComponent: function(
122 - internalInstance,
123 - nextElement,
124 - transaction,
125 - context,
126 - ) {
127 - var prevElement = internalInstance._currentElement;
128 -
129 - if (nextElement === prevElement && context === internalInstance._context) {
130 - // Since elements are immutable after the owner is rendered,
131 - // we can do a cheap identity compare here to determine if this is a
132 - // superfluous reconcile. It's possible for state to be mutable but such
133 - // change should trigger an update of the owner which would recreate
134 - // the element. We explicitly check for the existence of an owner since
135 - // it's possible for an element created outside a composite to be
136 - // deeply mutated and reused.
137 -
138 - // TODO: Bailing out early is just a perf optimization right?
139 - // TODO: Removing the return statement should affect correctness?
140 - return;
141 - }
142 -
143 - if (__DEV__) {
144 - if (internalInstance._debugID !== 0) {
145 - ReactInstrumentation.debugTool.onBeforeUpdateComponent(
146 - internalInstance._debugID,
147 - nextElement,
148 - );
149 - }
150 - }
151 -
152 - var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);
153 -
154 - if (refsChanged) {
155 - ReactRef.detachRefs(internalInstance, prevElement);
156 - }
157 -
158 - internalInstance.receiveComponent(nextElement, transaction, context);
159 -
160 - if (
161 - refsChanged &&
162 - internalInstance._currentElement &&
163 - internalInstance._currentElement.ref != null
164 - ) {
165 - transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
166 - }
167 -
168 - if (__DEV__) {
169 - if (internalInstance._debugID !== 0) {
170 - ReactInstrumentation.debugTool.onUpdateComponent(
171 - internalInstance._debugID,
172 - );
173 - }
174 - }
175 - },
176 -
177 - /**
178 - * Flush any dirty changes in a component.
179 - *
180 - * @param {ReactComponent} internalInstance
181 - * @param {ReactReconcileTransaction} transaction
182 - * @internal
183 - */
184 - performUpdateIfNecessary: function(
185 - internalInstance,
186 - transaction,
187 - updateBatchNumber,
188 - ) {
189 - if (internalInstance._updateBatchNumber !== updateBatchNumber) {
190 - if (__DEV__) {
191 - // The component's enqueued batch number should always be the current
192 - // batch or the following one.
193 - warning(
194 - internalInstance._updateBatchNumber == null ||
195 - internalInstance._updateBatchNumber === updateBatchNumber + 1,
196 - 'performUpdateIfNecessary: Unexpected batch number (current %s, ' +
197 - 'pending %s)',
198 - updateBatchNumber,
199 - internalInstance._updateBatchNumber,
200 - );
201 - }
202 - return;
203 - }
204 - if (__DEV__) {
205 - if (internalInstance._debugID !== 0) {
206 - ReactInstrumentation.debugTool.onBeforeUpdateComponent(
207 - internalInstance._debugID,
208 - internalInstance._currentElement,
209 - );
210 - }
211 - }
212 - internalInstance.performUpdateIfNecessary(transaction);
213 - if (__DEV__) {
214 - if (internalInstance._debugID !== 0) {
215 - ReactInstrumentation.debugTool.onUpdateComponent(
216 - internalInstance._debugID,
217 - );
218 - }
219 - }
220 - },
221 -};
222 -
223 -module.exports = ReactReconciler;
src/renderers/shared/stack/reconciler/ReactRef.js deleted
-144
@@ -1,144 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactRef
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var ReactOwner = require('ReactOwner');
14 -
15 -import type {ReactInstance} from 'ReactInstanceType';
16 -import type {ReactElement} from 'ReactElementType';
17 -
18 -var ReactRef = {};
19 -
20 -if (__DEV__) {
21 - var ReactCompositeComponentTypes = require('ReactCompositeComponentTypes');
22 - var {ReactComponentTreeHook} = require('ReactGlobalSharedState');
23 - var warning = require('fbjs/lib/warning');
24 -
25 - var warnedAboutStatelessRefs = {};
26 -}
27 -
28 -function attachRef(ref, component, owner) {
29 - if (__DEV__) {
30 - if (
31 - component._compositeType ===
32 - ReactCompositeComponentTypes.StatelessFunctional
33 - ) {
34 - let info = '';
35 - let ownerName;
36 - if (owner) {
37 - if (typeof owner.getName === 'function') {
38 - ownerName = owner.getName();
39 - }
40 - if (ownerName) {
41 - info += '\n\nCheck the render method of `' + ownerName + '`.';
42 - }
43 - }
44 -
45 - let warningKey = ownerName || component._debugID;
46 - let element = component._currentElement;
47 - if (element && element._source) {
48 - warningKey =
49 - element._source.fileName + ':' + element._source.lineNumber;
50 - }
51 - if (!warnedAboutStatelessRefs[warningKey]) {
52 - warnedAboutStatelessRefs[warningKey] = true;
53 - warning(
54 - false,
55 - 'Stateless function components cannot be given refs. ' +
56 - 'Attempts to access this ref will fail.%s%s',
57 - info,
58 - ReactComponentTreeHook.getStackAddendumByID(component._debugID),
59 - );
60 - }
61 - }
62 - }
63 -
64 - if (typeof ref === 'function') {
65 - ref(component.getPublicInstance());
66 - } else {
67 - // Legacy ref
68 - ReactOwner.addComponentAsRefTo(component, ref, owner);
69 - }
70 -}
71 -
72 -function detachRef(ref, component, owner) {
73 - if (typeof ref === 'function') {
74 - ref(null);
75 - } else {
76 - // Legacy ref
77 - ReactOwner.removeComponentAsRefFrom(component, ref, owner);
78 - }
79 -}
80 -
81 -ReactRef.attachRefs = function(
82 - instance: ReactInstance,
83 - element: ReactElement | string | number | null | false,
84 -): void {
85 - if (element === null || typeof element !== 'object') {
86 - return;
87 - }
88 - var ref = element.ref;
89 - if (ref != null) {
90 - attachRef(ref, instance, element._owner);
91 - }
92 -};
93 -
94 -ReactRef.shouldUpdateRefs = function(
95 - prevElement: ReactElement | string | number | null | false,
96 - nextElement: ReactElement | string | number | null | false,
97 -): boolean {
98 - // If either the owner or a `ref` has changed, make sure the newest owner
99 - // has stored a reference to `this`, and the previous owner (if different)
100 - // has forgotten the reference to `this`. We use the element instead
101 - // of the public this.props because the post processing cannot determine
102 - // a ref. The ref conceptually lives on the element.
103 -
104 - // TODO: Should this even be possible? The owner cannot change because
105 - // it's forbidden by shouldUpdateReactComponent. The ref can change
106 - // if you swap the keys of but not the refs. Reconsider where this check
107 - // is made. It probably belongs where the key checking and
108 - // instantiateReactComponent is done.
109 -
110 - var prevRef = null;
111 - var prevOwner = null;
112 - if (prevElement !== null && typeof prevElement === 'object') {
113 - prevRef = prevElement.ref;
114 - prevOwner = prevElement._owner;
115 - }
116 -
117 - var nextRef = null;
118 - var nextOwner = null;
119 - if (nextElement !== null && typeof nextElement === 'object') {
120 - nextRef = nextElement.ref;
121 - nextOwner = nextElement._owner;
122 - }
123 -
124 - return (
125 - prevRef !== nextRef ||
126 - // If owner changes but we have an unchanged function ref, don't update refs
127 - (typeof nextRef === 'string' && nextOwner !== prevOwner)
128 - );
129 -};
130 -
131 -ReactRef.detachRefs = function(
132 - instance: ReactInstance,
133 - element: ReactElement | string | number | null | false,
134 -): void {
135 - if (element === null || typeof element !== 'object') {
136 - return;
137 - }
138 - var ref = element.ref;
139 - if (ref != null) {
140 - detachRef(ref, instance, element._owner);
141 - }
142 -};
143 -
144 -module.exports = ReactRef;
src/renderers/shared/stack/reconciler/ReactSimpleEmptyComponent.js deleted
-49
@@ -1,49 +0,0 @@
1 -/**
2 - * Copyright (c) 2014-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactSimpleEmptyComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactReconciler = require('ReactReconciler');
13 -
14 -var ReactSimpleEmptyComponent = function(placeholderElement, instantiate) {
15 - this._currentElement = null;
16 - this._renderedComponent = instantiate(placeholderElement);
17 -};
18 -Object.assign(ReactSimpleEmptyComponent.prototype, {
19 - mountComponent: function(
20 - transaction,
21 - hostParent,
22 - hostContainerInfo,
23 - context,
24 - parentDebugID, // 0 in production and for roots
25 - ) {
26 - return ReactReconciler.mountComponent(
27 - this._renderedComponent,
28 - transaction,
29 - hostParent,
30 - hostContainerInfo,
31 - context,
32 - parentDebugID,
33 - );
34 - },
35 - receiveComponent: function() {},
36 - getHostNode: function() {
37 - return ReactReconciler.getHostNode(this._renderedComponent);
38 - },
39 - unmountComponent: function(safely, skipLifecycle) {
40 - ReactReconciler.unmountComponent(
41 - this._renderedComponent,
42 - safely,
43 - skipLifecycle,
44 - );
45 - this._renderedComponent = null;
46 - },
47 -});
48 -
49 -module.exports = ReactSimpleEmptyComponent;
src/renderers/shared/stack/reconciler/ReactUpdateQueue.js deleted
-255
@@ -1,255 +0,0 @@
1 -/**
2 - * Copyright (c) 2015-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactUpdateQueue
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactInstanceMap = require('ReactInstanceMap');
13 -var ReactInstrumentation = require('ReactInstrumentation');
14 -var ReactUpdates = require('ReactUpdates');
15 -var {ReactCurrentOwner} = require('ReactGlobalSharedState');
16 -
17 -if (__DEV__) {
18 - var warning = require('fbjs/lib/warning');
19 - var warnOnInvalidCallback = function(callback: mixed, callerName: string) {
20 - warning(
21 - callback === null || typeof callback === 'function',
22 - '%s(...): Expected the last optional `callback` argument to be a ' +
23 - 'function. Instead received: %s.',
24 - callerName,
25 - '' + callback,
26 - );
27 - };
28 -}
29 -
30 -function enqueueUpdate(internalInstance) {
31 - ReactUpdates.enqueueUpdate(internalInstance);
32 -}
33 -
34 -function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
35 - var internalInstance = ReactInstanceMap.get(publicInstance);
36 - if (!internalInstance) {
37 - if (__DEV__) {
38 - var ctor = publicInstance.constructor;
39 - warning(
40 - false,
41 - 'Can only update a mounted or mounting component. This usually means ' +
42 - 'you called setState, replaceState, or forceUpdate on an unmounted ' +
43 - 'component. This is a no-op.\n\nPlease check the code for the ' +
44 - '%s component.',
45 - (ctor && (ctor.displayName || ctor.name)) || 'ReactClass',
46 - );
47 - }
48 - return null;
49 - }
50 -
51 - if (__DEV__) {
52 - warning(
53 - ReactCurrentOwner.current == null,
54 - 'Cannot update during an existing state transition (such as within ' +
55 - "`render` or another component's constructor). Render methods should " +
56 - 'be a pure function of props and state; constructor side-effects are ' +
57 - 'an anti-pattern, but can be moved to `componentWillMount`.',
58 - );
59 - }
60 -
61 - return internalInstance;
62 -}
63 -
64 -/**
65 - * ReactUpdateQueue allows for state updates to be scheduled into a later
66 - * reconciliation step.
67 - */
68 -var ReactUpdateQueue = {
69 - /**
70 - * Checks whether or not this composite component is mounted.
71 - * @param {ReactClass} publicInstance The instance we want to test.
72 - * @return {boolean} True if mounted, false otherwise.
73 - * @protected
74 - * @final
75 - */
76 - isMounted: function(publicInstance) {
77 - if (__DEV__) {
78 - var owner = ReactCurrentOwner.current;
79 - if (owner !== null) {
80 - warning(
81 - owner._warnedAboutRefsInRender,
82 - '%s is accessing isMounted inside its render() function. ' +
83 - 'render() should be a pure function of props and state. It should ' +
84 - 'never access something that requires stale data from the previous ' +
85 - 'render, such as refs. Move this logic to componentDidMount and ' +
86 - 'componentDidUpdate instead.',
87 - owner.getName() || 'A component',
88 - );
89 - owner._warnedAboutRefsInRender = true;
90 - }
91 - }
92 - var internalInstance = ReactInstanceMap.get(publicInstance);
93 - if (internalInstance) {
94 - // During componentWillMount and render this will still be null but after
95 - // that will always render to something. At least for now. So we can use
96 - // this hack.
97 - return !!internalInstance._renderedComponent;
98 - } else {
99 - return false;
100 - }
101 - },
102 -
103 - enqueueCallbackInternal: function(internalInstance, callback) {
104 - if (internalInstance._pendingCallbacks) {
105 - internalInstance._pendingCallbacks.push(callback);
106 - } else {
107 - internalInstance._pendingCallbacks = [callback];
108 - }
109 - enqueueUpdate(internalInstance);
110 - },
111 -
112 - /**
113 - * Forces an update. This should only be invoked when it is known with
114 - * certainty that we are **not** in a DOM transaction.
115 - *
116 - * You may want to call this when you know that some deeper aspect of the
117 - * component's state has changed but `setState` was not called.
118 - *
119 - * This will not invoke `shouldComponentUpdate`, but it will invoke
120 - * `componentWillUpdate` and `componentDidUpdate`.
121 - *
122 - * @param {ReactClass} publicInstance The instance that should rerender.
123 - * @param {?function} callback Called after component is updated.
124 - * @param {?string} callerName Name of the calling function in the public API.
125 - * @internal
126 - */
127 - enqueueForceUpdate: function(publicInstance, callback, callerName) {
128 - var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
129 -
130 - if (!internalInstance) {
131 - return;
132 - }
133 -
134 - callback = callback === undefined ? null : callback;
135 - if (callback !== null) {
136 - if (__DEV__) {
137 - warnOnInvalidCallback(callback, callerName);
138 - }
139 - if (internalInstance._pendingCallbacks) {
140 - internalInstance._pendingCallbacks.push(callback);
141 - } else {
142 - internalInstance._pendingCallbacks = [callback];
143 - }
144 - }
145 -
146 - internalInstance._pendingForceUpdate = true;
147 -
148 - enqueueUpdate(internalInstance);
149 - },
150 -
151 - /**
152 - * Replaces all of the state. Always use this or `setState` to mutate state.
153 - * You should treat `this.state` as immutable.
154 - *
155 - * There is no guarantee that `this.state` will be immediately updated, so
156 - * accessing `this.state` after calling this method may return the old value.
157 - *
158 - * @param {ReactClass} publicInstance The instance that should rerender.
159 - * @param {object} completeState Next state.
160 - * @param {?function} callback Called after state is updated.
161 - * @param {?string} Name of the calling function in the public API.
162 - * @internal
163 - */
164 - enqueueReplaceState: function(
165 - publicInstance,
166 - completeState,
167 - callback,
168 - callerName,
169 - ) {
170 - var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
171 -
172 - if (!internalInstance) {
173 - return;
174 - }
175 -
176 - internalInstance._pendingStateQueue = [completeState];
177 - internalInstance._pendingReplaceState = true;
178 -
179 - callback = callback === undefined ? null : callback;
180 - if (callback !== null) {
181 - if (__DEV__) {
182 - warnOnInvalidCallback(callback, callerName);
183 - }
184 - if (internalInstance._pendingCallbacks) {
185 - internalInstance._pendingCallbacks.push(callback);
186 - } else {
187 - internalInstance._pendingCallbacks = [callback];
188 - }
189 - }
190 -
191 - enqueueUpdate(internalInstance);
192 - },
193 -
194 - /**
195 - * Sets a subset of the state. This only exists because _pendingState is
196 - * internal. This provides a merging strategy that is not available to deep
197 - * properties which is confusing. TODO: Expose pendingState or don't use it
198 - * during the merge.
199 - *
200 - * @param {ReactClass} publicInstance The instance that should rerender.
201 - * @param {object} partialState Next partial state to be merged with state.
202 - * @param {?function} callback Called after state is updated.
203 - * @param {?string} Name of the calling function in the public API.
204 - * @internal
205 - */
206 - enqueueSetState: function(
207 - publicInstance,
208 - partialState,
209 - callback,
210 - callerName,
211 - ) {
212 - if (__DEV__) {
213 - ReactInstrumentation.debugTool.onSetState();
214 - warning(
215 - partialState != null,
216 - 'setState(...): You passed an undefined or null state object; ' +
217 - 'instead, use forceUpdate().',
218 - );
219 - }
220 -
221 - var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
222 -
223 - if (!internalInstance) {
224 - return;
225 - }
226 -
227 - var queue =
228 - internalInstance._pendingStateQueue ||
229 - (internalInstance._pendingStateQueue = []);
230 - queue.push(partialState);
231 -
232 - callback = callback === undefined ? null : callback;
233 - if (callback !== null) {
234 - if (__DEV__) {
235 - warnOnInvalidCallback(callback, callerName);
236 - }
237 - if (internalInstance._pendingCallbacks) {
238 - internalInstance._pendingCallbacks.push(callback);
239 - } else {
240 - internalInstance._pendingCallbacks = [callback];
241 - }
242 - }
243 -
244 - enqueueUpdate(internalInstance);
245 - },
246 -
247 - enqueueElementInternal: function(internalInstance, nextElement, nextContext) {
248 - internalInstance._pendingElement = nextElement;
249 - // TODO: introduce _pendingContext instead of setting it directly.
250 - internalInstance._context = nextContext;
251 - enqueueUpdate(internalInstance);
252 - },
253 -};
254 -
255 -module.exports = ReactUpdateQueue;
src/renderers/shared/stack/reconciler/ReactUpdates.js deleted
-220
@@ -1,220 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule ReactUpdates
8 - */
9 -
10 -'use strict';
11 -
12 -var PooledClass = require('PooledClass');
13 -var ReactReconciler = require('ReactReconciler');
14 -var Transaction = require('Transaction');
15 -
16 -var invariant = require('fbjs/lib/invariant');
17 -
18 -var dirtyComponents = [];
19 -var updateBatchNumber = 0;
20 -
21 -var batchingStrategy = null;
22 -
23 -function ensureInjected() {
24 - invariant(
25 - ReactUpdates.ReactReconcileTransaction && batchingStrategy,
26 - 'ReactUpdates: must inject a reconcile transaction class and batching ' +
27 - 'strategy',
28 - );
29 -}
30 -
31 -var NESTED_UPDATES = {
32 - initialize: function() {
33 - this.dirtyComponentsLength = dirtyComponents.length;
34 - },
35 - close: function() {
36 - if (this.dirtyComponentsLength !== dirtyComponents.length) {
37 - // Additional updates were enqueued by componentDidUpdate handlers or
38 - // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run
39 - // these new updates so that if A's componentDidUpdate calls setState on
40 - // B, B will update before the callback A's updater provided when calling
41 - // setState.
42 - dirtyComponents.splice(0, this.dirtyComponentsLength);
43 - flushBatchedUpdates();
44 - } else {
45 - dirtyComponents.length = 0;
46 - }
47 - },
48 -};
49 -
50 -var TRANSACTION_WRAPPERS = [NESTED_UPDATES];
51 -
52 -function ReactUpdatesFlushTransaction() {
53 - this.reinitializeTransaction();
54 - this.dirtyComponentsLength = null;
55 - this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(
56 - /* useCreateElement */ true,
57 - );
58 -}
59 -
60 -Object.assign(ReactUpdatesFlushTransaction.prototype, Transaction, {
61 - getTransactionWrappers: function() {
62 - return TRANSACTION_WRAPPERS;
63 - },
64 -
65 - destructor: function() {
66 - this.dirtyComponentsLength = null;
67 - ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);
68 - this.reconcileTransaction = null;
69 - },
70 -
71 - perform: function(method, scope, a) {
72 - // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`
73 - // with this transaction's wrappers around it.
74 - return Transaction.perform.call(
75 - this,
76 - this.reconcileTransaction.perform,
77 - this.reconcileTransaction,
78 - method,
79 - scope,
80 - a,
81 - );
82 - },
83 -});
84 -
85 -PooledClass.addPoolingTo(ReactUpdatesFlushTransaction);
86 -
87 -function batchedUpdates(callback, a, b, c, d, e) {
88 - ensureInjected();
89 - return batchingStrategy.batchedUpdates(callback, a, b, c, d, e);
90 -}
91 -
92 -/**
93 - * Array comparator for ReactComponents by mount ordering.
94 - *
95 - * @param {ReactComponent} c1 first component you're comparing
96 - * @param {ReactComponent} c2 second component you're comparing
97 - * @return {number} Return value usable by Array.prototype.sort().
98 - */
99 -function mountOrderComparator(c1, c2) {
100 - return c1._mountOrder - c2._mountOrder;
101 -}
102 -
103 -function runBatchedUpdates(transaction) {
104 - var len = transaction.dirtyComponentsLength;
105 - invariant(
106 - len === dirtyComponents.length,
107 - "Expected flush transaction's stored dirty-components length (%s) to " +
108 - 'match dirty-components array length (%s).',
109 - len,
110 - dirtyComponents.length,
111 - );
112 -
113 - // Since reconciling a component higher in the owner hierarchy usually (not
114 - // always -- see shouldComponentUpdate()) will reconcile children, reconcile
115 - // them before their children by sorting the array.
116 - dirtyComponents.sort(mountOrderComparator);
117 -
118 - // Any updates enqueued while reconciling must be performed after this entire
119 - // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and
120 - // C, B could update twice in a single batch if C's render enqueues an update
121 - // to B (since B would have already updated, we should skip it, and the only
122 - // way we can know to do so is by checking the batch counter).
123 - updateBatchNumber++;
124 -
125 - for (var i = 0; i < len; i++) {
126 - // If a component is unmounted before pending changes apply, it will still
127 - // be here, but we assume that it has cleared its _pendingCallbacks and
128 - // that performUpdateIfNecessary is a noop.
129 - var component = dirtyComponents[i];
130 -
131 - ReactReconciler.performUpdateIfNecessary(
132 - component,
133 - transaction.reconcileTransaction,
134 - updateBatchNumber,
135 - );
136 - }
137 -}
138 -
139 -var flushBatchedUpdates = function() {
140 - // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
141 - // array and perform any updates enqueued by mount-ready handlers (i.e.,
142 - // componentDidUpdate) but we need to check here too in order to catch
143 - // updates enqueued by setState callbacks.
144 - while (dirtyComponents.length) {
145 - var transaction = ReactUpdatesFlushTransaction.getPooled();
146 - transaction.perform(runBatchedUpdates, null, transaction);
147 - ReactUpdatesFlushTransaction.release(transaction);
148 - }
149 -};
150 -
151 -/**
152 - * Mark a component as needing a rerender, adding an optional callback to a
153 - * list of functions which will be executed once the rerender occurs.
154 - */
155 -function enqueueUpdate(component) {
156 - ensureInjected();
157 -
158 - // Various parts of our code (such as ReactCompositeComponent's
159 - // _renderValidatedComponent) assume that calls to render aren't nested;
160 - // verify that that's the case. (This is called by each top-level update
161 - // function, like setState, forceUpdate, etc.; creation and
162 - // destruction of top-level components is guarded in ReactMount.)
163 -
164 - if (!batchingStrategy.isBatchingUpdates) {
165 - batchingStrategy.batchedUpdates(enqueueUpdate, component);
166 - return;
167 - }
168 -
169 - dirtyComponents.push(component);
170 - if (component._updateBatchNumber == null) {
171 - component._updateBatchNumber = updateBatchNumber + 1;
172 - }
173 -}
174 -
175 -var ReactUpdatesInjection = {
176 - injectReconcileTransaction: function(ReconcileTransaction) {
177 - invariant(
178 - ReconcileTransaction,
179 - 'ReactUpdates: must provide a reconcile transaction class',
180 - );
181 - ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
182 - },
183 -
184 - injectBatchingStrategy: function(_batchingStrategy) {
185 - invariant(
186 - _batchingStrategy,
187 - 'ReactUpdates: must provide a batching strategy',
188 - );
189 - invariant(
190 - typeof _batchingStrategy.batchedUpdates === 'function',
191 - 'ReactUpdates: must provide a batchedUpdates() function',
192 - );
193 - invariant(
194 - typeof _batchingStrategy.isBatchingUpdates === 'boolean',
195 - 'ReactUpdates: must provide an isBatchingUpdates boolean attribute',
196 - );
197 - batchingStrategy = _batchingStrategy;
198 - },
199 -
200 - getBatchingStrategy: function() {
201 - return batchingStrategy;
202 - },
203 -};
204 -
205 -var ReactUpdates = {
206 - /**
207 - * React references `ReactReconcileTransaction` using this property in order
208 - * to allow dependency injection.
209 - *
210 - * @internal
211 - */
212 - ReactReconcileTransaction: null,
213 -
214 - batchedUpdates: batchedUpdates,
215 - enqueueUpdate: enqueueUpdate,
216 - flushBatchedUpdates: flushBatchedUpdates,
217 - injection: ReactUpdatesInjection,
218 -};
219 -
220 -module.exports = ReactUpdates;
src/renderers/shared/stack/reconciler/Transaction.js deleted
-241
@@ -1,241 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule Transaction
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var invariant = require('fbjs/lib/invariant');
14 -
15 -var OBSERVED_ERROR = {};
16 -
17 -/**
18 - * `Transaction` creates a black box that is able to wrap any method such that
19 - * certain invariants are maintained before and after the method is invoked
20 - * (Even if an exception is thrown while invoking the wrapped method). Whoever
21 - * instantiates a transaction can provide enforcers of the invariants at
22 - * creation time. The `Transaction` class itself will supply one additional
23 - * automatic invariant for you - the invariant that any transaction instance
24 - * should not be run while it is already being run. You would typically create a
25 - * single instance of a `Transaction` for reuse multiple times, that potentially
26 - * is used to wrap several different methods. Wrappers are extremely simple -
27 - * they only require implementing two methods.
28 - *
29 - * <pre>
30 - * wrappers (injected at creation time)
31 - * + +
32 - * | |
33 - * +-----------------|--------|--------------+
34 - * | v | |
35 - * | +---------------+ | |
36 - * | +--| wrapper1 |---|----+ |
37 - * | | +---------------+ v | |
38 - * | | +-------------+ | |
39 - * | | +----| wrapper2 |--------+ |
40 - * | | | +-------------+ | | |
41 - * | | | | | |
42 - * | v v v v | wrapper
43 - * | +---+ +---+ +---------+ +---+ +---+ | invariants
44 - * perform(anyMethod) | | | | | | | | | | | | maintained
45 - * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
46 - * | | | | | | | | | | | |
47 - * | | | | | | | | | | | |
48 - * | | | | | | | | | | | |
49 - * | +---+ +---+ +---------+ +---+ +---+ |
50 - * | initialize close |
51 - * +-----------------------------------------+
52 - * </pre>
53 - *
54 - * Use cases:
55 - * - Preserving the input selection ranges before/after reconciliation.
56 - * Restoring selection even in the event of an unexpected error.
57 - * - Deactivating events while rearranging the DOM, preventing blurs/focuses,
58 - * while guaranteeing that afterwards, the event system is reactivated.
59 - * - Flushing a queue of collected DOM mutations to the main UI thread after a
60 - * reconciliation takes place in a worker thread.
61 - * - Invoking any collected `componentDidUpdate` callbacks after rendering new
62 - * content.
63 - * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue
64 - * to preserve the `scrollTop` (an automatic scroll aware DOM).
65 - * - (Future use case): Layout calculations before and after DOM updates.
66 - *
67 - * Transactional plugin API:
68 - * - A module that has an `initialize` method that returns any precomputation.
69 - * - and a `close` method that accepts the precomputation. `close` is invoked
70 - * when the wrapped process is completed, or has failed.
71 - *
72 - * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules
73 - * that implement `initialize` and `close`.
74 - * @return {Transaction} Single transaction for reuse in thread.
75 - *
76 - * @class Transaction
77 - */
78 -var TransactionImpl = {
79 - /**
80 - * Sets up this instance so that it is prepared for collecting metrics. Does
81 - * so such that this setup method may be used on an instance that is already
82 - * initialized, in a way that does not consume additional memory upon reuse.
83 - * That can be useful if you decide to make your subclass of this mixin a
84 - * "PooledClass".
85 - */
86 - reinitializeTransaction: function(): void {
87 - this.transactionWrappers = this.getTransactionWrappers();
88 - if (this.wrapperInitData) {
89 - this.wrapperInitData.length = 0;
90 - } else {
91 - this.wrapperInitData = [];
92 - }
93 - this._isInTransaction = false;
94 - },
95 -
96 - _isInTransaction: false,
97 -
98 - /**
99 - * @abstract
100 - * @return {Array<TransactionWrapper>} Array of transaction wrappers.
101 - */
102 - getTransactionWrappers: null,
103 -
104 - isInTransaction: function(): boolean {
105 - return !!this._isInTransaction;
106 - },
107 -
108 - /**
109 - * Executes the function within a safety window. Use this for the top level
110 - * methods that result in large amounts of computation/mutations that would
111 - * need to be safety checked. The optional arguments helps prevent the need
112 - * to bind in many cases.
113 - *
114 - * @param {function} method Member of scope to call.
115 - * @param {Object} scope Scope to invoke from.
116 - * @param {Object?=} a Argument to pass to the method.
117 - * @param {Object?=} b Argument to pass to the method.
118 - * @param {Object?=} c Argument to pass to the method.
119 - * @param {Object?=} d Argument to pass to the method.
120 - * @param {Object?=} e Argument to pass to the method.
121 - * @param {Object?=} f Argument to pass to the method.
122 - *
123 - * @return {*} Return value from `method`.
124 - */
125 - perform: function<
126 - A,
127 - B,
128 - C,
129 - D,
130 - E,
131 - F,
132 - G,
133 - T: (a: A, b: B, c: C, d: D, e: E, f: F) => G
134 - >(method: T, scope: any, a: A, b: B, c: C, d: D, e: E, f: F): G {
135 - invariant(
136 - !this.isInTransaction(),
137 - 'Transaction.perform(...): Cannot initialize a transaction when there ' +
138 - 'is already an outstanding transaction.',
139 - );
140 - var errorThrown;
141 - var ret;
142 - try {
143 - this._isInTransaction = true;
144 - // Catching errors makes debugging more difficult, so we start with
145 - // errorThrown set to true before setting it to false after calling
146 - // close -- if it's still set to true in the finally block, it means
147 - // one of these calls threw.
148 - errorThrown = true;
149 - this.initializeAll(0);
150 - ret = method.call(scope, a, b, c, d, e, f);
151 - errorThrown = false;
152 - } finally {
153 - try {
154 - if (errorThrown) {
155 - // If `method` throws, prefer to show that stack trace over any thrown
156 - // by invoking `closeAll`.
157 - try {
158 - this.closeAll(0);
159 - } catch (err) {}
160 - } else {
161 - // Since `method` didn't throw, we don't want to silence the exception
162 - // here.
163 - this.closeAll(0);
164 - }
165 - } finally {
166 - this._isInTransaction = false;
167 - }
168 - }
169 - return ret;
170 - },
171 -
172 - initializeAll: function(startIndex: number): void {
173 - var transactionWrappers = this.transactionWrappers;
174 - for (var i = startIndex; i < transactionWrappers.length; i++) {
175 - var wrapper = transactionWrappers[i];
176 - try {
177 - // Catching errors makes debugging more difficult, so we start with the
178 - // OBSERVED_ERROR state before overwriting it with the real return value
179 - // of initialize -- if it's still set to OBSERVED_ERROR in the finally
180 - // block, it means wrapper.initialize threw.
181 - this.wrapperInitData[i] = OBSERVED_ERROR;
182 - this.wrapperInitData[i] = wrapper.initialize
183 - ? wrapper.initialize.call(this)
184 - : null;
185 - } finally {
186 - if (this.wrapperInitData[i] === OBSERVED_ERROR) {
187 - // The initializer for wrapper i threw an error; initialize the
188 - // remaining wrappers but silence any exceptions from them to ensure
189 - // that the first error is the one to bubble up.
190 - try {
191 - this.initializeAll(i + 1);
192 - } catch (err) {}
193 - }
194 - }
195 - }
196 - },
197 -
198 - /**
199 - * Invokes each of `this.transactionWrappers.close[i]` functions, passing into
200 - * them the respective return values of `this.transactionWrappers.init[i]`
201 - * (`close`rs that correspond to initializers that failed will not be
202 - * invoked).
203 - */
204 - closeAll: function(startIndex: number): void {
205 - invariant(
206 - this.isInTransaction(),
207 - 'Transaction.closeAll(): Cannot close transaction when none are open.',
208 - );
209 - var transactionWrappers = this.transactionWrappers;
210 - for (var i = startIndex; i < transactionWrappers.length; i++) {
211 - var wrapper = transactionWrappers[i];
212 - var initData = this.wrapperInitData[i];
213 - var errorThrown;
214 - try {
215 - // Catching errors makes debugging more difficult, so we start with
216 - // errorThrown set to true before setting it to false after calling
217 - // close -- if it's still set to true in the finally block, it means
218 - // wrapper.close threw.
219 - errorThrown = true;
220 - if (initData !== OBSERVED_ERROR && wrapper.close) {
221 - wrapper.close.call(this, initData);
222 - }
223 - errorThrown = false;
224 - } finally {
225 - if (errorThrown) {
226 - // The closer for wrapper i threw an error; close the remaining
227 - // wrappers but silence any exceptions from them to ensure that the
228 - // first error is the one to bubble up.
229 - try {
230 - this.closeAll(i + 1);
231 - } catch (e) {}
232 - }
233 - }
234 - }
235 - this.wrapperInitData.length = 0;
236 - },
237 -};
238 -
239 -export type Transaction = typeof TransactionImpl;
240 -
241 -module.exports = TransactionImpl;
src/renderers/shared/stack/reconciler/__tests__/Transaction-test.js deleted
-306
@@ -1,306 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - */
9 -
10 -'use strict';
11 -
12 -var Transaction;
13 -
14 -var INIT_ERRORED = 'initErrored'; // Just a dummy value to check for.
15 -describe('Transaction', () => {
16 - beforeEach(() => {
17 - jest.resetModules();
18 - Transaction = require('Transaction');
19 - });
20 -
21 - /**
22 - * We should not invoke closers for inits that failed. We should pass init
23 - * return values to closers when those inits are successful. We should not
24 - * invoke the actual method when any of the initializers fail.
25 - */
26 - it('should invoke closers with/only-with init returns', () => {
27 - var throwInInit = function() {
28 - throw new Error('close[0] should receive Transaction.OBSERVED_ERROR');
29 - };
30 -
31 - var performSideEffect;
32 - var dontPerformThis = function() {
33 - performSideEffect = 'This should never be set to this';
34 - };
35 -
36 - /**
37 - * New test Transaction subclass.
38 - */
39 - var TestTransaction = function() {
40 - this.reinitializeTransaction();
41 - this.firstCloseParam = INIT_ERRORED; // WON'T be set to something else
42 - this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
43 - this.lastCloseParam = INIT_ERRORED; // WON'T be set to something else
44 - };
45 - Object.assign(TestTransaction.prototype, Transaction);
46 - TestTransaction.prototype.getTransactionWrappers = function() {
47 - return [
48 - {
49 - initialize: throwInInit,
50 - close: function(initResult) {
51 - this.firstCloseParam = initResult;
52 - },
53 - },
54 - {
55 - initialize: function() {
56 - return 'asdf';
57 - },
58 - close: function(initResult) {
59 - this.secondCloseParam = initResult;
60 - },
61 - },
62 - {
63 - initialize: throwInInit,
64 - close: function(initResult) {
65 - this.lastCloseParam = initResult;
66 - },
67 - },
68 - ];
69 - };
70 -
71 - var transaction = new TestTransaction();
72 -
73 - expect(function() {
74 - transaction.perform(dontPerformThis);
75 - }).toThrow();
76 -
77 - expect(performSideEffect).toBe(undefined);
78 - expect(transaction.firstCloseParam).toBe(INIT_ERRORED);
79 - expect(transaction.secondCloseParam).toBe('asdf');
80 - expect(transaction.lastCloseParam).toBe(INIT_ERRORED);
81 - expect(transaction.isInTransaction()).toBe(false);
82 - });
83 -
84 - it('should invoke closers and wrapped method when inits success', () => {
85 - var performSideEffect;
86 - /**
87 - * New test Transaction subclass.
88 - */
89 - var TestTransaction = function() {
90 - this.reinitializeTransaction();
91 - this.firstCloseParam = INIT_ERRORED; // WILL be set to something else
92 - this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
93 - this.lastCloseParam = INIT_ERRORED; // WILL be set to something else
94 - };
95 - Object.assign(TestTransaction.prototype, Transaction);
96 - TestTransaction.prototype.getTransactionWrappers = function() {
97 - return [
98 - {
99 - initialize: function() {
100 - return 'firstResult';
101 - },
102 - close: function(initResult) {
103 - this.firstCloseParam = initResult;
104 - },
105 - },
106 - {
107 - initialize: function() {
108 - return 'secondResult';
109 - },
110 - close: function(initResult) {
111 - this.secondCloseParam = initResult;
112 - },
113 - },
114 - {
115 - initialize: function() {
116 - return 'thirdResult';
117 - },
118 - close: function(initResult) {
119 - this.lastCloseParam = initResult;
120 - },
121 - },
122 - ];
123 - };
124 -
125 - var transaction = new TestTransaction();
126 -
127 - transaction.perform(function() {
128 - performSideEffect = 'SIDE_EFFECT';
129 - });
130 -
131 - expect(performSideEffect).toBe('SIDE_EFFECT');
132 - expect(transaction.firstCloseParam).toBe('firstResult');
133 - expect(transaction.secondCloseParam).toBe('secondResult');
134 - expect(transaction.lastCloseParam).toBe('thirdResult');
135 - expect(transaction.isInTransaction()).toBe(false);
136 - });
137 -
138 - /**
139 - * When the operation throws, the transaction should throw, but all of the
140 - * error-free closers should execute gracefully without issue. If a closer
141 - * throws an error, the transaction should prefer to throw the error
142 - * encountered earlier in the operation.
143 - */
144 - it('should throw when wrapped operation throws', () => {
145 - var performSideEffect;
146 - /**
147 - * New test Transaction subclass.
148 - */
149 - var TestTransaction = function() {
150 - this.reinitializeTransaction();
151 - this.firstCloseParam = INIT_ERRORED; // WILL be set to something else
152 - this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
153 - this.lastCloseParam = INIT_ERRORED; // WILL be set to something else
154 - };
155 - Object.assign(TestTransaction.prototype, Transaction);
156 - // Now, none of the close/inits throw, but the operation we wrap will throw.
157 - TestTransaction.prototype.getTransactionWrappers = function() {
158 - return [
159 - {
160 - initialize: function() {
161 - return 'firstResult';
162 - },
163 - close: function(initResult) {
164 - this.firstCloseParam = initResult;
165 - },
166 - },
167 - {
168 - initialize: function() {
169 - return 'secondResult';
170 - },
171 - close: function(initResult) {
172 - this.secondCloseParam = initResult;
173 - },
174 - },
175 - {
176 - initialize: function() {
177 - return 'thirdResult';
178 - },
179 - close: function(initResult) {
180 - this.lastCloseParam = initResult;
181 - },
182 - },
183 - {
184 - initialize: function() {
185 - return 'fourthResult';
186 - },
187 - close: function(initResult) {
188 - throw new Error('The transaction should throw a TypeError.');
189 - },
190 - },
191 - ];
192 - };
193 -
194 - var transaction = new TestTransaction();
195 -
196 - expect(
197 - (function() {
198 - var isTypeError = false;
199 - try {
200 - transaction.perform(function() {
201 - throw new TypeError('Thrown in main wrapped operation');
202 - });
203 - } catch (err) {
204 - isTypeError = err instanceof TypeError;
205 - }
206 - return isTypeError;
207 - })(),
208 - ).toBe(true);
209 -
210 - expect(performSideEffect).toBe(undefined);
211 - expect(transaction.firstCloseParam).toBe('firstResult');
212 - expect(transaction.secondCloseParam).toBe('secondResult');
213 - expect(transaction.lastCloseParam).toBe('thirdResult');
214 - expect(transaction.isInTransaction()).toBe(false);
215 - });
216 -
217 - it('should throw errors in transaction close', () => {
218 - var TestTransaction = function() {
219 - this.reinitializeTransaction();
220 - };
221 - Object.assign(TestTransaction.prototype, Transaction);
222 - var exceptionMsg = 'This exception should throw.';
223 - TestTransaction.prototype.getTransactionWrappers = function() {
224 - return [
225 - {
226 - close: function(initResult) {
227 - throw new Error(exceptionMsg);
228 - },
229 - },
230 - ];
231 - };
232 -
233 - var transaction = new TestTransaction();
234 - expect(function() {
235 - transaction.perform(function() {});
236 - }).toThrowError(exceptionMsg);
237 - expect(transaction.isInTransaction()).toBe(false);
238 - });
239 -
240 - it('should allow nesting of transactions', () => {
241 - var performSideEffect;
242 - var nestedPerformSideEffect;
243 - /**
244 - * New test Transaction subclass.
245 - */
246 - var TestTransaction = function() {
247 - this.reinitializeTransaction();
248 - this.firstCloseParam = INIT_ERRORED; // WILL be set to something else
249 - };
250 - Object.assign(TestTransaction.prototype, Transaction);
251 - TestTransaction.prototype.getTransactionWrappers = function() {
252 - return [
253 - {
254 - initialize: function() {
255 - return 'firstResult';
256 - },
257 - close: function(initResult) {
258 - this.firstCloseParam = initResult;
259 - },
260 - },
261 - {
262 - initialize: function() {
263 - this.nestedTransaction = new NestedTransaction();
264 - },
265 - close: function() {
266 - // Test performing a transaction in another transaction's close()
267 - this.nestedTransaction.perform(function() {
268 - nestedPerformSideEffect = 'NESTED_SIDE_EFFECT';
269 - });
270 - },
271 - },
272 - ];
273 - };
274 -
275 - var NestedTransaction = function() {
276 - this.reinitializeTransaction();
277 - };
278 - Object.assign(NestedTransaction.prototype, Transaction);
279 - NestedTransaction.prototype.getTransactionWrappers = function() {
280 - return [
281 - {
282 - initialize: function() {
283 - this.hasInitializedNested = true;
284 - },
285 - close: function() {
286 - this.hasClosedNested = true;
287 - },
288 - },
289 - ];
290 - };
291 -
292 - var transaction = new TestTransaction();
293 -
294 - transaction.perform(function() {
295 - performSideEffect = 'SIDE_EFFECT';
296 - });
297 -
298 - expect(performSideEffect).toBe('SIDE_EFFECT');
299 - expect(nestedPerformSideEffect).toBe('NESTED_SIDE_EFFECT');
300 - expect(transaction.firstCloseParam).toBe('firstResult');
301 - expect(transaction.isInTransaction()).toBe(false);
302 - expect(transaction.nestedTransaction.hasClosedNested).toBe(true);
303 - expect(transaction.nestedTransaction.hasInitializedNested).toBe(true);
304 - expect(transaction.nestedTransaction.isInTransaction()).toBe(false);
305 - });
306 -});
src/renderers/shared/stack/reconciler/flattenStackChildren.js deleted
-109
@@ -1,109 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule flattenStackChildren
8 - * @flow
9 - */
10 -
11 -'use strict';
12 -
13 -var KeyEscapeUtils = require('KeyEscapeUtils');
14 -var traverseStackChildren = require('traverseStackChildren');
15 -
16 -if (__DEV__) {
17 - var warning = require('fbjs/lib/warning');
18 -}
19 -
20 -var ReactComponentTreeHook;
21 -
22 -if (
23 - typeof process !== 'undefined' &&
24 - process.env &&
25 - process.env.NODE_ENV === 'test'
26 -) {
27 - // Temporary hack.
28 - // Inline requires don't work well with Jest:
29 - // https://github.com/facebook/react/issues/7240
30 - // Remove the inline requires when we don't need them anymore:
31 - // https://github.com/facebook/react/pull/7178
32 - ReactComponentTreeHook = require('ReactGlobalSharedState')
33 - .ReactComponentTreeHook;
34 -}
35 -
36 -/**
37 - * @param {function} traverseContext Context passed through traversal.
38 - * @param {?ReactComponent} child React child component.
39 - * @param {!string} name String name of key path to child.
40 - * @param {number=} selfDebugID Optional debugID of the current internal instance.
41 - */
42 -function flattenSingleChildIntoContext(
43 - traverseContext: mixed,
44 - child: React$Element<any>,
45 - name: string,
46 - selfDebugID?: number,
47 -): void {
48 - // We found a component instance.
49 - if (traverseContext && typeof traverseContext === 'object') {
50 - const result = traverseContext;
51 - const keyUnique = result[name] === undefined;
52 - if (__DEV__) {
53 - if (!ReactComponentTreeHook) {
54 - ReactComponentTreeHook = require('ReactGlobalSharedState')
55 - .ReactComponentTreeHook;
56 - }
57 - if (!keyUnique) {
58 - warning(
59 - false,
60 - 'flattenChildren(...): Encountered two children with the same key, ' +
61 - '`%s`. ' +
62 - 'Keys should be unique so that components maintain their identity ' +
63 - 'across updates. Non-unique keys may cause children to be ' +
64 - 'duplicated and/or omitted — the behavior is unsupported and ' +
65 - 'could change in a future version.%s',
66 - KeyEscapeUtils.unescapeInDev(name),
67 - ReactComponentTreeHook.getStackAddendumByID(selfDebugID),
68 - );
69 - }
70 - }
71 - if (keyUnique && child != null) {
72 - result[name] = child;
73 - }
74 - }
75 -}
76 -
77 -/**
78 - * Flattens children that are typically specified as `props.children`. Any null
79 - * children will not be included in the resulting object.
80 - * @return {!object} flattened children keyed by name.
81 - */
82 -function flattenStackChildren(
83 - children: React$Element<any>,
84 - selfDebugID?: number,
85 -): ?{[name: string]: React$Element<any>} {
86 - if (children == null) {
87 - return children;
88 - }
89 - var result = {};
90 -
91 - if (__DEV__) {
92 - traverseStackChildren(
93 - children,
94 - (traverseContext, child, name) =>
95 - flattenSingleChildIntoContext(
96 - traverseContext,
97 - child,
98 - name,
99 - selfDebugID,
100 - ),
101 - result,
102 - );
103 - } else {
104 - traverseStackChildren(children, flattenSingleChildIntoContext, result);
105 - }
106 - return result;
107 -}
108 -
109 -module.exports = flattenStackChildren;
src/renderers/shared/stack/reconciler/getHostComponentFromComposite.js deleted
-28
@@ -1,28 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule getHostComponentFromComposite
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactNodeTypes = require('ReactNodeTypes');
13 -
14 -function getHostComponentFromComposite(inst) {
15 - var type;
16 -
17 - while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {
18 - inst = inst._renderedComponent;
19 - }
20 -
21 - if (type === ReactNodeTypes.HOST) {
22 - return inst._renderedComponent;
23 - } else if (type === ReactNodeTypes.EMPTY) {
24 - return null;
25 - }
26 -}
27 -
28 -module.exports = getHostComponentFromComposite;
src/renderers/shared/stack/reconciler/instantiateReactComponent.js deleted
-156
@@ -1,156 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule instantiateReactComponent
8 - */
9 -
10 -'use strict';
11 -
12 -var ReactCompositeComponent = require('ReactCompositeComponent');
13 -var ReactEmptyComponent = require('ReactEmptyComponent');
14 -var ReactHostComponent = require('ReactHostComponent');
15 -
16 -var invariant = require('fbjs/lib/invariant');
17 -
18 -if (__DEV__) {
19 - var warning = require('fbjs/lib/warning');
20 -}
21 -
22 -var nextDebugID = 1;
23 -
24 -// To avoid a cyclic dependency, we create the final class in this module
25 -var ReactCompositeComponentWrapper = function(element) {
26 - this.construct(element);
27 -};
28 -
29 -function getDeclarationErrorAddendum(owner) {
30 - if (owner) {
31 - var name = owner.getName();
32 - if (name) {
33 - return '\n\nCheck the render method of `' + name + '`.';
34 - }
35 - }
36 - return '';
37 -}
38 -
39 -/**
40 - * Check if the type reference is a known internal type. I.e. not a user
41 - * provided composite type.
42 - *
43 - * @param {function} type
44 - * @return {boolean} Returns true if this is a valid internal type.
45 - */
46 -function isInternalComponentType(type) {
47 - return (
48 - typeof type === 'function' &&
49 - typeof type.prototype !== 'undefined' &&
50 - typeof type.prototype.mountComponent === 'function' &&
51 - typeof type.prototype.receiveComponent === 'function'
52 - );
53 -}
54 -
55 -/**
56 - * Given a ReactNode, create an instance that will actually be mounted.
57 - *
58 - * @param {ReactNode} node
59 - * @param {boolean} shouldHaveDebugID
60 - * @return {object} A new instance of the element's constructor.
61 - * @protected
62 - */
63 -function instantiateReactComponent(node, shouldHaveDebugID) {
64 - var instance;
65 -
66 - if (node === null || node === false) {
67 - instance = ReactEmptyComponent.create(instantiateReactComponent);
68 - } else if (typeof node === 'object') {
69 - var element = node;
70 - var type = element.type;
71 - if (typeof type !== 'function' && typeof type !== 'string') {
72 - var info = '';
73 - if (__DEV__) {
74 - if (
75 - type === undefined ||
76 - (typeof type === 'object' &&
77 - type !== null &&
78 - Object.keys(type).length === 0)
79 - ) {
80 - info +=
81 - ' You likely forgot to export your component from the file ' +
82 - "it's defined in.";
83 - }
84 - }
85 - info += getDeclarationErrorAddendum(element._owner);
86 - invariant(
87 - false,
88 - 'Element type is invalid: expected a string (for built-in components) ' +
89 - 'or a class/function (for composite components) but got: %s.%s',
90 - type == null ? type : typeof type,
91 - info,
92 - );
93 - }
94 -
95 - // Special case string values
96 - if (typeof element.type === 'string') {
97 - instance = ReactHostComponent.createInternalComponent(element);
98 - } else if (isInternalComponentType(element.type)) {
99 - // This is temporarily available for custom components that are not string
100 - // representations. I.e. ART. Once those are updated to use the string
101 - // representation, we can drop this code path.
102 - instance = new element.type(element);
103 -
104 - // We renamed this. Allow the old name for compat. :(
105 - if (!instance.getHostNode) {
106 - instance.getHostNode = instance.getNativeNode;
107 - }
108 - } else {
109 - instance = new ReactCompositeComponentWrapper(element);
110 - }
111 - } else if (typeof node === 'string' || typeof node === 'number') {
112 - instance = ReactHostComponent.createInstanceForText(node);
113 - } else {
114 - invariant(false, 'Encountered invalid React node of type %s', typeof node);
115 - }
116 -
117 - if (__DEV__) {
118 - warning(
119 - typeof instance.mountComponent === 'function' &&
120 - typeof instance.receiveComponent === 'function' &&
121 - typeof instance.getHostNode === 'function' &&
122 - typeof instance.unmountComponent === 'function',
123 - 'Only React Components can be mounted.',
124 - );
125 - }
126 -
127 - // These two fields are used by the DOM and ART diffing algorithms
128 - // respectively. Instead of using expandos on components, we should be
129 - // storing the state needed by the diffing algorithms elsewhere.
130 - instance._mountIndex = 0;
131 - instance._mountImage = null;
132 -
133 - if (__DEV__) {
134 - instance._debugID = shouldHaveDebugID ? nextDebugID++ : 0;
135 - }
136 -
137 - // Internal instances should fully constructed at this point, so they should
138 - // not get any new fields added to them at this point.
139 - if (__DEV__) {
140 - if (Object.preventExtensions) {
141 - Object.preventExtensions(instance);
142 - }
143 - }
144 -
145 - return instance;
146 -}
147 -
148 -Object.assign(
149 - ReactCompositeComponentWrapper.prototype,
150 - ReactCompositeComponent,
151 - {
152 - _instantiateReactComponent: instantiateReactComponent,
153 - },
154 -);
155 -
156 -module.exports = instantiateReactComponent;
src/renderers/shared/stack/reconciler/traverseStackChildren.js deleted
-198
@@ -1,198 +0,0 @@
1 -/**
2 - * Copyright (c) 2013-present, Facebook, Inc.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @providesModule traverseStackChildren
8 - */
9 -
10 -'use strict';
11 -
12 -var invariant = require('fbjs/lib/invariant');
13 -var KeyEscapeUtils = require('KeyEscapeUtils');
14 -
15 -var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
16 -var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
17 -// The Symbol used to tag the ReactElement type. If there is no native Symbol
18 -// nor polyfill, then a plain number is used for performance.
19 -var REACT_ELEMENT_TYPE =
20 - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
21 - 0xeac7;
22 -
23 -if (__DEV__) {
24 - var warning = require('fbjs/lib/warning');
25 - var {
26 - getCurrentStackAddendum,
27 - } = require('ReactGlobalSharedState').ReactComponentTreeHook;
28 -}
29 -
30 -var SEPARATOR = '.';
31 -var SUBSEPARATOR = ':';
32 -
33 -/**
34 - * This is inlined from ReactElement since this file is shared between
35 - * isomorphic and renderers. We could extract this to a
36 - *
37 - */
38 -
39 -/**
40 - * TODO: Test that a single child and an array with one item have the same key
41 - * pattern.
42 - */
43 -
44 -var didWarnAboutMaps = false;
45 -
46 -/**
47 - * Generate a key string that identifies a component within a set.
48 - *
49 - * @param {*} component A component that could contain a manual key.
50 - * @param {number} index Index that is used if a manual key is not provided.
51 - * @return {string}
52 - */
53 -function getComponentKey(component, index) {
54 - // Do some typechecking here since we call this blindly. We want to ensure
55 - // that we don't block potential future ES APIs.
56 - if (component && typeof component === 'object' && component.key != null) {
57 - // Explicit key
58 - return KeyEscapeUtils.escape(component.key);
59 - }
60 - // Implicit key determined by the index in the set
61 - return index.toString(36);
62 -}
63 -
64 -/**
65 - * @param {?*} children Children tree container.
66 - * @param {!string} nameSoFar Name of the key path so far.
67 - * @param {!function} callback Callback to invoke with each child found.
68 - * @param {?*} traverseContext Used to pass information throughout the traversal
69 - * process.
70 - * @return {!number} The number of children in this subtree.
71 - */
72 -function traverseStackChildrenImpl(
73 - children,
74 - nameSoFar,
75 - callback,
76 - traverseContext,
77 -) {
78 - var type = typeof children;
79 -
80 - if (type === 'undefined' || type === 'boolean') {
81 - // All of the above are perceived as null.
82 - children = null;
83 - }
84 -
85 - if (
86 - children === null ||
87 - type === 'string' ||
88 - type === 'number' ||
89 - // The following is inlined from ReactElement. This means we can optimize
90 - // some checks. React Fiber also inlines this logic for similar purposes.
91 - (type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)
92 - ) {
93 - callback(
94 - traverseContext,
95 - children,
96 - // If it's the only child, treat the name as if it was wrapped in an array
97 - // so that it's consistent if the number of children grows.
98 - nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar,
99 - );
100 - return 1;
101 - }
102 -
103 - var child;
104 - var nextName;
105 - var subtreeCount = 0; // Count of children found in the current subtree.
106 - var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
107 -
108 - if (Array.isArray(children)) {
109 - for (var i = 0; i < children.length; i++) {
110 - child = children[i];
111 - nextName = nextNamePrefix + getComponentKey(child, i);
112 - subtreeCount += traverseStackChildrenImpl(
113 - child,
114 - nextName,
115 - callback,
116 - traverseContext,
117 - );
118 - }
119 - } else {
120 - var iteratorFn =
121 - (ITERATOR_SYMBOL && children[ITERATOR_SYMBOL]) ||
122 - children[FAUX_ITERATOR_SYMBOL];
123 - if (typeof iteratorFn === 'function') {
124 - if (__DEV__) {
125 - // Warn about using Maps as children
126 - if (iteratorFn === children.entries) {
127 - warning(
128 - didWarnAboutMaps,
129 - 'Using Maps as children is unsupported and will likely yield ' +
130 - 'unexpected results. Convert it to a sequence/iterable of keyed ' +
131 - 'ReactElements instead.%s',
132 - getCurrentStackAddendum(),
133 - );
134 - didWarnAboutMaps = true;
135 - }
136 - }
137 -
138 - var iterator = iteratorFn.call(children);
139 - var step;
140 - var ii = 0;
141 - while (!(step = iterator.next()).done) {
142 - child = step.value;
143 - nextName = nextNamePrefix + getComponentKey(child, ii++);
144 - subtreeCount += traverseStackChildrenImpl(
145 - child,
146 - nextName,
147 - callback,
148 - traverseContext,
149 - );
150 - }
151 - } else if (type === 'object') {
152 - var addendum = '';
153 - if (__DEV__) {
154 - addendum =
155 - ' If you meant to render a collection of children, use an array ' +
156 - 'instead.' +
157 - getCurrentStackAddendum();
158 - }
159 - var childrenString = '' + children;
160 - invariant(
161 - false,
162 - 'Objects are not valid as a React child (found: %s).%s',
163 - childrenString === '[object Object]'
164 - ? 'object with keys {' + Object.keys(children).join(', ') + '}'
165 - : childrenString,
166 - addendum,
167 - );
168 - }
169 - }
170 -
171 - return subtreeCount;
172 -}
173 -
174 -/**
175 - * Traverses children that are typically specified as `props.children`, but
176 - * might also be specified through attributes:
177 - *
178 - * - `traverseStackChildren(this.props.children, ...)`
179 - * - `traverseStackChildren(this.props.leftPanelChildren, ...)`
180 - *
181 - * The `traverseContext` is an optional argument that is passed through the
182 - * entire traversal. It can be used to store accumulations or anything else that
183 - * the callback might find relevant.
184 - *
185 - * @param {?*} children Children tree object.
186 - * @param {!function} callback To invoke upon traversing each child.
187 - * @param {?*} traverseContext Context for traversal.
188 - * @return {!number} The number of children in this subtree.
189 - */
190 -function traverseStackChildren(children, callback, traverseContext) {
191 - if (children == null) {
192 - return 0;
193 - }
194 -
195 - return traverseStackChildrenImpl(children, '', callback, traverseContext);
196 -}
197 -
198 -module.exports = traverseStackChildren;
src/shared/ReactInstanceType.js new
+29
@@ -0,0 +1,29 @@
1 +/**
2 + * Copyright 2016-present, Facebook, Inc.
3 + * All rights reserved.
4 + *
5 + * This source code is licensed under the BSD-style license found in the
6 + * LICENSE file in the root directory of this source tree. An additional grant
7 + * of patent rights can be found in the PATENTS file in the same directory.
8 + *
9 + * @providesModule ReactInstanceType
10 + * @flow
11 + */
12 +
13 +'use strict';
14 +
15 +// TODO: delete this file.
16 +// It was only necessary for Stack.
17 +
18 +import type {ReactElement} from 'ReactElementType';
19 +
20 +export type DebugID = number;
21 +
22 +export type ReactInstance = {
23 + mountComponent: any,
24 + unmountComponent: any,
25 + receiveComponent: any,
26 + getName: () => string,
27 + getPublicInstance: any,
28 + _currentElement: ReactElement,
29 +};