From be368a6570117c2fef3f7d82d75d52581ae8dd18 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Feb 2018 12:51:58 -0800 Subject: [PATCH] Don't look up properties in import shims This'll match more closely what wasm eventually does natively, which is importing these functions directly and not allowing changing them over time. Closes #25 --- crates/wasm-bindgen-cli-support/src/js.rs | 14 ++-- tests/import-class.rs | 79 +++++++++++++++++++++++ 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/crates/wasm-bindgen-cli-support/src/js.rs b/crates/wasm-bindgen-cli-support/src/js.rs index a94001b0..8c304f3b 100644 --- a/crates/wasm-bindgen-cli-support/src/js.rs +++ b/crates/wasm-bindgen-cli-support/src/js.rs @@ -955,18 +955,24 @@ impl<'a, 'b> SubContext<'a, 'b> { } let invoc_args = invoc_args.join(", "); - let name = &import.function.name; + let function_name = &import.function.name; let invoc = match import.class { Some(ref class) if import.method => { - format!("{}.prototype.{}.call({})", class, name, invoc_args) + self.cx.globals.push_str(&format!(" + const {}_target = {}.prototype.{}; + ", name, class, function_name)); + format!("{}_target.call({})", name, invoc_args) } Some(ref class) if import.js_new => { format!("new {}({})", class, invoc_args) } Some(ref class) => { - format!("{}.{}({})", class, name, invoc_args) + self.cx.globals.push_str(&format!(" + const {}_target = {}.{}; + ", name, class, function_name)); + format!("{}_target({})", name, invoc_args) } - None => format!("{}({})", name, invoc_args), + None => format!("{}({})", function_name, invoc_args), }; let invoc = match import.function.ret { Some(shared::TYPE_NUMBER) => format!("return {};", invoc), diff --git a/tests/import-class.rs b/tests/import-class.rs index 6a6d801a..19606383 100644 --- a/tests/import-class.rs +++ b/tests/import-class.rs @@ -199,3 +199,82 @@ fn new_constructors() { "#) .test(); } + +#[test] +fn switch_methods() { + test_support::project() + .file("src/lib.rs", r#" + #![feature(proc_macro)] + + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + #[wasm_bindgen(module = "./test")] + extern { + type Foo; + + #[wasm_bindgen(constructor)] + fn new() -> Foo; + + #[wasm_bindgen(static = Foo)] + fn a(); + + #[wasm_bindgen(method)] + fn b(this: &Foo); + } + + #[wasm_bindgen] + #[no_mangle] + pub extern fn a() { + Foo::a(); + } + + #[wasm_bindgen] + #[no_mangle] + pub extern fn b() { + Foo::new().b(); + } + "#) + .file("test.ts", r#" + import { a, b } from "./out"; + import * as assert from "assert"; + + let called = false; + + export class Foo { + constructor() { + } + + static a() { + called = true; + } + + b() { + called = true; + } + } + + export function test() { + assert.strictEqual(called, false); + a(); + assert.strictEqual(called, true); + called = false; + Foo.a = function() {}; + assert.strictEqual(called, false); + a(); + assert.strictEqual(called, true); + + called = false; + assert.strictEqual(called, false); + b(); + assert.strictEqual(called, true); + called = false; + Foo.prototype.b = function() {}; + assert.strictEqual(called, false); + b(); + assert.strictEqual(called, true); + } + "#) + .test(); +}