From 10640b2aad8bca252b665e3372095b89302bb808 Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Sat, 14 Aug 2021 16:57:06 +0200 Subject: [PATCH] perf: partially replace `.concat` with `.push` (#13609) --- .../babel-cli/src/babel-external-helpers.ts | 6 +- packages/babel-cli/src/babel/options.ts | 9 ++- packages/babel-helper-define-map/src/index.js | 4 +- packages/babel-helpers/src/helpers.js | 4 +- packages/babel-node/src/_babel-node.js | 8 ++- packages/babel-node/src/babel-node.js | 4 +- .../babel-parser/src/plugins/flow/index.js | 3 +- .../src/index.js | 2 +- .../src/transformer-legacy.js | 6 +- .../src/transformClass.ts | 13 ++-- .../src/no-helper-implementation.js | 2 +- .../src/index.js | 12 ++-- .../src/rest.js | 4 +- packages/babel-traverse/src/path/family.ts | 70 ++++++++++--------- .../src/path/inference/inferer-reference.ts | 2 +- .../babel-types/src/comments/addComments.ts | 2 +- .../flow/removeTypeDuplicates.ts | 8 ++- .../typescript/removeTypeDuplicates.ts | 8 +-- 18 files changed, 93 insertions(+), 74 deletions(-) diff --git a/packages/babel-cli/src/babel-external-helpers.ts b/packages/babel-cli/src/babel-external-helpers.ts index 5c6ef24de6ca..930cf56717ef 100755 --- a/packages/babel-cli/src/babel-external-helpers.ts +++ b/packages/babel-cli/src/babel-external-helpers.ts @@ -10,7 +10,11 @@ function collect( const values = value.split(","); - return previousValue ? previousValue.concat(values) : values; + if (previousValue) { + previousValue.push(...values); + return previousValue; + } + return values; } commander.option( diff --git a/packages/babel-cli/src/babel/options.ts b/packages/babel-cli/src/babel/options.ts index 19eb9b20c62c..da35ca377b5a 100644 --- a/packages/babel-cli/src/babel/options.ts +++ b/packages/babel-cli/src/babel/options.ts @@ -192,7 +192,8 @@ export default function parseArgv(args: Array): CmdOptions | null { let filenames = commander.args.reduce(function (globbed, input) { let files = glob.sync(input); if (!files.length) files = [input]; - return globbed.concat(files); + globbed.push(...files); + return globbed; }, []); filenames = Array.from(new Set(filenames)); @@ -353,5 +354,9 @@ function collect( const values = value.split(","); - return previousValue ? previousValue.concat(values) : values; + if (previousValue) { + previousValue.push(...values); + return previousValue; + } + return values; } diff --git a/packages/babel-helper-define-map/src/index.js b/packages/babel-helper-define-map/src/index.js index 290a50c20202..2d90fb6d2675 100644 --- a/packages/babel-helper-define-map/src/index.js +++ b/packages/babel-helper-define-map/src/index.js @@ -42,8 +42,8 @@ export function push( if (node.decorators) { const decorators = (map.decorators = map.decorators || t.arrayExpression([])); - decorators.elements = decorators.elements.concat( - node.decorators.map(dec => dec.expression).reverse(), + decorators.elements.push( + ...node.decorators.map(dec => dec.expression).reverse(), ); } diff --git a/packages/babel-helpers/src/helpers.js b/packages/babel-helpers/src/helpers.js index 73c4e1a4d8bd..5994fb6826af 100644 --- a/packages/babel-helpers/src/helpers.js +++ b/packages/babel-helpers/src/helpers.js @@ -316,7 +316,7 @@ helpers.extends = helper("7.0.0-beta.0")` } `; -// This old helper can be removed in babel v8 +// TODO(babel-8): This old helper can be removed in babel v8 helpers.objectSpread = helper("7.0.0-beta.0")` import defineProperty from "defineProperty"; @@ -325,7 +325,7 @@ helpers.objectSpread = helper("7.0.0-beta.0")` var source = (arguments[i] != null) ? Object(arguments[i]) : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { - ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) { + ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function(sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } diff --git a/packages/babel-node/src/_babel-node.js b/packages/babel-node/src/_babel-node.js index 9792d975831a..7331d99943da 100644 --- a/packages/babel-node/src/_babel-node.js +++ b/packages/babel-node/src/_babel-node.js @@ -21,7 +21,11 @@ function collect(value, previousValue): Array { const values = value.split(","); - return previousValue ? previousValue.concat(values) : values; + if (previousValue) { + previousValue.push(...values); + return previousValue; + } + return values; } program.option("-e, --eval [script]", "Evaluate script"); @@ -197,7 +201,7 @@ if (program.eval || program.print) { } // add back on node and concat the sliced args - process.argv = ["node"].concat(args); + process.argv = ["node", ...args]; process.execArgv.push(fileURLToPath(import.meta.url)); Module.runMain(); diff --git a/packages/babel-node/src/babel-node.js b/packages/babel-node/src/babel-node.js index 8ef4607f58f2..909c6bb978aa 100755 --- a/packages/babel-node/src/babel-node.js +++ b/packages/babel-node/src/babel-node.js @@ -8,7 +8,7 @@ import path from "path"; import child_process from "child_process"; import { fileURLToPath } from "url"; -let args = [ +const args = [ path.join(path.dirname(fileURLToPath(import.meta.url)), "_babel-node"), ]; @@ -69,7 +69,7 @@ getV8Flags(async function (err, v8Flags) { // append arguments passed after -- if (argSeparator > -1) { - args = args.concat(userArgs); + args.push(...userArgs); } try { diff --git a/packages/babel-parser/src/plugins/flow/index.js b/packages/babel-parser/src/plugins/flow/index.js index 5b5bae52ea2e..2a29bae384c3 100644 --- a/packages/babel-parser/src/plugins/flow/index.js +++ b/packages/babel-parser/src/plugins/flow/index.js @@ -1961,7 +1961,8 @@ export default (superClass: Class): Class => if (failed && valid.length === 1) { this.state = state; - this.state.noArrowAt = noArrowAt.concat(valid[0].start); + noArrowAt.push(valid[0].start); + this.state.noArrowAt = noArrowAt; ({ consequent, failed } = this.tryParseConditionalConsequent()); } } diff --git a/packages/babel-plugin-proposal-async-generator-functions/src/index.js b/packages/babel-plugin-proposal-async-generator-functions/src/index.js index a81607084357..0d4d4492faa5 100644 --- a/packages/babel-plugin-proposal-async-generator-functions/src/index.js +++ b/packages/babel-plugin-proposal-async-generator-functions/src/index.js @@ -47,7 +47,7 @@ export default declare(api => { } // push the rest of the original loop body onto our new body - block.body = block.body.concat(node.body.body); + block.body.push(...node.body.body); t.inherits(loop, node); t.inherits(loop.body, node.body); diff --git a/packages/babel-plugin-proposal-decorators/src/transformer-legacy.js b/packages/babel-plugin-proposal-decorators/src/transformer-legacy.js index e19a775524cf..5b8dd8d202b8 100644 --- a/packages/babel-plugin-proposal-decorators/src/transformer-legacy.js +++ b/packages/babel-plugin-proposal-decorators/src/transformer-legacy.js @@ -157,7 +157,7 @@ function applyTargetDecorators(path, state, decoratedProps) { WARNING_CALLS.add(node.value); - acc = acc.concat([ + acc.push( t.assignmentExpression( "=", t.cloneNode(descriptor), @@ -184,9 +184,9 @@ function applyTargetDecorators(path, state, decoratedProps) { ]), ]), ), - ]); + ); } else { - acc = acc.concat( + acc.push( t.callExpression(state.addHelper("applyDecoratedDescriptor"), [ t.cloneNode(target), t.cloneNode(property), diff --git a/packages/babel-plugin-transform-classes/src/transformClass.ts b/packages/babel-plugin-transform-classes/src/transformClass.ts index 4f4a8b6b332e..a23465dbb920 100644 --- a/packages/babel-plugin-transform-classes/src/transformClass.ts +++ b/packages/babel-plugin-transform-classes/src/transformClass.ts @@ -136,9 +136,8 @@ export default function transformClass( if (classState.userConstructor) { const { constructorBody, userConstructor, construct } = classState; - constructorBody.body = constructorBody.body.concat( - userConstructor.body.body, - ); + + constructorBody.body.push(...userConstructor.body.body); t.inherits(construct, userConstructor); t.inherits(constructorBody, userConstructor.body); } @@ -695,7 +694,7 @@ export default function transformClass( extractDynamicKeys(); - let { body } = classState; + const { body } = classState; const { closureParams, closureArgs } = setupClosureParamsArgs(); buildBody(); @@ -712,8 +711,10 @@ export default function transformClass( ); } - body = body.concat( - classState.staticPropBody.map(fn => fn(t.cloneNode(classState.classRef))), + body.push( + ...classState.staticPropBody.map(fn => + fn(t.cloneNode(classState.classRef)), + ), ); const isStrict = path.isInStrictMode(); diff --git a/packages/babel-plugin-transform-for-of/src/no-helper-implementation.js b/packages/babel-plugin-transform-for-of/src/no-helper-implementation.js index 2624f0bc9093..c867a5d0960a 100644 --- a/packages/babel-plugin-transform-for-of/src/no-helper-implementation.js +++ b/packages/babel-plugin-transform-for-of/src/no-helper-implementation.js @@ -24,7 +24,7 @@ export default function transformWithoutHelper(loose, path, state) { } // push the rest of the original loop body onto our new body - block.body = block.body.concat(node.body.body); + block.body.push(...node.body.body); t.inherits(loop, node); t.inherits(loop.body, node.body); diff --git a/packages/babel-plugin-transform-modules-systemjs/src/index.js b/packages/babel-plugin-transform-modules-systemjs/src/index.js index 4dd75d8146cc..b9407d8c1e10 100644 --- a/packages/babel-plugin-transform-modules-systemjs/src/index.js +++ b/packages/babel-plugin-transform-modules-systemjs/src/index.js @@ -295,7 +295,7 @@ export default declare((api, options) => { const exportMap = Object.create(null); const modules = []; - let beforeBody = []; + const beforeBody = []; const setters = []; const sources = []; const variableIds = []; @@ -475,7 +475,7 @@ export default declare((api, options) => { } modules.forEach(function (specifiers) { - let setterBody = []; + const setterBody = []; const target = scope.generateUid(specifiers.key); for (let specifier of specifiers.imports) { @@ -540,8 +540,8 @@ export default declare((api, options) => { } } - setterBody = setterBody.concat( - constructExportCall( + setterBody.push( + ...constructExportCall( path, t.identifier(exportIdent), exportNames, @@ -589,8 +589,8 @@ export default declare((api, options) => { } if (exportNames.length) { - beforeBody = beforeBody.concat( - constructExportCall( + beforeBody.push( + ...constructExportCall( path, t.identifier(exportIdent), exportNames, diff --git a/packages/babel-plugin-transform-parameters/src/rest.js b/packages/babel-plugin-transform-parameters/src/rest.js index cfba76ce4ae4..2d2f422d3c90 100644 --- a/packages/babel-plugin-transform-parameters/src/rest.js +++ b/packages/babel-plugin-transform-parameters/src/rest.js @@ -305,9 +305,7 @@ export default function convertFunctionRest(path) { return true; } - state.references = state.references.concat( - state.candidates.map(({ path }) => path), - ); + state.references.push(...state.candidates.map(({ path }) => path)); const start = t.numericLiteral(paramsCount); const key = scope.generateUidIdentifier("key"); diff --git a/packages/babel-traverse/src/path/family.ts b/packages/babel-traverse/src/path/family.ts index 4bf873690081..6b49758ba489 100644 --- a/packages/babel-traverse/src/path/family.ts +++ b/packages/babel-traverse/src/path/family.ts @@ -46,7 +46,9 @@ function addCompletionRecords( records: Completion[], context: CompletionContext, ): Completion[] { - if (path) return records.concat(_getCompletionRecords(path, context)); + if (path) { + records.push(..._getCompletionRecords(path, context)); + } return records; } @@ -73,9 +75,9 @@ function completionRecordForSwitch( if (normalCompletions.length) { lastNormalCompletions = normalCompletions; } - records = records.concat(breakCompletions); + records.push(...breakCompletions); } - records = records.concat(lastNormalCompletions); + records.push(...lastNormalCompletions); return records; } @@ -117,7 +119,7 @@ function getStatementListCompletion( paths: NodePath[], context: CompletionContext, ): Completion[] { - let completions = []; + const completions = []; if (context.canHaveBreak) { let lastNormalCompletions = []; for (let i = 0; i < paths.length; i++) { @@ -155,11 +157,11 @@ function getStatementListCompletion( // When we have seen normal completions from the last statement // it is safe to stop populating break and mark normal completions as break normalCompletionToBreak(lastNormalCompletions); - completions = completions.concat(lastNormalCompletions); + completions.push(...lastNormalCompletions); // Declarations have empty completion record, however they can not be nested // directly in return statement, i.e. `return (var a = 1)` is invalid. if (lastNormalCompletions.some(c => c.path.isDeclaration())) { - completions = completions.concat(statementCompletions); + completions.push(...statementCompletions); replaceBreakStatementInBreakCompletion( statementCompletions, /* reachable */ true, @@ -170,7 +172,7 @@ function getStatementListCompletion( /* reachable */ false, ); } else { - completions = completions.concat(statementCompletions); + completions.push(...statementCompletions); if (!context.shouldPopulateBreak) { replaceBreakStatementInBreakCompletion( statementCompletions, @@ -181,14 +183,18 @@ function getStatementListCompletion( break; } if (i === paths.length - 1) { - completions = completions.concat(statementCompletions); + completions.push(...statementCompletions); } else { - completions = completions.concat( - statementCompletions.filter(c => c.type === BREAK_COMPLETION), - ); - lastNormalCompletions = statementCompletions.filter( - c => c.type === NORMAL_COMPLETION, - ); + lastNormalCompletions = []; + for (let i = 0; i < statementCompletions.length; i++) { + const c = statementCompletions[i]; + if (c.type === BREAK_COMPLETION) { + completions.push(c); + } + if (c.type === NORMAL_COMPLETION) { + lastNormalCompletions.push(c); + } + } } } } else if (paths.length) { @@ -202,7 +208,7 @@ function getStatementListCompletion( (pathCompletions.length === 1 && !pathCompletions[0].path.isVariableDeclaration()) ) { - completions = completions.concat(pathCompletions); + completions.push(...pathCompletions); break; } } @@ -225,29 +231,25 @@ function _getCompletionRecords( path.isLabeledStatement() ) { // @ts-expect-error(flow->ts): todo - records = addCompletionRecords(path.get("body"), records, context); + return addCompletionRecords(path.get("body"), records, context); } else if (path.isProgram() || path.isBlockStatement()) { - records = records.concat( - // @ts-expect-error(flow->ts): todo - getStatementListCompletion(path.get("body"), context), - ); + // @ts-expect-error(flow->ts): todo + return getStatementListCompletion(path.get("body"), context); } else if (path.isFunction()) { return _getCompletionRecords(path.get("body"), context); } else if (path.isTryStatement()) { records = addCompletionRecords(path.get("block"), records, context); records = addCompletionRecords(path.get("handler"), records, context); } else if (path.isCatchClause()) { - records = addCompletionRecords(path.get("body"), records, context); + return addCompletionRecords(path.get("body"), records, context); } else if (path.isSwitchStatement()) { - records = completionRecordForSwitch(path.get("cases"), records, context); + return completionRecordForSwitch(path.get("cases"), records, context); } else if (path.isSwitchCase()) { - records = records.concat( - getStatementListCompletion(path.get("consequent"), { - canHaveBreak: true, - shouldPopulateBreak: false, - inCaseClause: true, - }), - ); + return getStatementListCompletion(path.get("consequent"), { + canHaveBreak: true, + shouldPopulateBreak: false, + inCaseClause: true, + }); } else if (path.isBreakStatement()) { records.push(BreakCompletion(path)); } else { @@ -495,7 +497,7 @@ export function getBindingIdentifierPaths( [x: string]: NodePath; } { const path = this; - let search = [].concat(path); + const search = [path]; const ids = Object.create(null); while (search.length) { @@ -517,7 +519,7 @@ export function getBindingIdentifierPaths( if (id.isExportDeclaration()) { const declaration = id.get("declaration"); - if (declaration.isDeclaration()) { + if (t.isDeclaration(declaration)) { search.push(declaration); } continue; @@ -537,8 +539,10 @@ export function getBindingIdentifierPaths( for (let i = 0; i < keys.length; i++) { const key = keys[i]; const child = id.get(key); - if (Array.isArray(child) || child.node) { - search = search.concat(child); + if (Array.isArray(child)) { + search.push(...child); + } else if (child.node) { + search.push(child); } } } diff --git a/packages/babel-traverse/src/path/inference/inferer-reference.ts b/packages/babel-traverse/src/path/inference/inferer-reference.ts index fc745dd14344..a2ef981955ee 100644 --- a/packages/babel-traverse/src/path/inference/inferer-reference.ts +++ b/packages/babel-traverse/src/path/inference/inferer-reference.ts @@ -84,7 +84,7 @@ function getTypeAnnotationBindingConstantViolations(binding, path, name) { }*/ // add back on function constant violations since we can't track calls - constantViolations = constantViolations.concat(functionConstantViolations); + constantViolations.push(...functionConstantViolations); // push on inferred types of violated paths for (const violation of constantViolations) { diff --git a/packages/babel-types/src/comments/addComments.ts b/packages/babel-types/src/comments/addComments.ts index 7aba0779766b..a01ce1c42b94 100644 --- a/packages/babel-types/src/comments/addComments.ts +++ b/packages/babel-types/src/comments/addComments.ts @@ -16,7 +16,7 @@ export default function addComments( if (type === "leading") { node[key] = comments.concat(node[key]); } else { - node[key] = node[key].concat(comments); + node[key].push(...comments); } } else { node[key] = comments; diff --git a/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts index dbe07300fa32..717b993d5a0d 100644 --- a/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts +++ b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts @@ -17,13 +17,14 @@ function getQualifiedName(node: t.GenericTypeAnnotation["id"]) { * Dedupe type annotations. */ export default function removeTypeDuplicates( + // todo(babel-8): change type to Array<...> nodes: ReadonlyArray, ): t.FlowType[] { const generics = {}; const bases = {}; // store union type groups to circular references - const typeGroups = []; + const typeGroups = new Set(); const types = []; @@ -47,9 +48,10 @@ export default function removeTypeDuplicates( } if (isUnionTypeAnnotation(node)) { - if (typeGroups.indexOf(node.types) < 0) { + if (!typeGroups.has(node.types)) { + // todo(babel-8): use .push when nodes is mutable nodes = nodes.concat(node.types); - typeGroups.push(node.types); + typeGroups.add(node.types); } continue; } diff --git a/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts b/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts index b418dafc4b42..da5c565f198f 100644 --- a/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts +++ b/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts @@ -15,7 +15,7 @@ export default function removeTypeDuplicates( const bases = {}; // store union type groups to circular references - const typeGroups = []; + const typeGroups = new Set(); const types = []; @@ -40,9 +40,9 @@ export default function removeTypeDuplicates( } if (isTSUnionType(node)) { - if (typeGroups.indexOf(node.types) < 0) { - nodes = nodes.concat(node.types); - typeGroups.push(node.types); + if (!typeGroups.has(node.types)) { + nodes.push(...node.types); + typeGroups.add(node.types); } continue; }