diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index b0aa321ff2d..0e05685b3f8 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -517,6 +517,10 @@ impl ToTokens for ast::ImportType { fn none() -> Self::Abi { 0 } } + impl<'a> ::wasm_bindgen::convert::OptionIntoWasmAbi for &'a #name { + fn none() -> Self::Abi { 0 } + } + impl ::wasm_bindgen::convert::FromWasmAbi for #name { type Abi = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi>::Abi; diff --git a/crates/backend/src/defined.rs b/crates/backend/src/defined.rs index 1fcbe740952..7d94387154c 100644 --- a/crates/backend/src/defined.rs +++ b/crates/backend/src/defined.rs @@ -10,6 +10,20 @@ pub enum ImportedTypeKind { Reference, } +impl ImportedTypes for Option +where + T: ImportedTypes, +{ + fn imported_types(&self, f: &mut F) + where + F: FnMut(&Ident, ImportedTypeKind), + { + if let Some(inner) = self { + inner.imported_types(f); + } + } +} + /// Iterate over definitions of and references to imported types in the AST. pub trait ImportedTypes { fn imported_types(&self, f: &mut F) @@ -147,19 +161,74 @@ impl ImportedTypes for syn::TypePath { where F: FnMut(&Ident, ImportedTypeKind), { - if self.qself.is_some() - || self.path.leading_colon.is_some() - || self.path.segments.len() != 1 - { - return; + self.qself.imported_types(f); + self.path.imported_types(f); + } +} + +impl ImportedTypes for syn::QSelf { + fn imported_types(&self, _: &mut F) + where + F: FnMut(&Ident, ImportedTypeKind), + { + // TODO + } +} + +impl ImportedTypes for syn::Path { + fn imported_types(&self, f: &mut F) + where + F: FnMut(&Ident, ImportedTypeKind), + { + for seg in self.segments.iter() { + seg.arguments.imported_types(f); } f( - &self.path.segments.last().unwrap().value().ident, + &self.segments.last().unwrap().value().ident, ImportedTypeKind::Reference, ); } } +impl ImportedTypes for syn::PathArguments { + fn imported_types(&self, f: &mut F) + where + F: FnMut(&Ident, ImportedTypeKind), + { + match self { + syn::PathArguments::AngleBracketed(data) => { + for arg in data.args.iter() { + arg.imported_types(f); + } + } +//TOCHECK + syn::PathArguments::Parenthesized(data) => { + for input in data.inputs.iter() { + input.imported_types(f); + } + // TODO do we need to handle output here? + // https://docs.rs/syn/0.14.0/syn/struct.ParenthesizedGenericArguments.html + } + syn::PathArguments::None => {} + } + } +} + +impl ImportedTypes for syn::GenericArgument { + fn imported_types(&self, f: &mut F) + where + F: FnMut(&Ident, ImportedTypeKind), + { + match self { + syn::GenericArgument::Lifetime(_) => {} + syn::GenericArgument::Type(ty) => ty.imported_types(f), + syn::GenericArgument::Binding(_) => {}, // TODO + syn::GenericArgument::Const(_) => {}, // TODO + } + } +} + + impl ImportedTypes for ast::ImportFunction { fn imported_types(&self, f: &mut F) where diff --git a/crates/web-sys/tests/all/element.rs b/crates/web-sys/tests/all/element.rs index 2bf44f15ef6..79781343727 100644 --- a/crates/web-sys/tests/all/element.rs +++ b/crates/web-sys/tests/all/element.rs @@ -13,7 +13,11 @@ fn element() { #[wasm_bindgen] pub fn test_element(element: &web_sys::Element) { - assert_eq!(element.local_name(), "div", "Shouldn't have a div local name"); +/* Tests needed for: + namespace_uri +*/ + assert_eq!(element.prefix(), None, "Shouldn't have a prefix"); + assert_eq!(element.local_name(), "div", "Should have a div local name"); assert_eq!(element.tag_name(), "div", "Should be a div tag"); assert!(!element.has_attribute("id"), "Shouldn't have an id"); element.set_id("beep"); @@ -27,7 +31,11 @@ fn element() { assert_eq!(element.class_name(), "", "Shouldn't have a class name"); element.set_class_name("test thing"); assert_eq!(element.class_name(), "test thing", "Should have a class name"); + assert_eq!(element.get_attribute("class").unwrap(), "test thing", "Should have a class name"); assert_eq!(element.remove_attribute("class").unwrap(), (), "Should return nothing if removed"); +/* Tests needed for: + get_attribute_ns +*/ /*TODO should we enable toggle_attribute tests? (Firefox Nightly + Chrome canary only) // TODO toggle_attribute should permit a single argument when optional arguments are supported @@ -44,11 +52,19 @@ fn element() { // TODO check get_attribute here when supported assert_eq!(element.remove_attribute("title").unwrap(), (), "Should return nothing if removed"); assert!(!element.has_attribute("title"), "Should not have a title"); +/* Tests needed for: + set_attribute_ns +*/ assert!(!element.has_attributes(), "Should not have any attributes"); assert_eq!(element.set_attribute("title", "boop").unwrap(), (), "Should return nothing if set correctly"); assert!(element.has_attributes(), "Should have attributes"); assert_eq!(element.remove_attribute("title").unwrap(), (), "Should return nothing if removed"); +/* Tests needed for: + remove_attribute_ns + has_attribure_ns + closest +*/ assert_eq!(element.matches(".this-is-a-thing").unwrap(), false, "Should not match selector"); assert_eq!(element.webkit_matches_selector(".this-is-a-thing").unwrap(), false, "Should not match selector"); @@ -57,15 +73,53 @@ fn element() { assert_eq!(element.webkit_matches_selector(".this-is-a-thing").unwrap(), true, "Should match selector"); assert_eq!(element.remove_attribute("class").unwrap(), (), "Should return nothing if removed"); - // TODO non standard moz_matches_selector should we even support? + /* Tests needed for: + insert_adjacent_element insert_adjacent_text set_pointer_capture release_pointer_capture has_pointer_capture set_capture release_capture + scroll_top + set_scroll_top + scroll_left + set_scroll_left + scroll_width + scroll_height + scroll, + scroll_to + scroll_by + client_top + client_left + client_width + client_height + scroll_top_max + scroll_left_max +*/ + assert_eq!(element.inner_html(), "", "Should return no content"); + element.set_inner_html("Hey!Web!"); + assert_eq!(element.inner_html(), "Hey!Web!", "Should return HTML conent"); + assert_eq!(element.query_selector_all("strong").unwrap().length(), 1, "Should return one element"); + assert!(element.query_selector("strong").unwrap().is_some(), "Should return an element"); + element.set_inner_html(""); + assert_eq!(element.inner_html(), "", "Should return no content"); + +/* Tests needed for: + outer_html + set_outer_html + insert_adjacent_html +*/ + + assert!(element.query_selector(".none-existant").unwrap().is_none(), "Should return no results"); + assert_eq!(element.query_selector_all(".none-existant").unwrap().length(), 0, "Should return no results"); +/* Tests needed for: + slot + set_slot + request_fullscreen + request_pointer_lock */ } "#, diff --git a/crates/web-sys/webidls/available/Document.webidl b/crates/web-sys/webidls/enabled/Document.webidl similarity index 98% rename from crates/web-sys/webidls/available/Document.webidl rename to crates/web-sys/webidls/enabled/Document.webidl index eaf8feae802..5266c3dffde 100644 --- a/crates/web-sys/webidls/available/Document.webidl +++ b/crates/web-sys/webidls/enabled/Document.webidl @@ -14,6 +14,7 @@ * https://drafts.csswg.org/cssom-view/#extensions-to-the-document-interface */ +/*TODO interface WindowProxy; interface nsISupports; interface URI; @@ -21,6 +22,7 @@ interface nsIDocShell; interface nsILoadGroup; enum VisibilityState { "hidden", "visible" }; +*/ /* https://dom.spec.whatwg.org/#dictdef-elementcreationoptions */ dictionary ElementCreationOptions { @@ -33,8 +35,11 @@ dictionary ElementCreationOptions { /* https://dom.spec.whatwg.org/#interface-document */ [Constructor] interface Document : Node { + +/*TODO [Throws] readonly attribute DOMImplementation implementation; +*/ [Pure, Throws, BinaryName="documentURIFromJS", NeedsCallerType] readonly attribute DOMString URL; [Pure, Throws, BinaryName="documentURIFromJS", NeedsCallerType] @@ -54,6 +59,7 @@ interface Document : Node { readonly attribute DocumentType? doctype; [Pure] readonly attribute Element? documentElement; + [Pure] HTMLCollection getElementsByTagName(DOMString localName); [Pure, Throws] @@ -73,8 +79,10 @@ interface Document : Node { Text createTextNode(DOMString data); [NewObject] Comment createComment(DOMString data); +/*TODO [NewObject, Throws] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data); +*/ [CEReactions, Throws] Node importNode(Node node, optional boolean deep = false); @@ -84,8 +92,10 @@ interface Document : Node { [NewObject, Throws, NeedsCallerType] Event createEvent(DOMString interface); +/*TODO [NewObject, Throws] Range createRange(); +*/ // NodeFilter.SHOW_ALL = 0xFFFFFFFF [NewObject, Throws] @@ -100,22 +110,26 @@ interface Document : Node { // These are not in the spec, but leave them for now for backwards compat. // So sort of like Gecko extensions +/*TODO [NewObject, Throws] CDATASection createCDATASection(DOMString data); [NewObject, Throws] Attr createAttribute(DOMString name); [NewObject, Throws] Attr createAttributeNS(DOMString? namespace, DOMString name); +*/ }; // https://html.spec.whatwg.org/multipage/dom.html#the-document-object partial interface Document { +/*TODO [PutForwards=href, Unforgeable] readonly attribute Location? location; //(HTML only) attribute DOMString domain; readonly attribute DOMString referrer; //(HTML only) attribute DOMString cookie; readonly attribute DOMString lastModified; readonly attribute DOMString readyState; +*/ // DOM tree accessors //(Not proxy yet)getter object (DOMString name); @@ -135,6 +149,7 @@ partial interface Document { [SameObject] readonly attribute HTMLCollection scripts; [Pure] NodeList getElementsByName(DOMString elementName); + //(Not implemented)readonly attribute DOMElementMap cssElementMap; // dynamic markup insertion @@ -174,7 +189,9 @@ partial interface Document { * True if this document is synthetic : stand alone image, video, audio file, * etc. */ +/*Non standard [Func="IsChromeOrXBL"] readonly attribute boolean mozSyntheticDocument; +*/ /** * Returns the script element whose script is currently being processed. * @@ -257,17 +274,23 @@ partial interface Document { // versions have it uppercase. [LenientSetter, Unscopable, Func="nsDocument::IsUnprefixedFullscreenEnabled"] readonly attribute boolean fullscreen; +/*Non standard [BinaryName="fullscreen"] readonly attribute boolean mozFullScreen; +*/ [LenientSetter, Func="nsDocument::IsUnprefixedFullscreenEnabled", NeedsCallerType] readonly attribute boolean fullscreenEnabled; +/*Non standard [BinaryName="fullscreenEnabled", NeedsCallerType] readonly attribute boolean mozFullScreenEnabled; +*/ [Func="nsDocument::IsUnprefixedFullscreenEnabled"] void exitFullscreen(); +/*Non standard [BinaryName="exitFullscreen"] void mozCancelFullScreen(); +*/ // Events handlers [Func="nsDocument::IsUnprefixedFullscreenEnabled"] @@ -289,8 +312,11 @@ partial interface Document { // https://w3c.github.io/page-visibility/#extensions-to-the-document-interface partial interface Document { readonly attribute boolean hidden; + +/*TODO readonly attribute VisibilityState visibilityState; attribute EventHandler onvisibilitychange; +*/ }; // https://drafts.csswg.org/cssom/#extensions-to-the-document-interface @@ -339,6 +365,7 @@ partial interface Document { partial interface Document { // XBL support. Wish we could make these [ChromeOnly], but // that would likely break bindings running with the page principal. +/*Non standard [Func="IsChromeOrXBL"] NodeList? getAnonymousNodes(Element elt); [Func="IsChromeOrXBL"] @@ -348,6 +375,7 @@ partial interface Document { Element? getBindingParent(Node node); [Throws, Func="IsChromeOrXBL", NeedsSubjectPrincipal] void loadBindingDocument(DOMString documentURL); +*/ // Touch bits // XXXbz I can't find the sane spec for this stuff, so just cribbing @@ -375,10 +403,12 @@ partial interface Document { // XXXbz and another hack for the fact that we can't usefully have optional // distinguishing arguments but need a working zero-arg form of // createTouchList(). +/*TODO [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"] TouchList createTouchList(); [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"] TouchList createTouchList(sequence touches); +*/ [ChromeOnly] attribute boolean styleSheetChangeEventsEnabled; @@ -458,8 +488,10 @@ partial interface Document { // http://w3c.github.io/selection-api/#extensions-to-document-interface partial interface Document { +/*TODO [Throws] Selection? getSelection(); +*/ }; // Extension to give chrome JS the ability to determine whether @@ -478,10 +510,12 @@ partial interface Document { // Extension to give chrome and XBL JS the ability to determine whether // the document is sandboxed without permission to run scripts // and whether inline scripts are blocked by the document's CSP. +/*Non standard partial interface Document { [Func="IsChromeOrXBL"] readonly attribute boolean hasScriptsBlockedBySandbox; [Func="IsChromeOrXBL"] readonly attribute boolean inlineScriptAllowedByCSP; }; +*/ // For more information on Flash classification, see // toolkit/components/url-classifier/flash-block-lists.rst diff --git a/crates/web-sys/webidls/enabled/Element.webidl b/crates/web-sys/webidls/enabled/Element.webidl index 94cb7cc01cd..f374c92d3fc 100644 --- a/crates/web-sys/webidls/enabled/Element.webidl +++ b/crates/web-sys/webidls/enabled/Element.webidl @@ -29,8 +29,10 @@ interface Element : Node { attribute DOMString id; [CEReactions, Pure] attribute DOMString className; +/*TODO [Constant, PutForwards=value] readonly attribute DOMTokenList classList; +*/ [SameObject] readonly attribute NamedNodeMap attributes; @@ -248,10 +250,8 @@ partial interface Element { partial interface Element { [Throws, Pure] Element? querySelector(DOMString selectors); -/*TODO [Throws, Pure] NodeList querySelectorAll(DOMString selectors); -*/ }; // https://dom.spec.whatwg.org/#dictdef-shadowrootinit diff --git a/crates/web-sys/webidls/available/EventTarget.webidl b/crates/web-sys/webidls/enabled/EventTarget.webidl similarity index 100% rename from crates/web-sys/webidls/available/EventTarget.webidl rename to crates/web-sys/webidls/enabled/EventTarget.webidl diff --git a/crates/web-sys/webidls/available/Node.webidl b/crates/web-sys/webidls/enabled/Node.webidl similarity index 99% rename from crates/web-sys/webidls/available/Node.webidl rename to crates/web-sys/webidls/enabled/Node.webidl index db3ded8cac8..3aed1f93eb3 100644 --- a/crates/web-sys/webidls/available/Node.webidl +++ b/crates/web-sys/webidls/enabled/Node.webidl @@ -10,8 +10,10 @@ * liability, trademark and document use rules apply. */ +/*TODO interface Principal; interface URI; +*/ interface Node : EventTarget { const unsigned short ELEMENT_NODE = 1; @@ -38,8 +40,10 @@ interface Node : EventTarget { readonly attribute boolean isConnected; [Pure] readonly attribute Document? ownerDocument; +/*TODO [Pure] Node getRootNode(optional GetRootNodeOptions options); +*/ [Pure] readonly attribute Node? parentNode; [Pure] @@ -207,12 +211,16 @@ interface Node : EventTarget { [ChromeOnly, Throws] Promise localize(L10nCallback l10nCallback); +/*Unsupported ifdef #ifdef ACCESSIBILITY [Func="mozilla::dom::AccessibleNode::IsAOMEnabled", SameObject] readonly attribute AccessibleNode? accessibleNode; #endif +*/ }; +/*TODO dictionary GetRootNodeOptions { boolean composed = false; }; +*/ diff --git a/crates/web-sys/webidls/available/NodeList.webidl b/crates/web-sys/webidls/enabled/NodeList.webidl similarity index 100% rename from crates/web-sys/webidls/available/NodeList.webidl rename to crates/web-sys/webidls/enabled/NodeList.webidl diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index cfdaa3b56b4..d3de58a6d1c 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -27,11 +27,11 @@ mod util; use std::collections::BTreeSet; use std::fs; use std::io::{self, Read}; -use std::iter::FromIterator; +use std::iter::{self, FromIterator}; use std::path::Path; use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports}; -use backend::util::{ident_ty, rust_ident, wrap_import_function}; +use backend::util::{ident_ty, raw_ident, rust_ident, wrap_import_function}; use failure::ResultExt; use heck::{CamelCase, ShoutySnakeCase}; use quote::ToTokens; @@ -82,7 +82,7 @@ fn compile_ast(mut ast: backend::ast::Program) -> String { let mut defined = BTreeSet::from_iter( vec![ "str", "char", "bool", "JsValue", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", - "usize", "isize", "f32", "f64", "Result", "String", "Vec", + "usize", "isize", "f32", "f64", "Result", "String", "Vec", "Option", ].into_iter() .map(|id| proc_macro2::Ident::new(id, proc_macro2::Span::call_site())), ); @@ -401,8 +401,10 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::InterfaceMember { webidl::ast::InterfaceMember::Const(cnst) => { cnst.webidl_parse(program, first_pass, self_name) } + webidl::ast::InterfaceMember::Iterable(iterable) => { + iterable.webidl_parse(program, first_pass, self_name) + } // TODO - webidl::ast::InterfaceMember::Iterable(_) | webidl::ast::InterfaceMember::Maplike(_) | webidl::ast::InterfaceMember::Setlike(_) => { warn!("Unsupported WebIDL interface member: {:?}", self); @@ -520,6 +522,50 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute { } } +impl<'a> WebidlParse<&'a str> for webidl::ast::Iterable { + fn webidl_parse( + &self, + program: &mut backend::ast::Program, + first_pass: &FirstPassRecord<'_>, + self_name: &'a str, + ) -> Result<()> { + if util::is_chrome_only(&self.extended_attributes) { + return Ok(()); + } + +/* TODO + let throws = util::throws(&self.extended_attributes); + let return_value = webidl::ast::ReturnType::NonVoid(self.value_type.clone()); + let args = []; + first_pass + .create_basic_method( + &args, + Some(&"values".to_string()), + &return_value, + self_name, + false, + false, // Should be false + ) + .map(wrap_import_function) + .map(|import| program.imports.push(import)); + + first_pass + .create_basic_method( + &args, + Some(&"keys".to_string()), + &return_value, // Should be a number + self_name, + false, + false, // Should be false + ) + .map(wrap_import_function) + .map(|import| program.imports.push(import)); +*/ + + Ok(()) + } +} + impl<'a> WebidlParse<&'a str> for webidl::ast::StaticAttribute { fn webidl_parse( &self,