diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 57387b2de93..12469d150dd 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -222,6 +222,7 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte .map(|arg| (&*arg.name, &*arg.type_, arg.variadic)), Some(self_ty), kind, + false, ).map(|function| { program.imports.push(backend::ast::Import { module: None, @@ -320,12 +321,14 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute { return Ok(()); } - create_getter(&self.name, &self.type_, self_name, false) + let is_structural = util::is_structural(&self.extended_attributes); + + create_getter(&self.name, &self.type_, self_name, false, is_structural) .map(wrap_import_function) .map(|import| program.imports.push(import)); if !self.read_only { - create_setter(&self.name, &self.type_, self_name, false) + create_setter(&self.name, &self.type_, self_name, false, is_structural) .map(wrap_import_function) .map(|import| program.imports.push(import)); } @@ -340,12 +343,14 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::StaticAttribute { return Ok(()); } - create_getter(&self.name, &self.type_, self_name, true) + let is_structural = util::is_structural(&self.extended_attributes); + + create_getter(&self.name, &self.type_, self_name, true, is_structural) .map(wrap_import_function) .map(|import| program.imports.push(import)); if !self.read_only { - create_setter(&self.name, &self.type_, self_name, true) + create_setter(&self.name, &self.type_, self_name, true, is_structural) .map(wrap_import_function) .map(|import| program.imports.push(import)); } diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index b79445dbb23..480aba66cd6 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -151,6 +151,7 @@ pub fn create_function<'a, I>( arguments: I, ret: Option, kind: backend::ast::ImportFunctionKind, + structural: bool, ) -> Option where I: Iterator, @@ -184,7 +185,7 @@ where rust_name, js_ret, catch: false, - structural: false, + structural, kind, shim, }) @@ -233,6 +234,7 @@ pub fn create_basic_method( .map(|arg| (&*arg.name, &*arg.type_, arg.variadic)), ret, kind, + false, ) } @@ -241,6 +243,7 @@ pub fn create_getter( ty: &webidl::ast::Type, self_name: &str, is_static: bool, + is_structural: bool, ) -> Option { let ret = match webidl_ty_to_syn_ty(ty, TypePosition::Return) { None => { @@ -259,7 +262,7 @@ pub fn create_getter( }), }; - create_function(name, iter::empty(), ret, kind) + create_function(name, iter::empty(), ret, kind, is_structural) } pub fn create_setter( @@ -267,6 +270,7 @@ pub fn create_setter( ty: &webidl::ast::Type, self_name: &str, is_static: bool, + is_structural: bool, ) -> Option { let kind = backend::ast::ImportFunctionKind::Method { class: self_name.to_string(), @@ -282,6 +286,7 @@ pub fn create_setter( iter::once((name, ty, false)), None, kind, + is_structural, ) } @@ -289,29 +294,24 @@ pub fn create_setter( pub fn is_chrome_only(ext_attrs: &[Box]) -> bool { ext_attrs.iter().any(|external_attribute| { return match &**external_attribute { - ExtendedAttribute::ArgumentList(al) => { - println!("ArgumentList"); - al.name == "ChromeOnly" - } - ExtendedAttribute::Identifier(i) => { - println!("Identifier"); - i.lhs == "ChromeOnly" - } - ExtendedAttribute::IdentifierList(il) => { - println!("IdentifierList"); - il.lhs == "ChromeOnly" - } - ExtendedAttribute::NamedArgumentList(nal) => { - println!("NamedArgumentList"); - nal.lhs_name == "ChromeOnly" - } + ExtendedAttribute::ArgumentList(al) => al.name == "ChromeOnly", + ExtendedAttribute::Identifier(i) => i.lhs == "ChromeOnly", + ExtendedAttribute::IdentifierList(il) => il.lhs == "ChromeOnly", + ExtendedAttribute::NamedArgumentList(nal) => nal.lhs_name == "ChromeOnly", ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name)) => { name == "ChromeOnly" } - ExtendedAttribute::NoArguments(_na) => { - println!("NoArguments"); - false - } + ExtendedAttribute::NoArguments(_na) => false, }; }) } + +pub fn is_structural(attrs: &[Box]) -> bool { + attrs.iter().any(|attr| { + if let ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(ref name)) = **attr { + name == "Unforgeable" + } else { + false + } + }) +} diff --git a/tests/all/webidl/simple.rs b/tests/all/webidl/simple.rs index f833b70b0f7..7263753361e 100644 --- a/tests/all/webidl/simple.rs +++ b/tests/all/webidl/simple.rs @@ -324,3 +324,49 @@ fn one_method_using_an_undefined_import_doesnt_break_all_other_methods() { ) .test(); } + +#[test] +fn unforgeable_is_structural() { + project() + .file( + "foo.webidl", + r#" + [Constructor()] + interface Foo { + [Unforgeable] readonly attribute short uno; + readonly attribute short dos; + }; + "#, + ) + .file( + "foo.js", + r#" + export class Foo { + constructor() { + this.uno = 1; + } + get dos() { + return 2; + } + } + "#, + ) + .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; + + #[wasm_bindgen] + pub fn test() { + let f = foo::Foo::new(); + assert_eq!(f.uno(), 1); + assert_eq!(f.dos(), 2); + } + "#, + ) + .test(); +}