add jsx-runtime and jsx-dev-runtime (#18299)
This PR adds the jsx-runtime and jsx-dev-runtime modules for the JSX Babel Plugin. WWW still relies on jsx/jsxs/jsxDEV from the "react" module, so once we refactor the code to point to the runtime modules we will remove jsx/jsxs/jsxDEV from the "react" module.
Luna Ruan committed
Mar 17, 2020 at 13:22 UTC
90f8fe6f5509cab7d6d280b4ed17181697f394e9
18 files changed
+927
-88
packages/react/index.classic.fb.js
+1
-4
@@ -50,8 +50,5 @@ export {
50
DEPRECATED_createResponder,
51
// enableScopeAPI
52
unstable_createScope,
53
- // enableJSXTransformAPI
54
- jsx,
55
- jsxs,
56
- jsxDEV,
53
} from './src/React';
54
+export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';
packages/react/index.experimental.js
-4
@@ -45,8 +45,4 @@ export {
45
unstable_withSuspenseConfig,
46
// enableBlocksAPI
47
block,
48
- // enableJSXTransformAPI
49
- jsx,
50
- jsxs,
51
- jsxDEV,
48
} from './src/React';
packages/react/index.js
-3
@@ -76,7 +76,4 @@ export {
76
DEPRECATED_createResponder,
77
unstable_createFundamental,
78
unstable_createScope,
79
- jsx,
80
- jsxs,
81
- jsxDEV,
79
} from './src/React';
packages/react/index.modern.fb.js
+1
-4
@@ -49,8 +49,5 @@ export {
49
DEPRECATED_createResponder,
50
// enableScopeAPI
51
unstable_createScope,
52
- // enableJSXTransformAPI
53
- jsx,
54
- jsxs,
55
- jsxDEV,
52
} from './src/React';
53
+export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';
packages/react/jsx-dev-runtime.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+ * @flow
8
+ */
9
+
10
+export {Fragment, jsxDEV} from './src/jsx/ReactJSX';
packages/react/jsx-runtime.js
new
+9
@@ -0,0 +1,9 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+ * @flow
8
+ */
9
+export {Fragment, jsx, jsxs} from './src/jsx/ReactJSX';
packages/react/npm/jsx-dev-runtime.js
new
+7
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+if (process.env.NODE_ENV === 'production') {
4
+ module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');
5
+} else {
6
+ module.exports = require('./cjs/react-jsx-dev-runtime.development.js');
7
+}
packages/react/npm/jsx-runtime.js
new
+7
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+if (process.env.NODE_ENV === 'production') {
4
+ module.exports = require('./cjs/react-jsx-runtime.production.min.js');
5
+} else {
6
+ module.exports = require('./cjs/react-jsx-runtime.development.js');
7
+}
packages/react/package.json
+3
-1
@@ -14,7 +14,9 @@
14
"build-info.json",
15
"index.js",
16
"cjs/",
17
- "umd/"
17
+ "umd/",
18
+ "jsx-runtime.js",
19
+ "jsx-dev-runtime.js"
20
],
21
"main": "index.js",
22
"repository": {
packages/react/src/React.js
-15
@@ -24,7 +24,6 @@ import {
24
createFactory as createFactoryProd,
25
cloneElement as cloneElementProd,
26
isValidElement,
27
- jsx as jsxProd,
27
} from './ReactElement';
28
import {createContext} from './ReactContext';
29
import {lazy} from './ReactLazy';
@@ -52,9 +51,6 @@ import {
51
createElementWithValidation,
52
createFactoryWithValidation,
53
cloneElementWithValidation,
55
- jsxWithValidation,
56
- jsxWithValidationStatic,
57
- jsxWithValidationDynamic,
54
} from './ReactElementValidator';
55
import createMutableSource from './createMutableSource';
56
import ReactSharedInternals from './ReactSharedInternals';
@@ -67,12 +63,6 @@ const createElement = __DEV__ ? createElementWithValidation : createElementProd;
63
const cloneElement = __DEV__ ? cloneElementWithValidation : cloneElementProd;
64
const createFactory = __DEV__ ? createFactoryWithValidation : createFactoryProd;
65
70
-const jsxDEV = __DEV__ ? jsxWithValidation : undefined;
71
-const jsx = __DEV__ ? jsxWithValidationDynamic : jsxProd;
72
-// we may want to special case jsxs internally to take advantage of static children.
73
-// for now we can ship identical prod functions
74
-const jsxs = __DEV__ ? jsxWithValidationStatic : jsxProd;
75
-
66
const Children = {
67
map,
68
forEach,
@@ -127,9 +117,4 @@ export {
117
createFundamental as unstable_createFundamental,
118
// enableScopeAPI
119
createScope as unstable_createScope,
130
- // enableJSXTransformAPI
131
- jsx,
132
- jsxs,
133
- // TODO: jsxDEV should not be exposed as a name. We might want to move it to a different entry point.
134
- jsxDEV,
120
};
packages/react/src/ReactDebugCurrentFrame.js
+7
@@ -23,6 +23,13 @@ export function setCurrentlyValidatingElement(element: null | ReactElement) {
23
}
24
25
if (__DEV__) {
26
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement = function(
27
+ element: null | ReactElement,
28
+ ) {
29
+ if (__DEV__) {
30
+ currentlyValidatingElement = element;
31
+ }
32
+ };
33
// Stack implementation injected by the current renderer.
34
ReactDebugCurrentFrame.getCurrentStack = (null: null | (() => string));
35
packages/react/src/__tests__/ReactElementJSX-test.js
+74
-56
@@ -12,6 +12,8 @@
12
let React;
13
let ReactDOM;
14
let ReactTestUtils;
15
+let JSXRuntime;
16
+let JSXDEVRuntime;
17
18
// NOTE: We're explicitly not using JSX here. This is intended to test
19
// a new React.jsx api which does not have a JSX transformer yet.
@@ -29,6 +31,8 @@ describe('ReactElement.jsx', () => {
31
global.Symbol = undefined;
32
33
React = require('react');
34
+ JSXRuntime = require('react/jsx-runtime');
35
+ JSXDEVRuntime = require('react/jsx-dev-runtime');
36
ReactDOM = require('react-dom');
37
ReactTestUtils = require('react-dom/test-utils');
38
});
@@ -37,32 +41,35 @@ describe('ReactElement.jsx', () => {
41
global.Symbol = originalSymbol;
42
});
43
40
- if (!__EXPERIMENTAL__) {
41
- it("empty test so Jest doesn't complain", () => {});
42
- return;
43
- }
44
-
44
it('allows static methods to be called using the type property', () => {
45
class StaticMethodComponentClass extends React.Component {
46
render() {
48
- return React.jsx('div', {});
47
+ return JSXRuntime.jsx('div', {});
48
}
49
}
50
StaticMethodComponentClass.someStaticMethod = () => 'someReturnValue';
51
53
- const element = React.jsx(StaticMethodComponentClass, {});
52
+ const element = JSXRuntime.jsx(StaticMethodComponentClass, {});
53
expect(element.type.someStaticMethod()).toBe('someReturnValue');
54
});
55
56
it('identifies valid elements', () => {
57
class Component extends React.Component {
58
render() {
60
- return React.jsx('div', {});
59
+ return JSXRuntime.jsx('div', {});
60
}
61
}
62
64
- expect(React.isValidElement(React.jsx('div', {}))).toEqual(true);
65
- expect(React.isValidElement(React.jsx(Component, {}))).toEqual(true);
63
+ expect(React.isValidElement(JSXRuntime.jsx('div', {}))).toEqual(true);
64
+ expect(React.isValidElement(JSXRuntime.jsx(Component, {}))).toEqual(true);
65
+ expect(
66
+ React.isValidElement(JSXRuntime.jsx(JSXRuntime.Fragment, {})),
67
+ ).toEqual(true);
68
+ if (__DEV__) {
69
+ expect(React.isValidElement(JSXDEVRuntime.jsxDEV('div', {}))).toEqual(
70
+ true,
71
+ );
72
+ }
73
74
expect(React.isValidElement(null)).toEqual(false);
75
expect(React.isValidElement(true)).toEqual(false);
@@ -83,12 +90,12 @@ describe('ReactElement.jsx', () => {
90
expect(React.isValidElement(Component)).toEqual(false);
91
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
92
86
- const jsonElement = JSON.stringify(React.jsx('div', {}));
93
+ const jsonElement = JSON.stringify(JSXRuntime.jsx('div', {}));
94
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
95
});
96
97
it('is indistinguishable from a plain object', () => {
91
- const element = React.jsx('div', {className: 'foo'});
98
+ const element = JSXRuntime.jsx('div', {className: 'foo'});
99
const object = {};
100
expect(element.constructor).toBe(object.constructor);
101
});
@@ -96,37 +103,37 @@ describe('ReactElement.jsx', () => {
103
it('should use default prop value when removing a prop', () => {
104
class Component extends React.Component {
105
render() {
99
- return React.jsx('span', {});
106
+ return JSXRuntime.jsx('span', {});
107
}
108
}
109
Component.defaultProps = {fruit: 'persimmon'};
110
111
const container = document.createElement('div');
112
const instance = ReactDOM.render(
106
- React.jsx(Component, {fruit: 'mango'}),
113
+ JSXRuntime.jsx(Component, {fruit: 'mango'}),
114
container,
115
);
116
expect(instance.props.fruit).toBe('mango');
117
111
- ReactDOM.render(React.jsx(Component, {}), container);
118
+ ReactDOM.render(JSXRuntime.jsx(Component, {}), container);
119
expect(instance.props.fruit).toBe('persimmon');
120
});
121
122
it('should normalize props with default values', () => {
123
class Component extends React.Component {
124
render() {
118
- return React.jsx('span', {children: this.props.prop});
125
+ return JSXRuntime.jsx('span', {children: this.props.prop});
126
}
127
}
128
Component.defaultProps = {prop: 'testKey'};
129
130
const instance = ReactTestUtils.renderIntoDocument(
124
- React.jsx(Component, {}),
131
+ JSXRuntime.jsx(Component, {}),
132
);
133
expect(instance.props.prop).toBe('testKey');
134
135
const inst2 = ReactTestUtils.renderIntoDocument(
129
- React.jsx(Component, {prop: null}),
136
+ JSXRuntime.jsx(Component, {prop: null}),
137
);
138
expect(inst2.props.prop).toBe(null);
139
});
@@ -134,7 +141,7 @@ describe('ReactElement.jsx', () => {
141
it('throws when changing a prop (in dev) after element creation', () => {
142
class Outer extends React.Component {
143
render() {
137
- const el = React.jsx('div', {className: 'moo'});
144
+ const el = JSXRuntime.jsx('div', {className: 'moo'});
145
146
if (__DEV__) {
147
expect(function() {
@@ -150,7 +157,7 @@ describe('ReactElement.jsx', () => {
157
}
158
}
159
const outer = ReactTestUtils.renderIntoDocument(
153
- React.jsx(Outer, {color: 'orange'}),
160
+ JSXRuntime.jsx(Outer, {color: 'orange'}),
161
);
162
if (__DEV__) {
163
expect(ReactDOM.findDOMNode(outer).className).toBe('moo');
@@ -163,7 +170,7 @@ describe('ReactElement.jsx', () => {
170
const container = document.createElement('div');
171
class Outer extends React.Component {
172
render() {
166
- const el = React.jsx('div', {children: this.props.sound});
173
+ const el = JSXRuntime.jsx('div', {children: this.props.sound});
174
175
if (__DEV__) {
176
expect(function() {
@@ -179,7 +186,7 @@ describe('ReactElement.jsx', () => {
186
}
187
}
188
Outer.defaultProps = {sound: 'meow'};
182
- const outer = ReactDOM.render(React.jsx(Outer, {}), container);
189
+ const outer = ReactDOM.render(JSXRuntime.jsx(Outer, {}), container);
190
expect(ReactDOM.findDOMNode(outer).textContent).toBe('meow');
191
if (__DEV__) {
192
expect(ReactDOM.findDOMNode(outer).className).toBe('');
@@ -191,11 +198,11 @@ describe('ReactElement.jsx', () => {
198
it('does not warn for NaN props', () => {
199
class Test extends React.Component {
200
render() {
194
- return React.jsx('div', {});
201
+ return JSXRuntime.jsx('div', {});
202
}
203
}
204
const test = ReactTestUtils.renderIntoDocument(
198
- React.jsx(Test, {value: +undefined}),
205
+ JSXRuntime.jsx(Test, {value: +undefined}),
206
);
207
expect(test.props.value).toBeNaN();
208
});
@@ -204,21 +211,23 @@ describe('ReactElement.jsx', () => {
211
const container = document.createElement('div');
212
class Child extends React.Component {
213
render() {
207
- return React.jsx('div', {children: this.props.key});
214
+ return JSXRuntime.jsx('div', {children: this.props.key});
215
}
216
}
217
class Parent extends React.Component {
218
render() {
212
- return React.jsxs('div', {
219
+ return JSXRuntime.jsxs('div', {
220
children: [
214
- React.jsx(Child, {}, '0'),
215
- React.jsx(Child, {}, '1'),
216
- React.jsx(Child, {}, '2'),
221
+ JSXRuntime.jsx(Child, {}, '0'),
222
+ JSXRuntime.jsx(Child, {}, '1'),
223
+ JSXRuntime.jsx(Child, {}, '2'),
224
],
225
});
226
}
227
}
221
- expect(() => ReactDOM.render(React.jsx(Parent, {}), container)).toErrorDev(
228
+ expect(() =>
229
+ ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
230
+ ).toErrorDev(
231
'Child: `key` is not a prop. Trying to access it will result ' +
232
'in `undefined` being returned. If you need to access the same ' +
233
'value within the child component, you should pass it as a different ' +
@@ -229,7 +238,10 @@ describe('ReactElement.jsx', () => {
238
it('warns when a jsxs is passed something that is not an array', () => {
239
const container = document.createElement('div');
240
expect(() =>
232
- ReactDOM.render(React.jsxs('div', {children: 'foo'}, null), container),
241
+ ReactDOM.render(
242
+ JSXRuntime.jsxs('div', {children: 'foo'}, null),
243
+ container,
244
+ ),
245
).toErrorDev(
246
'React.jsx: Static children should always be an array. ' +
247
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
@@ -239,7 +251,7 @@ describe('ReactElement.jsx', () => {
251
});
252
253
it('should warn when `key` is being accessed on a host element', () => {
242
- const element = React.jsxs('div', {}, '3');
254
+ const element = JSXRuntime.jsxs('div', {}, '3');
255
expect(
256
() => void element.props.key,
257
).toErrorDev(
@@ -255,17 +267,19 @@ describe('ReactElement.jsx', () => {
267
const container = document.createElement('div');
268
class Child extends React.Component {
269
render() {
258
- return React.jsx('div', {children: this.props.ref});
270
+ return JSXRuntime.jsx('div', {children: this.props.ref});
271
}
272
}
273
class Parent extends React.Component {
274
render() {
263
- return React.jsx('div', {
264
- children: React.jsx(Child, {ref: 'childElement'}),
275
+ return JSXRuntime.jsx('div', {
276
+ children: JSXRuntime.jsx(Child, {ref: 'childElement'}),
277
});
278
}
279
}
268
- expect(() => ReactDOM.render(React.jsx(Parent, {}), container)).toErrorDev(
280
+ expect(() =>
281
+ ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
282
+ ).toErrorDev(
283
'Child: `ref` is not a prop. Trying to access it will result ' +
284
'in `undefined` being returned. If you need to access the same ' +
285
'value within the child component, you should pass it as a different ' +
@@ -292,15 +306,16 @@ describe('ReactElement.jsx', () => {
306
jest.resetModules();
307
308
React = require('react');
309
+ JSXRuntime = require('react/jsx-runtime');
310
311
class Component extends React.Component {
312
render() {
298
- return React.jsx('div');
313
+ return JSXRuntime.jsx('div');
314
}
315
}
316
302
- expect(React.isValidElement(React.jsx('div', {}))).toEqual(true);
303
- expect(React.isValidElement(React.jsx(Component, {}))).toEqual(true);
317
+ expect(React.isValidElement(JSXRuntime.jsx('div', {}))).toEqual(true);
318
+ expect(React.isValidElement(JSXRuntime.jsx(Component, {}))).toEqual(true);
319
320
expect(React.isValidElement(null)).toEqual(false);
321
expect(React.isValidElement(true)).toEqual(false);
@@ -321,29 +336,32 @@ describe('ReactElement.jsx', () => {
336
expect(React.isValidElement(Component)).toEqual(false);
337
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
338
324
- const jsonElement = JSON.stringify(React.jsx('div', {}));
339
+ const jsonElement = JSON.stringify(JSXRuntime.jsx('div', {}));
340
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(false);
341
});
342
343
it('should warn when unkeyed children are passed to jsx', () => {
344
const container = document.createElement('div');
345
+
346
class Child extends React.Component {
347
render() {
332
- return React.jsx('div', {});
348
+ return JSXRuntime.jsx('div', {});
349
}
350
}
351
class Parent extends React.Component {
352
render() {
337
- return React.jsx('div', {
353
+ return JSXRuntime.jsx('div', {
354
children: [
339
- React.jsx(Child, {}),
340
- React.jsx(Child, {}),
341
- React.jsx(Child, {}),
355
+ JSXRuntime.jsx(Child, {}),
356
+ JSXRuntime.jsx(Child, {}),
357
+ JSXRuntime.jsx(Child, {}),
358
],
359
});
360
}
361
}
346
- expect(() => ReactDOM.render(React.jsx(Parent, {}), container)).toErrorDev(
362
+ expect(() =>
363
+ ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
364
+ ).toErrorDev(
365
'Warning: Each child in a list should have a unique "key" prop.\n\n' +
366
'Check the render method of `Parent`. See https://fb.me/react-warning-keys for more information.\n' +
367
' in Child (created by Parent)\n' +
@@ -356,18 +374,18 @@ describe('ReactElement.jsx', () => {
374
const container = document.createElement('div');
375
class Child extends React.Component {
376
render() {
359
- return React.jsx('div', {});
377
+ return JSXRuntime.jsx('div', {});
378
}
379
}
380
class Parent extends React.Component {
381
render() {
364
- return React.jsx('div', {
365
- children: [React.jsx(Child, {key: '0'})],
382
+ return JSXRuntime.jsx('div', {
383
+ children: [JSXRuntime.jsx(Child, {key: '0'})],
384
});
385
}
386
}
387
expect(() =>
370
- ReactDOM.render(React.jsx(Parent, {}), container),
388
+ ReactDOM.render(JSXRuntime.jsx(Parent, {}), container),
389
).toErrorDev(
390
'Warning: React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
391
'Explicitly pass a key after spreading props in your JSX call. ' +
@@ -380,21 +398,21 @@ describe('ReactElement.jsx', () => {
398
const container = document.createElement('div');
399
class Child extends React.Component {
400
render() {
383
- return React.jsx('div', {});
401
+ return JSXRuntime.jsx('div', {});
402
}
403
}
404
class Parent extends React.Component {
405
render() {
388
- return React.jsxs('div', {
406
+ return JSXRuntime.jsxs('div', {
407
children: [
390
- React.jsx(Child, {}),
391
- React.jsx(Child, {}),
392
- React.jsx(Child, {}),
408
+ JSXRuntime.jsx(Child, {}),
409
+ JSXRuntime.jsx(Child, {}),
410
+ JSXRuntime.jsx(Child, {}),
411
],
412
});
413
}
414
}
415
// TODO: an explicit expect for no warning?
398
- ReactDOM.render(React.jsx(Parent, {}), container);
416
+ ReactDOM.render(JSXRuntime.jsx(Parent, {}), container);
417
});
418
});
packages/react/src/jsx/ReactJSX.js
new
+22
@@ -0,0 +1,22 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+ * @flow
8
+ */
9
+import {REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
10
+import {
11
+ jsxWithValidationStatic,
12
+ jsxWithValidationDynamic,
13
+ jsxWithValidation,
14
+} from './ReactJSXElementValidator';
15
+import {jsx as jsxProd} from './ReactJSXElement';
16
+const jsx = __DEV__ ? jsxWithValidationDynamic : jsxProd;
17
+// we may want to special case jsxs internally to take advantage of static children.
18
+// for now we can ship identical prod functions
19
+const jsxs = __DEV__ ? jsxWithValidationStatic : jsxProd;
20
+const jsxDEV = __DEV__ ? jsxWithValidation : undefined;
21
+
22
+export {REACT_FRAGMENT_TYPE as Fragment, jsx, jsxs, jsxDEV};
packages/react/src/jsx/ReactJSXElement.js
new
+345
@@ -0,0 +1,345 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+import getComponentName from 'shared/getComponentName';
9
+import ReactSharedInternals from 'shared/ReactSharedInternals';
10
+
11
+import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
12
+
13
+const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
14
+
15
+const hasOwnProperty = Object.prototype.hasOwnProperty;
16
+
17
+const RESERVED_PROPS = {
18
+ key: true,
19
+ ref: true,
20
+ __self: true,
21
+ __source: true,
22
+};
23
+
24
+let specialPropKeyWarningShown;
25
+let specialPropRefWarningShown;
26
+let didWarnAboutStringRefs;
27
+
28
+if (__DEV__) {
29
+ didWarnAboutStringRefs = {};
30
+}
31
+
32
+function hasValidRef(config) {
33
+ if (__DEV__) {
34
+ if (hasOwnProperty.call(config, 'ref')) {
35
+ const getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
36
+ if (getter && getter.isReactWarning) {
37
+ return false;
38
+ }
39
+ }
40
+ }
41
+ return config.ref !== undefined;
42
+}
43
+
44
+function hasValidKey(config) {
45
+ if (__DEV__) {
46
+ if (hasOwnProperty.call(config, 'key')) {
47
+ const getter = Object.getOwnPropertyDescriptor(config, 'key').get;
48
+ if (getter && getter.isReactWarning) {
49
+ return false;
50
+ }
51
+ }
52
+ }
53
+ return config.key !== undefined;
54
+}
55
+
56
+function warnIfStringRefCannotBeAutoConverted(config) {
57
+ if (__DEV__) {
58
+ if (
59
+ typeof config.ref === 'string' &&
60
+ ReactCurrentOwner.current &&
61
+ config.__self &&
62
+ ReactCurrentOwner.current.stateNode !== config.__self
63
+ ) {
64
+ const componentName = getComponentName(ReactCurrentOwner.current.type);
65
+
66
+ if (!didWarnAboutStringRefs[componentName]) {
67
+ console.error(
68
+ 'Component "%s" contains the string ref "%s". ' +
69
+ 'Support for string refs will be removed in a future major release. ' +
70
+ 'This case cannot be automatically converted to an arrow function. ' +
71
+ 'We ask you to manually fix this case by using useRef() or createRef() instead. ' +
72
+ 'Learn more about using refs safely here: ' +
73
+ 'https://fb.me/react-strict-mode-string-ref',
74
+ getComponentName(ReactCurrentOwner.current.type),
75
+ config.ref,
76
+ );
77
+ didWarnAboutStringRefs[componentName] = true;
78
+ }
79
+ }
80
+ }
81
+}
82
+
83
+function defineKeyPropWarningGetter(props, displayName) {
84
+ if (__DEV__) {
85
+ const warnAboutAccessingKey = function() {
86
+ if (!specialPropKeyWarningShown) {
87
+ specialPropKeyWarningShown = true;
88
+ console.error(
89
+ '%s: `key` is not a prop. Trying to access it will result ' +
90
+ 'in `undefined` being returned. If you need to access the same ' +
91
+ 'value within the child component, you should pass it as a different ' +
92
+ 'prop. (https://fb.me/react-special-props)',
93
+ displayName,
94
+ );
95
+ }
96
+ };
97
+ warnAboutAccessingKey.isReactWarning = true;
98
+ Object.defineProperty(props, 'key', {
99
+ get: warnAboutAccessingKey,
100
+ configurable: true,
101
+ });
102
+ }
103
+}
104
+
105
+function defineRefPropWarningGetter(props, displayName) {
106
+ if (__DEV__) {
107
+ const warnAboutAccessingRef = function() {
108
+ if (!specialPropRefWarningShown) {
109
+ specialPropRefWarningShown = true;
110
+ console.error(
111
+ '%s: `ref` is not a prop. Trying to access it will result ' +
112
+ 'in `undefined` being returned. If you need to access the same ' +
113
+ 'value within the child component, you should pass it as a different ' +
114
+ 'prop. (https://fb.me/react-special-props)',
115
+ displayName,
116
+ );
117
+ }
118
+ };
119
+ warnAboutAccessingRef.isReactWarning = true;
120
+ Object.defineProperty(props, 'ref', {
121
+ get: warnAboutAccessingRef,
122
+ configurable: true,
123
+ });
124
+ }
125
+}
126
+
127
+/**
128
+ * Factory method to create a new React element. This no longer adheres to
129
+ * the class pattern, so do not use new to call it. Also, instanceof check
130
+ * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
131
+ * if something is a React Element.
132
+ *
133
+ * @param {*} type
134
+ * @param {*} props
135
+ * @param {*} key
136
+ * @param {string|object} ref
137
+ * @param {*} owner
138
+ * @param {*} self A *temporary* helper to detect places where `this` is
139
+ * different from the `owner` when React.createElement is called, so that we
140
+ * can warn. We want to get rid of owner and replace string `ref`s with arrow
141
+ * functions, and as long as `this` and owner are the same, there will be no
142
+ * change in behavior.
143
+ * @param {*} source An annotation object (added by a transpiler or otherwise)
144
+ * indicating filename, line number, and/or other information.
145
+ * @internal
146
+ */
147
+const ReactElement = function(type, key, ref, self, source, owner, props) {
148
+ const element = {
149
+ // This tag allows us to uniquely identify this as a React Element
150
+ $$typeof: REACT_ELEMENT_TYPE,
151
+
152
+ // Built-in properties that belong on the element
153
+ type: type,
154
+ key: key,
155
+ ref: ref,
156
+ props: props,
157
+
158
+ // Record the component responsible for creating this element.
159
+ _owner: owner,
160
+ };
161
+
162
+ if (__DEV__) {
163
+ // The validation flag is currently mutative. We put it on
164
+ // an external backing store so that we can freeze the whole object.
165
+ // This can be replaced with a WeakMap once they are implemented in
166
+ // commonly used development environments.
167
+ element._store = {};
168
+
169
+ // To make comparing ReactElements easier for testing purposes, we make
170
+ // the validation flag non-enumerable (where possible, which should
171
+ // include every environment we run tests in), so the test framework
172
+ // ignores it.
173
+ Object.defineProperty(element._store, 'validated', {
174
+ configurable: false,
175
+ enumerable: false,
176
+ writable: true,
177
+ value: false,
178
+ });
179
+ // self and source are DEV only properties.
180
+ Object.defineProperty(element, '_self', {
181
+ configurable: false,
182
+ enumerable: false,
183
+ writable: false,
184
+ value: self,
185
+ });
186
+ // Two elements created in two different places should be considered
187
+ // equal for testing purposes and therefore we hide it from enumeration.
188
+ Object.defineProperty(element, '_source', {
189
+ configurable: false,
190
+ enumerable: false,
191
+ writable: false,
192
+ value: source,
193
+ });
194
+ if (Object.freeze) {
195
+ Object.freeze(element.props);
196
+ Object.freeze(element);
197
+ }
198
+ }
199
+
200
+ return element;
201
+};
202
+
203
+/**
204
+ * https://github.com/reactjs/rfcs/pull/107
205
+ * @param {*} type
206
+ * @param {object} props
207
+ * @param {string} key
208
+ */
209
+export function jsx(type, config, maybeKey) {
210
+ let propName;
211
+
212
+ // Reserved names are extracted
213
+ const props = {};
214
+
215
+ let key = null;
216
+ let ref = null;
217
+
218
+ // Currently, key can be spread in as a prop. This causes a potential
219
+ // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
220
+ // or <div key="Hi" {...props} /> ). We want to deprecate key spread,
221
+ // but as an intermediary step, we will use jsxDEV for everything except
222
+ // <div {...props} key="Hi" />, because we aren't currently able to tell if
223
+ // key is explicitly declared to be undefined or not.
224
+ if (maybeKey !== undefined) {
225
+ key = '' + maybeKey;
226
+ }
227
+
228
+ if (hasValidKey(config)) {
229
+ key = '' + config.key;
230
+ }
231
+
232
+ if (hasValidRef(config)) {
233
+ ref = config.ref;
234
+ }
235
+
236
+ // Remaining properties are added to a new props object
237
+ for (propName in config) {
238
+ if (
239
+ hasOwnProperty.call(config, propName) &&
240
+ !RESERVED_PROPS.hasOwnProperty(propName)
241
+ ) {
242
+ props[propName] = config[propName];
243
+ }
244
+ }
245
+
246
+ // Resolve default props
247
+ if (type && type.defaultProps) {
248
+ const defaultProps = type.defaultProps;
249
+ for (propName in defaultProps) {
250
+ if (props[propName] === undefined) {
251
+ props[propName] = defaultProps[propName];
252
+ }
253
+ }
254
+ }
255
+
256
+ return ReactElement(
257
+ type,
258
+ key,
259
+ ref,
260
+ undefined,
261
+ undefined,
262
+ ReactCurrentOwner.current,
263
+ props,
264
+ );
265
+}
266
+
267
+/**
268
+ * https://github.com/reactjs/rfcs/pull/107
269
+ * @param {*} type
270
+ * @param {object} props
271
+ * @param {string} key
272
+ */
273
+export function jsxDEV(type, config, maybeKey, source, self) {
274
+ if (__DEV__) {
275
+ let propName;
276
+
277
+ // Reserved names are extracted
278
+ const props = {};
279
+
280
+ let key = null;
281
+ let ref = null;
282
+
283
+ // Currently, key can be spread in as a prop. This causes a potential
284
+ // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
285
+ // or <div key="Hi" {...props} /> ). We want to deprecate key spread,
286
+ // but as an intermediary step, we will use jsxDEV for everything except
287
+ // <div {...props} key="Hi" />, because we aren't currently able to tell if
288
+ // key is explicitly declared to be undefined or not.
289
+ if (maybeKey !== undefined) {
290
+ key = '' + maybeKey;
291
+ }
292
+
293
+ if (hasValidKey(config)) {
294
+ key = '' + config.key;
295
+ }
296
+
297
+ if (hasValidRef(config)) {
298
+ ref = config.ref;
299
+ warnIfStringRefCannotBeAutoConverted(config);
300
+ }
301
+
302
+ // Remaining properties are added to a new props object
303
+ for (propName in config) {
304
+ if (
305
+ hasOwnProperty.call(config, propName) &&
306
+ !RESERVED_PROPS.hasOwnProperty(propName)
307
+ ) {
308
+ props[propName] = config[propName];
309
+ }
310
+ }
311
+
312
+ // Resolve default props
313
+ if (type && type.defaultProps) {
314
+ const defaultProps = type.defaultProps;
315
+ for (propName in defaultProps) {
316
+ if (props[propName] === undefined) {
317
+ props[propName] = defaultProps[propName];
318
+ }
319
+ }
320
+ }
321
+
322
+ if (key || ref) {
323
+ const displayName =
324
+ typeof type === 'function'
325
+ ? type.displayName || type.name || 'Unknown'
326
+ : type;
327
+ if (key) {
328
+ defineKeyPropWarningGetter(props, displayName);
329
+ }
330
+ if (ref) {
331
+ defineRefPropWarningGetter(props, displayName);
332
+ }
333
+ }
334
+
335
+ return ReactElement(
336
+ type,
337
+ key,
338
+ ref,
339
+ self,
340
+ source,
341
+ ReactCurrentOwner.current,
342
+ props,
343
+ );
344
+ }
345
+}
packages/react/src/jsx/ReactJSXElementValidator.js
new
+407
@@ -0,0 +1,407 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+/**
9
+ * ReactElementValidator provides a wrapper around a element factory
10
+ * which validates the props passed to the element. This is intended to be
11
+ * used only in DEV and could be replaced by a static type checker for languages
12
+ * that support it.
13
+ */
14
+import isValidElementType from 'shared/isValidElementType';
15
+import getComponentName from 'shared/getComponentName';
16
+import checkPropTypes from 'shared/checkPropTypes';
17
+import {
18
+ getIteratorFn,
19
+ REACT_FORWARD_REF_TYPE,
20
+ REACT_MEMO_TYPE,
21
+ REACT_FRAGMENT_TYPE,
22
+ REACT_ELEMENT_TYPE,
23
+} from 'shared/ReactSymbols';
24
+import {warnAboutSpreadingKeyToJSX} from 'shared/ReactFeatureFlags';
25
+
26
+import {jsxDEV} from './ReactJSXElement';
27
+import ReactSharedInternals from 'shared/ReactSharedInternals';
28
+
29
+const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
30
+const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
31
+
32
+let propTypesMisspellWarningShown;
33
+
34
+if (__DEV__) {
35
+ propTypesMisspellWarningShown = false;
36
+}
37
+
38
+const hasOwnProperty = Object.prototype.hasOwnProperty;
39
+
40
+/**
41
+ * Verifies the object is a ReactElement.
42
+ * See https://reactjs.org/docs/react-api.html#isvalidelement
43
+ * @param {?object} object
44
+ * @return {boolean} True if `object` is a ReactElement.
45
+ * @final
46
+ */
47
+export function isValidElement(object) {
48
+ if (__DEV__) {
49
+ return (
50
+ typeof object === 'object' &&
51
+ object !== null &&
52
+ object.$$typeof === REACT_ELEMENT_TYPE
53
+ );
54
+ }
55
+}
56
+
57
+function getDeclarationErrorAddendum() {
58
+ if (__DEV__) {
59
+ if (ReactCurrentOwner.current) {
60
+ const name = getComponentName(ReactCurrentOwner.current.type);
61
+ if (name) {
62
+ return '\n\nCheck the render method of `' + name + '`.';
63
+ }
64
+ }
65
+ return '';
66
+ }
67
+}
68
+
69
+function getSourceInfoErrorAddendum(source) {
70
+ if (__DEV__) {
71
+ if (source !== undefined) {
72
+ const fileName = source.fileName.replace(/^.*[\\\/]/, '');
73
+ const lineNumber = source.lineNumber;
74
+ return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
75
+ }
76
+ return '';
77
+ }
78
+}
79
+
80
+/**
81
+ * Warn if there's no key explicitly set on dynamic arrays of children or
82
+ * object keys are not valid. This allows us to keep track of children between
83
+ * updates.
84
+ */
85
+const ownerHasKeyUseWarning = {};
86
+
87
+function getCurrentComponentErrorInfo(parentType) {
88
+ if (__DEV__) {
89
+ let info = getDeclarationErrorAddendum();
90
+
91
+ if (!info) {
92
+ const parentName =
93
+ typeof parentType === 'string'
94
+ ? parentType
95
+ : parentType.displayName || parentType.name;
96
+ if (parentName) {
97
+ info = `\n\nCheck the top-level render call using <${parentName}>.`;
98
+ }
99
+ }
100
+ return info;
101
+ }
102
+}
103
+
104
+/**
105
+ * Warn if the element doesn't have an explicit key assigned to it.
106
+ * This element is in an array. The array could grow and shrink or be
107
+ * reordered. All children that haven't already been validated are required to
108
+ * have a "key" property assigned to it. Error statuses are cached so a warning
109
+ * will only be shown once.
110
+ *
111
+ * @internal
112
+ * @param {ReactElement} element Element that requires a key.
113
+ * @param {*} parentType element's parent's type.
114
+ */
115
+function validateExplicitKey(element, parentType) {
116
+ if (__DEV__) {
117
+ if (!element._store || element._store.validated || element.key != null) {
118
+ return;
119
+ }
120
+ element._store.validated = true;
121
+
122
+ const currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
123
+ if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
124
+ return;
125
+ }
126
+ ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
127
+
128
+ // Usually the current owner is the offender, but if it accepts children as a
129
+ // property, it may be the creator of the child that's responsible for
130
+ // assigning it a key.
131
+ let childOwner = '';
132
+ if (
133
+ element &&
134
+ element._owner &&
135
+ element._owner !== ReactCurrentOwner.current
136
+ ) {
137
+ // Give the component that originally created this child.
138
+ childOwner = ` It was passed a child from ${getComponentName(
139
+ element._owner.type,
140
+ )}.`;
141
+ }
142
+
143
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(element);
144
+ console.error(
145
+ 'Each child in a list should have a unique "key" prop.' +
146
+ '%s%s See https://fb.me/react-warning-keys for more information.',
147
+ currentComponentErrorInfo,
148
+ childOwner,
149
+ );
150
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(null);
151
+ }
152
+}
153
+
154
+/**
155
+ * Ensure that every element either is passed in a static location, in an
156
+ * array with an explicit keys property defined, or in an object literal
157
+ * with valid key property.
158
+ *
159
+ * @internal
160
+ * @param {ReactNode} node Statically passed child of any type.
161
+ * @param {*} parentType node's parent's type.
162
+ */
163
+function validateChildKeys(node, parentType) {
164
+ if (__DEV__) {
165
+ if (typeof node !== 'object') {
166
+ return;
167
+ }
168
+ if (Array.isArray(node)) {
169
+ for (let i = 0; i < node.length; i++) {
170
+ const child = node[i];
171
+ if (isValidElement(child)) {
172
+ validateExplicitKey(child, parentType);
173
+ }
174
+ }
175
+ } else if (isValidElement(node)) {
176
+ // This element was passed in a valid location.
177
+ if (node._store) {
178
+ node._store.validated = true;
179
+ }
180
+ } else if (node) {
181
+ const iteratorFn = getIteratorFn(node);
182
+ if (typeof iteratorFn === 'function') {
183
+ // Entry iterators used to provide implicit keys,
184
+ // but now we print a separate warning for them later.
185
+ if (iteratorFn !== node.entries) {
186
+ const iterator = iteratorFn.call(node);
187
+ let step;
188
+ while (!(step = iterator.next()).done) {
189
+ if (isValidElement(step.value)) {
190
+ validateExplicitKey(step.value, parentType);
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+}
198
+
199
+/**
200
+ * Given an element, validate that its props follow the propTypes definition,
201
+ * provided by the type.
202
+ *
203
+ * @param {ReactElement} element
204
+ */
205
+function validatePropTypes(element) {
206
+ if (__DEV__) {
207
+ const type = element.type;
208
+ if (type === null || type === undefined || typeof type === 'string') {
209
+ return;
210
+ }
211
+ const name = getComponentName(type);
212
+ let propTypes;
213
+ if (typeof type === 'function') {
214
+ propTypes = type.propTypes;
215
+ } else if (
216
+ typeof type === 'object' &&
217
+ (type.$$typeof === REACT_FORWARD_REF_TYPE ||
218
+ // Note: Memo only checks outer props here.
219
+ // Inner props are checked in the reconciler.
220
+ type.$$typeof === REACT_MEMO_TYPE)
221
+ ) {
222
+ propTypes = type.propTypes;
223
+ } else {
224
+ return;
225
+ }
226
+ if (propTypes) {
227
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(element);
228
+ checkPropTypes(propTypes, element.props, 'prop', name);
229
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(null);
230
+ } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
231
+ propTypesMisspellWarningShown = true;
232
+ console.error(
233
+ 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?',
234
+ name || 'Unknown',
235
+ );
236
+ }
237
+ if (
238
+ typeof type.getDefaultProps === 'function' &&
239
+ !type.getDefaultProps.isReactClassApproved
240
+ ) {
241
+ console.error(
242
+ 'getDefaultProps is only used on classic React.createClass ' +
243
+ 'definitions. Use a static property named `defaultProps` instead.',
244
+ );
245
+ }
246
+ }
247
+}
248
+
249
+/**
250
+ * Given a fragment, validate that it can only be provided with fragment props
251
+ * @param {ReactElement} fragment
252
+ */
253
+function validateFragmentProps(fragment) {
254
+ if (__DEV__) {
255
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(fragment);
256
+
257
+ const keys = Object.keys(fragment.props);
258
+ for (let i = 0; i < keys.length; i++) {
259
+ const key = keys[i];
260
+ if (key !== 'children' && key !== 'key') {
261
+ console.error(
262
+ 'Invalid prop `%s` supplied to `React.Fragment`. ' +
263
+ 'React.Fragment can only have `key` and `children` props.',
264
+ key,
265
+ );
266
+ break;
267
+ }
268
+ }
269
+
270
+ if (fragment.ref !== null) {
271
+ console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
272
+ }
273
+
274
+ ReactDebugCurrentFrame.setCurrentlyValidatingElement(null);
275
+ }
276
+}
277
+
278
+export function jsxWithValidation(
279
+ type,
280
+ props,
281
+ key,
282
+ isStaticChildren,
283
+ source,
284
+ self,
285
+) {
286
+ if (__DEV__) {
287
+ const validType = isValidElementType(type);
288
+
289
+ // We warn in this case but don't throw. We expect the element creation to
290
+ // succeed and there will likely be errors in render.
291
+ if (!validType) {
292
+ let info = '';
293
+ if (
294
+ type === undefined ||
295
+ (typeof type === 'object' &&
296
+ type !== null &&
297
+ Object.keys(type).length === 0)
298
+ ) {
299
+ info +=
300
+ ' You likely forgot to export your component from the file ' +
301
+ "it's defined in, or you might have mixed up default and named imports.";
302
+ }
303
+
304
+ const sourceInfo = getSourceInfoErrorAddendum(source);
305
+ if (sourceInfo) {
306
+ info += sourceInfo;
307
+ } else {
308
+ info += getDeclarationErrorAddendum();
309
+ }
310
+
311
+ let typeString;
312
+ if (type === null) {
313
+ typeString = 'null';
314
+ } else if (Array.isArray(type)) {
315
+ typeString = 'array';
316
+ } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
317
+ typeString = `<${getComponentName(type.type) || 'Unknown'} />`;
318
+ info =
319
+ ' Did you accidentally export a JSX literal instead of a component?';
320
+ } else {
321
+ typeString = typeof type;
322
+ }
323
+
324
+ console.error(
325
+ 'React.jsx: type is invalid -- expected a string (for ' +
326
+ 'built-in components) or a class/function (for composite ' +
327
+ 'components) but got: %s.%s',
328
+ typeString,
329
+ info,
330
+ );
331
+ }
332
+
333
+ const element = jsxDEV(type, props, key, source, self);
334
+
335
+ // The result can be nullish if a mock or a custom function is used.
336
+ // TODO: Drop this when these are no longer allowed as the type argument.
337
+ if (element == null) {
338
+ return element;
339
+ }
340
+
341
+ // Skip key warning if the type isn't valid since our key validation logic
342
+ // doesn't expect a non-string/function type and can throw confusing errors.
343
+ // We don't want exception behavior to differ between dev and prod.
344
+ // (Rendering will throw with a helpful message and as soon as the type is
345
+ // fixed, the key warnings will appear.)
346
+
347
+ if (validType) {
348
+ const children = props.children;
349
+ if (children !== undefined) {
350
+ if (isStaticChildren) {
351
+ if (Array.isArray(children)) {
352
+ for (let i = 0; i < children.length; i++) {
353
+ validateChildKeys(children[i], type);
354
+ }
355
+
356
+ if (Object.freeze) {
357
+ Object.freeze(children);
358
+ }
359
+ } else {
360
+ console.error(
361
+ 'React.jsx: Static children should always be an array. ' +
362
+ 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
363
+ 'Use the Babel transform instead.',
364
+ );
365
+ }
366
+ } else {
367
+ validateChildKeys(children, type);
368
+ }
369
+ }
370
+ }
371
+
372
+ if (warnAboutSpreadingKeyToJSX) {
373
+ if (hasOwnProperty.call(props, 'key')) {
374
+ console.error(
375
+ 'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
376
+ 'Explicitly pass a key after spreading props in your JSX call. ' +
377
+ 'E.g. <%s {...props} key={key} />',
378
+ getComponentName(type) || 'ComponentName',
379
+ );
380
+ }
381
+ }
382
+
383
+ if (type === REACT_FRAGMENT_TYPE) {
384
+ validateFragmentProps(element);
385
+ } else {
386
+ validatePropTypes(element);
387
+ }
388
+
389
+ return element;
390
+ }
391
+}
392
+
393
+// These two functions exist to still get child warnings in dev
394
+// even with the prod transform. This means that jsxDEV is purely
395
+// opt-in behavior for better messages but that we won't stop
396
+// giving you warnings if you use production apis.
397
+export function jsxWithValidationStatic(type, props, key) {
398
+ if (__DEV__) {
399
+ return jsxWithValidation(type, props, key, true);
400
+ }
401
+}
402
+
403
+export function jsxWithValidationDynamic(type, props, key) {
404
+ if (__DEV__) {
405
+ return jsxWithValidation(type, props, key, false);
406
+ }
407
+}
scripts/rollup/bundles.js
+32
@@ -76,6 +76,38 @@ const bundles = [
76
externals: [],
77
},
78
79
+ /******* React JSX Runtime *******/
80
+ {
81
+ bundleTypes: [
82
+ NODE_DEV,
83
+ NODE_PROD,
84
+ NODE_PROFILING,
85
+ FB_WWW_DEV,
86
+ FB_WWW_PROD,
87
+ FB_WWW_PROFILING,
88
+ ],
89
+ moduleType: ISOMORPHIC,
90
+ entry: 'react/jsx-runtime',
91
+ global: 'JSXRuntime',
92
+ externals: ['react'],
93
+ },
94
+
95
+ /******* React JSX DEV Runtime *******/
96
+ {
97
+ bundleTypes: [
98
+ NODE_DEV,
99
+ NODE_PROD,
100
+ NODE_PROFILING,
101
+ FB_WWW_DEV,
102
+ FB_WWW_PROD,
103
+ FB_WWW_PROFILING,
104
+ ],
105
+ moduleType: ISOMORPHIC,
106
+ entry: 'react/jsx-dev-runtime',
107
+ global: 'JSXDEVRuntime',
108
+ externals: ['react'],
109
+ },
110
+
111
/******* React DOM *******/
112
{
113
bundleTypes: [
scripts/rollup/forks.js
+1
-1
@@ -58,7 +58,7 @@ const forks = Object.freeze({
58
if (entry === 'react') {
59
return 'react/src/ReactSharedInternals';
60
}
61
- if (dependencies.indexOf('react') === -1) {
61
+ if (!entry.startsWith('react/') && dependencies.indexOf('react') === -1) {
62
// React internals are unavailable if we can't reference the package.
63
// We return an error because we only want to throw if this module gets used.
64
return new Error(
scripts/rollup/modules.js
+1
@@ -14,6 +14,7 @@ const importSideEffects = Object.freeze({
14
scheduler: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
15
'scheduler/tracing': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
16
'react-dom/server': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
17
+ 'react/jsx-dev-runtime': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
18
});
19
20
// Bundles exporting globals that other modules rely on.