Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve @babel/runtime esm stability #12883

Merged
merged 3 commits into from Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintignore
Expand Up @@ -26,3 +26,6 @@ packages/babel-parser/test/expressions
eslint/*/lib
eslint/*/node_modules
eslint/*/test/fixtures

test/runtime-integration/*/output.js
test/runtime-integration/*/output-absolute.js
2 changes: 2 additions & 0 deletions .flowconfig
Expand Up @@ -5,6 +5,8 @@
<PROJECT_ROOT>/codemods/.*/lib
<PROJECT_ROOT>/codemods/.*/test
<PROJECT_ROOT>/node_modules/module-deps/
<PROJECT_ROOT>/node_modules/webpack-cli/
<PROJECT_ROOT>/test/runtime-integration/

[include]
packages/*/src
Expand Down
81 changes: 81 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -269,3 +269,84 @@ jobs:
run: make test-flow
- name: Run TypeScript Tests
run: make test-typescript

runtime-interop:
name: Test @babel/runtime integrations
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use Node.js latest
uses: actions/setup-node@v2-beta
with:
node-version: "*"
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: yarn-${{ hashFiles('yarn.lock') }}
- name: Install
run: yarn install
- uses: actions/download-artifact@v2
with:
name: babel-artifact
- name: Generate runtime helpers
run: |
make build-plugin-transform-runtime-dist
- name: Generate absoluteRuntime tests
run: yarn test:runtime:generate-absolute-runtime
- name: Test bundlers
run: yarn test:runtime:bundlers
- name: Test Node.js
run: yarn test:runtime:node
- name: Use Node.js 10
uses: actions/setup-node@v2-beta
with:
node-version: 10
- name: Test Node.js 10
run: yarn test:runtime:node
- name: Use Node.js 12.0
uses: actions/setup-node@v2-beta
with:
node-version: "12.0" # quoted, otherwise it's just 13
- name: Test Node.js 12.0
run: yarn test:runtime:node
- name: Use Node.js 12.17
uses: actions/setup-node@v2-beta
with:
node-version: 12.17
- name: Test Node.js 12.17
run: yarn test:runtime:node
- name: Use Node.js 13.0
uses: actions/setup-node@v2-beta
with:
node-version: "13.0" # quoted, otherwise it's just 13
- name: Test Node.js 13.0
run: yarn test:runtime:node
# - name: Use Node.js 13.2
# uses: actions/setup-node@v2-beta
# with:
# node-version: 13.2
# - name: Test Node.js 13.2
# run: yarn test:runtime:node
# - name: Use Node.js 13.6
# uses: actions/setup-node@v2-beta
# with:
# node-version: 13.6
# - name: Test Node.js 13.6
# run: yarn test:runtime:node
- name: Use Node.js 13.7
uses: actions/setup-node@v2-beta
with:
node-version: 13.7
- name: Test Node.js 13.7
run: yarn test:runtime:node
- name: Use Node.js 14.2
uses: actions/setup-node@v2-beta
with:
node-version: 14.2
- name: Test Node.js 14.2
run: yarn test:runtime:node
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -79,3 +79,6 @@ packages/babel-standalone/babel.min.js

tsconfig.json
tsconfig.tsbuildinfo

/test/runtime-integration/*/output.js
/test/runtime-integration/*/absolute-output.js
8 changes: 6 additions & 2 deletions package.json
Expand Up @@ -12,7 +12,10 @@
"lint": "make lint",
"test": "make test",
"version": "yarn --immutable-cache && git add yarn.lock",
"test:esm": "node test/esm/index.js"
"test:esm": "node test/esm/index.js",
"test:runtime:generate-absolute-runtime": "node test/runtime-integration/generate-absolute-runtime.cjs",
"test:runtime:bundlers": "node test/runtime-integration/bundlers.cjs",
"test:runtime:node": "node test/runtime-integration/node.cjs"
},
"devDependencies": {
"@babel/cli": "^7.12.0",
Expand Down Expand Up @@ -73,7 +76,8 @@
"codemods/*",
"eslint/*",
"packages/*",
"test/esm"
"test/esm",
"test/runtime-integration/*"
],
"resolutions": {
"browserslist": "npm:4.14.5",
Expand Down
16 changes: 16 additions & 0 deletions packages/babel-plugin-transform-runtime/scripts/build-dist.js
Expand Up @@ -248,6 +248,7 @@ function buildHelper(
[transformRuntime, { corejs, version: runtimeVersion }],
buildRuntimeRewritePlugin(runtimeName, helperName),
esm ? null : addDefaultCJSExport,
esm ? useRelativeImports : null,
].filter(Boolean),
overrides: [
{
Expand Down Expand Up @@ -318,3 +319,18 @@ function addDefaultCJSExport({ template }) {
},
};
}

function useRelativeImports() {
const RE = /^@babel\/runtime(?:-corejs[23])?\/helpers\/(?<name>.+)$/;

return {
visitor: {
ImportDeclaration(path) {
path.node.source.value = path.node.source.value.replace(
RE,
"../$<name>/_index.mjs"
);
},
},
};
}
7 changes: 0 additions & 7 deletions packages/babel-plugin-transform-runtime/src/index.js
Expand Up @@ -88,13 +88,6 @@ export default declare((api, options, dirname) => {
// TODO(Babel 8): Remove this check, it's always true
const DUAL_MODE_RUNTIME = "7.13.0";
const supportsCJSDefault = hasMinVersion(DUAL_MODE_RUNTIME, runtimeVersion);
if (supportsCJSDefault && useESModules && !absoluteRuntime) {
console.warn(
`[@babel/plugin-transform-runtime] The 'useESModules' option is not necessary when using` +
` a @babel/runtime version >= ${DUAL_MODE_RUNTIME} and not using the 'absoluteRuntime'` +
` option, because it automatically detects the necessary module format.`,
);
}

function has(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions packages/babel-runtime-corejs2/helpers/temporalRef/_index.mjs
@@ -1,5 +1,5 @@
import undef from "@babel/runtime-corejs2/helpers/temporalUndefined";
import err from "@babel/runtime-corejs2/helpers/tdz";
import undef from "../temporalUndefined/_index.mjs";
import err from "../tdz/_index.mjs";
export default function _temporalRef(val, name) {
return val === undef ? err(name) : val;
}
8 changes: 4 additions & 4 deletions packages/babel-runtime-corejs2/helpers/toArray/_index.mjs
@@ -1,7 +1,7 @@
import arrayWithHoles from "@babel/runtime-corejs2/helpers/arrayWithHoles";
import iterableToArray from "@babel/runtime-corejs2/helpers/iterableToArray";
import unsupportedIterableToArray from "@babel/runtime-corejs2/helpers/unsupportedIterableToArray";
import nonIterableRest from "@babel/runtime-corejs2/helpers/nonIterableRest";
import arrayWithHoles from "../arrayWithHoles/_index.mjs";
import iterableToArray from "../iterableToArray/_index.mjs";
import unsupportedIterableToArray from "../unsupportedIterableToArray/_index.mjs";
import nonIterableRest from "../nonIterableRest/_index.mjs";
export default function _toArray(arr) {
return arrayWithHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableRest();
}
4 changes: 2 additions & 2 deletions packages/babel-runtime/helpers/temporalRef/_index.mjs
@@ -1,5 +1,5 @@
import undef from "@babel/runtime/helpers/temporalUndefined";
import err from "@babel/runtime/helpers/tdz";
import undef from "../temporalUndefined/_index.mjs";
import err from "../tdz/_index.mjs";
export default function _temporalRef(val, name) {
return val === undef ? err(name) : val;
}
8 changes: 4 additions & 4 deletions packages/babel-runtime/helpers/toArray/_index.mjs
@@ -1,7 +1,7 @@
import arrayWithHoles from "@babel/runtime/helpers/arrayWithHoles";
import iterableToArray from "@babel/runtime/helpers/iterableToArray";
import unsupportedIterableToArray from "@babel/runtime/helpers/unsupportedIterableToArray";
import nonIterableRest from "@babel/runtime/helpers/nonIterableRest";
import arrayWithHoles from "../arrayWithHoles/_index.mjs";
import iterableToArray from "../iterableToArray/_index.mjs";
import unsupportedIterableToArray from "../unsupportedIterableToArray/_index.mjs";
import nonIterableRest from "../nonIterableRest/_index.mjs";
export default function _toArray(arr) {
return arrayWithHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableRest();
}
48 changes: 48 additions & 0 deletions test/runtime-integration/bundlers.cjs
@@ -0,0 +1,48 @@
const cp = require("child_process");
const path = require("path");
const fs = require("fs");

for (const absolute of [false, true]) {
const output = absolute ? "output-absolute.js" : "output.js";
const title = absolute ? "(absolute runtime)" : "";

const webpack = absolute
? "webpack --config webpack.absolute.config.js"
: "webpack";
const rollup = absolute ? "rollup -c rollup.absolute.config.js" : "rollup -c";

// TODO: This never worked in any Babel version
if (!absolute) {
test(`Webpack 5 ${title}`, webpack, "webpack-5", output, true);
}
test(`Webpack 4 ${title}`, webpack, "webpack-4", output);
test(`Webpack 3 ${title}`, webpack, "webpack-3", output);
test(`Rollup ${title}`, rollup, "rollup", output);
}

function test(name, command, directory, output, first) {
console.log(`Building with ${name}`);
cp.execSync(`yarn ${command}`, {
cwd: path.join(__dirname, directory),
encoding: "utf8",
});
console.log(`Testing the ${name} bundle`);
const out = cp.execSync(`node ${output}`, {
cwd: path.join(__dirname, directory),
encoding: "utf8",
});

const expectedPath = path.join(__dirname, "expected-bundler.txt");
let expected = fs.readFileSync(expectedPath, "utf8");

if (expected === out) {
console.log("OK");
} else if (first && process.env.OVERWRITE) {
fs.writeFileSync(expectedPath, out);
expected = out;
console.log("UPDATED");
} else {
console.error("FAILED\n");
console.error(out);
}
}
20 changes: 20 additions & 0 deletions test/runtime-integration/expected-bundler-absolute.txt
@@ -0,0 +1,20 @@
================== import - auto ====================
typeof inheritsLoose: function
A.__proto__ === B true
================= import - esm ======================
typeof toArray: function
arr: 1,2,3
=============== import - corejs ====================
typeof Set: function
arr: 1,2,3
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
typeof toPrimitive: object
typeof toPrimitive.default: function
Value: 2
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
20 changes: 20 additions & 0 deletions test/runtime-integration/expected-bundler.txt
@@ -0,0 +1,20 @@
================== import - auto ====================
typeof inheritsLoose: function
A.__proto__ === B true
================= import - esm ======================
typeof toArray: function
arr: 1,2,3
=============== import - corejs ====================
typeof Set: function
arr: 1,2,3
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
typeof toPrimitive: object
typeof toPrimitive.default: function
Value: 2
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
9 changes: 9 additions & 0 deletions test/runtime-integration/expected-cjs-10.txt
@@ -0,0 +1,9 @@
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Unexpected token export
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
9 changes: 9 additions & 0 deletions test/runtime-integration/expected-cjs-absolute-10.txt
@@ -0,0 +1,9 @@
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Unexpected token export
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
9 changes: 9 additions & 0 deletions test/runtime-integration/expected-cjs-absolute-13.0.txt
@@ -0,0 +1,9 @@
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Unexpected token 'export'
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
13 changes: 13 additions & 0 deletions test/runtime-integration/expected-cjs-absolute.txt
@@ -0,0 +1,13 @@
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Must use import to load ES Module: <ROOT>/packages/babel-runtime/helpers/esm/toPrimitive.js
require() of ES modules is not supported.
require() of <ROOT>/packages/babel-runtime/helpers/esm/toPrimitive.js from <ROOT>/test/runtime-integration/src/absolute/require-esm.cjs is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename toPrimitive.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from <ROOT>/packages/babel-runtime/helpers/esm/package.json.

=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
9 changes: 9 additions & 0 deletions test/runtime-integration/expected-cjs.txt
@@ -0,0 +1,9 @@
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Must use import to load ES Module: <ROOT>/packages/babel-runtime/helpers/toPrimitive/_index.mjs
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3
Empty file.
18 changes: 18 additions & 0 deletions test/runtime-integration/expected-esm.txt
@@ -0,0 +1,18 @@
================== import - auto ====================
typeof inheritsLoose: function
A.__proto__ === B true
================= import - esm ======================
typeof toArray: function
arr: 1,2,3
=============== import - corejs ====================
typeof Set: function
arr: 1,2,3
================= require - auto ====================
typeof objectWithoutProperties: function
typeof objectWithoutProperties.default: function
obj: { b: 2, [Symbol(Symbol.toStringTag)]: 5 }
================= require - esm =====================
Error: Must use import to load ES Module: <ROOT>/packages/babel-runtime/helpers/toPrimitive/_index.mjs
=============== require - corejs ====================
typeof Set: function
arr: 1,2,3