From ae3f5d905a01dcfe4b1dd32def6e2341ec23465e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Tue, 1 Jun 2021 07:17:30 -0400 Subject: [PATCH] Back parser state `exportedIdentifiers` by set (#13406) --- .../many-named-export/1-length.bench.mjs | 34 +++++++++++++++++++ packages/babel-parser/package.json | 2 +- packages/babel-parser/src/parser/base.js | 3 ++ packages/babel-parser/src/parser/statement.js | 4 +-- packages/babel-parser/src/parser/util.js | 6 ++-- packages/babel-parser/src/tokenizer/state.js | 4 --- yarn.lock | 19 ++++++++--- 7 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 packages/babel-parser/benchmark/many-named-export/1-length.bench.mjs diff --git a/packages/babel-parser/benchmark/many-named-export/1-length.bench.mjs b/packages/babel-parser/benchmark/many-named-export/1-length.bench.mjs new file mode 100644 index 000000000000..b7c46eec4388 --- /dev/null +++ b/packages/babel-parser/benchmark/many-named-export/1-length.bench.mjs @@ -0,0 +1,34 @@ +import Benchmark from "benchmark"; +import baseline from "@babel-baseline/parser"; +import current from "../../lib/index.js"; +import { report } from "../util.mjs"; + +const suite = new Benchmark.Suite(); +// All codepoints in [0x4e00, 0x9ffc] are valid identifier name per Unicode 13 +function createInput(length) { + if (length > 0x9ffc - 0x4e00) { + throw new Error( + `Length greater than ${ + 0x9ffc - 0x4e00 + } is not supported! Consider modify the \`createInput\`.` + ); + } + let source = "export { "; + for (let i = 0; i < length; i++) { + source += String.fromCharCode(0x4e00 + i) + ","; + } + return source + " } from './foo'"; +} +function benchCases(name, implementation, options) { + for (const length of [256, 512, 1024, 2048]) { + const input = createInput(length); + suite.add(`${name} ${length} length-1 named export`, () => { + implementation.parse(input, options); + }); + } +} + +benchCases("baseline", baseline, { sourceType: "module" }); +benchCases("current", current, { sourceType: "module" }); + +suite.on("cycle", report).run(); diff --git a/packages/babel-parser/package.json b/packages/babel-parser/package.json index 78ffa6373163..9b1590e1453b 100644 --- a/packages/babel-parser/package.json +++ b/packages/babel-parser/package.json @@ -33,7 +33,7 @@ "node": ">=6.0.0" }, "devDependencies": { - "@babel-baseline/parser": "npm:@babel/parser@^7.14.0", + "@babel-baseline/parser": "npm:@babel/parser@^7.14.4", "@babel/code-frame": "workspace:*", "@babel/helper-fixtures": "workspace:*", "@babel/helper-validator-identifier": "workspace:*", diff --git a/packages/babel-parser/src/parser/base.js b/packages/babel-parser/src/parser/base.js index 74c26a791ba8..4c5c213ebd1b 100644 --- a/packages/babel-parser/src/parser/base.js +++ b/packages/babel-parser/src/parser/base.js @@ -18,6 +18,9 @@ export default class BaseParser { declare expressionScope: ExpressionScopeHandler; declare plugins: PluginsMap; declare filename: ?string; + // Names of exports store. `default` is stored as a name for both + // `export default foo;` and `export { foo as default };`. + declare exportedIdentifiers: Set; sawUnambiguousESM: boolean = false; ambiguousScriptDifferentAst: boolean = false; diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index f3c9772c3023..b9c6b9822b74 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -2114,7 +2114,7 @@ export default class StatementParser extends ExpressionParser { | N.ExportDefaultSpecifier, name: string, ): void { - if (this.state.exportedIdentifiers.indexOf(name) > -1) { + if (this.exportedIdentifiers.has(name)) { this.raise( node.start, name === "default" @@ -2123,7 +2123,7 @@ export default class StatementParser extends ExpressionParser { name, ); } - this.state.exportedIdentifiers.push(name); + this.exportedIdentifiers.add(name); } // Parses a comma-separated list of module exports. diff --git a/packages/babel-parser/src/parser/util.js b/packages/babel-parser/src/parser/util.js index c4c05a6f9f24..115a00884916 100644 --- a/packages/babel-parser/src/parser/util.js +++ b/packages/babel-parser/src/parser/util.js @@ -349,8 +349,8 @@ export default class UtilParser extends Tokenizer { const oldLabels = this.state.labels; this.state.labels = []; - const oldExportedIdentifiers = this.state.exportedIdentifiers; - this.state.exportedIdentifiers = []; + const oldExportedIdentifiers = this.exportedIdentifiers; + this.exportedIdentifiers = new Set(); // initialize scopes const oldInModule = this.inModule; @@ -372,7 +372,7 @@ export default class UtilParser extends Tokenizer { return () => { // Revert state this.state.labels = oldLabels; - this.state.exportedIdentifiers = oldExportedIdentifiers; + this.exportedIdentifiers = oldExportedIdentifiers; // Revert scopes this.inModule = oldInModule; diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index ed6c90c7abb9..390c78c018b0 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -148,10 +148,6 @@ export default class State { // after a non-directive is parsed strictErrors: Map = new Map(); - // Names of exports store. `default` is stored as a name for both - // `export default foo;` and `export { foo as default };`. - exportedIdentifiers: Array = []; - // Tokens length in token store tokensLength: number = 0; diff --git a/yarn.lock b/yarn.lock index 999d002d8ad3..718a8af9d395 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,12 +5,12 @@ __metadata: version: 4 cacheKey: 7 -"@babel-baseline/parser@npm:@babel/parser@^7.14.0, npm-babel-parser@npm:@babel/parser@^7.14.0": - version: 7.14.0 - resolution: "@babel/parser@npm:7.14.0" +"@babel-baseline/parser@npm:@babel/parser@^7.14.4": + version: 7.14.4 + resolution: "@babel/parser@npm:7.14.4" bin: parser: ./bin/babel-parser.js - checksum: ef6165f3038b9f8761a02768ab14034f4935baf2e050a2924aa093f54e3164732bce7fee81b3c8ff3be03048091e4ea208a72b23a3715debf7fd06b79495c9e9 + checksum: 3bc067c1ee0e0178d365e1b2988ea1a0d6d37af37870ea1a7e80729b3bdc40acda083cac44ce72f63a5b31a489e35120f617bd41f312dec4c86cf814cff8e64a languageName: node linkType: hard @@ -963,7 +963,7 @@ __metadata: version: 0.0.0-use.local resolution: "@babel/parser@workspace:packages/babel-parser" dependencies: - "@babel-baseline/parser": "npm:@babel/parser@^7.14.0" + "@babel-baseline/parser": "npm:@babel/parser@^7.14.4" "@babel/code-frame": "workspace:*" "@babel/helper-fixtures": "workspace:*" "@babel/helper-validator-identifier": "workspace:*" @@ -11641,6 +11641,15 @@ fsevents@^1.2.7: languageName: node linkType: hard +"npm-babel-parser@npm:@babel/parser@^7.14.0": + version: 7.14.0 + resolution: "@babel/parser@npm:7.14.0" + bin: + parser: ./bin/babel-parser.js + checksum: ef6165f3038b9f8761a02768ab14034f4935baf2e050a2924aa093f54e3164732bce7fee81b3c8ff3be03048091e4ea208a72b23a3715debf7fd06b79495c9e9 + languageName: node + linkType: hard + "npm-run-path@npm:^2.0.0": version: 2.0.2 resolution: "npm-run-path@npm:2.0.2"