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

Implement new transform-runtime protocol for runtime package name #160

Merged
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
48 changes: 35 additions & 13 deletions packages/babel-helper-define-polyfill-provider/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ function instantiateProvider<Options>(
}
if (!polyfillsNames.has(name)) {
console.warn(
`Internal error in the ${provider.name} provider: ` +
`Internal error in the ${providerName} provider: ` +
`unknown polyfill "${name}".`,
);
}
Expand All @@ -219,7 +219,7 @@ function instantiateProvider<Options>(

if (!debug || !name) return;

if (debugLog().polyfills.has(provider.name)) return;
if (debugLog().polyfills.has(providerName)) return;
debugLog().polyfills.add(name);
debugLog().polyfillsSupport ??= polyfillsSupport;
},
Expand Down Expand Up @@ -247,11 +247,11 @@ function instantiateProvider<Options>(
};

const provider = factory(api, providerOptions, dirname);
const providerName = provider.name || factory.name;

if (typeof provider[methodName] !== "function") {
throw new Error(
`The "${provider.name || factory.name}" provider doesn't ` +
`support the "${method}" polyfilling method.`,
`The "${providerName}" provider doesn't support the "${method}" polyfilling method.`,
);
}

Expand All @@ -267,7 +267,7 @@ function instantiateProvider<Options>(
}

({ include, exclude } = validateIncludeExclude(
provider.name || factory.name,
providerName,
polyfillsNames,
providerOptions.include || [],
providerOptions.exclude || [],
Expand All @@ -278,6 +278,7 @@ function instantiateProvider<Options>(
method,
targets,
provider,
providerName,
callProvider(payload: MetaDescriptor, path: NodePath) {
const utils = getUtils(path);
provider[methodName](payload, utils, path);
Expand All @@ -299,7 +300,7 @@ export default function definePolyfillProvider<Options>(
babelApi,
);

const { debug, method, targets, provider, callProvider } =
const { debug, method, targets, provider, providerName, callProvider } =
instantiateProvider<Options>(
factory,
options,
Expand All @@ -316,16 +317,37 @@ export default function definePolyfillProvider<Options>(
: createVisitor(callProvider);

if (debug && debug !== presetEnvSilentDebugHeader) {
console.log(`${provider.name}: \`DEBUG\` option`);
console.log(`${providerName}: \`DEBUG\` option`);
console.log(`\nUsing targets: ${stringifyTargetsMultiline(targets)}`);
console.log(`\nUsing polyfills with \`${method}\` method:`);
}

const { runtimeName } = provider;

return {
name: "inject-polyfills",
visitor,

pre() {
pre(file) {
if (runtimeName) {
if (
file.get("runtimeHelpersModuleName") &&
file.get("runtimeHelpersModuleName") !== runtimeName
) {
console.warn(
`Two different polyfill providers` +
` (${file.get("runtimeHelpersModuleProvider")}` +
` and ${providerName}) are trying to define two` +
` conflicting @babel/runtime alternatives:` +
` ${file.get("runtimeHelpersModuleName")} and ${runtimeName}.` +
` The second one will be ignored.`,
);
} else {
file.set("runtimeHelpersModuleName", runtimeName);
file.set("runtimeHelpersModuleProvider", providerName);
}
}

debugLog = {
polyfills: new Set(),
polyfillsSupport: undefined,
Expand Down Expand Up @@ -355,22 +377,22 @@ export default function definePolyfillProvider<Options>(
console.log(
method === "entry-global"
? debugLog.found
? `Based on your targets, the ${provider.name} polyfill did not add any polyfill.`
: `The entry point for the ${provider.name} polyfill has not been found.`
: `Based on your code and targets, the ${provider.name} polyfill did not add any polyfill.`,
? `Based on your targets, the ${providerName} polyfill did not add any polyfill.`
: `The entry point for the ${providerName} polyfill has not been found.`
: `Based on your code and targets, the ${providerName} polyfill did not add any polyfill.`,
);

return;
}

if (method === "entry-global") {
console.log(
`The ${provider.name} polyfill entry has been replaced with ` +
`The ${providerName} polyfill entry has been replaced with ` +
`the following polyfills:`,
);
} else {
console.log(
`The ${provider.name} polyfill added the following polyfills:`,
`The ${providerName} polyfill added the following polyfills:`,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export type Utils = {

export type ProviderResult = {
name: string;
runtimeName?: string;
polyfills?: string[] | { [name: string]: Targets };
filterPolyfills?: (name: string) => boolean;
entryGlobal?: (meta: MetaDescriptor, utils: Utils, path: NodePath) => void;
Expand Down
31 changes: 31 additions & 0 deletions packages/babel-helper-define-polyfill-provider/test/misc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as babel from "@babel/core";
import definePolyfillProvider from "../lib";

function transform(code, objs) {
return babel.transformSync(code, {
configFile: false,
plugins: objs.map(obj => [
definePolyfillProvider(() => ({ usagePure() {}, ...obj })),
{ method: "usage-pure" },
]),
});
}

describe("misc", () => {
it("warns if two different providers provide a @babel/runtime alternative", () => {
const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
try {
transform("code", [
{ name: "provider-1", runtimeName: "@provider-1/babel-runtime" },
{ name: "provider-2", runtimeName: "@provider-2/babel-runtime" },
]);

expect(warn).toHaveBeenCalledTimes(1);
expect(warn.mock.lastCall[0]).toMatchInlineSnapshot(
`"Two different polyfill providers (provider-1 and provider-2) are trying to define two conflicting @babel/runtime alternatives: @provider-1/babel-runtime and @provider-2/babel-runtime. The second one will be ignored."`,
);
} finally {
warn.mockRestore();
}
});
});
17 changes: 11 additions & 6 deletions packages/babel-plugin-polyfill-corejs2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import defineProvider from "@babel/helper-define-polyfill-provider";
import type { NodePath } from "@babel/traverse";
import { types as t } from "@babel/core";

const BABEL_RUNTIME = "@babel/runtime-corejs2";

const presetEnvCompat = "#__secret_key__@babel/preset-env__compatibility";
const runtimeCompat = "#__secret_key__@babel/runtime__compatibility";

Expand All @@ -22,7 +24,7 @@ type Options = {
entryInjectRegenerator: boolean;
};
"#__secret_key__@babel/runtime__compatibility": void | {
useBabelRuntime: string;
useBabelRuntime: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change? If so this PR should be landed in a new major.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but these packages are still at 0.x (so breaking changes are in minor releases)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, 0.x -> 0.x+1 is what I mean for a new major.

runtimeVersion: string;
ext: string;
};
Expand All @@ -34,10 +36,11 @@ export default defineProvider<Options>(function (
[presetEnvCompat]: { entryInjectRegenerator } = {
entryInjectRegenerator: false,
},
[runtimeCompat]: { useBabelRuntime, runtimeVersion, ext = ".js" } = {
useBabelRuntime: "",
runtimeVersion: "",
},
[runtimeCompat]: {
useBabelRuntime = false,
runtimeVersion = "",
ext = ".js",
} = {},
},
) {
const resolve = api.createMetaResolver({
Expand All @@ -55,7 +58,7 @@ export default defineProvider<Options>(function (
);

const coreJSBase = useBabelRuntime
? `${useBabelRuntime}/core-js`
? `${BABEL_RUNTIME}/core-js`
: method === "usage-pure"
? "core-js/library/fn"
: "core-js/modules";
Expand Down Expand Up @@ -94,6 +97,8 @@ export default defineProvider<Options>(function (
return {
name: "corejs2",

runtimeName: BABEL_RUNTIME,

polyfills,

entryGlobal(meta, utils, path) {
Expand Down
12 changes: 8 additions & 4 deletions packages/babel-plugin-polyfill-corejs3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
coreJSModule,
isCoreJSSource,
coreJSPureHelper,
BABEL_RUNTIME,
} from "./utils";

import defineProvider from "@babel/helper-define-polyfill-provider";
Expand All @@ -30,7 +31,8 @@ type Options = {
proposals?: boolean;
shippedProposals?: boolean;
"#__secret_key__@babel/runtime__compatibility": void | {
useBabelRuntime: string;
useBabelRuntime: boolean;
babelRuntimePath: string;
ext: string;
};
};
Expand Down Expand Up @@ -61,7 +63,7 @@ export default defineProvider<Options>(function (
version = 3,
proposals,
shippedProposals,
[runtimeCompat]: { useBabelRuntime, ext = ".js" } = { useBabelRuntime: "" },
[runtimeCompat]: { useBabelRuntime = false, ext = ".js" } = {},
},
) {
const isWebpack = babel.caller(caller => caller?.name === "babel-loader");
Expand All @@ -77,8 +79,8 @@ export default defineProvider<Options>(function (
function getCoreJSPureBase(useProposalBase) {
return useBabelRuntime
? useProposalBase
? `${useBabelRuntime}/core-js`
: `${useBabelRuntime}/core-js-stable`
? `${BABEL_RUNTIME}/core-js`
: `${BABEL_RUNTIME}/core-js-stable`
: useProposalBase
? "core-js-pure/features"
: "core-js-pure/stable";
Expand Down Expand Up @@ -142,6 +144,8 @@ export default defineProvider<Options>(function (
return {
name: "corejs3",

runtimeName: BABEL_RUNTIME,

polyfills: corejs3Polyfills,

filterPolyfills(name) {
Expand Down
6 changes: 4 additions & 2 deletions packages/babel-plugin-polyfill-corejs3/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { types as t } from "@babel/core";
import corejsEntries from "../core-js-compat/entries.js";

export const BABEL_RUNTIME = "@babel/runtime-corejs3";

export function callMethod(path: any, id: t.Identifier) {
const { object } = path.node;

Expand Down Expand Up @@ -40,10 +42,10 @@ export function coreJSModule(name: string) {

export function coreJSPureHelper(
name: string,
useBabelRuntime: string,
useBabelRuntime: boolean,
ext: string,
) {
return useBabelRuntime
? `${useBabelRuntime}/core-js/${name}${ext}`
? `${BABEL_RUNTIME}/core-js/${name}${ext}`
: `core-js-pure/features/${name}.js`;
}
17 changes: 11 additions & 6 deletions packages/babel-plugin-polyfill-regenerator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import defineProvider from "@babel/helper-define-polyfill-provider";
import type { PluginPass } from "@babel/core";

const runtimeCompat = "#__secret_key__@babel/runtime__compatibility";

Expand All @@ -18,12 +19,7 @@ export default defineProvider<Options>(({ debug, targets, babel }, options) => {
);
}

const { [runtimeCompat]: { useBabelRuntime } = { useBabelRuntime: "" } } =
options;

const pureName = useBabelRuntime
? `${useBabelRuntime}/regenerator`
: "regenerator-runtime";
const { [runtimeCompat]: { useBabelRuntime = false } = {} } = options;

return {
name: "regenerator",
Expand All @@ -38,6 +34,15 @@ export default defineProvider<Options>(({ debug, targets, babel }, options) => {
},
usagePure(meta, utils, path) {
if (isRegenerator(meta)) {
let pureName = "regenerator-runtime";
if (useBabelRuntime) {
const runtimeName =
((path.hub as any).file as PluginPass).get(
"runtimeHelpersModuleName",
) ?? "@babel/runtime";
pureName = `${runtimeName}/regenerator`;
}

path.replaceWith(
utils.injectDefaultImport(pureName, "regenerator-runtime"),
);
Expand Down