Use set in parser scope (#13408)

* chore: rename benchmark

* perf: back parser scope names storage by set

* chore: add benchmark
This commit is contained in:
Huáng Jùnliàng
2021-06-01 10:35:19 -04:00
committed by GitHub
parent cbad50ac1d
commit b281fe352c
5 changed files with 85 additions and 46 deletions

View File

@@ -11,7 +11,7 @@ import * as N from "../../types";
// Reference implementation: https://github.com/facebook/flow/blob/23aeb2a2ef6eb4241ce178fde5d8f17c5f747fb5/src/typing/env.ml#L536-L584
class FlowScope extends Scope {
// declare function foo(): type;
declareFunctions: string[] = [];
declareFunctions: Set<string> = new Set();
}
export default class FlowScopeHandler extends ScopeHandler<FlowScope> {
@@ -24,7 +24,7 @@ export default class FlowScopeHandler extends ScopeHandler<FlowScope> {
if (bindingType & BIND_FLAGS_FLOW_DECLARE_FN) {
this.checkRedeclarationInScope(scope, name, bindingType, pos);
this.maybeExportDefined(scope, name);
scope.declareFunctions.push(name);
scope.declareFunctions.add(name);
return;
}
@@ -40,8 +40,8 @@ export default class FlowScopeHandler extends ScopeHandler<FlowScope> {
if (bindingType & BIND_FLAGS_FLOW_DECLARE_FN) {
return (
!scope.declareFunctions.includes(name) &&
(scope.lexical.includes(name) || scope.functions.includes(name))
!scope.declareFunctions.has(name) &&
(scope.lexical.has(name) || scope.functions.has(name))
);
}
@@ -49,7 +49,7 @@ export default class FlowScopeHandler extends ScopeHandler<FlowScope> {
}
checkLocalExport(id: N.Identifier) {
if (this.scopeStack[0].declareFunctions.indexOf(id.name) === -1) {
if (!this.scopeStack[0].declareFunctions.has(id.name)) {
super.checkLocalExport(id);
}
}

View File

@@ -14,22 +14,22 @@ import {
import * as N from "../../types";
class TypeScriptScope extends Scope {
types: string[] = [];
types: Set<string> = new Set();
// enums (which are also in .types)
enums: string[] = [];
enums: Set<string> = new Set();
// const enums (which are also in .enums and .types)
constEnums: string[] = [];
constEnums: Set<string> = new Set();
// classes (which are also in .lexical) and interface (which are also in .types)
classes: string[] = [];
classes: Set<string> = new Set();
// namespaces and ambient functions (or classes) are too difficult to track,
// especially without type analysis.
// We need to track them anyway, to avoid "X is not defined" errors
// when exporting them.
exportOnlyBindings: string[] = [];
exportOnlyBindings: Set<string> = new Set();
}
// See https://github.com/babel/babel/pull/9766#discussion_r268920730 for an
@@ -44,7 +44,7 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
const scope = this.currentScope();
if (bindingType & BIND_FLAGS_TS_EXPORT_ONLY) {
this.maybeExportDefined(scope, name);
scope.exportOnlyBindings.push(name);
scope.exportOnlyBindings.add(name);
return;
}
@@ -56,11 +56,11 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
this.checkRedeclarationInScope(scope, name, bindingType, pos);
this.maybeExportDefined(scope, name);
}
scope.types.push(name);
scope.types.add(name);
}
if (bindingType & BIND_FLAGS_TS_ENUM) scope.enums.push(name);
if (bindingType & BIND_FLAGS_TS_CONST_ENUM) scope.constEnums.push(name);
if (bindingType & BIND_FLAGS_CLASS) scope.classes.push(name);
if (bindingType & BIND_FLAGS_TS_ENUM) scope.enums.add(name);
if (bindingType & BIND_FLAGS_TS_CONST_ENUM) scope.constEnums.add(name);
if (bindingType & BIND_FLAGS_CLASS) scope.classes.add(name);
}
isRedeclaredInScope(
@@ -68,18 +68,18 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
name: string,
bindingType: BindingTypes,
): boolean {
if (scope.enums.indexOf(name) > -1) {
if (scope.enums.has(name)) {
if (bindingType & BIND_FLAGS_TS_ENUM) {
// Enums can be merged with other enums if they are both
// const or both non-const.
const isConst = !!(bindingType & BIND_FLAGS_TS_CONST_ENUM);
const wasConst = scope.constEnums.indexOf(name) > -1;
const wasConst = scope.constEnums.has(name);
return isConst !== wasConst;
}
return true;
}
if (bindingType & BIND_FLAGS_CLASS && scope.classes.indexOf(name) > -1) {
if (scope.lexical.indexOf(name) > -1) {
if (bindingType & BIND_FLAGS_CLASS && scope.classes.has(name)) {
if (scope.lexical.has(name)) {
// Classes can be merged with interfaces
return !!(bindingType & BIND_KIND_VALUE);
} else {
@@ -87,7 +87,7 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
return false;
}
}
if (bindingType & BIND_KIND_TYPE && scope.types.indexOf(name) > -1) {
if (bindingType & BIND_KIND_TYPE && scope.types.has(name)) {
return true;
}
@@ -95,9 +95,11 @@ export default class TypeScriptScopeHandler extends ScopeHandler<TypeScriptScope
}
checkLocalExport(id: N.Identifier) {
const topLevelScope = this.scopeStack[0];
const { name } = id;
if (
this.scopeStack[0].types.indexOf(id.name) === -1 &&
this.scopeStack[0].exportOnlyBindings.indexOf(id.name) === -1
!topLevelScope.types.has(name) &&
!topLevelScope.exportOnlyBindings.has(name)
) {
super.checkLocalExport(id);
}