diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index b78e52a0..04f409cc 100755 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -182,10 +182,10 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte program: &mut backend::ast::Program, interface: &'a webidl::ast::NonPartialInterface, ) -> Result<()> { - let mut add_constructor = |arguments: &[webidl::ast::Argument]| { + let mut add_constructor = |arguments: &[webidl::ast::Argument], class: &str| { let self_ty = ident_ty(rust_ident(&interface.name)); let kind = backend::ast::ImportFunctionKind::JsConstructor { - class: interface.name.to_string(), + class: class.to_string(), ty: self_ty.clone(), }; create_function( @@ -211,12 +211,22 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte webidl::ast::ArgumentListExtendedAttribute { arguments, name }, ) if name == "Constructor" => { - add_constructor(&*arguments); + add_constructor(arguments, &interface.name); } webidl::ast::ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) if name == "Constructor" => { - add_constructor(&[] as &[_]); + add_constructor(&[] as &[_], &interface.name); + } + webidl::ast::ExtendedAttribute::NamedArgumentList( + webidl::ast::NamedArgumentListExtendedAttribute { + lhs_name, + rhs_arguments, + rhs_name, + }, + ) if lhs_name == "NamedConstructor" => + { + add_constructor(rhs_arguments, rhs_name); } webidl::ast::ExtendedAttribute::ArgumentList(_) | webidl::ast::ExtendedAttribute::Identifier(_) diff --git a/tests/all/webidl/simple.rs b/tests/all/webidl/simple.rs index 7b67d6cc..767f25d6 100644 --- a/tests/all/webidl/simple.rs +++ b/tests/all/webidl/simple.rs @@ -118,3 +118,61 @@ fn property() { ) .test(); } + +#[test] +fn named_constructor() { + project() + .file( + "foo.webidl", + r#" + [NamedConstructor=Bar(double value)] + interface Foo { + [Pure] + readonly attribute double value; + }; + "#, + ) + .file( + // Not a perfect test, but it gets the job done. + "foo.ts", + r#" + export class Foo { + protected _value: number = 0; + get value(): number { + return this._value; + } + } + + export class Bar extends Foo { + constructor(_value: number) { + super(); + this._value = _value; + } + } + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(proc_macro, wasm_custom_section, wasm_import_module)] + + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + pub mod foo; + + use foo::Foo; + + #[wasm_bindgen] + pub fn test() { + let x = Foo::new(3.14159); + let tmp = x.value() == 3.14159; + assert!(tmp); + let tmp = x.value() != 0.; + assert!(tmp); + } + "#, + ) + .test(); +}