Merge pull request #2833 from vhf/rest-arguments-use
Have es2015 rest transform safely use `arguments`
This commit is contained in:
@@ -11,6 +11,10 @@ let buildRest = template(`
|
||||
}
|
||||
`);
|
||||
|
||||
let loadRest = template(`
|
||||
ARGUMENTS.length <= KEY || ARGUMENTS[KEY] === undefined ? undefined : ARGUMENTS[KEY]
|
||||
`);
|
||||
|
||||
let memberExpressionOptimisationVisitor = {
|
||||
Scope(path, state) {
|
||||
// check if this scope has a local binding that will shadow the rest parameter
|
||||
@@ -84,21 +88,6 @@ let memberExpressionOptimisationVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
function optimiseMemberExpression(parent, offset) {
|
||||
if (offset === 0) return;
|
||||
|
||||
let newExpr;
|
||||
let prop = parent.property;
|
||||
|
||||
if (t.isLiteral(prop)) {
|
||||
prop.value += offset;
|
||||
prop.raw = String(prop.value);
|
||||
} else { // // UnaryExpression, BinaryExpression
|
||||
newExpr = t.binaryExpression("+", prop, t.numericLiteral(offset));
|
||||
parent.property = newExpr;
|
||||
}
|
||||
}
|
||||
|
||||
function hasRest(node) {
|
||||
return t.isRestElement(node.params[node.params.length - 1]);
|
||||
}
|
||||
@@ -116,16 +105,25 @@ export let visitor = {
|
||||
// otherwise `arguments` will be remapped in arrow functions
|
||||
argsId._shadowedFunctionLiteral = path;
|
||||
|
||||
// support patterns
|
||||
if (t.isPattern(rest)) {
|
||||
let pattern = rest;
|
||||
rest = scope.generateUidIdentifier("ref");
|
||||
function optimiseCandidate(parent, parentPath, offset) {
|
||||
if (t.isReturnStatement(parentPath.parent) || t.isIdentifier(parentPath.parent.id)) {
|
||||
parentPath.replaceWith(loadRest({
|
||||
ARGUMENTS: argsId,
|
||||
KEY: t.numericLiteral(parent.property.value + offset)
|
||||
}));
|
||||
} else {
|
||||
if (offset === 0) return;
|
||||
let newExpr;
|
||||
let prop = parent.property;
|
||||
|
||||
let declar = t.variableDeclaration("let", pattern.elements.map(function (elem, index) {
|
||||
let accessExpr = t.memberExpression(rest, t.numericLiteral(index), true);
|
||||
return t.variableDeclarator(elem, accessExpr);
|
||||
}));
|
||||
node.body.body.unshift(declar);
|
||||
if (t.isLiteral(prop)) {
|
||||
prop.value += offset;
|
||||
prop.raw = String(prop.value);
|
||||
} else { // UnaryExpression, BinaryExpression
|
||||
newExpr = t.binaryExpression("+", prop, t.numericLiteral(offset));
|
||||
parent.property = newExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check and optimise for extremely common cases
|
||||
@@ -153,9 +151,7 @@ export let visitor = {
|
||||
if (state.candidates.length) {
|
||||
for (let candidate of (state.candidates: Array)) {
|
||||
candidate.replaceWith(argsId);
|
||||
if (candidate.parentPath.isMemberExpression()) {
|
||||
optimiseMemberExpression(candidate.parent, state.offset);
|
||||
}
|
||||
optimiseCandidate(candidate.parent, candidate.parentPath, state.offset);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -166,8 +162,6 @@ export let visitor = {
|
||||
// deopt shadowed functions as transforms like regenerator may try touch the allocation loop
|
||||
state.deopted = state.deopted || !!node.shadow;
|
||||
|
||||
//
|
||||
|
||||
let start = t.numericLiteral(node.params.length);
|
||||
let key = scope.generateUidIdentifier("key");
|
||||
let len = scope.generateUidIdentifier("len");
|
||||
|
||||
@@ -14,7 +14,7 @@ var somefun = function () {
|
||||
};
|
||||
var _d = args1[1];
|
||||
};
|
||||
let get1stArg = (...args) => args[0];
|
||||
let get3rdArg = (...args) => args[2];
|
||||
}
|
||||
|
||||
function demo1(...args) {
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
var concat = function () {
|
||||
var x = arguments[0];
|
||||
var y = arguments[1];
|
||||
var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0];
|
||||
var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
|
||||
};
|
||||
|
||||
var somefun = function () {
|
||||
var get2ndArg = function (a, b) {
|
||||
var _b = arguments[2];
|
||||
var _b = arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2];
|
||||
var somef = function (x, y, z) {
|
||||
var _a = arguments[3];
|
||||
var _a = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3];
|
||||
};
|
||||
var somefg = function (c, d, e, f) {
|
||||
var _a = arguments[4];
|
||||
var _a = arguments.length <= 4 || arguments[4] === undefined ? undefined : arguments[4];
|
||||
};
|
||||
var _d = arguments[3];
|
||||
var _d = arguments.length <= 3 || arguments[3] === undefined ? undefined : arguments[3];
|
||||
};
|
||||
var get1stArg = function () {
|
||||
return arguments[0];
|
||||
var get3rdArg = function () {
|
||||
return arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
var t = function () {
|
||||
var x = arguments[0];
|
||||
var y = arguments[1];
|
||||
var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0];
|
||||
var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
|
||||
};
|
||||
|
||||
function t() {
|
||||
var x = arguments[0];
|
||||
var y = arguments[1];
|
||||
var x = arguments.length <= 0 || arguments[0] === undefined ? undefined : arguments[0];
|
||||
var y = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user