From f45ce1f2396ab6558bc1e41303e5e3d5796b3c39 Mon Sep 17 00:00:00 2001 From: konstin Date: Sun, 15 Apr 2018 01:29:09 +0200 Subject: [PATCH] Do only use ConstructorToken when needed Also removing some effectively dead code --- crates/backend/src/ast.rs | 12 +----- crates/cli-support/src/js.rs | 75 ++++++++++++++++++++---------------- tests/all/classes.rs | 9 ++++- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index ed759eff..a725447c 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -203,7 +203,7 @@ impl Program { panic!("can only bindgen safe functions"); } - let mut opts = BindgenAttrs::find(&mut method.attrs); + let opts = BindgenAttrs::find(&mut method.attrs); let is_constructor = opts.constructor(); let constructor = if is_constructor { Some(method.sig.ident.to_string()) @@ -211,16 +211,6 @@ impl Program { None }; - if is_constructor { - let pos = opts.attrs - .iter() - .enumerate() - .find(|(_, a)| **a == BindgenAttr::Constructor) - .unwrap() - .0; - opts.attrs.remove(pos); - } - let (function, mutable) = Function::from_decl( method.sig.ident, Box::new(method.sig.decl.clone()), diff --git a/crates/cli-support/src/js.rs b/crates/cli-support/src/js.rs index a92a9143..5959dd93 100644 --- a/crates/cli-support/src/js.rs +++ b/crates/cli-support/src/js.rs @@ -318,41 +318,56 @@ impl<'a> Context<'a> { public ptr: number; "); - self.expose_constructor_token(); - - dst.push_str(&format!(" - constructor(...args) {{ - if (args.length === 1 && args[0] instanceof ConstructorToken) {{ - this.ptr = args[0].ptr; - return; - }} - ")); - - if let Some(constructor) = exports.constructor { - ts_dst.push_str(&format!("constructor(...args: [any] | [ConstructorToken]);\n")); + if self.config.debug || exports.constructor.is_some() { + self.expose_constructor_token(); dst.push_str(&format!(" - // This invocation of new will call this constructor with a ConstructorToken - let instance = {class}.{constructor}(...args); - this.ptr = instance.ptr; - ", class = class, constructor = constructor)); - } else { - ts_dst.push_str(&format!("constructor(...args: [ConstructorToken]);\n")); + static __construct(ptr) {{ + return new {}(new ConstructorToken(ptr)); + }} - dst.push_str("throw new Error('you cannot invoke `new` directly without having a \ + constructor(...args) {{ + if (args.length === 1 && args[0] instanceof ConstructorToken) {{ + this.ptr = args[0].ptr; + return; + }} + ", class)); + + if let Some(constructor) = exports.constructor { + ts_dst.push_str(&format!("constructor(...args: [any]);\n")); + + dst.push_str(&format!(" + // This invocation of new will call this constructor with a ConstructorToken + let instance = {class}.{constructor}(...args); + this.ptr = instance.ptr; + ", class = class, constructor = constructor)); + } else { + dst.push_str("throw new Error('you cannot invoke `new` directly without having a \ method annotated a constructor');"); - } + } - dst.push_str("}"); + dst.push_str("}"); + } else { + dst.push_str(&format!(" + static __construct(ptr) {{ + return new {}(ptr); + }} + + constructor(ptr) {{ + this.ptr = ptr; + }} + ", class)); + } let new_name = shared::new_function(&class); if self.wasm_import_needed(&new_name) { self.expose_add_heap_object(); + self.export(&new_name, &format!(" function(ptr) {{ - return addHeapObject(new {class}(new ConstructorToken(ptr))); + return addHeapObject({}.__construct(ptr)); }} - ", class = class)); + ", class)); } dst.push_str(&format!(" @@ -765,13 +780,6 @@ impl<'a> Context<'a> { } } "); - - self.typescript.push_str(" - class ConstructorToken { - constructor(ptr: number); - } - "); - } fn expose_get_string_from_wasm(&mut self) { @@ -1245,7 +1253,8 @@ impl<'a> Context<'a> { if let Some(name) = ty.rust_struct() { dst_ts.push_str(": "); dst_ts.push_str(name); - return format!("return new {name}(new ConstructorToken(ret));", name = name); + + return format!("return {}.__construct(ret)",&name); } if ty.is_number() { @@ -1575,11 +1584,11 @@ impl<'a, 'b> SubContext<'a, 'b> { continue } - if let Some(s) = arg.rust_struct() { + if let Some(class) = arg.rust_struct() { if arg.is_by_ref() { panic!("cannot invoke JS functions with custom ref types yet") } - let assign = format!("let c{0} = new {class}(new ConstructorToken(arg{0}));", i, class = s); + let assign = format!("let c{0} = {1}.__construct(arg{0});", i, class); extra.push_str(&assign); invoc_args.push(format!("c{}", i)); continue diff --git a/tests/all/classes.rs b/tests/all/classes.rs index 10088f4c..ad3b181c 100644 --- a/tests/all/classes.rs +++ b/tests/all/classes.rs @@ -379,6 +379,11 @@ fn constructors() { use wasm_bindgen::prelude::*; + #[wasm_bindgen] + pub fn cross_item_construction() -> Bar { + Bar::other_name(7, 8) + } + #[wasm_bindgen] pub struct Foo { number: u32, @@ -416,7 +421,7 @@ fn constructors() { "#) .file("test.ts", r#" import * as assert from "assert"; - import { Foo, Bar } from "./out"; + import { Foo, Bar, cross_item_construction } from "./out"; export function test() { const foo = new Foo(1); @@ -434,6 +439,8 @@ fn constructors() { const bar2 = Bar.other_name(5, 6); assert.strictEqual(bar2.get_sum(), 11); bar2.free(); + + assert.strictEqual(cross_item_construction().get_sum(), 15); } "#) .test();