You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
5.2 KiB
161 lines
5.2 KiB
"use strict"; |
|
|
|
Object.defineProperty(exports, "__esModule", { |
|
value: true |
|
}); |
|
exports.default = exports.Scope = void 0; |
|
var _scopeflags = require("./scopeflags"); |
|
var _parseError = require("../parse-error"); |
|
class Scope { |
|
constructor(flags) { |
|
this.var = new Set(); |
|
this.lexical = new Set(); |
|
this.functions = new Set(); |
|
this.flags = flags; |
|
} |
|
} |
|
exports.Scope = Scope; |
|
class ScopeHandler { |
|
constructor(parser, inModule) { |
|
this.parser = void 0; |
|
this.scopeStack = []; |
|
this.inModule = void 0; |
|
this.undefinedExports = new Map(); |
|
this.parser = parser; |
|
this.inModule = inModule; |
|
} |
|
get inTopLevel() { |
|
return (this.currentScope().flags & _scopeflags.SCOPE_PROGRAM) > 0; |
|
} |
|
get inFunction() { |
|
return (this.currentVarScopeFlags() & _scopeflags.SCOPE_FUNCTION) > 0; |
|
} |
|
get allowSuper() { |
|
return (this.currentThisScopeFlags() & _scopeflags.SCOPE_SUPER) > 0; |
|
} |
|
get allowDirectSuper() { |
|
return (this.currentThisScopeFlags() & _scopeflags.SCOPE_DIRECT_SUPER) > 0; |
|
} |
|
get inClass() { |
|
return (this.currentThisScopeFlags() & _scopeflags.SCOPE_CLASS) > 0; |
|
} |
|
get inClassAndNotInNonArrowFunction() { |
|
const flags = this.currentThisScopeFlags(); |
|
return (flags & _scopeflags.SCOPE_CLASS) > 0 && (flags & _scopeflags.SCOPE_FUNCTION) === 0; |
|
} |
|
get inStaticBlock() { |
|
for (let i = this.scopeStack.length - 1;; i--) { |
|
const { |
|
flags |
|
} = this.scopeStack[i]; |
|
if (flags & _scopeflags.SCOPE_STATIC_BLOCK) { |
|
return true; |
|
} |
|
if (flags & (_scopeflags.SCOPE_VAR | _scopeflags.SCOPE_CLASS)) { |
|
return false; |
|
} |
|
} |
|
} |
|
get inNonArrowFunction() { |
|
return (this.currentThisScopeFlags() & _scopeflags.SCOPE_FUNCTION) > 0; |
|
} |
|
get treatFunctionsAsVar() { |
|
return this.treatFunctionsAsVarInScope(this.currentScope()); |
|
} |
|
createScope(flags) { |
|
return new Scope(flags); |
|
} |
|
enter(flags) { |
|
this.scopeStack.push(this.createScope(flags)); |
|
} |
|
exit() { |
|
const scope = this.scopeStack.pop(); |
|
return scope.flags; |
|
} |
|
treatFunctionsAsVarInScope(scope) { |
|
return !!(scope.flags & (_scopeflags.SCOPE_FUNCTION | _scopeflags.SCOPE_STATIC_BLOCK) || !this.parser.inModule && scope.flags & _scopeflags.SCOPE_PROGRAM); |
|
} |
|
declareName(name, bindingType, loc) { |
|
let scope = this.currentScope(); |
|
if (bindingType & _scopeflags.BIND_SCOPE_LEXICAL || bindingType & _scopeflags.BIND_SCOPE_FUNCTION) { |
|
this.checkRedeclarationInScope(scope, name, bindingType, loc); |
|
if (bindingType & _scopeflags.BIND_SCOPE_FUNCTION) { |
|
scope.functions.add(name); |
|
} else { |
|
scope.lexical.add(name); |
|
} |
|
if (bindingType & _scopeflags.BIND_SCOPE_LEXICAL) { |
|
this.maybeExportDefined(scope, name); |
|
} |
|
} else if (bindingType & _scopeflags.BIND_SCOPE_VAR) { |
|
for (let i = this.scopeStack.length - 1; i >= 0; --i) { |
|
scope = this.scopeStack[i]; |
|
this.checkRedeclarationInScope(scope, name, bindingType, loc); |
|
scope.var.add(name); |
|
this.maybeExportDefined(scope, name); |
|
if (scope.flags & _scopeflags.SCOPE_VAR) break; |
|
} |
|
} |
|
if (this.parser.inModule && scope.flags & _scopeflags.SCOPE_PROGRAM) { |
|
this.undefinedExports.delete(name); |
|
} |
|
} |
|
maybeExportDefined(scope, name) { |
|
if (this.parser.inModule && scope.flags & _scopeflags.SCOPE_PROGRAM) { |
|
this.undefinedExports.delete(name); |
|
} |
|
} |
|
checkRedeclarationInScope(scope, name, bindingType, loc) { |
|
if (this.isRedeclaredInScope(scope, name, bindingType)) { |
|
this.parser.raise(_parseError.Errors.VarRedeclaration, { |
|
at: loc, |
|
identifierName: name |
|
}); |
|
} |
|
} |
|
isRedeclaredInScope(scope, name, bindingType) { |
|
if (!(bindingType & _scopeflags.BIND_KIND_VALUE)) return false; |
|
if (bindingType & _scopeflags.BIND_SCOPE_LEXICAL) { |
|
return scope.lexical.has(name) || scope.functions.has(name) || scope.var.has(name); |
|
} |
|
if (bindingType & _scopeflags.BIND_SCOPE_FUNCTION) { |
|
return scope.lexical.has(name) || !this.treatFunctionsAsVarInScope(scope) && scope.var.has(name); |
|
} |
|
return scope.lexical.has(name) && !(scope.flags & _scopeflags.SCOPE_SIMPLE_CATCH && scope.lexical.values().next().value === name) || !this.treatFunctionsAsVarInScope(scope) && scope.functions.has(name); |
|
} |
|
checkLocalExport(id) { |
|
const { |
|
name |
|
} = id; |
|
const topLevelScope = this.scopeStack[0]; |
|
if (!topLevelScope.lexical.has(name) && !topLevelScope.var.has(name) && !topLevelScope.functions.has(name)) { |
|
this.undefinedExports.set(name, id.loc.start); |
|
} |
|
} |
|
currentScope() { |
|
return this.scopeStack[this.scopeStack.length - 1]; |
|
} |
|
currentVarScopeFlags() { |
|
for (let i = this.scopeStack.length - 1;; i--) { |
|
const { |
|
flags |
|
} = this.scopeStack[i]; |
|
if (flags & _scopeflags.SCOPE_VAR) { |
|
return flags; |
|
} |
|
} |
|
} |
|
currentThisScopeFlags() { |
|
for (let i = this.scopeStack.length - 1;; i--) { |
|
const { |
|
flags |
|
} = this.scopeStack[i]; |
|
if (flags & (_scopeflags.SCOPE_VAR | _scopeflags.SCOPE_CLASS) && !(flags & _scopeflags.SCOPE_ARROW)) { |
|
return flags; |
|
} |
|
} |
|
} |
|
} |
|
exports.default = ScopeHandler; |
|
|
|
//# sourceMappingURL=scope.js.map
|
|
|