1
0
mirror of https://github.com/fluencelabs/wasm-bindgen synced 2025-03-31 17:31:06 +00:00

Automatically bind float math functions

These tend to have one "pretty obvious" definition in JS anyway, so
let's paper over this deficiency in rustc for now by automatically
resolving any imports for these functions.

Closes 
This commit is contained in:
Alex Crichton 2018-02-17 16:43:58 -08:00
parent 9e7a4e7e60
commit d66bc25749
2 changed files with 146 additions and 22 deletions
crates/wasm-bindgen-cli-support/src
tests

@ -192,6 +192,8 @@ impl<'a> Context<'a> {
}); });
} }
self.rewrite_imports(module_name);
let js = format!(" let js = format!("
/* tslint:disable */ /* tslint:disable */
import * as wasm from './{module_name}_wasm'; // imports from wasm file import * as wasm from './{module_name}_wasm'; // imports from wasm file
@ -204,7 +206,6 @@ impl<'a> Context<'a> {
imports = self.imports, imports = self.imports,
); );
self.rewrite_imports(module_name);
self.unexport_unused_internal_exports(); self.unexport_unused_internal_exports();
(js, self.typescript.clone()) (js, self.typescript.clone())
@ -257,30 +258,89 @@ impl<'a> Context<'a> {
} }
fn rewrite_imports(&mut self, module_name: &str) { fn rewrite_imports(&mut self, module_name: &str) {
for section in self.module.sections_mut() { let imports = self.module.sections_mut()
let imports = match *section { .iter_mut()
Section::Import(ref mut s) => s, .filter_map(|s| {
_ => continue, match *s {
}; Section::Import(ref mut s) => Some(s),
for import in imports.entries_mut() { _ => None,
if import.field().starts_with("__wbindgen") {
import.module_mut().truncate(0);
import.module_mut().push_str("./");
import.module_mut().push_str(module_name);
continue
} }
})
.flat_map(|s| s.entries_mut());
// rustc doesn't have support for importing from anything other for import in imports {
// than the module `env` so let's use the metadata here to if import.field().starts_with("__wbindgen") {
// rewrite the imports if they import from `env` until it's import.module_mut().truncate(0);
// fixed upstream. import.module_mut().push_str("./");
if self.imports_to_rewrite.contains(import.field()) { import.module_mut().push_str(module_name);
import.module_mut().truncate(0); continue
import.module_mut().push_str("./");
import.module_mut().push_str(module_name);
continue
}
} }
// rustc doesn't have support for importing from anything other
// than the module `env` so let's use the metadata here to
// rewrite the imports if they import from `env` until it's
// fixed upstream.
if self.imports_to_rewrite.contains(import.field()) {
import.module_mut().truncate(0);
import.module_mut().push_str("./");
import.module_mut().push_str(module_name);
continue
}
if import.module() != "env" {
continue
}
let mut globals = &mut self.globals;
let renamed_import = format!("__wbindgen_{}", import.field());
let mut bind_math = |expr: &str| {
globals.push_str(&format!("
export const {} = {};
", renamed_import, expr));
};
match import.field() {
"Math_acos" => bind_math("Math.acos"),
"Math_asin" => bind_math("Math.asin"),
"Math_atan" => bind_math("Math.atan"),
"Math_atan2" => bind_math("Math.atan2"),
"Math_cbrt" => bind_math("Math.cbrt"),
"Math_cosh" => bind_math("Math.cosh"),
"Math_expm1" => bind_math("Math.expm1"),
"Math_hypot" => bind_math("Math.hypot"),
"Math_log1p" => bind_math("Math.log1p"),
"Math_sinh" => bind_math("Math.sinh"),
"Math_tan" => bind_math("Math.tan"),
"Math_tanh" => bind_math("Math.tanh"),
"cos" => bind_math("Math.cos"),
"cosf" => bind_math("Math.cos"),
"exp" => bind_math("Math.exp"),
"expf" => bind_math("Math.exp"),
"log2" => bind_math("Math.log2"),
"log2f" => bind_math("Math.log2"),
"log10" => bind_math("Math.log10"),
"log10f" => bind_math("Math.log10"),
"log" => bind_math("Math.log"),
"logf" => bind_math("Math.log"),
"round" => bind_math("Math.round"),
"roundf" => bind_math("Math.round"),
"sin" => bind_math("Math.sin"),
"sinf" => bind_math("Math.sin"),
"pow" => bind_math("Math.pow"),
"powf" => bind_math("Math.pow"),
"exp2" => bind_math("(a) => Math.pow(2, a)"),
"exp2f" => bind_math("(a) => Math.pow(2, a)"),
"fmod" => bind_math("(a, b) => a % b"),
"fmodf" => bind_math("(a, b) => a % b"),
"fma" => bind_math("(a, b, c) => (a * b) + c"),
"fmaf" => bind_math("(a, b, c) => (a * b) + c"),
_ => continue,
}
import.module_mut().truncate(0);
import.module_mut().push_str("./");
import.module_mut().push_str(module_name);
*import.field_mut() = renamed_import.clone();
} }
} }

64
tests/math.rs Normal file

@ -0,0 +1,64 @@
extern crate test_support;
#[test]
fn auto_bind_math() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
#[no_mangle]
pub extern fn math(a: f32, b: f64) -> f64 {
b.acos() +
b.asin() +
b.atan() +
b.atan2(b) +
b.cbrt() +
b.cosh() +
b.exp_m1() +
b.ln_1p() +
b.sinh() +
b.tan() +
b.tanh() +
b.hypot(b) +
b.cos() +
b.exp() +
b.exp2() +
b.mul_add(b, b) +
b.log(b) +
b.log10() +
b.log2() +
b.powi(8) +
b.powf(b) +
b.round() +
b.sin() +
(b % (a as f64)) +
((a.cos() +
a.exp() +
a.exp2() +
a.mul_add(a, a) +
a.log(a) +
a.log10() +
a.log2() +
a.powi(8) +
a.powf(a) +
a.round() +
a.sin() +
(a % (b as f32))) as f64) +
(b + 2.0f64.powf(a as f64))
}
"#)
.file("test.ts", r#"
import { math } from "./out";
export function test() {
math(1.0, 2.0);
}
"#)
.test();
}