mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-10 06:06:06 +00:00
Support imports outside of wasm_bindgen!
This commit is contained in:
parent
66ae545bff
commit
a12a8f414c
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashSet, HashMap};
|
||||||
|
|
||||||
use shared;
|
use shared;
|
||||||
use parity_wasm::elements::*;
|
use parity_wasm::elements::*;
|
||||||
@ -352,21 +352,55 @@ impl Js {
|
|||||||
typescript_exports.push_str("\n");
|
typescript_exports.push_str("\n");
|
||||||
}
|
}
|
||||||
exports.push_str("}");
|
exports.push_str("}");
|
||||||
let mut imports = String::new();
|
let wasm_imports = self.typescript_wasm_imports(m);
|
||||||
let mut typescript_imports = String::new();
|
|
||||||
|
let mut imports_object = String::new();
|
||||||
|
let mut extra_imports_interface = String::new();
|
||||||
|
let mut imports_bound = HashSet::new();
|
||||||
|
let mut imports_interface = String::new();
|
||||||
for &(ref import, ref val, ref ts_import) in self.imports.iter() {
|
for &(ref import, ref val, ref ts_import) in self.imports.iter() {
|
||||||
imports.push_str(import);
|
imports_bound.insert(import.clone());
|
||||||
imports.push_str(":");
|
imports_object.push_str(import);
|
||||||
imports.push_str(val);
|
imports_object.push_str(":");
|
||||||
imports.push_str(",\n");
|
imports_object.push_str(val);
|
||||||
typescript_imports.push_str(ts_import);
|
imports_object.push_str(",\n");
|
||||||
typescript_imports.push_str("\n");
|
imports_interface.push_str(ts_import);
|
||||||
|
imports_interface.push_str("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user otherwise specified functions to import which *weren't*
|
||||||
|
// part of wasm-bindgen we want to make sure they come through here as
|
||||||
|
// well.
|
||||||
|
for (import, typescript) in wasm_imports.iter() {
|
||||||
|
// ignore any internal functions we have for ourselves
|
||||||
|
if import.starts_with("__wbindgen") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Ignore anything we just bound above,
|
||||||
|
if imports_bound.contains(import) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if extra_imports_interface.len() == 0 {
|
||||||
|
extra_imports_interface.push_str("interface ExtraImports {\n");
|
||||||
|
imports_interface.push_str("env: ExtraImports;\n");
|
||||||
|
}
|
||||||
|
imports_object.push_str(import);
|
||||||
|
imports_object.push_str(":");
|
||||||
|
imports_object.push_str("imports.env.");
|
||||||
|
imports_object.push_str(import);
|
||||||
|
imports_object.push_str(",\n");
|
||||||
|
extra_imports_interface.push_str(typescript);
|
||||||
|
extra_imports_interface.push_str("\n");
|
||||||
|
}
|
||||||
|
if extra_imports_interface.len() > 0 {
|
||||||
|
extra_imports_interface.push_str("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.wasm_import_needed("__wbindgen_object_clone_ref", m) {
|
if self.wasm_import_needed("__wbindgen_object_clone_ref", m) {
|
||||||
self.expose_add_heap_object();
|
self.expose_add_heap_object();
|
||||||
self.expose_get_object();
|
self.expose_get_object();
|
||||||
imports.push_str("
|
imports_object.push_str("
|
||||||
__wbindgen_object_clone_ref: function(idx: number): number {
|
__wbindgen_object_clone_ref: function(idx: number): number {
|
||||||
// If this object is on the stack promote it to the heap.
|
// If this object is on the stack promote it to the heap.
|
||||||
if ((idx & 1) === 1) {
|
if ((idx & 1) === 1) {
|
||||||
@ -386,12 +420,12 @@ impl Js {
|
|||||||
|
|
||||||
if self.wasm_import_needed("__wbindgen_object_drop_ref", m) {
|
if self.wasm_import_needed("__wbindgen_object_drop_ref", m) {
|
||||||
self.expose_drop_ref();
|
self.expose_drop_ref();
|
||||||
imports.push_str("__wbindgen_object_drop_ref: dropRef,\n");
|
imports_object.push_str("__wbindgen_object_drop_ref: dropRef,\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.wasm_import_needed("__wbindgen_throw", m) {
|
if self.wasm_import_needed("__wbindgen_throw", m) {
|
||||||
self.expose_get_string_from_wasm();
|
self.expose_get_string_from_wasm();
|
||||||
imports.push_str("__wbindgen_throw: function(ptr: number, len: number) {
|
imports_object.push_str("__wbindgen_throw: function(ptr: number, len: number) {
|
||||||
throw new Error(getStringFromWasm(ptr, len));
|
throw new Error(getStringFromWasm(ptr, len));
|
||||||
},\n");
|
},\n");
|
||||||
}
|
}
|
||||||
@ -419,9 +453,11 @@ impl Js {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
export interface Imports {{
|
export interface Imports {{
|
||||||
{typescript_imports}
|
{imports_interface}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
{extra_imports_interface}
|
||||||
|
|
||||||
export interface Exports {{
|
export interface Exports {{
|
||||||
module: WebAssembly.Module;
|
module: WebAssembly.Module;
|
||||||
instance: WebAssembly.Module;
|
instance: WebAssembly.Module;
|
||||||
@ -437,7 +473,7 @@ impl Js {
|
|||||||
export function instantiate(bytes: any, imports: Imports): Promise<Exports> {{
|
export function instantiate(bytes: any, imports: Imports): Promise<Exports> {{
|
||||||
let wasm_imports: WasmImportsTop = {{
|
let wasm_imports: WasmImportsTop = {{
|
||||||
env: {{
|
env: {{
|
||||||
{imports}
|
{imports_object}
|
||||||
}},
|
}},
|
||||||
}};
|
}};
|
||||||
return WebAssembly.instantiate(bytes, wasm_imports).then(xform);
|
return WebAssembly.instantiate(bytes, wasm_imports).then(xform);
|
||||||
@ -445,11 +481,15 @@ impl Js {
|
|||||||
",
|
",
|
||||||
globals = self.globals,
|
globals = self.globals,
|
||||||
exports = exports,
|
exports = exports,
|
||||||
imports = imports,
|
imports_object = imports_object,
|
||||||
writes = writes,
|
writes = writes,
|
||||||
typescript_imports = typescript_imports,
|
extra_imports_interface = extra_imports_interface,
|
||||||
|
imports_interface = imports_interface,
|
||||||
typescript_exports = typescript_exports,
|
typescript_exports = typescript_exports,
|
||||||
wasm_imports = self.typescript_wasm_imports(m),
|
wasm_imports = wasm_imports.values()
|
||||||
|
.map(|s| &**s)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
wasm_exports = self.typescript_wasm_exports(m),
|
wasm_exports = self.typescript_wasm_exports(m),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -465,17 +505,21 @@ impl Js {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typescript_wasm_imports(&self, m: &Module) -> String {
|
/// Returns a map of import name to the typescript definition for that name.
|
||||||
|
///
|
||||||
|
/// This function generates the list of imports that a wasm module has,
|
||||||
|
/// using the source of truth (the was module itself) to generate this list.
|
||||||
|
fn typescript_wasm_imports(&self, m: &Module) -> HashMap<String, String> {
|
||||||
let imports = match m.import_section() {
|
let imports = match m.import_section() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return String::new(),
|
None => return HashMap::new(),
|
||||||
};
|
};
|
||||||
let types = match m.type_section() {
|
let types = match m.type_section() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return String::new(),
|
None => return HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ts = String::new();
|
let mut map = HashMap::new();
|
||||||
for import in imports.entries() {
|
for import in imports.entries() {
|
||||||
assert_eq!(import.module(), "env");
|
assert_eq!(import.module(), "env");
|
||||||
|
|
||||||
@ -488,6 +532,7 @@ impl Js {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut ts = String::new();
|
||||||
ts.push_str(import.field());
|
ts.push_str(import.field());
|
||||||
ts.push_str("(");
|
ts.push_str("(");
|
||||||
// TODO: probably match `arg` to catch exhaustive errors in the
|
// TODO: probably match `arg` to catch exhaustive errors in the
|
||||||
@ -504,11 +549,18 @@ impl Js {
|
|||||||
} else {
|
} else {
|
||||||
ts.push_str("number");
|
ts.push_str("number");
|
||||||
}
|
}
|
||||||
ts.push_str(";\n");
|
ts.push_str(";");
|
||||||
|
|
||||||
|
map.insert(import.field().to_string(), ts);
|
||||||
}
|
}
|
||||||
return ts;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a block describing all the raw wasm exports that this module
|
||||||
|
/// has.
|
||||||
|
///
|
||||||
|
/// This uses the module itself as the source of truth to help flesh out
|
||||||
|
/// bugs in this program.
|
||||||
fn typescript_wasm_exports(&self, m: &Module) -> String {
|
fn typescript_wasm_exports(&self, m: &Module) -> String {
|
||||||
let imported_functions = match m.import_section() {
|
let imported_functions = match m.import_section() {
|
||||||
Some(s) => s.functions(),
|
Some(s) => s.functions(),
|
||||||
|
@ -152,3 +152,46 @@ fn exceptions() {
|
|||||||
"#)
|
"#)
|
||||||
.test();
|
.test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn other_imports() {
|
||||||
|
test_support::project()
|
||||||
|
.file("src/lib.rs", r#"
|
||||||
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn another_import(a: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm_bindgen! {
|
||||||
|
pub fn foo(a: u32) {
|
||||||
|
unsafe { another_import(a); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.file("test.ts", r#"
|
||||||
|
import * as assert from "assert";
|
||||||
|
import { Exports, Imports } from "./out";
|
||||||
|
|
||||||
|
let ARG: number | null = null;
|
||||||
|
|
||||||
|
export const imports: Imports = {
|
||||||
|
env: {
|
||||||
|
another_import(a: number) {
|
||||||
|
assert.strictEqual(ARG, null);
|
||||||
|
ARG = a;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function test(wasm: Exports) {
|
||||||
|
wasm.foo(2);
|
||||||
|
assert.strictEqual(ARG, 2);
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user