mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-11-28 05:52:21 +03:00
Add an --output-js
flag
This'll output just vanilla JS rather than TypeScript! Closes #8
This commit is contained in:
parent
25faad9390
commit
b38c273ee5
@ -16,6 +16,7 @@ pub struct Project {
|
|||||||
files: Vec<(String, String)>,
|
files: Vec<(String, String)>,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
uglify: bool,
|
uglify: bool,
|
||||||
|
js: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn project() -> Project {
|
pub fn project() -> Project {
|
||||||
@ -29,6 +30,7 @@ pub fn project() -> Project {
|
|||||||
Project {
|
Project {
|
||||||
debug: true,
|
debug: true,
|
||||||
uglify: false,
|
uglify: false,
|
||||||
|
js: false,
|
||||||
files: vec![
|
files: vec![
|
||||||
("Cargo.toml".to_string(), format!(r#"
|
("Cargo.toml".to_string(), format!(r#"
|
||||||
[package]
|
[package]
|
||||||
@ -133,6 +135,11 @@ impl Project {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn js(&mut self, js: bool) -> &mut Project {
|
||||||
|
self.js = js;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn test(&mut self) {
|
pub fn test(&mut self) {
|
||||||
let root = root();
|
let root = root();
|
||||||
drop(fs::remove_dir_all(&root));
|
drop(fs::remove_dir_all(&root));
|
||||||
@ -170,27 +177,41 @@ impl Project {
|
|||||||
.uglify_wasm_names(self.uglify)
|
.uglify_wasm_names(self.uglify)
|
||||||
.generate()
|
.generate()
|
||||||
.expect("failed to run bindgen");
|
.expect("failed to run bindgen");
|
||||||
|
if self.js {
|
||||||
|
obj.write_js_to(root.join("out.js")).expect("failed to write js");
|
||||||
|
} else {
|
||||||
obj.write_ts_to(root.join("out.ts")).expect("failed to write ts");
|
obj.write_ts_to(root.join("out.ts")).expect("failed to write ts");
|
||||||
|
}
|
||||||
obj.write_wasm_to(root.join("out.wasm")).expect("failed to write wasm");
|
obj.write_wasm_to(root.join("out.wasm")).expect("failed to write wasm");
|
||||||
|
let out_dir = if self.js {
|
||||||
|
root.join("out")
|
||||||
|
} else {
|
||||||
|
root.clone()
|
||||||
|
};
|
||||||
|
|
||||||
let mut cmd = Command::new("node");
|
let mut cmd = Command::new("node");
|
||||||
cmd.arg(typescript())
|
cmd.arg(typescript())
|
||||||
.current_dir(&target_dir)
|
.current_dir(&target_dir)
|
||||||
.arg(root.join("run.ts"))
|
.arg(root.join("run.ts"))
|
||||||
.arg("--strict")
|
|
||||||
.arg("--noImplicitAny")
|
|
||||||
.arg("--strictNullChecks")
|
|
||||||
.arg("--strictFunctionTypes")
|
|
||||||
.arg("--noUnusedLocals")
|
.arg("--noUnusedLocals")
|
||||||
.arg("--noUnusedParameters")
|
.arg("--noUnusedParameters")
|
||||||
.arg("--noImplicitReturns")
|
.arg("--noImplicitReturns")
|
||||||
.arg("--declaration")
|
|
||||||
.arg("--lib")
|
.arg("--lib")
|
||||||
.arg("es6");
|
.arg("es6")
|
||||||
|
.arg("--outDir").arg(&out_dir);
|
||||||
|
if self.js {
|
||||||
|
cmd.arg("--allowJs");
|
||||||
|
} else {
|
||||||
|
cmd.arg("--noImplicitAny")
|
||||||
|
.arg("--strict")
|
||||||
|
.arg("--strictNullChecks")
|
||||||
|
.arg("--declaration")
|
||||||
|
.arg("--strictFunctionTypes");
|
||||||
|
}
|
||||||
run(&mut cmd, "node");
|
run(&mut cmd, "node");
|
||||||
|
|
||||||
let mut cmd = Command::new("node");
|
let mut cmd = Command::new("node");
|
||||||
cmd.arg("run.js")
|
cmd.arg(out_dir.join("run.js"))
|
||||||
.current_dir(&root);
|
.current_dir(&root);
|
||||||
run(&mut cmd, "node");
|
run(&mut cmd, "node");
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,21 @@ impl Object {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_js_to<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
|
||||||
|
self._write_js_to(path.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _write_js_to(&self, path: &Path) -> Result<(), Error> {
|
||||||
|
let js = self.generate_js();
|
||||||
|
let mut f = File::create(path).with_context(|_| {
|
||||||
|
format!("failed to create file at {:?}", path)
|
||||||
|
})?;
|
||||||
|
f.write_all(js.as_bytes()).with_context(|_| {
|
||||||
|
format!("failed to write file at {:?}", path)
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_wasm_to<P: AsRef<Path>>(self, path: P) -> Result<(), Error> {
|
pub fn write_wasm_to<P: AsRef<Path>>(self, path: P) -> Result<(), Error> {
|
||||||
self._write_wasm_to(path.as_ref())
|
self._write_wasm_to(path.as_ref())
|
||||||
}
|
}
|
||||||
@ -118,6 +133,16 @@ impl Object {
|
|||||||
let mut ts = ts::Js::default();
|
let mut ts = ts::Js::default();
|
||||||
ts.nodejs = self.nodejs;
|
ts.nodejs = self.nodejs;
|
||||||
ts.debug = self.debug;
|
ts.debug = self.debug;
|
||||||
|
ts.ts = true;
|
||||||
|
ts.generate_program(&self.program, &self.module);
|
||||||
|
ts.to_string(&self.module, &self.program)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_js(&self) -> String {
|
||||||
|
let mut ts = ts::Js::default();
|
||||||
|
ts.nodejs = self.nodejs;
|
||||||
|
ts.debug = self.debug;
|
||||||
|
ts.ts = false;
|
||||||
ts.generate_program(&self.program, &self.module);
|
ts.generate_program(&self.program, &self.module);
|
||||||
ts.to_string(&self.module, &self.program)
|
ts.to_string(&self.module, &self.program)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use shared;
|
use shared;
|
||||||
use parity_wasm::elements::*;
|
use parity_wasm::elements::*;
|
||||||
@ -14,10 +15,10 @@ pub struct Js {
|
|||||||
classes: Vec<String>,
|
classes: Vec<String>,
|
||||||
pub nodejs: bool,
|
pub nodejs: bool,
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
|
pub ts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Js {
|
impl Js {
|
||||||
|
|
||||||
pub fn generate_program(&mut self,
|
pub fn generate_program(&mut self,
|
||||||
program: &shared::Program,
|
program: &shared::Program,
|
||||||
m: &Mapped) {
|
m: &Mapped) {
|
||||||
@ -51,26 +52,37 @@ impl Js {
|
|||||||
dst.push_str(&format!("
|
dst.push_str(&format!("
|
||||||
export class {} {{
|
export class {} {{
|
||||||
", s.name));
|
", s.name));
|
||||||
|
let number = self.typed("number");
|
||||||
|
let symbol = self.typed("Symbol");
|
||||||
|
let void = self.typed("void");
|
||||||
|
if self.ts {
|
||||||
|
dst.push_str("
|
||||||
|
public ptr: number;
|
||||||
|
");
|
||||||
|
}
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_check_token();
|
self.expose_check_token();
|
||||||
dst.push_str(&format!("
|
dst.push_str(&format!("
|
||||||
constructor(public ptr: number, sym: Symbol) {{
|
constructor(ptr{}, sym{}) {{
|
||||||
_checkToken(sym);
|
_checkToken(sym);
|
||||||
|
this.ptr = ptr;
|
||||||
}}
|
}}
|
||||||
"));
|
", number, symbol));
|
||||||
} else {
|
} else {
|
||||||
dst.push_str(&format!("
|
dst.push_str(&format!("
|
||||||
constructor(public ptr: number) {{}}
|
constructor(ptr{}) {{
|
||||||
"));
|
this.ptr = ptr;
|
||||||
|
}}
|
||||||
|
", number));
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.push_str(&format!("
|
dst.push_str(&format!("
|
||||||
free(): void {{
|
free(){} {{
|
||||||
const ptr = this.ptr;
|
const ptr = this.ptr;
|
||||||
this.ptr = 0;
|
this.ptr = 0;
|
||||||
wasm_exports.{}(ptr);
|
wasm_exports.{}(ptr);
|
||||||
}}
|
}}
|
||||||
", m.export_name(&s.free_function())));
|
", void, m.export_name(&s.free_function())));
|
||||||
|
|
||||||
self.wasm_exports_bound.insert(s.name.clone());
|
self.wasm_exports_bound.insert(s.name.clone());
|
||||||
|
|
||||||
@ -130,7 +142,6 @@ impl Js {
|
|||||||
dst.push_str(", ");
|
dst.push_str(", ");
|
||||||
}
|
}
|
||||||
dst.push_str(&name);
|
dst.push_str(&name);
|
||||||
dst.push_str(": ");
|
|
||||||
|
|
||||||
let mut pass = |arg: &str| {
|
let mut pass = |arg: &str| {
|
||||||
if passed_args.len() > 0 {
|
if passed_args.len() > 0 {
|
||||||
@ -140,7 +151,7 @@ impl Js {
|
|||||||
};
|
};
|
||||||
match *arg {
|
match *arg {
|
||||||
shared::Type::Number => {
|
shared::Type::Number => {
|
||||||
dst.push_str("number");
|
dst.push_str(&format!("{}", self.typed("number")));
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_assert_num();
|
self.expose_assert_num();
|
||||||
arg_conversions.push_str(&format!("_assertNum({});\n", name));
|
arg_conversions.push_str(&format!("_assertNum({});\n", name));
|
||||||
@ -148,7 +159,7 @@ impl Js {
|
|||||||
pass(&name)
|
pass(&name)
|
||||||
}
|
}
|
||||||
shared::Type::Boolean => {
|
shared::Type::Boolean => {
|
||||||
dst.push_str("boolean");
|
dst.push_str(&format!("{}", self.typed("boolean")));
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_assert_bool();
|
self.expose_assert_bool();
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
@ -160,7 +171,7 @@ impl Js {
|
|||||||
}
|
}
|
||||||
shared::Type::BorrowedStr |
|
shared::Type::BorrowedStr |
|
||||||
shared::Type::String => {
|
shared::Type::String => {
|
||||||
dst.push_str("string");
|
dst.push_str(&format!("{}", self.typed("string")));
|
||||||
self.expose_pass_string_to_wasm(m);
|
self.expose_pass_string_to_wasm(m);
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
const [ptr{i}, len{i}] = passStringToWasm({arg});
|
const [ptr{i}, len{i}] = passStringToWasm({arg});
|
||||||
@ -176,7 +187,7 @@ impl Js {
|
|||||||
}
|
}
|
||||||
shared::Type::ByRef(ref s) |
|
shared::Type::ByRef(ref s) |
|
||||||
shared::Type::ByMutRef(ref s) => {
|
shared::Type::ByMutRef(ref s) => {
|
||||||
dst.push_str(s);
|
dst.push_str(&format!("{}", self.typed(s)));
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_assert_class();
|
self.expose_assert_class();
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
@ -186,7 +197,7 @@ impl Js {
|
|||||||
pass(&format!("{}.ptr", name));
|
pass(&format!("{}.ptr", name));
|
||||||
}
|
}
|
||||||
shared::Type::ByValue(ref s) => {
|
shared::Type::ByValue(ref s) => {
|
||||||
dst.push_str(s);
|
dst.push_str(&format!("{}", self.typed(s)));
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_assert_class();
|
self.expose_assert_class();
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
@ -200,7 +211,7 @@ impl Js {
|
|||||||
pass(&format!("ptr{}", i));
|
pass(&format!("ptr{}", i));
|
||||||
}
|
}
|
||||||
shared::Type::JsObject => {
|
shared::Type::JsObject => {
|
||||||
dst.push_str("any");
|
dst.push_str(&format!("{}", self.typed("any")));
|
||||||
self.expose_add_heap_object();
|
self.expose_add_heap_object();
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
const idx{i} = addHeapObject({arg});
|
const idx{i} = addHeapObject({arg});
|
||||||
@ -208,7 +219,7 @@ impl Js {
|
|||||||
pass(&format!("idx{}", i));
|
pass(&format!("idx{}", i));
|
||||||
}
|
}
|
||||||
shared::Type::JsObjectRef => {
|
shared::Type::JsObjectRef => {
|
||||||
dst.push_str("any");
|
dst.push_str(&format!("{}", self.typed("any")));
|
||||||
self.expose_borrowed_objects();
|
self.expose_borrowed_objects();
|
||||||
arg_conversions.push_str(&format!("\
|
arg_conversions.push_str(&format!("\
|
||||||
const idx{i} = addBorrowedObject({arg});
|
const idx{i} = addBorrowedObject({arg});
|
||||||
@ -218,22 +229,22 @@ impl Js {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst.push_str("): ");
|
dst.push_str(")");
|
||||||
let convert_ret = match ret {
|
let convert_ret = match ret {
|
||||||
None => {
|
None => {
|
||||||
dst.push_str("void");
|
dst.push_str(&format!("{}", self.typed("void")));
|
||||||
format!("return ret;")
|
format!("return ret;")
|
||||||
}
|
}
|
||||||
Some(&shared::Type::Number) => {
|
Some(&shared::Type::Number) => {
|
||||||
dst.push_str("number");
|
dst.push_str(&format!("{}", self.typed("number")));
|
||||||
format!("return ret;")
|
format!("return ret;")
|
||||||
}
|
}
|
||||||
Some(&shared::Type::Boolean) => {
|
Some(&shared::Type::Boolean) => {
|
||||||
dst.push_str("boolean");
|
dst.push_str(&format!("{}", self.typed("boolean")));
|
||||||
format!("return ret != 0;")
|
format!("return ret != 0;")
|
||||||
}
|
}
|
||||||
Some(&shared::Type::JsObject) => {
|
Some(&shared::Type::JsObject) => {
|
||||||
dst.push_str("any");
|
dst.push_str(&format!("{}", self.typed("any")));
|
||||||
self.expose_take_object();
|
self.expose_take_object();
|
||||||
format!("return takeObject(ret);")
|
format!("return takeObject(ret);")
|
||||||
}
|
}
|
||||||
@ -242,7 +253,7 @@ impl Js {
|
|||||||
Some(&shared::Type::ByMutRef(_)) |
|
Some(&shared::Type::ByMutRef(_)) |
|
||||||
Some(&shared::Type::ByRef(_)) => panic!(),
|
Some(&shared::Type::ByRef(_)) => panic!(),
|
||||||
Some(&shared::Type::ByValue(ref name)) => {
|
Some(&shared::Type::ByValue(ref name)) => {
|
||||||
dst.push_str(name);
|
dst.push_str(&format!("{}", self.typed(name)));
|
||||||
if self.debug {
|
if self.debug {
|
||||||
format!("\
|
format!("\
|
||||||
return new {name}(ret, token);
|
return new {name}(ret, token);
|
||||||
@ -254,7 +265,7 @@ impl Js {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(&shared::Type::String) => {
|
Some(&shared::Type::String) => {
|
||||||
dst.push_str("string");
|
dst.push_str(&format!("{}", self.typed("string")));
|
||||||
self.expose_get_string_from_wasm();
|
self.expose_get_string_from_wasm();
|
||||||
self.expose_wasm_exports();
|
self.expose_wasm_exports();
|
||||||
format!("
|
format!("
|
||||||
@ -309,6 +320,7 @@ impl Js {
|
|||||||
{
|
{
|
||||||
let mut dst = String::new();
|
let mut dst = String::new();
|
||||||
let mut ts_dst = String::new();
|
let mut ts_dst = String::new();
|
||||||
|
let number = self.typed("number");
|
||||||
|
|
||||||
dst.push_str(&format!("function {0}_shim(", import.name));
|
dst.push_str(&format!("function {0}_shim(", import.name));
|
||||||
|
|
||||||
@ -324,35 +336,35 @@ impl Js {
|
|||||||
dst.push_str(", ");
|
dst.push_str(", ");
|
||||||
ts_dst.push_str(", ");
|
ts_dst.push_str(", ");
|
||||||
}
|
}
|
||||||
ts_dst.push_str(&format!("arg{}: ", i));
|
ts_dst.push_str(&format!("arg{}", i));
|
||||||
match *arg {
|
match *arg {
|
||||||
shared::Type::Number => {
|
shared::Type::Number => {
|
||||||
ts_dst.push_str("number");
|
ts_dst.push_str(&self.typed("number").to_string());
|
||||||
invocation.push_str(&format!("arg{}", i));
|
invocation.push_str(&format!("arg{}", i));
|
||||||
dst.push_str(&format!("arg{}: number", i));
|
dst.push_str(&format!("arg{}{}", i, number));
|
||||||
}
|
}
|
||||||
shared::Type::Boolean => {
|
shared::Type::Boolean => {
|
||||||
ts_dst.push_str("boolean");
|
ts_dst.push_str(&self.typed("boolean").to_string());
|
||||||
invocation.push_str(&format!("arg{} != 0", i));
|
invocation.push_str(&format!("arg{} != 0", i));
|
||||||
dst.push_str(&format!("arg{}: number", i));
|
dst.push_str(&format!("arg{}{}", i, number));
|
||||||
}
|
}
|
||||||
shared::Type::BorrowedStr => {
|
shared::Type::BorrowedStr => {
|
||||||
ts_dst.push_str("string");
|
ts_dst.push_str(&self.typed("string").to_string());
|
||||||
self.expose_get_string_from_wasm();
|
self.expose_get_string_from_wasm();
|
||||||
invocation.push_str(&format!("getStringFromWasm(ptr{0}, len{0})", i));
|
invocation.push_str(&format!("getStringFromWasm(ptr{0}, len{0})", i));
|
||||||
dst.push_str(&format!("ptr{0}: number, len{0}: number", i));
|
dst.push_str(&format!("ptr{0}{1}, len{0}{1}", i, number));
|
||||||
}
|
}
|
||||||
shared::Type::JsObject => {
|
shared::Type::JsObject => {
|
||||||
ts_dst.push_str("any");
|
ts_dst.push_str(&self.typed("any").to_string());
|
||||||
self.expose_take_object();
|
self.expose_take_object();
|
||||||
invocation.push_str(&format!("takeObject(arg{})", i));
|
invocation.push_str(&format!("takeObject(arg{})", i));
|
||||||
dst.push_str(&format!("arg{}: number", i));
|
dst.push_str(&format!("arg{}{}", i, number));
|
||||||
}
|
}
|
||||||
shared::Type::JsObjectRef => {
|
shared::Type::JsObjectRef => {
|
||||||
ts_dst.push_str("any");
|
ts_dst.push_str(&self.typed("any").to_string());
|
||||||
self.expose_get_object();
|
self.expose_get_object();
|
||||||
invocation.push_str(&format!("getObject(arg{})", i));
|
invocation.push_str(&format!("getObject(arg{})", i));
|
||||||
dst.push_str(&format!("arg{}: number", i));
|
dst.push_str(&format!("arg{}{}", i, number));
|
||||||
}
|
}
|
||||||
shared::Type::String |
|
shared::Type::String |
|
||||||
shared::Type::ByRef(_) |
|
shared::Type::ByRef(_) |
|
||||||
@ -362,29 +374,29 @@ impl Js {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ts_dst.push_str("): ");
|
ts_dst.push_str(")");
|
||||||
dst.push_str("): ");
|
dst.push_str(")");
|
||||||
let invoc = format!("_imports.{}({})", import.name, invocation);
|
let invoc = format!("_imports.{}({})", import.name, invocation);
|
||||||
let invoc = match import.ret {
|
let invoc = match import.ret {
|
||||||
Some(shared::Type::Number) => {
|
Some(shared::Type::Number) => {
|
||||||
ts_dst.push_str("number");
|
ts_dst.push_str(&self.typed("number").to_string());
|
||||||
dst.push_str("number");
|
dst.push_str(&self.typed("number").to_string());
|
||||||
invoc
|
invoc
|
||||||
}
|
}
|
||||||
Some(shared::Type::Boolean) => {
|
Some(shared::Type::Boolean) => {
|
||||||
ts_dst.push_str("boolean");
|
ts_dst.push_str(&self.typed("boolean").to_string());
|
||||||
dst.push_str("number");
|
dst.push_str(&self.typed("number").to_string());
|
||||||
format!("{} ? 1 : 0", invoc)
|
format!("{} ? 1 : 0", invoc)
|
||||||
}
|
}
|
||||||
Some(shared::Type::JsObject) => {
|
Some(shared::Type::JsObject) => {
|
||||||
ts_dst.push_str("any");
|
ts_dst.push_str(&self.typed("any").to_string());
|
||||||
dst.push_str("number");
|
dst.push_str(&self.typed("number").to_string());
|
||||||
self.expose_add_heap_object();
|
self.expose_add_heap_object();
|
||||||
format!("addHeapObject({})", invoc)
|
format!("addHeapObject({})", invoc)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
ts_dst.push_str("void");
|
ts_dst.push_str(&self.typed("void").to_string());
|
||||||
dst.push_str("void");
|
dst.push_str(&self.typed("void").to_string());
|
||||||
invoc
|
invoc
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
@ -400,18 +412,19 @@ impl Js {
|
|||||||
if self.debug {
|
if self.debug {
|
||||||
self.expose_global_slab();
|
self.expose_global_slab();
|
||||||
self.expose_global_stack();
|
self.expose_global_stack();
|
||||||
|
let void = self.typed("void");
|
||||||
self.exports.push(
|
self.exports.push(
|
||||||
(
|
(
|
||||||
"assertHeapAndStackEmpty".to_string(),
|
"assertHeapAndStackEmpty".to_string(),
|
||||||
"function(): void {
|
format!("function(){} {{
|
||||||
if (stack.length > 0)
|
if (stack.length > 0)
|
||||||
throw new Error('stack is not empty');
|
throw new Error('stack is not empty');
|
||||||
for (let i = 0; i < slab.length; i++) {
|
for (let i = 0; i < slab.length; i++) {{
|
||||||
if (typeof(slab[i]) !== 'number')
|
if (typeof(slab[i]) !== 'number')
|
||||||
throw new Error('slab is not empty');
|
throw new Error('slab is not empty');
|
||||||
}
|
}}
|
||||||
}".to_string(),
|
}}", void),
|
||||||
"assertHeapAndStackEmpty(): void;\n".to_string(),
|
format!("assertHeapAndStackEmpty(){};\n", void),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -544,11 +557,14 @@ impl Js {
|
|||||||
throw new Error('corrupt slab');
|
throw new Error('corrupt slab');
|
||||||
val.cnt += 1;
|
val.cnt += 1;
|
||||||
")
|
")
|
||||||
} else {
|
} else if me.ts {
|
||||||
String::from("(val as {cnt:number}).cnt += 1;")
|
String::from("(val as {cnt:number}).cnt += 1;")
|
||||||
|
} else {
|
||||||
|
String::from("val.cnt += 1;")
|
||||||
};
|
};
|
||||||
|
let number = me.typed("number");
|
||||||
format!("
|
format!("
|
||||||
function(idx: number): number {{
|
function(idx{}){} {{
|
||||||
// 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)
|
||||||
return addHeapObject(getObject(idx));
|
return addHeapObject(getObject(idx));
|
||||||
@ -559,7 +575,7 @@ impl Js {
|
|||||||
{}
|
{}
|
||||||
return idx;
|
return idx;
|
||||||
}}
|
}}
|
||||||
", bump_cnt)
|
", number, number, bump_cnt)
|
||||||
});
|
});
|
||||||
|
|
||||||
bind("__wbindgen_object_drop_ref", &|me| {
|
bind("__wbindgen_object_drop_ref", &|me| {
|
||||||
@ -580,15 +596,16 @@ impl Js {
|
|||||||
|
|
||||||
bind("__wbindgen_number_get", &|me| {
|
bind("__wbindgen_number_get", &|me| {
|
||||||
me.expose_global_memory();
|
me.expose_global_memory();
|
||||||
String::from("
|
let number = me.typed("number");
|
||||||
function(n: number, invalid: number): number {
|
format!("
|
||||||
|
function(n{0}, invalid{0}){0} {{
|
||||||
let obj = getObject(n);
|
let obj = getObject(n);
|
||||||
if (typeof(obj) === 'number')
|
if (typeof(obj) === 'number')
|
||||||
return obj;
|
return obj;
|
||||||
(new Uint8Array(memory.buffer))[invalid] = 1;
|
(new Uint8Array(memory.buffer))[invalid] = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}}
|
||||||
")
|
", number)
|
||||||
});
|
});
|
||||||
|
|
||||||
bind("__wbindgen_undefined_new", &|me| {
|
bind("__wbindgen_undefined_new", &|me| {
|
||||||
@ -631,16 +648,17 @@ impl Js {
|
|||||||
bind("__wbindgen_symbol_new", &|me| {
|
bind("__wbindgen_symbol_new", &|me| {
|
||||||
me.expose_get_string_from_wasm();
|
me.expose_get_string_from_wasm();
|
||||||
me.expose_add_heap_object();
|
me.expose_add_heap_object();
|
||||||
String::from("(ptr, len) => {
|
let symbol = me.typed("Symbol");
|
||||||
let a: Symbol;
|
format!("(ptr, len) => {{
|
||||||
|
let a{};
|
||||||
console.log(ptr, len);
|
console.log(ptr, len);
|
||||||
if (ptr === 0) {
|
if (ptr === 0) {{
|
||||||
a = Symbol();
|
a = Symbol();
|
||||||
} else {
|
}} else {{
|
||||||
a = Symbol(getStringFromWasm(ptr, len));
|
a = Symbol(getStringFromWasm(ptr, len));
|
||||||
}
|
}}
|
||||||
return addHeapObject(a);
|
return addHeapObject(a);
|
||||||
}")
|
}}", symbol)
|
||||||
});
|
});
|
||||||
|
|
||||||
bind("__wbindgen_is_symbol", &|me| {
|
bind("__wbindgen_is_symbol", &|me| {
|
||||||
@ -650,11 +668,12 @@ impl Js {
|
|||||||
|
|
||||||
bind("__wbindgen_throw", &|me| {
|
bind("__wbindgen_throw", &|me| {
|
||||||
me.expose_get_string_from_wasm();
|
me.expose_get_string_from_wasm();
|
||||||
String::from("
|
let number = me.typed("number");
|
||||||
function(ptr: number, len: number) {
|
format!("
|
||||||
|
function(ptr{}, len{}) {{
|
||||||
throw new Error(getStringFromWasm(ptr, len));
|
throw new Error(getStringFromWasm(ptr, len));
|
||||||
}
|
}}
|
||||||
")
|
", number, number)
|
||||||
});
|
});
|
||||||
|
|
||||||
bind("__wbindgen_string_get", &|me| {
|
bind("__wbindgen_string_get", &|me| {
|
||||||
@ -679,10 +698,8 @@ impl Js {
|
|||||||
if self.exposed_globals.contains(&"wasm_exports") {
|
if self.exposed_globals.contains(&"wasm_exports") {
|
||||||
writes.push_str("wasm_exports = exports;\n");
|
writes.push_str("wasm_exports = exports;\n");
|
||||||
}
|
}
|
||||||
format!("
|
let mut interfaces = format!("
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
{globals}
|
|
||||||
|
|
||||||
interface WasmImportsTop {{
|
interface WasmImportsTop {{
|
||||||
env: WasmImports,
|
env: WasmImports,
|
||||||
}}
|
}}
|
||||||
@ -708,26 +725,7 @@ impl Js {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
{extra_exports_interface}
|
{extra_exports_interface}
|
||||||
|
|
||||||
function xform(obj: WebAssembly.ResultObject): Exports {{
|
|
||||||
let {{ module, instance }} = obj;
|
|
||||||
let exports: WasmExports = instance.exports;
|
|
||||||
{writes}
|
|
||||||
return {exports};
|
|
||||||
}}
|
|
||||||
export function instantiate(bytes: any, _imports: Imports): Promise<Exports> {{
|
|
||||||
let wasm_imports: WasmImportsTop = {{
|
|
||||||
env: {{
|
|
||||||
{imports_object}
|
|
||||||
}},
|
|
||||||
}};
|
|
||||||
return WebAssembly.instantiate(bytes, wasm_imports).then(xform);
|
|
||||||
}}
|
|
||||||
",
|
",
|
||||||
globals = self.globals,
|
|
||||||
exports = exports,
|
|
||||||
imports_object = imports_object,
|
|
||||||
writes = writes,
|
|
||||||
imports_interface = imports_interface,
|
imports_interface = imports_interface,
|
||||||
extra_imports_interface = extra_imports_interface,
|
extra_imports_interface = extra_imports_interface,
|
||||||
exports_interface = exports_interface,
|
exports_interface = exports_interface,
|
||||||
@ -740,6 +738,52 @@ impl Js {
|
|||||||
.map(|s| &**s)
|
.map(|s| &**s)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
|
);
|
||||||
|
if !self.ts {
|
||||||
|
interfaces.truncate(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let any = self.typed("any");
|
||||||
|
let imports_ty = self.typed("Imports");
|
||||||
|
let exports_ty = self.typed("Exports");
|
||||||
|
let result_ty = self.typed("WebAssembly.ResultObject");
|
||||||
|
let promise_ty = self.typed("Promise<Exports>");
|
||||||
|
let wasm_exports_ty = self.typed("WasmExports");
|
||||||
|
let wasm_imports_ty = self.typed("WasmImportsTop");
|
||||||
|
|
||||||
|
format!("
|
||||||
|
/* tslint:disable */
|
||||||
|
{globals}
|
||||||
|
|
||||||
|
{interfaces}
|
||||||
|
|
||||||
|
function xform(obj{result_ty}){exports_ty} {{
|
||||||
|
let {{ module, instance }} = obj;
|
||||||
|
let exports{wasm_exports_ty} = instance.exports;
|
||||||
|
{writes}
|
||||||
|
return {exports};
|
||||||
|
}}
|
||||||
|
export function instantiate(bytes{any}, _imports{imports_ty}){promise_ty} {{
|
||||||
|
let wasm_imports{wasm_imports_ty} = {{
|
||||||
|
env: {{
|
||||||
|
{imports_object}
|
||||||
|
}},
|
||||||
|
}};
|
||||||
|
return WebAssembly.instantiate(bytes, wasm_imports).then(xform);
|
||||||
|
}}
|
||||||
|
",
|
||||||
|
globals = self.globals,
|
||||||
|
interfaces = interfaces,
|
||||||
|
any = any,
|
||||||
|
result_ty = result_ty,
|
||||||
|
exports_ty = exports_ty,
|
||||||
|
promise_ty = promise_ty,
|
||||||
|
imports_ty = imports_ty,
|
||||||
|
wasm_imports_ty = wasm_imports_ty,
|
||||||
|
wasm_exports_ty = wasm_exports_ty,
|
||||||
|
exports = exports,
|
||||||
|
imports_object = imports_object,
|
||||||
|
writes = writes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,13 +834,13 @@ impl Js {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
ts.push_str(", ");
|
ts.push_str(", ");
|
||||||
}
|
}
|
||||||
ts.push_str(&format!("arg{}: number", i));
|
ts.push_str(&format!("arg{}{}", i, self.typed("number")));
|
||||||
}
|
}
|
||||||
ts.push_str("): ");
|
ts.push_str(")");
|
||||||
if ty.return_type().is_none() {
|
if ty.return_type().is_none() {
|
||||||
ts.push_str("void");
|
ts.push_str(&self.typed("void").to_string());
|
||||||
} else {
|
} else {
|
||||||
ts.push_str("number");
|
ts.push_str(&self.typed("number").to_string());
|
||||||
}
|
}
|
||||||
ts.push_str(";");
|
ts.push_str(";");
|
||||||
|
|
||||||
@ -853,13 +897,13 @@ impl Js {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
ts.push_str(", ");
|
ts.push_str(", ");
|
||||||
}
|
}
|
||||||
ts.push_str(&format!("arg{}: number", i));
|
ts.push_str(&format!("arg{}{}", i, self.typed("number")));
|
||||||
}
|
}
|
||||||
ts.push_str("): ");
|
ts.push_str(")");
|
||||||
if ty.return_type().is_none() {
|
if ty.return_type().is_none() {
|
||||||
ts.push_str("void");
|
ts.push_str(&self.typed("void").to_string());
|
||||||
} else {
|
} else {
|
||||||
ts.push_str("number");
|
ts.push_str(&self.typed("number").to_string());
|
||||||
}
|
}
|
||||||
ts.push_str(";");
|
ts.push_str(";");
|
||||||
map.insert(export.field().to_string(), ts);
|
map.insert(export.field().to_string(), ts);
|
||||||
@ -889,15 +933,23 @@ impl Js {
|
|||||||
if (obj.cnt > 0)
|
if (obj.cnt > 0)
|
||||||
return;
|
return;
|
||||||
")
|
")
|
||||||
} else {
|
} else if self.ts {
|
||||||
String::from("
|
String::from("
|
||||||
(obj as {cnt:number}).cnt -= 1;
|
(obj as {cnt:number}).cnt -= 1;
|
||||||
if ((obj as {cnt:number}).cnt > 0)
|
if ((obj as {cnt:number}).cnt > 0)
|
||||||
return;
|
return;
|
||||||
")
|
")
|
||||||
|
} else {
|
||||||
|
String::from("
|
||||||
|
obj.cnt -= 1;
|
||||||
|
if (obj.cnt > 0)
|
||||||
|
return;
|
||||||
|
")
|
||||||
};
|
};
|
||||||
|
let number = self.typed("number");
|
||||||
|
let void = self.typed("void");
|
||||||
self.globals.push_str(&format!("
|
self.globals.push_str(&format!("
|
||||||
function dropRef(idx: number): void {{
|
function dropRef(idx{}){} {{
|
||||||
{}
|
{}
|
||||||
|
|
||||||
let obj = slab[idx >> 1];
|
let obj = slab[idx >> 1];
|
||||||
@ -907,34 +959,35 @@ impl Js {
|
|||||||
slab[idx >> 1] = slab_next;
|
slab[idx >> 1] = slab_next;
|
||||||
slab_next = idx >> 1;
|
slab_next = idx >> 1;
|
||||||
}}
|
}}
|
||||||
", validate_owned, dec_ref));
|
", number, void, validate_owned, dec_ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_global_stack(&mut self) {
|
fn expose_global_stack(&mut self) {
|
||||||
if !self.exposed_globals.insert("stack") {
|
if !self.exposed_globals.insert("stack") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("
|
let ty = self.typed("any[]");
|
||||||
let stack: any[] = [];
|
self.globals.push_str(&format!("
|
||||||
");
|
let stack{} = [];
|
||||||
|
", ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_global_slab(&mut self) {
|
fn expose_global_slab(&mut self) {
|
||||||
if !self.exposed_globals.insert("slab") {
|
if !self.exposed_globals.insert("slab") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("
|
let ty = self.typed("({ obj: any, cnt: number } | number)[]");
|
||||||
let slab: ({ obj: any, cnt: number } | number)[] = [];
|
self.globals.push_str(&format!("let slab{} = [];", ty));
|
||||||
");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_global_slab_next(&mut self) {
|
fn expose_global_slab_next(&mut self) {
|
||||||
if !self.exposed_globals.insert("slab_next") {
|
if !self.exposed_globals.insert("slab_next") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("
|
let ty = self.typed("number");
|
||||||
let slab_next: number = 0;
|
self.globals.push_str(&format!("
|
||||||
");
|
let slab_next{} = 0;
|
||||||
|
", ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_get_object(&mut self) {
|
fn expose_get_object(&mut self) {
|
||||||
@ -950,13 +1003,19 @@ impl Js {
|
|||||||
throw new Error('corrupt slab');
|
throw new Error('corrupt slab');
|
||||||
return val.obj;
|
return val.obj;
|
||||||
")
|
")
|
||||||
} else {
|
} else if self.ts {
|
||||||
String::from("
|
String::from("
|
||||||
return (val as {obj:any}).obj;
|
return (val as {obj:any}).obj;
|
||||||
")
|
")
|
||||||
|
} else {
|
||||||
|
String::from("
|
||||||
|
return val.obj;
|
||||||
|
")
|
||||||
};
|
};
|
||||||
|
let number = self.typed("number");
|
||||||
|
let any = self.typed("any");
|
||||||
self.globals.push_str(&format!("
|
self.globals.push_str(&format!("
|
||||||
function getObject(idx: number): any {{
|
function getObject(idx{}){} {{
|
||||||
if ((idx & 1) === 1) {{
|
if ((idx & 1) === 1) {{
|
||||||
return stack[idx >> 1];
|
return stack[idx >> 1];
|
||||||
}} else {{
|
}} else {{
|
||||||
@ -964,58 +1023,65 @@ impl Js {
|
|||||||
{}
|
{}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
", get_obj));
|
", number, any, get_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_global_memory(&mut self) {
|
fn expose_global_memory(&mut self) {
|
||||||
if !self.exposed_globals.insert("memory") {
|
if !self.exposed_globals.insert("memory") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("let memory: WebAssembly.Memory;\n");
|
let mem = self.typed("WebAssembly.Memory");
|
||||||
|
self.globals.push_str(&format!("let memory{};\n", mem));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_wasm_exports(&mut self) {
|
fn expose_wasm_exports(&mut self) {
|
||||||
if !self.exposed_globals.insert("wasm_exports") {
|
if !self.exposed_globals.insert("wasm_exports") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("let wasm_exports: WasmExports;\n");
|
let ty = self.typed("WasmExports");
|
||||||
|
self.globals.push_str(&format!("let wasm_exports{};\n", ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_check_token(&mut self) {
|
fn expose_check_token(&mut self) {
|
||||||
if !self.exposed_globals.insert("check_token") {
|
if !self.exposed_globals.insert("check_token") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("\
|
let symbol = self.typed("Symbol");
|
||||||
|
let void = self.typed("void");
|
||||||
|
self.globals.push_str(&format!("
|
||||||
const token = Symbol('foo');
|
const token = Symbol('foo');
|
||||||
function _checkToken(sym: Symbol): void {
|
function _checkToken(sym{}){} {{
|
||||||
if (token !== sym)
|
if (token !== sym)
|
||||||
throw new Error('cannot invoke `new` directly');
|
throw new Error('cannot invoke `new` directly');
|
||||||
}
|
}}
|
||||||
");
|
", symbol, void));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_assert_num(&mut self) {
|
fn expose_assert_num(&mut self) {
|
||||||
if !self.exposed_globals.insert("assert_num") {
|
if !self.exposed_globals.insert("assert_num") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("\
|
let number = self.typed("number");
|
||||||
function _assertNum(n: number): void {
|
let void = self.typed("void");
|
||||||
|
self.globals.push_str(&format!("
|
||||||
|
function _assertNum(n{}){} {{
|
||||||
if (typeof(n) !== 'number')
|
if (typeof(n) !== 'number')
|
||||||
throw new Error('expected a number argument');
|
throw new Error('expected a number argument');
|
||||||
}
|
}}
|
||||||
");
|
", number, void));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_assert_bool(&mut self) {
|
fn expose_assert_bool(&mut self) {
|
||||||
if !self.exposed_globals.insert("assert_bool") {
|
if !self.exposed_globals.insert("assert_bool") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("\
|
let boolean = self.typed("boolean");
|
||||||
function _assertBoolean(n: boolean) {
|
self.globals.push_str(&format!("
|
||||||
|
function _assertBoolean(n{}) {{
|
||||||
if (typeof(n) !== 'boolean')
|
if (typeof(n) !== 'boolean')
|
||||||
throw new Error('expected a boolean argument');
|
throw new Error('expected a boolean argument');
|
||||||
}
|
}}
|
||||||
");
|
", boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_pass_string_to_wasm(&mut self, m: &Mapped) {
|
fn expose_pass_string_to_wasm(&mut self, m: &Mapped) {
|
||||||
@ -1024,9 +1090,11 @@ impl Js {
|
|||||||
}
|
}
|
||||||
self.expose_wasm_exports();
|
self.expose_wasm_exports();
|
||||||
self.expose_global_memory();
|
self.expose_global_memory();
|
||||||
|
let string = self.typed("string");
|
||||||
|
let ret = self.typed("[number, number]");
|
||||||
if self.nodejs {
|
if self.nodejs {
|
||||||
self.globals.push_str(&format!("
|
self.globals.push_str(&format!("
|
||||||
function passStringToWasm(arg: string): [number, number] {{
|
function passStringToWasm(arg{}){} {{
|
||||||
if (typeof(arg) !== 'string')
|
if (typeof(arg) !== 'string')
|
||||||
throw new Error('expected a string argument');
|
throw new Error('expected a string argument');
|
||||||
const buf = Buffer.from(arg);
|
const buf = Buffer.from(arg);
|
||||||
@ -1035,10 +1103,10 @@ impl Js {
|
|||||||
buf.copy(Buffer.from(memory.buffer), ptr);
|
buf.copy(Buffer.from(memory.buffer), ptr);
|
||||||
return [ptr, len];
|
return [ptr, len];
|
||||||
}}
|
}}
|
||||||
", m.export_name("__wbindgen_malloc")));
|
", string, ret, m.export_name("__wbindgen_malloc")));
|
||||||
} else {
|
} else {
|
||||||
self.globals.push_str(&format!("
|
self.globals.push_str(&format!("
|
||||||
function passStringToWasm(arg: string): [number, number] {{
|
function passStringToWasm(arg{}){} {{
|
||||||
if (typeof(arg) !== 'string')
|
if (typeof(arg) !== 'string')
|
||||||
throw new Error('expected a string argument');
|
throw new Error('expected a string argument');
|
||||||
const buf = new TextEncoder('utf-8').encode(arg);
|
const buf = new TextEncoder('utf-8').encode(arg);
|
||||||
@ -1048,7 +1116,7 @@ impl Js {
|
|||||||
array.set(buf, ptr);
|
array.set(buf, ptr);
|
||||||
return [ptr, len];
|
return [ptr, len];
|
||||||
}}
|
}}
|
||||||
", m.export_name("__wbindgen_malloc")));
|
", string, ret, m.export_name("__wbindgen_malloc")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,25 +1124,27 @@ impl Js {
|
|||||||
if !self.exposed_globals.insert("get_string_from_wasm") {
|
if !self.exposed_globals.insert("get_string_from_wasm") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let number = self.typed("number");
|
||||||
|
let string = self.typed("string");
|
||||||
if self.nodejs {
|
if self.nodejs {
|
||||||
self.expose_global_memory();
|
self.expose_global_memory();
|
||||||
self.globals.push_str("
|
self.globals.push_str(&format!("
|
||||||
function getStringFromWasm(ptr: number, len: number): string {
|
function getStringFromWasm(ptr{}, len{}){} {{
|
||||||
const buf = Buffer.from(memory.buffer).slice(ptr, ptr + len);
|
const buf = Buffer.from(memory.buffer).slice(ptr, ptr + len);
|
||||||
const ret = buf.toString();
|
const ret = buf.toString();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}}
|
||||||
");
|
", number, number, string));
|
||||||
} else {
|
} else {
|
||||||
self.expose_global_memory();
|
self.expose_global_memory();
|
||||||
self.globals.push_str("
|
self.globals.push_str(&format!("
|
||||||
function getStringFromWasm(ptr: number, len: number): string {
|
function getStringFromWasm(ptr{}, len{}){} {{
|
||||||
const mem = new Uint8Array(memory.buffer);
|
const mem = new Uint8Array(memory.buffer);
|
||||||
const slice = mem.slice(ptr, ptr + len);
|
const slice = mem.slice(ptr, ptr + len);
|
||||||
const ret = new TextDecoder('utf-8').decode(slice);
|
const ret = new TextDecoder('utf-8').decode(slice);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}}
|
||||||
");
|
", number, number, string));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,13 +1152,14 @@ impl Js {
|
|||||||
if !self.exposed_globals.insert("assert_class") {
|
if !self.exposed_globals.insert("assert_class") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.globals.push_str("
|
let any = self.typed("any");
|
||||||
function _assertClass(instance: any, klass: any) {
|
self.globals.push_str(&format!("
|
||||||
|
function _assertClass(instance{}, klass{}) {{
|
||||||
if (!(instance instanceof klass))
|
if (!(instance instanceof klass))
|
||||||
throw new Error(`expected instance of ${klass.name}`);
|
throw new Error(`expected instance of ${{klass.name}}`);
|
||||||
return instance.ptr;
|
return instance.ptr;
|
||||||
}
|
}}
|
||||||
");
|
", any, any));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_borrowed_objects(&mut self) {
|
fn expose_borrowed_objects(&mut self) {
|
||||||
@ -1096,12 +1167,14 @@ impl Js {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.expose_global_stack();
|
self.expose_global_stack();
|
||||||
self.globals.push_str("
|
let any = self.typed("any");
|
||||||
function addBorrowedObject(obj: any): number {
|
let number = self.typed("number");
|
||||||
|
self.globals.push_str(&format!("
|
||||||
|
function addBorrowedObject(obj{}){} {{
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
return ((stack.length - 1) << 1) | 1;
|
return ((stack.length - 1) << 1) | 1;
|
||||||
}
|
}}
|
||||||
");
|
", any, number));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_take_object(&mut self) {
|
fn expose_take_object(&mut self) {
|
||||||
@ -1110,13 +1183,15 @@ impl Js {
|
|||||||
}
|
}
|
||||||
self.expose_get_object();
|
self.expose_get_object();
|
||||||
self.expose_drop_ref();
|
self.expose_drop_ref();
|
||||||
self.globals.push_str("
|
let number = self.typed("number");
|
||||||
function takeObject(idx: number): any {
|
let any = self.typed("any");
|
||||||
|
self.globals.push_str(&format!("
|
||||||
|
function takeObject(idx{}){} {{
|
||||||
const ret = getObject(idx);
|
const ret = getObject(idx);
|
||||||
dropRef(idx);
|
dropRef(idx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}}
|
||||||
");
|
", number, any));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_add_heap_object(&mut self) {
|
fn expose_add_heap_object(&mut self) {
|
||||||
@ -1131,13 +1206,19 @@ impl Js {
|
|||||||
throw new Error('corrupt slab');
|
throw new Error('corrupt slab');
|
||||||
slab_next = next;
|
slab_next = next;
|
||||||
")
|
")
|
||||||
} else {
|
} else if self.ts {
|
||||||
String::from("
|
String::from("
|
||||||
slab_next = next as number;
|
slab_next = next as number;
|
||||||
")
|
")
|
||||||
|
} else {
|
||||||
|
String::from("
|
||||||
|
slab_next = next;
|
||||||
|
")
|
||||||
};
|
};
|
||||||
|
let any = self.typed("any");
|
||||||
|
let number = self.typed("number");
|
||||||
self.globals.push_str(&format!("
|
self.globals.push_str(&format!("
|
||||||
function addHeapObject(obj: any): number {{
|
function addHeapObject(obj{}){} {{
|
||||||
if (slab_next == slab.length)
|
if (slab_next == slab.length)
|
||||||
slab.push(slab.length + 1);
|
slab.push(slab.length + 1);
|
||||||
const idx = slab_next;
|
const idx = slab_next;
|
||||||
@ -1146,6 +1227,40 @@ impl Js {
|
|||||||
slab[idx] = {{ obj, cnt: 1 }};
|
slab[idx] = {{ obj, cnt: 1 }};
|
||||||
return idx << 1;
|
return idx << 1;
|
||||||
}}
|
}}
|
||||||
", set_slab_next));
|
", any, number, set_slab_next));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn typed<T>(&self, t: T) -> MaybeEmit<Typed<T>> {
|
||||||
|
self.maybe(Typed(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe<T>(&self, t: T) -> MaybeEmit<T> {
|
||||||
|
MaybeEmit {
|
||||||
|
enabled: self.ts,
|
||||||
|
inner: t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MaybeEmit<T> {
|
||||||
|
enabled: bool,
|
||||||
|
inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> fmt::Display for MaybeEmit<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if self.enabled {
|
||||||
|
self.inner.fmt(f)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Typed<T>(T);
|
||||||
|
|
||||||
|
impl<T: fmt::Display> fmt::Display for Typed<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, ": {}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ Usage:
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h --help Show this screen.
|
-h --help Show this screen.
|
||||||
|
--output-js FILE Output Javascript file
|
||||||
--output-ts FILE Output TypeScript file
|
--output-ts FILE Output TypeScript file
|
||||||
--output-wasm FILE Output WASM file
|
--output-wasm FILE Output WASM file
|
||||||
--nodejs Generate output for node.js, not the browser
|
--nodejs Generate output for node.js, not the browser
|
||||||
@ -25,6 +26,7 @@ Options:
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
flag_output_js: Option<PathBuf>,
|
||||||
flag_output_ts: Option<PathBuf>,
|
flag_output_ts: Option<PathBuf>,
|
||||||
flag_output_wasm: Option<PathBuf>,
|
flag_output_wasm: Option<PathBuf>,
|
||||||
flag_nodejs: bool,
|
flag_nodejs: bool,
|
||||||
@ -43,9 +45,16 @@ fn main() {
|
|||||||
.debug(args.flag_debug)
|
.debug(args.flag_debug)
|
||||||
.uglify_wasm_names(!args.flag_debug);
|
.uglify_wasm_names(!args.flag_debug);
|
||||||
let ret = b.generate().expect("failed to generate bindings");
|
let ret = b.generate().expect("failed to generate bindings");
|
||||||
|
let mut written = false;
|
||||||
if let Some(ref ts) = args.flag_output_ts {
|
if let Some(ref ts) = args.flag_output_ts {
|
||||||
ret.write_ts_to(ts).expect("failed to write TypeScript output file");
|
ret.write_ts_to(ts).expect("failed to write TypeScript output file");
|
||||||
} else {
|
written = true;
|
||||||
|
}
|
||||||
|
if let Some(ref js) = args.flag_output_js {
|
||||||
|
ret.write_js_to(js).expect("failed to write Javascript output file");
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
if !written {
|
||||||
println!("{}", ret.generate_ts());
|
println!("{}", ret.generate_ts());
|
||||||
}
|
}
|
||||||
if let Some(ref wasm) = args.flag_output_wasm {
|
if let Some(ref wasm) = args.flag_output_wasm {
|
||||||
|
79
tests/js.rs
Normal file
79
tests/js.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
extern crate test_support;
|
||||||
|
|
||||||
|
const SRC: &str = r#"
|
||||||
|
#![feature(proc_macro)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
wasm_bindgen! {
|
||||||
|
pub struct A {}
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
pub fn new() -> A {
|
||||||
|
A {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn clone(a: &JsObject) -> JsObject {
|
||||||
|
drop(a.clone());
|
||||||
|
a.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "JS" {
|
||||||
|
fn bar(a: &JsObject, b: JsObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foo(
|
||||||
|
_: &str,
|
||||||
|
_: bool,
|
||||||
|
_: i32,
|
||||||
|
_: &A,
|
||||||
|
_: A,
|
||||||
|
a: JsObject,
|
||||||
|
b: &JsObject,
|
||||||
|
) -> String {
|
||||||
|
a.is_symbol();
|
||||||
|
a.as_f64();
|
||||||
|
a.as_string();
|
||||||
|
a.as_bool();
|
||||||
|
a.is_null();
|
||||||
|
a.is_undefined();
|
||||||
|
bar(b, a);
|
||||||
|
JsObject::from("a");
|
||||||
|
JsObject::from(3);
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn works() {
|
||||||
|
test_support::project()
|
||||||
|
.js(true)
|
||||||
|
.debug(true)
|
||||||
|
.file("src/lib.rs", SRC)
|
||||||
|
.file("test.ts", r#"
|
||||||
|
export const imports = {};
|
||||||
|
|
||||||
|
export function test(_) {
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn works_non_debug() {
|
||||||
|
test_support::project()
|
||||||
|
.js(true)
|
||||||
|
.debug(false)
|
||||||
|
.file("src/lib.rs", SRC)
|
||||||
|
.file("test.ts", r#"
|
||||||
|
export const imports = {};
|
||||||
|
|
||||||
|
export function test(_) {
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user