This commit is contained in:
Alex Crichton 2018-02-05 16:39:11 -08:00
parent 8f8da49dab
commit 0320bc0d7c
5 changed files with 163 additions and 19 deletions

View File

@ -26,6 +26,9 @@ impl<'a> Js<'a> {
for s in self.program.structs.iter() {
self.generate_struct(s);
}
for s in self.program.imported_structs.iter() {
self.generate_import_struct(s);
}
{
let mut bind = |name: &str, f: &Fn(&mut Self) -> String| {
@ -467,15 +470,56 @@ impl<'a> Js<'a> {
}
pub fn generate_import(&mut self, module: &str, import: &shared::Function) {
let mut dst = String::new();
let imported_name = format!("import{}", self.imports.len());
self.imports.push_str(&format!("
import {{ {} as {} }} from '{}';
", import.name, imported_name, module));
dst.push_str(&format!("function __wbg_import_{}(", import.name));
self.gen_import_shim(&import.mangled_import_name(None),
&imported_name,
import)
}
pub fn generate_import_struct(&mut self, import: &shared::ImportStruct) {
if let Some(ref module) = import.module {
self.imports.push_str(&format!("
import {{ {} }} from '{}';
", import.name, module));
}
for &(method, ref function) in import.functions.iter() {
self.generate_import_struct_function(&import.name,
method,
function);
}
}
fn generate_import_struct_function(
&mut self,
class: &str,
is_method: bool,
function: &shared::Function,
) {
let delegate = if is_method {
format!("{}.prototype.{}.call", class, function.name)
} else {
format!("{}.{}", class, function.name)
};
self.gen_import_shim(&function.mangled_import_name(Some(class)),
&delegate,
function)
}
fn gen_import_shim(
&mut self,
shim_name: &str,
shim_delegate: &str,
import: &shared::Function,
) {
let mut dst = String::new();
dst.push_str(&format!("function {}(", shim_name));
let mut invocation = String::new();
for (i, arg) in import.arguments.iter().enumerate() {
@ -518,7 +562,7 @@ impl<'a> Js<'a> {
}
}
dst.push_str(")");
let invoc = format!("{}({})", imported_name, invocation);
let invoc = format!("{}({})", shim_delegate, invocation);
let invoc = match import.ret {
Some(shared::Type::Number) => invoc,
Some(shared::Type::Boolean) => format!("{} ? 1 : 0", invoc),
@ -571,12 +615,16 @@ impl<'a> Js<'a> {
// fixed upstream.
let program_import = self.program.imports
.iter()
.find(|&&(_, ref f)| f.name == import.field());
if program_import.is_some() {
.any(|&(_, ref f)| f.mangled_import_name(None) == import.field());
let struct_import = self.program.imported_structs
.iter()
.flat_map(|s| s.functions.iter().map(move |f| (s, &f.1)))
.any(|(s, f)| f.mangled_import_name(Some(&s.name)) == import.field());
if program_import || struct_import {
import.module_mut().truncate(0);
import.module_mut().push_str("./");
import.module_mut().push_str(module_name);
import.field_mut().insert_str(0, "__wbg_import_");
continue
}
}
}

View File

@ -256,7 +256,7 @@ impl Function {
syn::Ident::from(generated_name)
}
fn shared(&self) -> shared::Function {
pub fn shared(&self) -> shared::Function {
shared::Function {
name: self.name.as_ref().to_string(),
arguments: self.arguments.iter().map(|t| t.shared()).collect(),

View File

@ -429,10 +429,9 @@ impl ToTokens for Receiver {
}
fn bindgen_import(import: &ast::Import, tokens: &mut Tokens) {
bindgen_import_function(&import.function,
&import.function.ident.to_string(),
Some(&import.module),
tokens);
let import_name = import.function.wasm_function.shared()
.mangled_import_name(None);
bindgen_import_function(&import.function, &import_name, tokens);
}
fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
@ -446,12 +445,9 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
let mut methods = Tokens::new();
for &(_is_method, ref f) in import.functions.iter() {
let import_name = format!("__wbg_{}_{}", name, f.ident);
bindgen_import_function(f,
&import_name,
import.module.as_ref().map(|s| &**s),
&mut methods);
let import_name = f.wasm_function.shared()
.mangled_import_name(Some(&import.name.to_string()));
bindgen_import_function(f, &import_name, &mut methods);
}
(my_quote! {
@ -463,7 +459,6 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
fn bindgen_import_function(import: &ast::ImportFunction,
import_name: &str,
_import_module: Option<&str>,
tokens: &mut Tokens) {
let vis = &import.rust_vis;
let ret = &import.rust_decl.output;

View File

@ -61,6 +61,13 @@ impl Function {
name.push_str(&self.name);
return name
}
pub fn mangled_import_name(&self, struct_: Option<&str>) -> String {
match struct_ {
Some(s) => format!("__wbg_s_{}_{}", s, self.name),
None => format!("__wbg_f_{}", self.name),
}
}
}
#[derive(Serialize, Deserialize)]

View File

@ -13,18 +13,112 @@ fn simple() {
wasm_bindgen! {
extern struct Math {
fn random() -> f64;
fn log(a: f64) -> f64;
}
pub fn get_random() -> f64 {
Math::random()
}
pub fn do_log(a: f64) -> f64 {
Math::log(a)
}
}
"#)
.file("test.ts", r#"
import * as wasm from "./out";
import * as assert from "assert";
export function test() {
wasm.get_random();
assert.strictEqual(wasm.do_log(1.0), Math.log(1.0));
}
"#)
.test();
}
#[test]
fn import_class() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
wasm_bindgen! {
#[wasm_module = "./test"]
extern struct Foo {
fn bar();
}
pub fn bar() {
Foo::bar();
}
}
"#)
.file("test.ts", r#"
import * as wasm from "./out";
import * as assert from "assert";
let called = false;
export class Foo {
static bar() {
called = true;
}
}
export function test() {
wasm.bar();
assert.strictEqual(called, true);
}
"#)
.test();
}
#[test]
fn construct() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
wasm_bindgen! {
#[wasm_module = "./test"]
extern struct Foo {
fn create() -> Foo;
fn doit(&self);
}
pub fn bar() {
let foo = Foo::bar();
}
}
"#)
.file("test.ts", r#"
import * as wasm from "./out";
import * as assert from "assert";
let called = false;
export class Foo {
static create() {
return new Foo();
}
doit() {
called = true;
}
}
export function test() {
wasm.bar();
assert.strictEqual(called, true);
}
"#)
.test();