mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-17 02:30:50 +00:00
Handle [Unforgeable] on interfaces
In addition to handling it on methods look like it also shows up on interfaces! Closes #780
This commit is contained in:
parent
986f561209
commit
cfb4be8d3c
56
crates/web-sys/tests/wasm/location.rs
Normal file
56
crates/web-sys/tests/wasm/location.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use wasm_bindgen_test::*;
|
||||
use web_sys::Window;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn href() {
|
||||
let loc = Window::location();
|
||||
loc.href().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn origin() {
|
||||
let loc = Window::location();
|
||||
loc.origin().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn protocol() {
|
||||
let loc = Window::location();
|
||||
loc.protocol().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn host() {
|
||||
let loc = Window::location();
|
||||
loc.host().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn hostname() {
|
||||
let loc = Window::location();
|
||||
loc.hostname().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn port() {
|
||||
let loc = Window::location();
|
||||
loc.port().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn pathname() {
|
||||
let loc = Window::location();
|
||||
loc.pathname().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn search() {
|
||||
let loc = Window::location();
|
||||
loc.search().unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn hash() {
|
||||
let loc = Window::location();
|
||||
loc.hash().unwrap();
|
||||
}
|
@ -52,3 +52,4 @@ pub mod title_element;
|
||||
pub mod xpath_result;
|
||||
pub mod dom_point;
|
||||
pub mod performance;
|
||||
pub mod location;
|
||||
|
@ -44,7 +44,7 @@ pub(crate) struct InterfaceData<'src> {
|
||||
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
||||
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||
pub(crate) superclass: Option<&'src str>,
|
||||
pub(crate) definition_attributes: Option<&'src [ExtendedAttribute<'src>]>,
|
||||
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
||||
}
|
||||
|
||||
/// We need to collect mixin data during the first pass, to be used later.
|
||||
@ -55,6 +55,7 @@ pub(crate) struct MixinData<'src> {
|
||||
pub(crate) attributes: Vec<&'src AttributeMixinMember<'src>>,
|
||||
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
||||
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
||||
}
|
||||
|
||||
/// We need to collect namespace data during the first pass, to be used later.
|
||||
@ -300,8 +301,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
||||
.or_default();
|
||||
interface_data.partial = false;
|
||||
interface_data.superclass = self.inheritance.map(|s| s.identifier.0);
|
||||
interface_data.definition_attributes = self.attributes.as_ref()
|
||||
.map(|l| &l.body.list[..]);
|
||||
interface_data.definition_attributes = self.attributes.as_ref();
|
||||
}
|
||||
if let Some(attrs) = &self.attributes {
|
||||
for attr in attrs.body.list.iter() {
|
||||
@ -510,6 +510,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{
|
||||
.entry(self.identifier.0)
|
||||
.or_default();
|
||||
mixin_data.partial = false;
|
||||
mixin_data.definition_attributes = self.attributes.as_ref();
|
||||
}
|
||||
|
||||
for member in &self.members.body {
|
||||
|
@ -330,7 +330,7 @@ impl<'src> FirstPassRecord<'src> {
|
||||
);
|
||||
|
||||
let kind = backend::ast::ImportFunctionKind::Normal;
|
||||
for mut import_function in self.create_imports(kind, id, data) {
|
||||
for mut import_function in self.create_imports(None, kind, id, data) {
|
||||
import_function.doc_comment = Some(doc_comment.clone());
|
||||
module.imports.push(
|
||||
backend::ast::Import {
|
||||
@ -413,11 +413,12 @@ impl<'src> FirstPassRecord<'src> {
|
||||
self.member_attribute(
|
||||
program,
|
||||
name,
|
||||
&member.attributes,
|
||||
member.modifier,
|
||||
member.readonly.is_some(),
|
||||
&member.type_,
|
||||
member.identifier.0,
|
||||
&member.attributes,
|
||||
data.definition_attributes,
|
||||
);
|
||||
}
|
||||
|
||||
@ -432,7 +433,6 @@ impl<'src> FirstPassRecord<'src> {
|
||||
self.member_attribute(
|
||||
program,
|
||||
name,
|
||||
&member.attributes,
|
||||
if let Some(s) = member.stringifier {
|
||||
Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s))
|
||||
} else {
|
||||
@ -441,6 +441,8 @@ impl<'src> FirstPassRecord<'src> {
|
||||
member.readonly.is_some(),
|
||||
&member.type_,
|
||||
member.identifier.0,
|
||||
&member.attributes,
|
||||
mixin_data.definition_attributes,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -450,11 +452,12 @@ impl<'src> FirstPassRecord<'src> {
|
||||
&self,
|
||||
program: &mut backend::ast::Program,
|
||||
self_name: &'src str,
|
||||
attrs: &'src Option<ExtendedAttributeList>,
|
||||
modifier: Option<weedle::interface::StringifierOrInheritOrStatic>,
|
||||
readonly: bool,
|
||||
type_: &'src weedle::types::AttributedType<'src>,
|
||||
identifier: &'src str,
|
||||
attrs: &'src Option<ExtendedAttributeList<'src>>,
|
||||
container_attrs: Option<&'src ExtendedAttributeList<'src>>,
|
||||
) {
|
||||
use weedle::interface::StringifierOrInheritOrStatic::*;
|
||||
|
||||
@ -465,8 +468,6 @@ impl<'src> FirstPassRecord<'src> {
|
||||
None => false,
|
||||
};
|
||||
|
||||
let is_structural = util::is_structural(attrs);
|
||||
let throws = util::throws(attrs);
|
||||
let global = self
|
||||
.interfaces
|
||||
.get(self_name)
|
||||
@ -478,9 +479,9 @@ impl<'src> FirstPassRecord<'src> {
|
||||
&type_.type_,
|
||||
self_name,
|
||||
is_static,
|
||||
is_structural,
|
||||
throws,
|
||||
global,
|
||||
attrs,
|
||||
container_attrs,
|
||||
) {
|
||||
program.imports.push(wrap_import_function(import_function));
|
||||
}
|
||||
@ -488,12 +489,12 @@ impl<'src> FirstPassRecord<'src> {
|
||||
if !readonly {
|
||||
for import_function in self.create_setter(
|
||||
identifier,
|
||||
type_.type_.clone(),
|
||||
&type_.type_,
|
||||
self_name,
|
||||
is_static,
|
||||
is_structural,
|
||||
throws,
|
||||
global,
|
||||
attrs,
|
||||
container_attrs,
|
||||
) {
|
||||
program.imports.push(wrap_import_function(import_function));
|
||||
}
|
||||
@ -533,7 +534,8 @@ impl<'src> FirstPassRecord<'src> {
|
||||
import_function_kind(backend::ast::OperationKind::IndexingDeleter)
|
||||
}
|
||||
};
|
||||
for method in self.create_imports(kind, id, op_data) {
|
||||
let attrs = data.definition_attributes;
|
||||
for method in self.create_imports(attrs, kind, id, op_data) {
|
||||
program.imports.push(wrap_import_function(method));
|
||||
}
|
||||
}
|
||||
|
@ -299,9 +299,9 @@ impl<'src> FirstPassRecord<'src> {
|
||||
ty: &weedle::types::Type<'src>,
|
||||
self_name: &str,
|
||||
is_static: bool,
|
||||
is_structural: bool,
|
||||
catch: bool,
|
||||
global: bool,
|
||||
attrs: &Option<ExtendedAttributeList>,
|
||||
container_attrs: Option<&ExtendedAttributeList>,
|
||||
) -> Option<backend::ast::ImportFunction> {
|
||||
let kind = backend::ast::OperationKind::Getter(Some(raw_ident(name)));
|
||||
let kind = self.import_function_kind(self_name, global, is_static, kind);
|
||||
@ -312,8 +312,8 @@ impl<'src> FirstPassRecord<'src> {
|
||||
None.into_iter(),
|
||||
&ret,
|
||||
kind,
|
||||
is_structural,
|
||||
catch,
|
||||
is_structural(attrs.as_ref(), container_attrs),
|
||||
throws(attrs),
|
||||
Some(format!("The `{}` getter\n\n{}", name, mdn_doc(self_name, Some(name))))
|
||||
)
|
||||
}
|
||||
@ -322,12 +322,12 @@ impl<'src> FirstPassRecord<'src> {
|
||||
pub fn create_setter(
|
||||
&self,
|
||||
name: &str,
|
||||
field_ty: weedle::types::Type<'src>,
|
||||
field_ty: &weedle::types::Type<'src>,
|
||||
self_name: &str,
|
||||
is_static: bool,
|
||||
is_structural: bool,
|
||||
catch: bool,
|
||||
global: bool,
|
||||
attrs: &Option<ExtendedAttributeList>,
|
||||
container_attrs: Option<&ExtendedAttributeList>,
|
||||
) -> Option<backend::ast::ImportFunction> {
|
||||
let kind = backend::ast::OperationKind::Setter(Some(raw_ident(name)));
|
||||
let kind = self.import_function_kind(self_name, global, is_static, kind);
|
||||
@ -338,8 +338,8 @@ impl<'src> FirstPassRecord<'src> {
|
||||
Some((name, &field_ty)).into_iter(),
|
||||
&IdlType::Void,
|
||||
kind,
|
||||
is_structural,
|
||||
catch,
|
||||
is_structural(attrs.as_ref(), container_attrs),
|
||||
throws(attrs),
|
||||
Some(format!("The `{}` setter\n\n{}", name, mdn_doc(self_name, Some(name))))
|
||||
)
|
||||
}
|
||||
@ -372,6 +372,7 @@ impl<'src> FirstPassRecord<'src> {
|
||||
|
||||
pub fn create_imports(
|
||||
&self,
|
||||
container_attrs: Option<&ExtendedAttributeList<'src>>,
|
||||
kind: backend::ast::ImportFunctionKind,
|
||||
id: &OperationId<'src>,
|
||||
data: &OperationData<'src>,
|
||||
@ -552,7 +553,7 @@ impl<'src> FirstPassRecord<'src> {
|
||||
.map(|(ty, orig_arg)| (orig_arg.name, ty)),
|
||||
&ret_ty,
|
||||
kind.clone(),
|
||||
force_structural || is_structural(&signature.orig.attrs),
|
||||
force_structural || is_structural(signature.orig.attrs.as_ref(), container_attrs),
|
||||
force_throws || throws(&signature.orig.attrs),
|
||||
None,
|
||||
));
|
||||
@ -562,7 +563,7 @@ impl<'src> FirstPassRecord<'src> {
|
||||
}
|
||||
|
||||
/// Search for an attribute by name in some webidl object's attributes.
|
||||
fn has_named_attribute(list: &Option<ExtendedAttributeList>, attribute: &str) -> bool {
|
||||
fn has_named_attribute(list: Option<&ExtendedAttributeList>, attribute: &str) -> bool {
|
||||
let list = match list {
|
||||
Some(list) => list,
|
||||
None => return false,
|
||||
@ -575,22 +576,26 @@ fn has_named_attribute(list: &Option<ExtendedAttributeList>, attribute: &str) ->
|
||||
|
||||
/// ChromeOnly is for things that are only exposed to privileged code in Firefox.
|
||||
pub fn is_chrome_only(ext_attrs: &Option<ExtendedAttributeList>) -> bool {
|
||||
has_named_attribute(ext_attrs, "ChromeOnly")
|
||||
has_named_attribute(ext_attrs.as_ref(), "ChromeOnly")
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as a no interface object.
|
||||
pub fn is_no_interface_object(ext_attrs: &Option<ExtendedAttributeList>) -> bool {
|
||||
has_named_attribute(ext_attrs, "NoInterfaceObject")
|
||||
has_named_attribute(ext_attrs.as_ref(), "NoInterfaceObject")
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as structural.
|
||||
pub fn is_structural(attrs: &Option<ExtendedAttributeList>) -> bool {
|
||||
has_named_attribute(attrs, "Unforgeable")
|
||||
pub fn is_structural(
|
||||
item_attrs: Option<&ExtendedAttributeList>,
|
||||
container_attrs: Option<&ExtendedAttributeList>,
|
||||
) -> bool {
|
||||
has_named_attribute(item_attrs, "Unforgeable") ||
|
||||
has_named_attribute(container_attrs, "Unforgeable")
|
||||
}
|
||||
|
||||
/// Whether a webidl object is marked as throwing.
|
||||
pub fn throws(attrs: &Option<ExtendedAttributeList>) -> bool {
|
||||
has_named_attribute(attrs, "Throws")
|
||||
has_named_attribute(attrs.as_ref(), "Throws")
|
||||
}
|
||||
|
||||
/// Create a syn `pub` token
|
||||
|
Loading…
x
Reference in New Issue
Block a user