Load jsx-runtime after existing imports (#12546)
Co-authored-by: Brian Ng <bng412@gmail.com> Co-authored-by: Babel Bot <babel-bot@users.noreply.github.com>
This commit is contained in:
parent
6c9a481e83
commit
4f83a09dd8
@ -89,6 +89,13 @@ export type ImportOptions = {
|
||||
* * false - No particular requirements for context of the access. (Default)
|
||||
*/
|
||||
ensureNoContext: boolean,
|
||||
|
||||
/**
|
||||
* Define whether the import should be loaded before or after the existing imports.
|
||||
* "after" is only allowed inside ECMAScript modules, since it's not possible to
|
||||
* reliably pick the location _after_ require() calls but _before_ other code in CJS.
|
||||
*/
|
||||
importPosition: "before" | "after",
|
||||
};
|
||||
|
||||
/**
|
||||
@ -120,6 +127,7 @@ export default class ImportInjector {
|
||||
importingInterop: "babel",
|
||||
ensureLiveReference: false,
|
||||
ensureNoContext: false,
|
||||
importPosition: "before",
|
||||
};
|
||||
|
||||
constructor(path, importedSource, opts) {
|
||||
@ -200,9 +208,11 @@ export default class ImportInjector {
|
||||
ensureLiveReference,
|
||||
ensureNoContext,
|
||||
nameHint,
|
||||
importPosition,
|
||||
|
||||
// Not meant for public usage. Allows code that absolutely must control
|
||||
// ordering to set a specific hoist value on the import nodes.
|
||||
// This is ignored when "importPosition" is "after".
|
||||
blockHoist,
|
||||
} = opts;
|
||||
|
||||
@ -215,6 +225,10 @@ export default class ImportInjector {
|
||||
const isModuleForNode = isMod && importingInterop === "node";
|
||||
const isModuleForBabel = isMod && importingInterop === "babel";
|
||||
|
||||
if (importPosition === "after" && !isMod) {
|
||||
throw new Error(`"importPosition": "after" is only supported in modules`);
|
||||
}
|
||||
|
||||
const builder = new ImportBuilder(
|
||||
importedSource,
|
||||
this._programScope,
|
||||
@ -397,7 +411,7 @@ export default class ImportInjector {
|
||||
|
||||
const { statements, resultName } = builder.done();
|
||||
|
||||
this._insertStatements(statements, blockHoist);
|
||||
this._insertStatements(statements, importPosition, blockHoist);
|
||||
|
||||
if (
|
||||
(isDefault || isNamed) &&
|
||||
@ -409,20 +423,32 @@ export default class ImportInjector {
|
||||
return resultName;
|
||||
}
|
||||
|
||||
_insertStatements(statements, blockHoist = 3) {
|
||||
statements.forEach(node => {
|
||||
node._blockHoist = blockHoist;
|
||||
});
|
||||
_insertStatements(statements, importPosition = "before", blockHoist = 3) {
|
||||
const body = this._programPath.get("body");
|
||||
|
||||
const targetPath = this._programPath.get("body").find(p => {
|
||||
const val = p.node._blockHoist;
|
||||
return Number.isFinite(val) && val < 4;
|
||||
});
|
||||
|
||||
if (targetPath) {
|
||||
targetPath.insertBefore(statements);
|
||||
if (importPosition === "after") {
|
||||
for (let i = body.length - 1; i >= 0; i--) {
|
||||
if (body[i].isImportDeclaration()) {
|
||||
body[i].insertAfter(statements);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._programPath.unshiftContainer("body", statements);
|
||||
statements.forEach(node => {
|
||||
node._blockHoist = blockHoist;
|
||||
});
|
||||
|
||||
const targetPath = body.find(p => {
|
||||
const val = p.node._blockHoist;
|
||||
return Number.isFinite(val) && val < 4;
|
||||
});
|
||||
|
||||
if (targetPath) {
|
||||
targetPath.insertBefore(statements);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._programPath.unshiftContainer("body", statements);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,18 +2,24 @@ import * as babel from "@babel/core";
|
||||
|
||||
import { ImportInjector } from "../";
|
||||
|
||||
function test(sourceType, opts, initializer, expectedCode) {
|
||||
function test(sourceType, opts, initializer, inputCode, expectedCode) {
|
||||
if (typeof opts === "function") {
|
||||
expectedCode = initializer;
|
||||
expectedCode = inputCode;
|
||||
inputCode = initializer;
|
||||
initializer = opts;
|
||||
opts = null;
|
||||
}
|
||||
if (expectedCode === undefined) {
|
||||
expectedCode = inputCode;
|
||||
inputCode = "";
|
||||
}
|
||||
|
||||
const result = babel.transform("", {
|
||||
const result = babel.transform(inputCode, {
|
||||
cwd: __dirname,
|
||||
sourceType,
|
||||
filename: "example" + (sourceType === "module" ? ".mjs" : ".js"),
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
plugins: [
|
||||
function ({ types: t }) {
|
||||
return {
|
||||
@ -1103,4 +1109,35 @@ describe("@babel/helper-module-imports", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("importPosition: after", () => {
|
||||
it("works in ES modules", () => {
|
||||
testModule(
|
||||
{ importPosition: "after" },
|
||||
m => m.addNamed("read", "source"),
|
||||
`
|
||||
import f from "foo";
|
||||
f();
|
||||
import b from "bar";
|
||||
b();
|
||||
`,
|
||||
`
|
||||
import f from "foo";
|
||||
f();
|
||||
import b from "bar";
|
||||
import { read as _read } from "source";
|
||||
b();
|
||||
_read;
|
||||
`,
|
||||
);
|
||||
});
|
||||
|
||||
it("is disallowed in CJS modules", () => {
|
||||
expect(() =>
|
||||
testScript({ importPosition: "after" }, m =>
|
||||
m.addNamed("read", "source"),
|
||||
),
|
||||
).toThrow(`"importPosition": "after" is only supported in modules`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
var _jsxFileName = "<CWD>/packages/babel-plugin-transform-react-jsx-development/test/fixtures/linux/auto-import-dev/input.js";
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxDEV(_Fragment, {
|
||||
children: /*#__PURE__*/_jsxDEV("div", {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
|
||||
var _jsxFileName = "<CWD>/packages/babel-plugin-transform-react-jsx-development/test/fixtures/linux/self-inside-arrow/input.mjs",
|
||||
_this = this;
|
||||
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsxDEV("div", {}, void 0, false, {
|
||||
fileName: _jsxFileName,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
var _jsxFileName = "<CWD>\\packages\\babel-plugin-transform-react-jsx-development\\test\\fixtures\\windows\\auto-import-dev-windows\\input.js";
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxDEV(_Fragment, {
|
||||
children: /*#__PURE__*/_jsxDEV("div", {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
|
||||
var _jsxFileName = "<CWD>\\packages\\babel-plugin-transform-react-jsx-development\\test\\fixtures\\windows\\self-inside-arrow-windows\\input.mjs",
|
||||
_this = this;
|
||||
|
||||
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsxDEV("div", {}, void 0, false, {
|
||||
fileName: _jsxFileName,
|
||||
|
||||
@ -638,6 +638,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
|
||||
reference = addNamed(path, importName, actualSource, {
|
||||
importedInterop: "uncompiled",
|
||||
importPosition: "after",
|
||||
});
|
||||
set(pass, `imports/${importName}`, reference);
|
||||
|
||||
|
||||
11
packages/babel-plugin-transform-react-jsx/test/fixtures/autoImport/after-polyfills-2/input.mjs
vendored
Normal file
11
packages/babel-plugin-transform-react-jsx/test/fixtures/autoImport/after-polyfills-2/input.mjs
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
|
||||
ReactDOM.render(
|
||||
<p>Hello, World!</p>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// Imports are hoisted, so this is still ok
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'react-app-polyfill/stable';
|
||||
import ReactDOM from 'react-dom';
|
||||
@ -0,0 +1,9 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
ReactDOM.render( /*#__PURE__*/_jsx("p", {
|
||||
children: "Hello, World!"
|
||||
}), document.getElementById('root')); // Imports are hoisted, so this is still ok
|
||||
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'react-app-polyfill/stable';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
@ -0,0 +1,10 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'react-app-polyfill/stable';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
ReactDOM.render(
|
||||
<p>Hello, World!</p>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
["transform-react-jsx", { "runtime": "automatic" }],
|
||||
"transform-modules-commonjs"
|
||||
],
|
||||
"sourceType": "module"
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
require("react-app-polyfill/ie11");
|
||||
|
||||
require("react-app-polyfill/stable");
|
||||
|
||||
var _reactDom = _interopRequireDefault(require("react-dom"));
|
||||
|
||||
var _jsxRuntime = require("react/jsx-runtime");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
_reactDom.default.render( /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
|
||||
children: "Hello, World!"
|
||||
}), document.getElementById('root'));
|
||||
@ -0,0 +1,10 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
|
||||
require('react-app-polyfill/ie11');
|
||||
require('react-app-polyfill/stable');
|
||||
const ReactDOM = require('react-dom');
|
||||
|
||||
ReactDOM.render(
|
||||
<p>Hello, World!</p>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugins": [["transform-react-jsx", { "runtime": "automatic" }]],
|
||||
"sourceType": "script"
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
var _reactJsxRuntime = require("react/jsx-runtime");
|
||||
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
require('react-app-polyfill/ie11');
|
||||
|
||||
require('react-app-polyfill/stable');
|
||||
|
||||
const ReactDOM = require('react-dom');
|
||||
|
||||
ReactDOM.render( /*#__PURE__*/_reactJsxRuntime.jsx("p", {
|
||||
children: "Hello, World!"
|
||||
}), document.getElementById('root'));
|
||||
10
packages/babel-plugin-transform-react-jsx/test/fixtures/autoImport/after-polyfills/input.mjs
vendored
Normal file
10
packages/babel-plugin-transform-react-jsx/test/fixtures/autoImport/after-polyfills/input.mjs
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'react-app-polyfill/stable';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
ReactDOM.render(
|
||||
<p>Hello, World!</p>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
@ -0,0 +1,8 @@
|
||||
// https://github.com/babel/babel/issues/12522
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'react-app-polyfill/stable';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
ReactDOM.render( /*#__PURE__*/_jsx("p", {
|
||||
children: "Hello, World!"
|
||||
}), document.getElementById('root'));
|
||||
@ -1,7 +1,7 @@
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsx(_Fragment, {
|
||||
children: /*#__PURE__*/_jsxs("div", {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import * as react from "react";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
var y = react.createElement("div", {
|
||||
foo: 1
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxs("div", {
|
||||
children: ["foo", "bar", "baz", /*#__PURE__*/_jsx("div", {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { createElement as _createElement } from "react";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsx(_Fragment, {
|
||||
children: /*#__PURE__*/_jsxs("div", {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import * as React from "react";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsx(React.Fragment, {}, "foo");
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsx(_Fragment, {});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsx(_Fragment, {
|
||||
children: /*#__PURE__*/_jsx("div", {})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxs("div", {
|
||||
children: [/*#__PURE__*/_jsx("span", {}), [/*#__PURE__*/_jsx("span", {}, '0'), /*#__PURE__*/_jsx("span", {}, '1')]]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("div", {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("div", {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
var HelloMessage = React.createClass({
|
||||
displayName: "HelloMessage",
|
||||
render: function () {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxs("div", {
|
||||
children: [/*#__PURE__*/_jsx("div", {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsxs as _jsxs } from "react/jsx-runtime";
|
||||
|
||||
var x = /*#__PURE__*/_jsxs("div", {
|
||||
children: [/*#__PURE__*/_jsx("div", {}, "1"), /*#__PURE__*/_jsx("div", {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user