Check exported bindings are defined (#9589)

* Check exported bindings are defined

* Add tests

* Update flow whitelist

* Add tests for builtins
This commit is contained in:
Daniel Tschinder
2019-02-26 13:28:10 -08:00
committed by GitHub
parent e883ff295d
commit 43eed1ac92
81 changed files with 1594 additions and 315 deletions

View File

@@ -16,6 +16,7 @@ import {
type BindingTypes,
SCOPE_CLASS,
} from "./scopeflags";
import * as N from "../types";
// Start an AST node, attaching a start offset.
class Scope {
@@ -40,6 +41,7 @@ export default class ScopeHandler {
scopeStack: Array<Scope> = [];
raise: raiseFunction;
inModule: boolean;
undefinedExports: Map<string, number> = new Map();
constructor(raise: raiseFunction, inModule: boolean) {
this.raise = raise;
@@ -95,6 +97,9 @@ export default class ScopeHandler {
scope.functions.indexOf(name) > -1 ||
scope.var.indexOf(name) > -1;
scope.lexical.push(name);
if (this.inModule && scope.flags & SCOPE_PROGRAM) {
this.undefinedExports.delete(name);
}
} else if (bindingType === BIND_SIMPLE_CATCH) {
const scope = this.currentScope();
scope.lexical.push(name);
@@ -122,6 +127,10 @@ export default class ScopeHandler {
}
scope.var.push(name);
if (this.inModule && scope.flags & SCOPE_PROGRAM) {
this.undefinedExports.delete(name);
}
if (scope.flags & SCOPE_VAR) break;
}
}
@@ -130,6 +139,16 @@ export default class ScopeHandler {
}
}
checkLocalExport(id: N.Identifier) {
// scope.functions must be empty as Module code is always strict.
if (
this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
this.scopeStack[0].var.indexOf(id.name) === -1
) {
this.undefinedExports.set(id.name, id.start);
}
}
currentScope(): Scope {
return this.scopeStack[this.scopeStack.length - 1];
}