/** * 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; } }, }, }; };