Skip to content

Commit

Permalink
Teach as-bind to recognize external decorator. (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
FGasper committed Aug 17, 2021
1 parent c8c689b commit d12f7ce
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
10 changes: 10 additions & 0 deletions test/tests/namespace-import/asc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@external("my_module", "my_log")
declare function log(str: string): void;

@external("my_log2")
declare function log2(str: string): void;

export function fn(): void {
log("ok");
log2("fine");
}
24 changes: 24 additions & 0 deletions test/tests/namespace-import/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe("as-bind", function() {
it("should support @external imports", async function() {
let from_wasm;
let from_wasm2;

const instance = await AsBind.instantiate(this.rawModule, {
my_module: {
my_log(str) {
from_wasm = str;
}
},
asc: {
my_log2(str) {
from_wasm2 = str;
}
}
});

instance.exports.fn();

assert(from_wasm === "ok");
assert(from_wasm2 === "fine");
});
});
32 changes: 28 additions & 4 deletions transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,43 @@ export default class AsBindTransform {
throw Error(`Can鈥檛 import or export generic functions.`);
}
importedFunction = importedFunction.instances.get("");

let external_module;
let external_name;

let decorators = importedFunction.declaration.decorators;

if (decorators) {
for (let decorator of decorators) {
if (decorator.name.text !== "external") continue;
if (!decorator.args) continue; // sanity check

if (decorator.args.length > 1) {
external_module = decorator.args[0].value;
external_name = decorator.args[1].value;
} else {
external_name = decorator.args[0].value;
}
}
}

// To know under what module name an imported function will be expected,
// we have to find the containing module of the given function, take the
// internal name (which is effectively the file path without extension)
// and only take the part after the last `/`
// (i.e. the file name without extension).
const moduleName = containingModule(importedFunction)
.internalName.split("/")
.slice(-1)[0];
const moduleName =
external_module ||
containingModule(importedFunction)
.internalName.split("/")
.slice(-1)[0];
if (!importedFunctions.hasOwnProperty(moduleName)) {
importedFunctions[moduleName] = {};
}
let importedFunctionName = importedFunction.name;
if (
if (external_name) {
importedFunctionName = external_name;
} else if (
importedFunction.parent &&
importedFunction.parent.kind === ElementKind.NAMESPACE
) {
Expand Down

0 comments on commit d12f7ce

Please sign in to comment.