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=">" ' +
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=">" ' + 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
+};