enable prefer const (#5113)
This commit is contained in:
@@ -5,7 +5,7 @@ import callDelegate from "babel-helper-call-delegate";
|
||||
import template from "babel-template";
|
||||
import * as t from "babel-types";
|
||||
|
||||
let buildDefaultParam = template(`
|
||||
const buildDefaultParam = template(`
|
||||
let VARIABLE_NAME =
|
||||
ARGUMENTS.length > ARGUMENT_KEY && ARGUMENTS[ARGUMENT_KEY] !== undefined ?
|
||||
ARGUMENTS[ARGUMENT_KEY]
|
||||
@@ -13,12 +13,12 @@ let buildDefaultParam = template(`
|
||||
DEFAULT_VALUE;
|
||||
`);
|
||||
|
||||
let buildCutOff = template(`
|
||||
const buildCutOff = template(`
|
||||
let $0 = $1[$2];
|
||||
`);
|
||||
|
||||
function hasDefaults(node) {
|
||||
for (let param of (node.params: Array<Object>)) {
|
||||
for (const param of (node.params: Array<Object>)) {
|
||||
if (!t.isIdentifier(param)) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ function isSafeBinding(scope, node) {
|
||||
return kind === "param" || kind === "local";
|
||||
}
|
||||
|
||||
let iifeVisitor = {
|
||||
const iifeVisitor = {
|
||||
ReferencedIdentifier(path, state) {
|
||||
const { scope, node } = path;
|
||||
if (node.name === "eval" || !isSafeBinding(scope, node)) {
|
||||
@@ -45,23 +45,23 @@ let iifeVisitor = {
|
||||
}
|
||||
};
|
||||
|
||||
export let visitor = {
|
||||
export const visitor = {
|
||||
Function(path) {
|
||||
let { node, scope } = path;
|
||||
const { node, scope } = path;
|
||||
if (!hasDefaults(node)) return;
|
||||
|
||||
// ensure it's a block, useful for arrow functions
|
||||
path.ensureBlock();
|
||||
|
||||
let state = {
|
||||
const state = {
|
||||
iife: false,
|
||||
scope: scope
|
||||
};
|
||||
|
||||
let body = [];
|
||||
const body = [];
|
||||
|
||||
//
|
||||
let argsIdentifier = t.identifier("arguments");
|
||||
const argsIdentifier = t.identifier("arguments");
|
||||
argsIdentifier._shadowedFunctionLiteral = path;
|
||||
|
||||
// push a default parameter definition
|
||||
@@ -77,12 +77,12 @@ export let visitor = {
|
||||
}
|
||||
|
||||
//
|
||||
let lastNonDefaultParam = getFunctionArity(node);
|
||||
const lastNonDefaultParam = getFunctionArity(node);
|
||||
|
||||
//
|
||||
let params = path.get("params");
|
||||
const params = path.get("params");
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
let param = params[i];
|
||||
const param = params[i];
|
||||
|
||||
if (!param.isAssignmentPattern()) {
|
||||
if (!state.iife && !param.isIdentifier()) {
|
||||
@@ -92,12 +92,12 @@ export let visitor = {
|
||||
continue;
|
||||
}
|
||||
|
||||
let left = param.get("left");
|
||||
let right = param.get("right");
|
||||
const left = param.get("left");
|
||||
const right = param.get("right");
|
||||
|
||||
//
|
||||
if (i >= lastNonDefaultParam || left.isPattern()) {
|
||||
let placeholder = scope.generateUidIdentifier("x");
|
||||
const placeholder = scope.generateUidIdentifier("x");
|
||||
placeholder._isDefaultPlaceholder = true;
|
||||
node.params[i] = placeholder;
|
||||
} else {
|
||||
@@ -119,10 +119,10 @@ export let visitor = {
|
||||
|
||||
// add declarations for trailing parameters
|
||||
for (let i = lastNonDefaultParam + 1; i < node.params.length; i++) {
|
||||
let param = node.params[i];
|
||||
const param = node.params[i];
|
||||
if (param._isDefaultPlaceholder) continue;
|
||||
|
||||
let declar = buildCutOff(param, argsIdentifier, t.numericLiteral(i));
|
||||
const declar = buildCutOff(param, argsIdentifier, t.numericLiteral(i));
|
||||
declar._blockHoist = node.params.length - i;
|
||||
body.push(declar);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import * as t from "babel-types";
|
||||
|
||||
export let visitor = {
|
||||
export const visitor = {
|
||||
Function(path) {
|
||||
let params: Array = path.get("params");
|
||||
const params: Array = path.get("params");
|
||||
|
||||
// If there's a rest param, no need to loop through it. Also, we need to
|
||||
// hoist one more level to get `declar` at the right spot.
|
||||
let hoistTweak = t.isRestElement(params[params.length - 1]) ? 1 : 0;
|
||||
let outputParamsLength = params.length - hoistTweak;
|
||||
const hoistTweak = t.isRestElement(params[params.length - 1]) ? 1 : 0;
|
||||
const outputParamsLength = params.length - hoistTweak;
|
||||
|
||||
for (let i = 0; i < outputParamsLength; i++) {
|
||||
let param = params[i];
|
||||
const param = params[i];
|
||||
if (param.isArrayPattern() || param.isObjectPattern()) {
|
||||
let uid = path.scope.generateUidIdentifier("ref");
|
||||
const uid = path.scope.generateUidIdentifier("ref");
|
||||
|
||||
let declar = t.variableDeclaration("let", [
|
||||
const declar = t.variableDeclaration("let", [
|
||||
t.variableDeclarator(param.node, uid)
|
||||
]);
|
||||
declar._blockHoist = outputParamsLength - i;
|
||||
|
||||
@@ -10,8 +10,8 @@ export default function () {
|
||||
visitor: visitors.merge([{
|
||||
ArrowFunctionExpression(path) {
|
||||
// default/rest visitors require access to `arguments`
|
||||
let params: Array<NodePath> = path.get("params");
|
||||
for (let param of params) {
|
||||
const params: Array<NodePath> = path.get("params");
|
||||
for (const param of params) {
|
||||
if (param.isRestElement() || param.isAssignmentPattern()) {
|
||||
path.arrowFunctionToShadowed();
|
||||
break;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import template from "babel-template";
|
||||
import * as t from "babel-types";
|
||||
|
||||
let buildRest = template(`
|
||||
const buildRest = template(`
|
||||
for (var LEN = ARGUMENTS.length,
|
||||
ARRAY = Array(ARRAY_LEN),
|
||||
KEY = START;
|
||||
@@ -13,19 +13,19 @@ let buildRest = template(`
|
||||
}
|
||||
`);
|
||||
|
||||
let restIndex = template(`
|
||||
const restIndex = template(`
|
||||
ARGUMENTS.length <= INDEX ? undefined : ARGUMENTS[INDEX]
|
||||
`);
|
||||
|
||||
let restIndexImpure = template(`
|
||||
const restIndexImpure = template(`
|
||||
REF = INDEX, ARGUMENTS.length <= REF ? undefined : ARGUMENTS[REF]
|
||||
`);
|
||||
|
||||
let restLength = template(`
|
||||
const restLength = template(`
|
||||
ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET
|
||||
`);
|
||||
|
||||
let memberExpressionOptimisationVisitor = {
|
||||
const memberExpressionOptimisationVisitor = {
|
||||
Scope(path, state) {
|
||||
// check if this scope has a local binding that will shadow the rest parameter
|
||||
if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
|
||||
@@ -43,7 +43,7 @@ let memberExpressionOptimisationVisitor = {
|
||||
"Function|ClassProperty": function (path, state) {
|
||||
// Detect whether any reference to rest is contained in nested functions to
|
||||
// determine if deopt is necessary.
|
||||
let oldNoOptimise = state.noOptimise;
|
||||
const oldNoOptimise = state.noOptimise;
|
||||
state.noOptimise = true;
|
||||
path.traverse(memberExpressionOptimisationVisitor, state);
|
||||
state.noOptimise = oldNoOptimise;
|
||||
@@ -54,7 +54,7 @@ let memberExpressionOptimisationVisitor = {
|
||||
},
|
||||
|
||||
ReferencedIdentifier(path, state) {
|
||||
let { node } = path;
|
||||
const { node } = path;
|
||||
|
||||
// we can't guarantee the purity of arguments
|
||||
if (node.name === "arguments") {
|
||||
@@ -67,7 +67,7 @@ let memberExpressionOptimisationVisitor = {
|
||||
if (state.noOptimise) {
|
||||
state.deopted = true;
|
||||
} else {
|
||||
let {parentPath} = path;
|
||||
const {parentPath} = path;
|
||||
|
||||
// Is this identifier the right hand side of a default parameter?
|
||||
if (parentPath.listKey === "params" && parentPath.key < state.offset) {
|
||||
@@ -77,9 +77,9 @@ let memberExpressionOptimisationVisitor = {
|
||||
// ex: `args[0]`
|
||||
// ex: `args.whatever`
|
||||
if (parentPath.isMemberExpression({ object: node })) {
|
||||
let grandparentPath = parentPath.parentPath;
|
||||
const grandparentPath = parentPath.parentPath;
|
||||
|
||||
let argsOptEligible = !state.deopted && !(
|
||||
const argsOptEligible = !state.deopted && !(
|
||||
// ex: `args[0] = "whatever"`
|
||||
(
|
||||
grandparentPath.isAssignmentExpression() &&
|
||||
@@ -134,7 +134,7 @@ let memberExpressionOptimisationVisitor = {
|
||||
// optimise single spread args in calls
|
||||
// ex: fn(...args)
|
||||
if (state.offset === 0 && parentPath.isSpreadElement()) {
|
||||
let call = parentPath.parentPath;
|
||||
const call = parentPath.parentPath;
|
||||
if (call.isCallExpression() && call.node.arguments.length === 1) {
|
||||
state.candidates.push({cause: "argSpread", path});
|
||||
return;
|
||||
@@ -175,7 +175,7 @@ function optimiseIndexGetter(path, argsId, offset) {
|
||||
|
||||
const { scope } = path;
|
||||
if (!scope.isPure(index)) {
|
||||
let temp = scope.generateUidIdentifierBasedOnNode(index);
|
||||
const temp = scope.generateUidIdentifierBasedOnNode(index);
|
||||
scope.push({id: temp, kind: "var"});
|
||||
path.parentPath.replaceWith(restIndexImpure({
|
||||
ARGUMENTS: argsId,
|
||||
@@ -201,20 +201,20 @@ function optimiseLengthGetter(path, argsId, offset) {
|
||||
}
|
||||
}
|
||||
|
||||
export let visitor = {
|
||||
export const visitor = {
|
||||
Function(path) {
|
||||
let { node, scope } = path;
|
||||
const { node, scope } = path;
|
||||
if (!hasRest(node)) return;
|
||||
|
||||
let rest = node.params.pop().argument;
|
||||
const rest = node.params.pop().argument;
|
||||
|
||||
let argsId = t.identifier("arguments");
|
||||
const argsId = t.identifier("arguments");
|
||||
|
||||
// otherwise `arguments` will be remapped in arrow functions
|
||||
argsId._shadowedFunctionLiteral = path;
|
||||
|
||||
// check and optimise for extremely common cases
|
||||
let state = {
|
||||
const state = {
|
||||
references: [],
|
||||
offset: node.params.length,
|
||||
|
||||
@@ -246,7 +246,7 @@ export let visitor = {
|
||||
|
||||
// There are only "shorthand" references
|
||||
if (!state.deopted && !state.references.length) {
|
||||
for (let {path, cause} of (state.candidates: Array)) {
|
||||
for (const {path, cause} of (state.candidates: Array)) {
|
||||
switch (cause) {
|
||||
case "indexGetter":
|
||||
optimiseIndexGetter(path, argsId, state.offset);
|
||||
@@ -268,9 +268,9 @@ 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");
|
||||
const start = t.numericLiteral(node.params.length);
|
||||
const key = scope.generateUidIdentifier("key");
|
||||
const len = scope.generateUidIdentifier("len");
|
||||
|
||||
let arrKey = key;
|
||||
let arrLen = len;
|
||||
@@ -293,7 +293,7 @@ export let visitor = {
|
||||
);
|
||||
}
|
||||
|
||||
let loop = buildRest({
|
||||
const loop = buildRest({
|
||||
ARGUMENTS: argsId,
|
||||
ARRAY_KEY: arrKey,
|
||||
ARRAY_LEN: arrLen,
|
||||
|
||||
Reference in New Issue
Block a user