Get imports working in a basic capacity

This commit is contained in:
Alex Crichton
2017-12-18 21:43:16 -08:00
parent 1ffcb90d2d
commit eda9beae25
7 changed files with 319 additions and 48 deletions

View File

@ -2,15 +2,16 @@ use shared;
#[derive(Default)]
pub struct Js {
pub expose_global_memory: bool,
pub expose_global_exports: bool,
pub expose_get_string_from_wasm: bool,
pub expose_pass_string_to_wasm: bool,
pub expose_assert_num: bool,
pub expose_assert_class: bool,
pub expose_token: bool,
pub exports: Vec<(String, String)>,
pub classes: Vec<String>,
expose_global_memory: bool,
expose_global_exports: bool,
expose_get_string_from_wasm: bool,
expose_pass_string_to_wasm: bool,
expose_assert_num: bool,
expose_assert_class: bool,
expose_token: bool,
exports: Vec<(String, String)>,
classes: Vec<String>,
imports: Vec<String>,
pub nodejs: bool,
}
@ -23,6 +24,9 @@ impl Js {
for s in program.structs.iter() {
self.generate_struct(s);
}
for s in program.imports.iter() {
self.generate_import(s);
}
}
pub fn generate_free_function(&mut self, func: &shared::Function) {
@ -160,7 +164,14 @@ impl Js {
}
Some(&shared::Type::String) => {
self.expose_get_string_from_wasm = true;
format!("return getStringFromWasm(ret);")
self.expose_global_exports = true;
format!("
const ptr = exports.__wbindgen_boxed_str_ptr(ret);
const len = exports.__wbindgen_boxed_str_len(ret);
const realRet = getStringFromWasm(ptr, len);
exports.__wbindgen_boxed_str_free(ret);
return realRet;
")
}
};
dst.push_str(") {\n ");
@ -186,8 +197,47 @@ impl Js {
return dst
}
pub fn generate_import(&mut self, import: &shared::Function) {
let mut dst = String::new();
dst.push_str(&format!("const {0} = imports.env.{0};\n", import.name));
dst.push_str(&format!("imports.env.{0} = function {0}_shim(", import.name));
let mut invocation = String::new();
for (i, arg) in import.arguments.iter().enumerate() {
if invocation.len() > 0 {
invocation.push_str(", ");
}
if i > 0 {
dst.push_str(", ");
}
match *arg {
shared::Type::Number => {
invocation.push_str(&format!("arg{}", i));
dst.push_str(&format!("arg{}", i));
}
shared::Type::BorrowedStr => {
self.expose_get_string_from_wasm = true;
invocation.push_str(&format!("getStringFromWasm(ptr{0}, len{0})", i));
dst.push_str(&format!("ptr{0}, len{0}", i));
}
shared::Type::String |
shared::Type::ByRef(_) |
shared::Type::ByMutRef(_) |
shared::Type::ByValue(_) => {
panic!("unsupported type in import");
}
}
}
dst.push_str(") {\n");
dst.push_str(&format!("return {}({});\n}}", import.name, invocation));
self.imports.push(dst);
}
pub fn to_string(&self) -> String {
let mut globals = String::new();
let mut real_globals = String::new();
if self.expose_global_memory ||
self.expose_pass_string_to_wasm ||
self.expose_get_string_from_wasm
@ -247,27 +297,22 @@ impl Js {
}
}
if self.expose_get_string_from_wasm {
real_globals.push_str("let getStringFromWasm = null;\n");
if self.nodejs {
globals.push_str("
function getStringFromWasm(ptr) {
getStringFromWasm = function getStringFromWasm(ptr, len) {
const mem = new Uint8Array(memory.buffer);
const data = exports.__wbindgen_boxed_str_ptr(ptr);
const len = exports.__wbindgen_boxed_str_len(ptr);
const buf = Buffer.from(mem.slice(data, data + len));
const buf = Buffer.from(mem.slice(ptr, ptr + len));
const ret = buf.toString();
exports.__wbindgen_boxed_str_free(ptr);
return ret;
}
");
} else {
globals.push_str("
function getStringFromWasm(ptr) {
getStringFromWasm = function getStringFromWasm(ptr, len) {
const mem = new Uint8Array(memory.buffer);
const data = exports.__wbindgen_boxed_str_ptr(ptr);
const len = exports.__wbindgen_boxed_str_len(ptr);
const slice = mem.slice(data, data + len);
const slice = mem.slice(ptr, ptr + len);
const ret = new TextDecoder('utf-8').decode(slice);
exports.__wbindgen_boxed_str_free(ptr);
return ret;
}
");
@ -295,15 +340,22 @@ impl Js {
exports.push_str(body);
exports.push_str(";\n");
}
let mut imports = String::new();
for import in self.imports.iter() {
imports.push_str(import);
imports.push_str("\n");
}
format!("
{}
function xform(obj) {{
{}
{}
return obj;
}}
export function instantiate(bytes, imports) {{
{}
return WebAssembly.instantiate(bytes, imports).then(xform);
}}
", globals, exports)
", real_globals, globals, exports, imports)
}
}

View File

@ -108,6 +108,7 @@ fn extract_program(module: &mut Module) -> shared::Program {
let mut ret = shared::Program {
structs: Vec::new(),
free_functions: Vec::new(),
imports: Vec::new(),
};
let data = match data {
Some(data) => data,
@ -125,9 +126,10 @@ fn extract_program(module: &mut Module) -> shared::Program {
Ok(f) => f,
Err(_) => continue,
};
let shared::Program { structs, free_functions } = p;
let shared::Program { structs, free_functions, imports } = p;
ret.structs.extend(structs);
ret.free_functions.extend(free_functions);
ret.imports.extend(imports);
}
data.entries_mut().remove(i);
}