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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user