Only bind module.exports if no local definition exists (#25869)

* Only bind module.exports if no local definition exists

Note that this uses `lookupSymbolForNameWorker`, which is really a
best-effort check since it only knows about symbols that it has already
encountered.

As a side-effect, even when `module` is bound as part of a
`module.exports` reference, it only declares it once instead of one
declaration per reference.

* Only type module.exports inside module files

It is an error inside script files, but the binder sometimes creates a
ModuleExports symbol because we doesn't know whether we have a commonjs
module until after binding is done.

* Only bind module.exports in a commonjs module

Note that this, too, is a best-effort check since evidence of
commonjs-ness may be found after a *reference* to module.exports. (A
reference to module.exports alone is not enough evidence that a file is
commonjs. It has to have an assignment to it.)
This commit is contained in:
Nathan Shively-Sanders
2018-07-30 12:27:59 -07:00
committed by GitHub
parent 9e740deee8
commit 4d84bde9b3
21 changed files with 221 additions and 50 deletions

View File

@@ -2072,7 +2072,10 @@ namespace ts {
if (isSpecialPropertyDeclaration(node as PropertyAccessExpression)) {
bindSpecialPropertyDeclaration(node as PropertyAccessExpression);
}
if (isInJavaScriptFile(node) && isModuleExportsPropertyAccessExpression(node as PropertyAccessExpression)) {
if (isInJavaScriptFile(node) &&
file.commonJsModuleIndicator &&
isModuleExportsPropertyAccessExpression(node as PropertyAccessExpression) &&
!lookupSymbolForNameWorker(container, "module" as __String)) {
declareSymbol(container.locals!, /*parent*/ undefined, (node as PropertyAccessExpression).expression as Identifier,
SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes);
}