[runtime-corejs3] Only polyfill instance methods when it might be needed (#9754)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import semver from "semver";
|
||||
import { types as t } from "@babel/core";
|
||||
|
||||
export function hasMinVersion(minVersion, runtimeVersion) {
|
||||
// If the range is unavailable, we're running the script during Babel's
|
||||
@@ -30,3 +31,16 @@ export function hasMinVersion(minVersion, runtimeVersion) {
|
||||
!semver.intersects(`>=8.0.0`, runtimeVersion)
|
||||
);
|
||||
}
|
||||
|
||||
// Note: We can't use NodePath#couldBeBaseType because it doesn't support arrays.
|
||||
// Even if we added support for arrays, this package needs to be compatible with
|
||||
// ^7.0.0 so we can't rely on it.
|
||||
export function typeAnnotationToString(node) {
|
||||
switch (node.type) {
|
||||
case "GenericTypeAnnotation":
|
||||
if (t.isIdentifier(node.id, { name: "Array" })) return "array";
|
||||
break;
|
||||
case "StringTypeAnnotation":
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { types as t } from "@babel/core";
|
||||
|
||||
import getCoreJS2Definitions from "./runtime-corejs2-definitions";
|
||||
import getCoreJS3Definitions from "./runtime-corejs3-definitions";
|
||||
import { typeAnnotationToString } from "./helpers";
|
||||
|
||||
function resolveAbsoluteRuntime(moduleName: string, dirname: string) {
|
||||
try {
|
||||
@@ -112,6 +113,16 @@ export default declare((api, options, dirname) => {
|
||||
);
|
||||
}
|
||||
|
||||
function maybeNeedsPolyfill(path, methods, name) {
|
||||
if (!methods[name].types) return true;
|
||||
|
||||
const typeAnnotation = path.get("object").getTypeAnnotation();
|
||||
const type = typeAnnotationToString(typeAnnotation);
|
||||
if (!type) return true;
|
||||
|
||||
return methods[name].types.some(name => name === type);
|
||||
}
|
||||
|
||||
if (has(options, "useBuiltIns")) {
|
||||
if (options.useBuiltIns) {
|
||||
throw new Error(
|
||||
@@ -284,7 +295,14 @@ export default declare((api, options, dirname) => {
|
||||
|
||||
// transform calling instance methods like `something.includes()`
|
||||
if (injectCoreJS3 && !hasStaticMapping(object.name, propertyName)) {
|
||||
if (hasMapping(InstanceProperties, propertyName)) {
|
||||
if (
|
||||
hasMapping(InstanceProperties, propertyName) &&
|
||||
maybeNeedsPolyfill(
|
||||
path.get("callee"),
|
||||
InstanceProperties,
|
||||
propertyName,
|
||||
)
|
||||
) {
|
||||
let context1, context2;
|
||||
if (t.isIdentifier(object)) {
|
||||
context1 = object;
|
||||
@@ -381,7 +399,11 @@ export default declare((api, options, dirname) => {
|
||||
!hasStaticMapping(objectName, propertyName)
|
||||
) {
|
||||
// transform getting of instance methods like `method = something.includes`
|
||||
if (injectCoreJS3 && hasMapping(InstanceProperties, propertyName)) {
|
||||
if (
|
||||
injectCoreJS3 &&
|
||||
hasMapping(InstanceProperties, propertyName) &&
|
||||
maybeNeedsPolyfill(path, InstanceProperties, propertyName)
|
||||
) {
|
||||
path.replaceWith(
|
||||
t.callExpression(
|
||||
this.addDefaultImport(
|
||||
|
||||
@@ -180,12 +180,16 @@ export default () => {
|
||||
},
|
||||
},
|
||||
|
||||
// NOTE: You can specify the object types whose method needs to be polyfilled.
|
||||
// e.g. concat: { types: ["array"] }
|
||||
// See ./helpers.js@typeAnnotationToString for the supported types
|
||||
|
||||
InstanceProperties: {
|
||||
at: { stable: false, path: "at" },
|
||||
bind: { stable: true, path: "bind" },
|
||||
codePointAt: { stable: true, path: "code-point-at" },
|
||||
codePoints: { stable: false, path: "code-points" },
|
||||
concat: { stable: true, path: "concat" },
|
||||
concat: { stable: true, path: "concat", types: ["array"] },
|
||||
copyWithin: { stable: true, path: "copy-within" },
|
||||
endsWith: { stable: true, path: "ends-with" },
|
||||
entries: { stable: true, path: "entries" },
|
||||
|
||||
Reference in New Issue
Block a user