mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
This ensures that we can keep overriding what runtime to use by resetting modules while still using the automatic JSX plugin. This is like the "inline requires" transform but just for JSX. I got sick of trying to figure out workarounds to hide the extra stack frame that appears due to the wrappers.
93 lines
3.2 KiB
JavaScript
93 lines
3.2 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
'use strict';
|
|
|
|
// Most of our tests call jest.resetModules in a beforeEach and the
|
|
// re-require all the React modules. However, the JSX runtime is injected by
|
|
// the compiler, so those bindings don't get updated. This causes warnings
|
|
// logged by the JSX runtime to not have a component stack, because component
|
|
// stack relies on the the secret internals object that lives on the React
|
|
// module, which because of the resetModules call is longer the same one.
|
|
//
|
|
// To workaround this issue, use a transform that calls require() again before
|
|
// every JSX invocation.
|
|
//
|
|
// Longer term we should migrate all our tests away from using require() and
|
|
// resetModules, and use import syntax instead so this kind of thing doesn't
|
|
// happen.
|
|
|
|
module.exports = function replaceJSXImportWithLazy(babel) {
|
|
const {types: t} = babel;
|
|
|
|
function getInlineRequire(moduleName) {
|
|
return t.callExpression(t.identifier('require'), [
|
|
t.stringLiteral(moduleName),
|
|
]);
|
|
}
|
|
|
|
return {
|
|
visitor: {
|
|
CallExpression: function (path, pass) {
|
|
let callee = path.node.callee;
|
|
if (callee.type === 'SequenceExpression') {
|
|
callee = callee.expressions[callee.expressions.length - 1];
|
|
}
|
|
if (callee.type === 'Identifier') {
|
|
// Sometimes we seem to hit this before the imports are transformed
|
|
// into requires and so we hit this case.
|
|
switch (callee.name) {
|
|
case '_jsxDEV':
|
|
path.node.callee = t.memberExpression(
|
|
getInlineRequire('react/jsx-dev-runtime'),
|
|
t.identifier('jsxDEV')
|
|
);
|
|
return;
|
|
case '_jsx':
|
|
path.node.callee = t.memberExpression(
|
|
getInlineRequire('react/jsx-runtime'),
|
|
t.identifier('jsx')
|
|
);
|
|
return;
|
|
case '_jsxs':
|
|
path.node.callee = t.memberExpression(
|
|
getInlineRequire('react/jsx-runtime'),
|
|
t.identifier('jsxs')
|
|
);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
if (callee.type !== 'MemberExpression') {
|
|
return;
|
|
}
|
|
if (callee.property.type !== 'Identifier') {
|
|
// Needs to be jsx, jsxs, jsxDEV.
|
|
return;
|
|
}
|
|
if (callee.object.type !== 'Identifier') {
|
|
// Needs to be _reactJsxDevRuntime or _reactJsxRuntime.
|
|
return;
|
|
}
|
|
// Replace the cached identifier with a new require call.
|
|
// Relying on the identifier name is a little flaky. Should ideally pick
|
|
// this from the import. For some reason it sometimes has the react prefix
|
|
// and other times it doesn't.
|
|
switch (callee.object.name) {
|
|
case '_reactJsxDevRuntime':
|
|
case '_jsxDevRuntime':
|
|
callee.object = getInlineRequire('react/jsx-dev-runtime');
|
|
return;
|
|
case '_reactJsxRuntime':
|
|
case '_jsxRuntime':
|
|
callee.object = getInlineRequire('react/jsx-runtime');
|
|
return;
|
|
}
|
|
},
|
|
},
|
|
};
|
|
};
|