Skip to content

Commit d12f7ce

Browse files
authored
Teach as-bind to recognize external decorator. (#95)
1 parent c8c689b commit d12f7ce

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

test/tests/namespace-import/asc.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@external("my_module", "my_log")
2+
declare function log(str: string): void;
3+
4+
@external("my_log2")
5+
declare function log2(str: string): void;
6+
7+
export function fn(): void {
8+
log("ok");
9+
log2("fine");
10+
}

test/tests/namespace-import/test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
describe("as-bind", function() {
2+
it("should support @external imports", async function() {
3+
let from_wasm;
4+
let from_wasm2;
5+
6+
const instance = await AsBind.instantiate(this.rawModule, {
7+
my_module: {
8+
my_log(str) {
9+
from_wasm = str;
10+
}
11+
},
12+
asc: {
13+
my_log2(str) {
14+
from_wasm2 = str;
15+
}
16+
}
17+
});
18+
19+
instance.exports.fn();
20+
21+
assert(from_wasm === "ok");
22+
assert(from_wasm2 === "fine");
23+
});
24+
});

transform.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,43 @@ export default class AsBindTransform {
8888
throw Error(`Can’t import or export generic functions.`);
8989
}
9090
importedFunction = importedFunction.instances.get("");
91+
92+
let external_module;
93+
let external_name;
94+
95+
let decorators = importedFunction.declaration.decorators;
96+
97+
if (decorators) {
98+
for (let decorator of decorators) {
99+
if (decorator.name.text !== "external") continue;
100+
if (!decorator.args) continue; // sanity check
101+
102+
if (decorator.args.length > 1) {
103+
external_module = decorator.args[0].value;
104+
external_name = decorator.args[1].value;
105+
} else {
106+
external_name = decorator.args[0].value;
107+
}
108+
}
109+
}
110+
91111
// To know under what module name an imported function will be expected,
92112
// we have to find the containing module of the given function, take the
93113
// internal name (which is effectively the file path without extension)
94114
// and only take the part after the last `/`
95115
// (i.e. the file name without extension).
96-
const moduleName = containingModule(importedFunction)
97-
.internalName.split("/")
98-
.slice(-1)[0];
116+
const moduleName =
117+
external_module ||
118+
containingModule(importedFunction)
119+
.internalName.split("/")
120+
.slice(-1)[0];
99121
if (!importedFunctions.hasOwnProperty(moduleName)) {
100122
importedFunctions[moduleName] = {};
101123
}
102124
let importedFunctionName = importedFunction.name;
103-
if (
125+
if (external_name) {
126+
importedFunctionName = external_name;
127+
} else if (
104128
importedFunction.parent &&
105129
importedFunction.parent.kind === ElementKind.NAMESPACE
106130
) {

0 commit comments

Comments
 (0)