Skip to content

Commit cb3a0ed

Browse files
committed
enforce direct import when types are incompatible with JS types
1 parent fb29d63 commit cb3a0ed

File tree

8 files changed

+55
-14
lines changed

8 files changed

+55
-14
lines changed

declarations.d.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ declare module "@webassemblyjs/ast" {
5353
module: string;
5454
descr: {
5555
type: string;
56-
valtype: string;
57-
id: string;
56+
valtype?: string;
57+
id?: Identifier;
58+
signature?: Signature;
5859
};
5960
name: string;
6061
}
@@ -64,16 +65,18 @@ declare module "@webassemblyjs/ast" {
6465
export class IndexLiteral extends Node {}
6566
export class NumberLiteral extends Node {}
6667
export class Global extends Node {}
67-
export class FuncParam extends Node {}
68+
export class FuncParam extends Node {
69+
valtype: string;
70+
}
6871
export class Instruction extends Node {}
6972
export class CallInstruction extends Instruction {}
7073
export class ObjectInstruction extends Instruction {}
7174
export class Func extends Node {
7275
signature: Signature;
7376
}
7477
export class Signature {
75-
params: any;
76-
result: any;
78+
params: FuncParam[];
79+
results: string[];
7780
}
7881
export class TypeInstructionFunc extends Node {}
7982
export class IndexInFuncSection extends Node {}
@@ -90,7 +93,7 @@ declare module "@webassemblyjs/ast" {
9093
init: Node[]
9194
): ObjectInstruction;
9295
export function func(initFuncId, funcParams, funcResults, funcBody): Func;
93-
export function typeInstructionFunc(params, result): TypeInstructionFunc;
96+
export function typeInstructionFunc(params: FuncParam[], results: string[]): TypeInstructionFunc;
9497
export function indexInFuncSection(index: IndexLiteral): IndexInFuncSection;
9598
export function moduleExport(
9699
identifier: string,

lib/dependencies/WebAssemblyImportDependency.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ const UnsupportedWebAssemblyFeatureError = require("../wasm/UnsupportedWebAssemb
1111
class WebAssemblyImportDependency extends ModuleDependency {
1212
constructor(request, name, description, onlyDirectImport) {
1313
super(request);
14+
/** @type {string} */
1415
this.name = name;
16+
/** @type {TODO} */
1517
this.description = description;
18+
/** @type {false | string} */
1619
this.onlyDirectImport = onlyDirectImport;
1720
}
1821

@@ -27,10 +30,11 @@ class WebAssemblyImportDependency extends ModuleDependency {
2730
this.module &&
2831
!this.module.type.startsWith("webassembly")
2932
) {
30-
const type = this.description.type;
3133
return [
3234
new UnsupportedWebAssemblyFeatureError(
33-
`${type} imports are only available for direct wasm to wasm dependencies`
35+
`Import with ${
36+
this.onlyDirectImport
37+
} can only be used for direct wasm to wasm dependencies`
3438
)
3539
];
3640
}

lib/wasm/WebAssemblyGenerator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ const addInitFunction = ({
275275
// Type section
276276
const functype = t.typeInstructionFunc(
277277
func.signature.params,
278-
func.signature.result
278+
func.signature.results
279279
);
280280

281281
// Func section

lib/wasm/WebAssemblyParser.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ const isMemoryImport = n => n.descr.type === "Memory";
2424
*/
2525
const isTableImport = n => n.descr.type === "Table";
2626

27+
const JS_COMPAT_TYPES = new Set(["i32", "u32", "f32"]);
28+
29+
/**
30+
* @param {t.ModuleImport} moduleImport the import
31+
* @returns {null | string} the type incompatible with js types
32+
*/
33+
const getJsIncompatibleType = moduleImport => {
34+
if (moduleImport.descr.type !== "FuncImportDescr") return null;
35+
const signature = moduleImport.descr.signature;
36+
for (const param of signature.params) {
37+
if (!JS_COMPAT_TYPES.has(param.valtype))
38+
return `${param.valtype} as parameter`;
39+
}
40+
for (const type of signature.results) {
41+
if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`;
42+
}
43+
return null;
44+
};
45+
2746
const decoderOpts = {
2847
ignoreCodeSection: true,
2948
ignoreDataSection: true
@@ -51,14 +70,18 @@ class WebAssemblyParser extends Tapable {
5170
},
5271

5372
ModuleImport({ node }) {
73+
/** @type {false | string} */
5474
let onlyDirectImport = false;
5575

5676
if (isMemoryImport(node) === true) {
57-
onlyDirectImport = true;
58-
}
59-
60-
if (isTableImport(node) === true) {
61-
onlyDirectImport = true;
77+
onlyDirectImport = "Memory";
78+
} else if (isTableImport(node) === true) {
79+
onlyDirectImport = "Table";
80+
} else {
81+
const incompatibleType = getJsIncompatibleType(node);
82+
if (incompatibleType) {
83+
onlyDirectImport = `Non-JS-compatible Func Sigurature (${incompatibleType})`;
84+
}
6285
}
6386

6487
const dep = new WebAssemblyImportDependency(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
it("should allow to run a WebAssembly module with non-js-compatible imports", function() {
2+
return import("./wasm.wasm").then(function(wasm) {
3+
const result = wasm.testI64();
4+
expect(result).toEqual(42);
5+
});
6+
});
68 Bytes
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
2+
3+
module.exports = function(config) {
4+
return supportsWebAssembly();
5+
};
119 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)