diff --git a/src/program.ts b/src/program.ts index f115ea789e..7170ba375a 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1141,11 +1141,12 @@ export class Program extends DiagnosticEmitter { let queuedImport = queuedImports[i]; let localIdentifier = queuedImport.localIdentifier; let foreignIdentifier = queuedImport.foreignIdentifier; + // File must be found here, as it would otherwise already have been reported by the parser + let foreignFile = assert(this.lookupForeignFile(queuedImport.foreignPath, queuedImport.foreignPathAlt)); if (foreignIdentifier) { // i.e. import { foo [as bar] } from "./baz" let element = this.lookupForeign( foreignIdentifier.text, - queuedImport.foreignPath, - queuedImport.foreignPathAlt, + foreignFile, queuedExports ); if (element) { @@ -1160,25 +1161,19 @@ export class Program extends DiagnosticEmitter { ++i; } } else { // i.e. import * as bar from "./bar" - let foreignFile = this.lookupForeignFile(queuedImport.foreignPath, queuedImport.foreignPathAlt); - if (foreignFile) { - let localFile = queuedImport.localFile; - let localName = localIdentifier.text; - localFile.add( + let localFile = queuedImport.localFile; + let localName = localIdentifier.text; + localFile.add( + localName, + foreignFile.asAliasNamespace( localName, - foreignFile.asAliasNamespace( - localName, - localFile, - localIdentifier - ), - localIdentifier // isImport - ); - queuedImports.splice(i, 1); - madeProgress = true; - } else { - ++i; - assert(false); // already reported by the parser not finding the file - } + localFile, + localIdentifier + ), + localIdentifier // isImport + ); + queuedImports.splice(i, 1); + madeProgress = true; } } if (!madeProgress) { @@ -1209,12 +1204,9 @@ export class Program extends DiagnosticEmitter { let localName = queuedExport.localIdentifier.text; let foreignPath = queuedExport.foreignPath; if (foreignPath) { // i.e. export { foo [as bar] } from "./baz" - let element = this.lookupForeign( - localName, - foreignPath, - assert(queuedExport.foreignPathAlt), // must be set if foreignPath is - queuedExports - ); + // File must be found here, as it would otherwise already have been reported by the parser + let foreignFile = assert(this.lookupForeignFile(foreignPath, assert(queuedExport.foreignPathAlt))); + let element = this.lookupForeign(localName, foreignFile, queuedExports); if (element) { file.ensureExport(exportName, element); } else { @@ -1725,40 +1717,48 @@ export class Program extends DiagnosticEmitter { private lookupForeign( /** Identifier within the other file. */ foreignName: string, - /** Normalized path to the other file. */ - foreignPath: string, - /** Alternative normalized path to the other file. */ - foreignPathAlt: string, + /** The other file. */ + foreignFile: File, /** So far queued exports. */ queuedExports: Map> ): DeclaredElement | null { do { - let foreignFile = this.lookupForeignFile(foreignPath, foreignPathAlt); - if (!foreignFile) return null; // no such file - - // search already resolved exports + // check if already resolved let element = foreignFile.lookupExport(foreignName); if (element) return element; - // otherwise traverse queued exports + // follow queued exports if (queuedExports.has(foreignFile)) { let fileQueuedExports = assert(queuedExports.get(foreignFile)); if (fileQueuedExports.has(foreignName)) { let queuedExport = assert(fileQueuedExports.get(foreignName)); let queuedExportForeignPath = queuedExport.foreignPath; - if (queuedExportForeignPath) { // imported from another file + + // re-exported from another file + if (queuedExportForeignPath) { + let otherFile = this.lookupForeignFile(queuedExportForeignPath, assert(queuedExport.foreignPathAlt)); + if (!otherFile) return null; foreignName = queuedExport.localIdentifier.text; - foreignPath = queuedExportForeignPath; - foreignPathAlt = assert(queuedExport.foreignPathAlt); + foreignFile = otherFile; continue; - } else { // local element of this file - element = foreignFile.lookupInSelf(queuedExport.localIdentifier.text); - if (element) return element; } + + // exported from this file + element = foreignFile.lookupInSelf(queuedExport.localIdentifier.text); + if (element) return element; } } break; } while (true); + + // follow star exports + var exportsStar = foreignFile.exportsStar; + if (exportsStar) { + for (let i = 0, k = exportsStar.length; i < k; ++i) { + let element = this.lookupForeign(foreignName, exportsStar[i], queuedExports); + if (element) return element; + } + } return null; } @@ -2334,10 +2334,13 @@ export class Program extends DiagnosticEmitter { : foreignPath + INDEX_SUFFIX; // resolve right away if the element exists - var element = this.lookupForeign(declaration.foreignName.text, foreignPath, foreignPathAlt, queuedExports); - if (element) { - parent.add(declaration.name.text, element, declaration.name /* isImport */); - return; + var foreignFile = this.lookupForeignFile(foreignPath, foreignPathAlt); + if (foreignFile) { + var element = this.lookupForeign(declaration.foreignName.text, foreignFile, queuedExports); + if (element) { + parent.add(declaration.name.text, element, declaration.name /* isImport */); + return; + } } // otherwise queue it diff --git a/tests/compiler/issues/1751.optimized.wat b/tests/compiler/issues/1751.optimized.wat new file mode 100644 index 0000000000..23da3862e2 --- /dev/null +++ b/tests/compiler/issues/1751.optimized.wat @@ -0,0 +1,4 @@ +(module + (memory $0 0) + (export "memory" (memory $0)) +) diff --git a/tests/compiler/issues/1751.ts b/tests/compiler/issues/1751.ts new file mode 100644 index 0000000000..23c21e98a5 --- /dev/null +++ b/tests/compiler/issues/1751.ts @@ -0,0 +1 @@ +import { Foo } from './1751/_reexport'; diff --git a/tests/compiler/issues/1751.untouched.wat b/tests/compiler/issues/1751.untouched.wat new file mode 100644 index 0000000000..525dea1bed --- /dev/null +++ b/tests/compiler/issues/1751.untouched.wat @@ -0,0 +1,8 @@ +(module + (memory $0 0) + (table $0 1 funcref) + (global $~lib/memory/__data_end i32 (i32.const 8)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 16392)) + (global $~lib/memory/__heap_base i32 (i32.const 16392)) + (export "memory" (memory $0)) +) diff --git a/tests/compiler/issues/1751/_common.ts b/tests/compiler/issues/1751/_common.ts new file mode 100644 index 0000000000..0120276916 --- /dev/null +++ b/tests/compiler/issues/1751/_common.ts @@ -0,0 +1 @@ +export { Foo } from "./_foo"; diff --git a/tests/compiler/issues/1751/_foo.ts b/tests/compiler/issues/1751/_foo.ts new file mode 100644 index 0000000000..223d0a8b39 --- /dev/null +++ b/tests/compiler/issues/1751/_foo.ts @@ -0,0 +1 @@ +export class Foo {} diff --git a/tests/compiler/issues/1751/_reexport.ts b/tests/compiler/issues/1751/_reexport.ts new file mode 100644 index 0000000000..da28848d46 --- /dev/null +++ b/tests/compiler/issues/1751/_reexport.ts @@ -0,0 +1 @@ +export * from './_common'; // should propagate