Skip to content

Also traverse star exports when walking queued exports #1780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 48 additions & 45 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<File,Map<string,QueuedExport>>
): 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;
}

Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/compiler/issues/1751.optimized.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(module
(memory $0 0)
(export "memory" (memory $0))
)
1 change: 1 addition & 0 deletions tests/compiler/issues/1751.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import { Foo } from './1751/_reexport';
8 changes: 8 additions & 0 deletions tests/compiler/issues/1751.untouched.wat
Original file line number Diff line number Diff line change
@@ -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))
)
1 change: 1 addition & 0 deletions tests/compiler/issues/1751/_common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Foo } from "./_foo";
1 change: 1 addition & 0 deletions tests/compiler/issues/1751/_foo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class Foo {}
1 change: 1 addition & 0 deletions tests/compiler/issues/1751/_reexport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './_common'; // should propagate