Befor generating

This commit is contained in:
marys committed 2026-06-01 13:17:37 +02:00
1 parent 3383f4bf4a
commit 1aa1b5f625
6756 files changed
+649946 -1

No files matched your search

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "convertFunctionParams", {
enumerable: true,
get: function () {
return _params.default;
}
});
exports.default = void 0;
var _helperPluginUtils = require("@babel/helper-plugin-utils");
var _params = require("./params.js");
var _rest = require("./rest.js");
var _default = exports.default = (0, _helperPluginUtils.declare)((api, options) => {
var _api$assumption, _api$assumption2;
api.assertVersion(7);
const ignoreFunctionLength = (_api$assumption = api.assumption("ignoreFunctionLength")) != null ? _api$assumption : options.loose;
const noNewArrows = (_api$assumption2 = api.assumption("noNewArrows")) != null ? _api$assumption2 : true;
return {
name: "transform-parameters",
visitor: {
Function(path) {
if (path.isArrowFunctionExpression() && path.get("params").some(param => param.isRestElement() || param.isAssignmentPattern())) {
path.arrowFunctionToExpression({
allowInsertArrowWithRest: false,
noNewArrows
});
if (!path.isFunctionExpression()) return;
}
const convertedRest = (0, _rest.default)(path);
const convertedParams = (0, _params.default)(path, ignoreFunctionLength);
if (convertedRest || convertedParams) {
path.scope.crawl();
}
}
}
};
});
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_helperPluginUtils","require","_params","_rest","_default","exports","default","declare","api","options","_api$assumption","_api$assumption2","assertVersion","ignoreFunctionLength","assumption","loose","noNewArrows","name","visitor","Function","path","isArrowFunctionExpression","get","some","param","isRestElement","isAssignmentPattern","arrowFunctionToExpression","allowInsertArrowWithRest","isFunctionExpression","convertedRest","convertFunctionRest","convertedParams","convertFunctionParams","scope","crawl"],"sources":["../src/index.ts"],"sourcesContent":["import { declare } from \"@babel/helper-plugin-utils\";\nimport convertFunctionParams from \"./params.ts\";\nimport convertFunctionRest from \"./rest.ts\";\nexport { convertFunctionParams };\n\nexport interface Options {\n loose?: boolean;\n}\n\nexport default declare((api, options: Options) => {\n api.assertVersion(REQUIRED_VERSION(7));\n\n const ignoreFunctionLength =\n api.assumption(\"ignoreFunctionLength\") ?? options.loose;\n // Todo(BABEL 8): Consider default it to false\n const noNewArrows = api.assumption(\"noNewArrows\") ?? true;\n\n return {\n name: \"transform-parameters\",\n\n visitor: {\n Function(path) {\n if (\n path.isArrowFunctionExpression() &&\n path\n .get(\"params\")\n .some(param => param.isRestElement() || param.isAssignmentPattern())\n ) {\n // default/rest visitors require access to `arguments`, so it cannot be an arrow\n path.arrowFunctionToExpression({\n allowInsertArrowWithRest: false,\n noNewArrows,\n });\n\n // In some cases arrowFunctionToExpression replaces the function with a wrapper.\n // Return early; the wrapped function will be visited later in the AST traversal.\n if (!path.isFunctionExpression()) return;\n }\n\n const convertedRest = convertFunctionRest(path);\n const convertedParams = convertFunctionParams(\n path,\n ignoreFunctionLength,\n );\n\n if (convertedRest || convertedParams) {\n // Manually reprocess this scope to ensure that the moved params are updated.\n path.scope.crawl();\n }\n },\n },\n };\n});\n"],"mappings":";;;;;;;;;;;;AAAA,IAAAA,kBAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,KAAA,GAAAF,OAAA;AAA4C,IAAAG,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAO7B,IAAAC,0BAAO,EAAC,CAACC,GAAG,EAAEC,OAAgB,KAAK;EAAA,IAAAC,eAAA,EAAAC,gBAAA;EAChDH,GAAG,CAACI,aAAa,CAAkB,CAAE,CAAC;EAEtC,MAAMC,oBAAoB,IAAAH,eAAA,GACxBF,GAAG,CAACM,UAAU,CAAC,sBAAsB,CAAC,YAAAJ,eAAA,GAAID,OAAO,CAACM,KAAK;EAEzD,MAAMC,WAAW,IAAAL,gBAAA,GAAGH,GAAG,CAACM,UAAU,CAAC,aAAa,CAAC,YAAAH,gBAAA,GAAI,IAAI;EAEzD,OAAO;IACLM,IAAI,EAAE,sBAAsB;IAE5BC,OAAO,EAAE;MACPC,QAAQA,CAACC,IAAI,EAAE;QACb,IACEA,IAAI,CAACC,yBAAyB,CAAC,CAAC,IAChCD,IAAI,CACDE,GAAG,CAAC,QAAQ,CAAC,CACbC,IAAI,CAACC,KAAK,IAAIA,KAAK,CAACC,aAAa,CAAC,CAAC,IAAID,KAAK,CAACE,mBAAmB,CAAC,CAAC,CAAC,EACtE;UAEAN,IAAI,CAACO,yBAAyB,CAAC;YAC7BC,wBAAwB,EAAE,KAAK;YAC/BZ;UACF,CAAC,CAAC;UAIF,IAAI,CAACI,IAAI,CAACS,oBAAoB,CAAC,CAAC,EAAE;QACpC;QAEA,MAAMC,aAAa,GAAG,IAAAC,aAAmB,EAACX,IAAI,CAAC;QAC/C,MAAMY,eAAe,GAAG,IAAAC,eAAqB,EAC3Cb,IAAI,EACJP,oBACF,CAAC;QAED,IAAIiB,aAAa,IAAIE,eAAe,EAAE;UAEpCZ,IAAI,CAACc,KAAK,CAACC,KAAK,CAAC,CAAC;QACpB;MACF;IACF;EACF,CAAC;AACH,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,144 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = convertFunctionParams;
var _core = require("@babel/core");
var _shadowUtils = require("./shadow-utils.js");
const buildDefaultParam = _core.template.statement(`
let VARIABLE_NAME =
arguments.length > ARGUMENT_KEY && arguments[ARGUMENT_KEY] !== undefined ?
arguments[ARGUMENT_KEY]
:
DEFAULT_VALUE;
`);
const buildLooseDefaultParam = _core.template.statement(`
if (ASSIGNMENT_IDENTIFIER === UNDEFINED) {
ASSIGNMENT_IDENTIFIER = DEFAULT_VALUE;
}
`);
const buildLooseDestructuredDefaultParam = _core.template.statement(`
let ASSIGNMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;
`);
const buildSafeArgumentsAccess = _core.template.statement(`
let $0 = arguments.length > $1 ? arguments[$1] : undefined;
`);
function convertFunctionParams(path, ignoreFunctionLength, shouldTransformParam, replaceRestElement) {
const params = path.get("params");
const isSimpleParameterList = params.every(param => param.isIdentifier());
if (isSimpleParameterList) return false;
const {
node,
scope
} = path;
const body = [];
const shadowedParams = new Set();
for (const param of params) {
(0, _shadowUtils.collectShadowedParamsNames)(param, scope, shadowedParams);
}
const state = {
needsOuterBinding: false,
scope
};
if (shadowedParams.size === 0) {
for (const param of params) {
if (!param.isIdentifier()) param.traverse(_shadowUtils.iifeVisitor, state);
if (state.needsOuterBinding) break;
}
}
let firstOptionalIndex = null;
for (let i = 0; i < params.length; i++) {
const param = params[i];
if (shouldTransformParam && !shouldTransformParam(i)) {
continue;
}
const transformedRestNodes = [];
if (replaceRestElement) {
replaceRestElement(path, param, transformedRestNodes);
}
const paramIsAssignmentPattern = param.isAssignmentPattern();
if (paramIsAssignmentPattern && (ignoreFunctionLength || _core.types.isMethod(node, {
kind: "set"
}))) {
const left = param.get("left");
const right = param.get("right");
const undefinedNode = scope.buildUndefinedNode();
if (left.isIdentifier()) {
body.push(buildLooseDefaultParam({
ASSIGNMENT_IDENTIFIER: _core.types.cloneNode(left.node),
DEFAULT_VALUE: right.node,
UNDEFINED: undefinedNode
}));
param.replaceWith(left.node);
} else if (left.isObjectPattern() || left.isArrayPattern()) {
const paramName = scope.generateUidIdentifier();
body.push(buildLooseDestructuredDefaultParam({
ASSIGNMENT_IDENTIFIER: left.node,
DEFAULT_VALUE: right.node,
PARAMETER_NAME: _core.types.cloneNode(paramName),
UNDEFINED: undefinedNode
}));
param.replaceWith(paramName);
}
} else if (paramIsAssignmentPattern) {
if (firstOptionalIndex === null) firstOptionalIndex = i;
const left = param.get("left");
const right = param.get("right");
const defNode = buildDefaultParam({
VARIABLE_NAME: left.node,
DEFAULT_VALUE: right.node,
ARGUMENT_KEY: _core.types.numericLiteral(i)
});
body.push(defNode);
} else if (firstOptionalIndex !== null) {
const defNode = buildSafeArgumentsAccess([param.node, _core.types.numericLiteral(i)]);
body.push(defNode);
} else if (param.isObjectPattern() || param.isArrayPattern()) {
const uid = path.scope.generateUidIdentifier("ref");
uid.typeAnnotation = param.node.typeAnnotation;
const defNode = _core.types.variableDeclaration("let", [_core.types.variableDeclarator(param.node, uid)]);
body.push(defNode);
param.replaceWith(_core.types.cloneNode(uid));
}
if (transformedRestNodes) {
for (const transformedNode of transformedRestNodes) {
body.push(transformedNode);
}
}
}
if (firstOptionalIndex !== null) {
node.params = node.params.slice(0, firstOptionalIndex);
}
path.ensureBlock();
const path2 = path;
const {
async,
generator
} = node;
if (generator || state.needsOuterBinding || shadowedParams.size > 0) {
body.push((0, _shadowUtils.buildScopeIIFE)(shadowedParams, path2.node.body));
path.set("body", _core.types.blockStatement(body));
const bodyPath = path2.get("body.body");
const arrowPath = bodyPath[bodyPath.length - 1].get("argument.callee");
arrowPath.arrowFunctionToExpression();
arrowPath.node.generator = generator;
arrowPath.node.async = async;
node.generator = false;
node.async = false;
if (async && !generator) {
path2.node.body = _core.template.statement.ast`{
try {
${path2.node.body.body}
} catch (e) {
return Promise.reject(e);
}
}`;
}
} else {
path2.get("body").unshiftContainer("body", body);
}
return true;
}
//# sourceMappingURL=params.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_core","require","_shadowUtils","buildDefaultParam","template","statement","buildLooseDefaultParam","buildLooseDestructuredDefaultParam","buildSafeArgumentsAccess","convertFunctionParams","path","ignoreFunctionLength","shouldTransformParam","replaceRestElement","params","get","isSimpleParameterList","every","param","isIdentifier","node","scope","body","shadowedParams","Set","collectShadowedParamsNames","state","needsOuterBinding","size","traverse","iifeVisitor","firstOptionalIndex","i","length","transformedRestNodes","paramIsAssignmentPattern","isAssignmentPattern","t","isMethod","kind","left","right","undefinedNode","buildUndefinedNode","push","ASSIGNMENT_IDENTIFIER","cloneNode","DEFAULT_VALUE","UNDEFINED","replaceWith","isObjectPattern","isArrayPattern","paramName","generateUidIdentifier","PARAMETER_NAME","defNode","VARIABLE_NAME","ARGUMENT_KEY","numericLiteral","uid","typeAnnotation","variableDeclaration","variableDeclarator","transformedNode","slice","ensureBlock","path2","async","generator","buildScopeIIFE","set","blockStatement","bodyPath","arrowPath","arrowFunctionToExpression","ast","unshiftContainer"],"sources":["../src/params.ts"],"sourcesContent":["import { template, types as t, type NodePath } from \"@babel/core\";\n\nimport {\n iifeVisitor,\n collectShadowedParamsNames,\n buildScopeIIFE,\n} from \"./shadow-utils.ts\";\n\nconst buildDefaultParam = template.statement(`\n let VARIABLE_NAME =\n arguments.length > ARGUMENT_KEY && arguments[ARGUMENT_KEY] !== undefined ?\n arguments[ARGUMENT_KEY]\n :\n DEFAULT_VALUE;\n`);\n\nconst buildLooseDefaultParam = template.statement(`\n if (ASSIGNMENT_IDENTIFIER === UNDEFINED) {\n ASSIGNMENT_IDENTIFIER = DEFAULT_VALUE;\n }\n`);\n\nconst buildLooseDestructuredDefaultParam = template.statement(`\n let ASSIGNMENT_IDENTIFIER = PARAMETER_NAME === UNDEFINED ? DEFAULT_VALUE : PARAMETER_NAME ;\n`);\n\nconst buildSafeArgumentsAccess = template.statement(`\n let $0 = arguments.length > $1 ? arguments[$1] : undefined;\n`);\n\n// last 2 parameters are optional -- they are used by transform-object-rest-spread/src/index.js\nexport default function convertFunctionParams(\n path: NodePath<t.Function>,\n ignoreFunctionLength: boolean | void,\n shouldTransformParam?: (index: number) => boolean,\n replaceRestElement?: (\n path: NodePath<t.Function>,\n paramPath: NodePath<t.Function[\"params\"][number]>,\n transformedRestNodes: t.Statement[],\n ) => void,\n) {\n const params = path.get(\"params\");\n\n const isSimpleParameterList = params.every(param => param.isIdentifier());\n if (isSimpleParameterList) return false;\n\n const { node, scope } = path;\n\n const body = [];\n const shadowedParams = new Set<string>();\n\n for (const param of params) {\n collectShadowedParamsNames(param, scope, shadowedParams);\n }\n\n const state = {\n needsOuterBinding: false,\n scope,\n };\n if (shadowedParams.size === 0) {\n for (const param of params) {\n if (!param.isIdentifier()) param.traverse(iifeVisitor, state);\n if (state.needsOuterBinding) break;\n }\n }\n\n let firstOptionalIndex = null;\n\n for (let i = 0; i < params.length; i++) {\n const param = params[i];\n\n if (shouldTransformParam && !shouldTransformParam(i)) {\n continue;\n }\n const transformedRestNodes: t.Statement[] = [];\n if (replaceRestElement) {\n replaceRestElement(path, param, transformedRestNodes);\n }\n\n const paramIsAssignmentPattern = param.isAssignmentPattern();\n if (\n paramIsAssignmentPattern &&\n (ignoreFunctionLength || t.isMethod(node, { kind: \"set\" }))\n ) {\n const left = param.get(\"left\");\n const right = param.get(\"right\");\n\n const undefinedNode = scope.buildUndefinedNode();\n\n if (left.isIdentifier()) {\n body.push(\n buildLooseDefaultParam({\n ASSIGNMENT_IDENTIFIER: t.cloneNode(left.node),\n DEFAULT_VALUE: right.node,\n UNDEFINED: undefinedNode,\n }),\n );\n param.replaceWith(left.node);\n } else if (left.isObjectPattern() || left.isArrayPattern()) {\n const paramName = scope.generateUidIdentifier();\n body.push(\n buildLooseDestructuredDefaultParam({\n ASSIGNMENT_IDENTIFIER: left.node,\n DEFAULT_VALUE: right.node,\n PARAMETER_NAME: t.cloneNode(paramName),\n UNDEFINED: undefinedNode,\n }),\n );\n param.replaceWith(paramName);\n }\n } else if (paramIsAssignmentPattern) {\n if (firstOptionalIndex === null) firstOptionalIndex = i;\n\n const left = param.get(\"left\");\n const right = param.get(\"right\");\n\n const defNode = buildDefaultParam({\n VARIABLE_NAME: left.node,\n DEFAULT_VALUE: right.node,\n ARGUMENT_KEY: t.numericLiteral(i),\n });\n body.push(defNode);\n } else if (firstOptionalIndex !== nullLine truncated
@@ -0,0 +1,284 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = convertFunctionRest;
var _core = require("@babel/core");
var _shadowUtils = require("./shadow-utils.js");
const buildRest = _core.template.statement(`
for (var LEN = ARGUMENTS.length,
ARRAY = new Array(ARRAY_LEN),
KEY = START;
KEY < LEN;
KEY++) {
ARRAY[ARRAY_KEY] = ARGUMENTS[KEY];
}
`);
const restIndex = _core.template.expression(`
(INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX]
`);
const restIndexImpure = _core.template.expression(`
REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF]
`);
const restLength = _core.template.expression(`
ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET
`);
function referencesRest(path, state) {
if (path.node.name === state.name) {
return path.scope.bindingIdentifierEquals(state.name, state.outerBinding);
}
return false;
}
const memberExpressionOptimisationVisitor = {
Scope(path, state) {
if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
path.skip();
}
},
Flow(path) {
if (path.isTypeCastExpression()) return;
path.skip();
},
Function(path, state) {
const oldNoOptimise = state.noOptimise;
state.noOptimise = true;
path.traverse(memberExpressionOptimisationVisitor, state);
state.noOptimise = oldNoOptimise;
path.skip();
},
ReferencedIdentifier(path, state) {
const {
node
} = path;
if (node.name === "arguments") {
state.deopted = true;
}
if (!referencesRest(path, state)) return;
if (state.noOptimise) {
state.deopted = true;
} else {
const {
parentPath
} = path;
if (parentPath.listKey === "params" && parentPath.key < state.offset) {
return;
}
if (parentPath.isMemberExpression({
object: node
})) {
const grandparentPath = parentPath.parentPath;
const argsOptEligible = !state.deopted && !(grandparentPath.isAssignmentExpression() && parentPath.node === grandparentPath.node.left || grandparentPath.isLVal() || grandparentPath.isForXStatement() || grandparentPath.isUpdateExpression() || grandparentPath.isUnaryExpression({
operator: "delete"
}) || (grandparentPath.isCallExpression() || grandparentPath.isNewExpression()) && parentPath.node === grandparentPath.node.callee);
if (argsOptEligible) {
if (parentPath.node.computed) {
if (parentPath.get("property").isBaseType("number")) {
state.candidates.push({
cause: "indexGetter",
path
});
return;
}
} else if (parentPath.node.property.name === "length") {
state.candidates.push({
cause: "lengthGetter",
path
});
return;
}
}
}
if (state.offset === 0 && parentPath.isSpreadElement()) {
const call = parentPath.parentPath;
if (call.isCallExpression() && call.node.arguments.length === 1) {
state.candidates.push({
cause: "argSpread",
path
});
return;
}
}
state.references.push(path);
}
},
BindingIdentifier(path, state) {
if (referencesRest(path, state)) {
state.deopted = true;
}
}
};
function getParamsCount(node) {
let count = node.params.length;
if (count > 0 && _core.types.isIdentifier(node.params[0], {
name: "this"
})) {
count -= 1;
}
return count;
}
function hasRest(node) {
const length = node.params.length;
return length > 0 && _core.types.isRestElement(node.params[length - 1]);
}
function optimiseIndexGetter(path, argsId, offset) {
const offsetLiteral = _core.types.numericLiteral(offset);
let index;
const parent = path.parent;
if (_core.types.isNumericLiteral(parent.property)) {
index = _core.types.numericLiteral(parent.property.value + offset);
} else if (offset === 0) {
index = parent.property;
} else {
index = _core.types.binaryExpression("+", parent.property, _core.types.cloneNode(offsetLiteral));
}
const {
scope,
parentPath
} = path;
if (!scope.isPure(index)) {
const temp = scope.generateUidIdentifierBasedOnNode(index);
scope.push({
id: temp,
kind: "var"
});
parentPath.replaceWith(restIndexImpure({
ARGUMENTS: argsId,
OFFSET: offsetLiteral,
INDEX: index,
REF: _core.types.cloneNode(temp)
}));
} else {
parentPath.replaceWith(restIndex({
ARGUMENTS: argsId,
OFFSET: offsetLiteral,
INDEX: index
}));
const replacedParentPath = parentPath;
const offsetTestPath = replacedParentPath.get("test");
const valRes = offsetTestPath.get("left").evaluate();
if (valRes.confident) {
if (valRes.value === true) {
replacedParentPath.replaceWith(scope.buildUndefinedNode());
} else {
offsetTestPath.replaceWith(offsetTestPath.get("right"));
}
}
}
}
function optimiseLengthGetter(path, argsId, offset) {
if (offset) {
path.parentPath.replaceWith(restLength({
ARGUMENTS: argsId,
OFFSET: _core.types.numericLiteral(offset)
}));
} else {
path.replaceWith(argsId);
}
}
function convertFunctionRest(path) {
const {
node,
scope
} = path;
if (!hasRest(node)) return false;
const restPath = path.get(`params.${node.params.length - 1}.argument`);
if (!restPath.isIdentifier()) {
const shadowedParams = new Set();
(0, _shadowUtils.collectShadowedParamsNames)(restPath, path.scope, shadowedParams);
let needsIIFE = shadowedParams.size > 0;
if (!needsIIFE) {
const state = {
needsOuterBinding: false,
scope
};
restPath.traverse(_shadowUtils.iifeVisitor, state);
needsIIFE = state.needsOuterBinding;
}
if (needsIIFE) {
path.ensureBlock();
path.set("body", _core.types.blockStatement([(0, _shadowUtils.buildScopeIIFE)(shadowedParams, path.node.body)]));
}
}
let rest = restPath.node;
node.params.pop();
if (_core.types.isPattern(rest)) {
const pattern = rest;
rest = scope.generateUidIdentifier("ref");
const declar = _core.types.variableDeclaration("let", [_core.types.variableDeclarator(pattern, rest)]);
path.ensureBlock();
node.body.body.unshift(declar);
} else if (rest.name === "arguments") {
scope.rename(rest.name);
}
const argsId = _core.types.identifier("arguments");
const paramsCount = getParamsCount(node);
const state = {
references: [],
offset: paramsCount,
argumentsNode: argsId,
outerBinding: scope.getBindingIdentifier(rest.name),
candidates: [],
name: rest.name,
deopted: false
};
path.traverse(memberExpressionOptimisationVisitor, state);
if (!state.deopted && !state.references.length) {
for (const {
path,
cause
} of state.candidates) {
const clonedArgsId = _core.types.cloneNode(argsId);
switch (cause) {
case "indexGetter":
optimiseIndexGetter(path, clonedArgsId, state.offset);
break;
case "lengthGetter":
optimiseLengthGetter(path, clonedArgsId, state.offset);
break;
default:
path.replaceWith(clonedArgsId);
}
}
return true;
}
state.references.push(...state.candidates.map(({
path
}) => path));
const start = _core.types.numericLiteral(paramsCount);
const key = scope.generateUidIdentifier("key");
const len = scope.generateUidIdentifier("len");
let arrKey, arrLen;
if (paramsCount) {
arrKey = _core.types.binaryExpression("-", _core.types.cloneNode(key), _core.types.cloneNode(start));
arrLen = _core.types.conditionalExpression(_core.types.binaryExpression(">", _core.types.cloneNode(len), _core.types.cloneNode(start)), _core.types.binaryExpression("-", _core.types.cloneNode(len), _core.types.cloneNode(start)), _core.types.numericLiteral(0));
} else {
arrKey = _core.types.identifier(key.name);
arrLen = _core.types.identifier(len.name);
}
const loop = buildRest({
ARGUMENTS: argsId,
ARRAY_KEY: arrKey,
ARRAY_LEN: arrLen,
START: start,
ARRAY: rest,
KEY: key,
LEN: len
});
if (state.deopted) {
node.body.body.unshift(loop);
} else {
let target = path.getEarliestCommonAncestorFrom(state.references).getStatementParent();
target.findParent(path => {
if (path.isLoop()) {
target = path;
} else {
return path.isFunction();
}
});
target.insertBefore(loop);
}
return true;
}
//# sourceMappingURL=rest.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_core","require","_shadowUtils","buildRest","template","statement","restIndex","expression","restIndexImpure","restLength","referencesRest","path","state","node","name","scope","bindingIdentifierEquals","outerBinding","memberExpressionOptimisationVisitor","Scope","skip","Flow","isTypeCastExpression","Function","oldNoOptimise","noOptimise","traverse","ReferencedIdentifier","deopted","parentPath","listKey","key","offset","isMemberExpression","object","grandparentPath","argsOptEligible","isAssignmentExpression","left","isLVal","isForXStatement","isUpdateExpression","isUnaryExpression","operator","isCallExpression","isNewExpression","callee","computed","get","isBaseType","candidates","push","cause","property","isSpreadElement","call","arguments","length","references","BindingIdentifier","getParamsCount","count","params","t","isIdentifier","hasRest","isRestElement","optimiseIndexGetter","argsId","offsetLiteral","numericLiteral","index","parent","isNumericLiteral","value","binaryExpression","cloneNode","isPure","temp","generateUidIdentifierBasedOnNode","id","kind","replaceWith","ARGUMENTS","OFFSET","INDEX","REF","replacedParentPath","offsetTestPath","valRes","evaluate","confident","buildUndefinedNode","optimiseLengthGetter","convertFunctionRest","restPath","shadowedParams","Set","collectShadowedParamsNames","needsIIFE","size","needsOuterBinding","iifeVisitor","ensureBlock","set","blockStatement","buildScopeIIFE","body","rest","pop","isPattern","pattern","generateUidIdentifier","declar","variableDeclaration","variableDeclarator","unshift","rename","identifier","paramsCount","argumentsNode","getBindingIdentifier","clonedArgsId","map","start","len","arrKey","arrLen","conditionalExpression","loop","ARRAY_KEY","ARRAY_LEN","START","ARRAY","KEY","LEN","target","getEarliestCommonAncestorFrom","getStatementParent","findParent","isLoop","isFunction","insertBefore"],"sources":["../src/rest.ts"],"sourcesContent":["import { template, types as t } from \"@babel/core\";\nimport type { NodePath, Visitor } from \"@babel/core\";\n\nimport {\n iifeVisitor,\n collectShadowedParamsNames,\n buildScopeIIFE,\n} from \"./shadow-utils.ts\";\n\nconst buildRest = template.statement(`\n for (var LEN = ARGUMENTS.length,\n ARRAY = new Array(ARRAY_LEN),\n KEY = START;\n KEY < LEN;\n KEY++) {\n ARRAY[ARRAY_KEY] = ARGUMENTS[KEY];\n }\n`);\n\nconst restIndex = template.expression(`\n (INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX]\n`);\n\nconst restIndexImpure = template.expression(`\n REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF]\n`);\n\nconst restLength = template.expression(`\n ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET\n`);\n\nfunction referencesRest(\n path: NodePath<t.Identifier | t.JSXIdentifier>,\n state: State,\n) {\n if (path.node.name === state.name) {\n // Check rest parameter is not shadowed by a binding in another scope.\n return path.scope.bindingIdentifierEquals(state.name, state.outerBinding);\n }\n\n return false;\n}\n\ntype Candidate = {\n cause: \"argSpread\" | \"indexGetter\" | \"lengthGetter\";\n path: NodePath<t.Identifier | t.JSXIdentifier>;\n};\n\ntype State = {\n references: NodePath<t.Identifier | t.JSXIdentifier>[];\n offset: number;\n\n argumentsNode: t.Identifier;\n outerBinding: t.Identifier;\n\n // candidate member expressions we could optimise if there are no other references\n candidates: Candidate[];\n\n // local rest binding name\n name: string;\n\n /*\n It may be possible to optimize the output code in certain ways, such as\n not generating code to initialize an array (perhaps substituting direct\n references to arguments[i] or arguments.length for reads of the\n corresponding rest parameter property) or positioning the initialization\n code so that it may not have to execute depending on runtime conditions.\n\n This property tracks eligibility for optimization. \"deopted\" means give up\n and don't perform optimization. For example, when any of rest's elements /\n properties is assigned to at the top level, or referenced at all in a\n nested function.\n */\n deopted: boolean;\n noOptimise?: boolean;\n};\n\nconst memberExpressionOptimisationVisitor: Visitor<State> = {\n Scope(path, state) {\n // check if this scope has a local binding that will shadow the rest parameter\n if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) {\n path.skip();\n }\n },\n\n Flow(path: NodePath<t.Flow>) {\n // Do not skip TypeCastExpressions as the contain valid non flow code\n if (path.isTypeCastExpression()) return;\n // don't touch reference in type annotations\n path.skip();\n },\n\n Function(path, state) {\n // Detect whether any reference to rest is contained in nested functions to\n // determine if deopt is necessary.\n const oldNoOptimise = state.noOptimise;\n state.noOptimise = truLine truncated
@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildScopeIIFE = buildScopeIIFE;
exports.collectShadowedParamsNames = collectShadowedParamsNames;
exports.iifeVisitor = void 0;
var _core = require("@babel/core");
const iifeVisitor = exports.iifeVisitor = {
"ReferencedIdentifier|BindingIdentifier"(path, state) {
const {
scope,
node
} = path;
const {
name
} = node;
if (name === "eval" || scope.getBinding(name) === state.scope.parent.getBinding(name) && state.scope.hasOwnBinding(name)) {
state.needsOuterBinding = true;
path.stop();
}
},
"TypeAnnotation|TSTypeAnnotation|TypeParameterDeclaration|TSTypeParameterDeclaration": path => path.skip()
};
function collectShadowedParamsNames(param, functionScope, shadowedParams) {
for (const name of Object.keys(param.getBindingIdentifiers())) {
var _functionScope$bindin;
const constantViolations = (_functionScope$bindin = functionScope.bindings[name]) == null ? void 0 : _functionScope$bindin.constantViolations;
if (constantViolations) {
for (const redeclarator of constantViolations) {
const node = redeclarator.node;
switch (node.type) {
case "VariableDeclarator":
{
if (node.init === null) {
const declaration = redeclarator.parentPath;
if (!declaration.parentPath.isFor() || declaration.parentPath.get("body") === declaration) {
redeclarator.remove();
break;
}
}
shadowedParams.add(name);
break;
}
case "FunctionDeclaration":
shadowedParams.add(name);
break;
}
}
}
}
}
function buildScopeIIFE(shadowedParams, body) {
const args = [];
const params = [];
for (const name of shadowedParams) {
args.push(_core.types.identifier(name));
params.push(_core.types.identifier(name));
}
return _core.types.returnStatement(_core.types.callExpression(_core.types.arrowFunctionExpression(params, body), args));
}
//# sourceMappingURL=shadow-utils.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_core","require","iifeVisitor","exports","ReferencedIdentifier|BindingIdentifier","path","state","scope","node","name","getBinding","parent","hasOwnBinding","needsOuterBinding","stop","skip","collectShadowedParamsNames","param","functionScope","shadowedParams","Object","keys","getBindingIdentifiers","_functionScope$bindin","constantViolations","bindings","redeclarator","type","init","declaration","parentPath","isFor","get","remove","add","buildScopeIIFE","body","args","params","push","t","identifier","returnStatement","callExpression","arrowFunctionExpression"],"sources":["../src/shadow-utils.ts"],"sourcesContent":["import { types as t } from \"@babel/core\";\nimport type { NodePath, Scope, Visitor } from \"@babel/core\";\n\ntype State = {\n needsOuterBinding: boolean;\n scope: Scope;\n};\n\nexport const iifeVisitor: Visitor<State> = {\n \"ReferencedIdentifier|BindingIdentifier\"(\n path: NodePath<t.Identifier>,\n state,\n ) {\n const { scope, node } = path;\n const { name } = node;\n\n if (\n name === \"eval\" ||\n (scope.getBinding(name) === state.scope.parent.getBinding(name) &&\n state.scope.hasOwnBinding(name))\n ) {\n state.needsOuterBinding = true;\n path.stop();\n }\n },\n // type annotations don't use or introduce \"real\" bindings\n \"TypeAnnotation|TSTypeAnnotation|TypeParameterDeclaration|TSTypeParameterDeclaration\":\n (path: NodePath) => path.skip(),\n};\n\nexport function collectShadowedParamsNames(\n param: NodePath<t.Function[\"params\"][number]>,\n functionScope: Scope,\n shadowedParams: Set<string>,\n) {\n for (const name of Object.keys(param.getBindingIdentifiers())) {\n const constantViolations = functionScope.bindings[name]?.constantViolations;\n if (constantViolations) {\n for (const redeclarator of constantViolations) {\n const node = redeclarator.node;\n // If a constant violation is a var or a function declaration,\n // we first check to see if it's a var without an init.\n // If so, we remove that declarator.\n // Otherwise, we have to wrap it in an IIFE.\n switch (node.type) {\n case \"VariableDeclarator\": {\n if (node.init === null) {\n const declaration = redeclarator.parentPath;\n // The following uninitialized var declarators should not be removed\n // for (var x in {})\n // for (var x;;)\n if (\n !declaration.parentPath.isFor() ||\n declaration.parentPath.get(\"body\") === declaration\n ) {\n redeclarator.remove();\n break;\n }\n }\n\n shadowedParams.add(name);\n break;\n }\n case \"FunctionDeclaration\":\n shadowedParams.add(name);\n break;\n }\n }\n }\n }\n}\n\nexport function buildScopeIIFE(\n shadowedParams: Set<string>,\n body: t.BlockStatement,\n) {\n const args = [];\n const params = [];\n\n for (const name of shadowedParams) {\n // We create them twice; the other option is to use t.cloneNode\n args.push(t.identifier(name));\n params.push(t.identifier(name));\n }\n\n return t.returnStatement(\n t.callExpression(t.arrowFunctionExpression(params, body), args),\n );\n}\n"],"mappings":";;;;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAQO,MAAMC,WAA2B,GAAAC,OAAA,CAAAD,WAAA,GAAG;EACzC,wCAAwCE,CACtCC,IAA4B,EAC5BC,KAAK,EACL;IACA,MAAM;MAAEC,KAAK;MAAEC;IAAK,CAAC,GAAGH,IAAI;IAC5B,MAAM;MAAEI;IAAK,CAAC,GAAGD,IAAI;IAErB,IACEC,IAAI,KAAK,MAAM,IACdF,KAAK,CAACG,UAAU,CAACD,IAAI,CAAC,KAAKH,KAAK,CAACC,KAAK,CAACI,MAAM,CAACD,UAAU,CAACD,IAAI,CAAC,IAC7DH,KAAK,CAACC,KAAK,CAACK,aAAa,CAACH,IAAI,CAAE,EAClC;MACAH,KAAK,CAACO,iBAAiB,GAAG,IAAI;MAC9BR,IAAI,CAACS,IAAI,CAAC,CAAC;IACb;EACF,CAAC;EAED,qFAAqF,EAClFT,IAAc,IAAKA,IAAI,CAACU,IAAI,CAAC;AAClC,CAAC;AAEM,SAASC,0BAA0BA,CACxCC,KAA6C,EAC7CC,aAAoB,EACpBC,cAA2B,EAC3B;EACA,KAAK,MAAMV,IAAI,IAAIW,MAAM,CAACC,IAAI,CAACJ,KAAK,CAACK,qBAAqB,CAAC,CAAC,CAAC,EAAE;IAAA,IAAAC,qBAAA;IAC7D,MAAMC,kBAAkB,IAAAD,qBAAA,GAAGL,aAAa,CAACO,QAAQ,CAAChB,IAAI,CAAC,qBAA5Bc,qBAAA,CAA8BC,kBAAkB;IAC3E,IAAIA,kBAAkB,EAAE;MACtB,KAAK,MAAME,YAAY,IAAIF,kBAAkB,EAAE;QAC7C,MAAMhB,IAAI,GAAGkB,YAAY,CAAClB,IAAI;QAK9B,QAAQA,IAAI,CAACmB,IAAI;UACf,KAAK,oBAAoB;YAAE;cACzB,IAAInB,IAAI,CAACoB,IAAI,KAAK,IAAI,EAAE;gBACtB,MAAMC,WAAW,GAAGH,YAAY,CAACI,UAAU;gBAI3C,IACE,CAACD,WAAW,CAACC,UAAU,CAACC,KAAK,CAAC,CAAC,IAC/BF,WAAW,CAACC,UAAU,CAACE,GAAG,CAAC,MAAM,CAAC,KAAKH,WAAW,EAClD;kBACAH,YAAY,CAACO,MAAM,CAAC,CAAC;kBACrB;gBACF;cACF;cAEAd,cAAc,CAACe,GAAG,CAACzB,IAAI,CAAC;cACxB;YACF;UACA,KAAK,qBAAqB;YACxBU,cAAc,CAACe,GAAG,CAACzB,IAAI,CAAC;YACxB;QACJ;MACF;IACF;EACF;AACF;AAEO,SAAS0B,cAAcA,CAC5BhB,cAA2B,EAC3BiB,IAAsB,EACtB;EACA,MAAMC,IAAI,GAAG,EAAE;EACf,MAAMC,MAAM,GAAG,EAAE;EAEjB,KAAK,MAAM7B,IAAI,IAAIU,cAAc,EAAE;IAEjCkB,IAAI,CAACE,IAAI,CAACC,WAAC,CAACC,UAAU,CAAChC,IAAI,CAAC,CAAC;IAC7B6B,MAAM,CAACC,IAAI,CAACC,WAAC,CAACC,ULine truncated