/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! Machinery to initialise interface prototype objects and interface objects. use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding; use dom::bindings::codegen::Bindings::HTMLAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLAudioElementBinding; use dom::bindings::codegen::Bindings::HTMLBRElementBinding; use dom::bindings::codegen::Bindings::HTMLBaseElementBinding; use dom::bindings::codegen::Bindings::HTMLBodyElementBinding; use dom::bindings::codegen::Bindings::HTMLButtonElementBinding; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; use dom::bindings::codegen::Bindings::HTMLDListElementBinding; use dom::bindings::codegen::Bindings::HTMLDataElementBinding; use dom::bindings::codegen::Bindings::HTMLDataListElementBinding; use dom::bindings::codegen::Bindings::HTMLDetailsElementBinding; use dom::bindings::codegen::Bindings::HTMLDialogElementBinding; use dom::bindings::codegen::Bindings::HTMLDirectoryElementBinding; use dom::bindings::codegen::Bindings::HTMLDivElementBinding; use dom::bindings::codegen::Bindings::HTMLElementBinding; use dom::bindings::codegen::Bindings::HTMLEmbedElementBinding; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding; use dom::bindings::codegen::Bindings::HTMLFontElementBinding; use dom::bindings::codegen::Bindings::HTMLFormElementBinding; use dom::bindings::codegen::Bindings::HTMLFrameElementBinding; use dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding; use dom::bindings::codegen::Bindings::HTMLHRElementBinding; use dom::bindings::codegen::Bindings::HTMLHeadElementBinding; use dom::bindings::codegen::Bindings::HTMLHeadingElementBinding; use dom::bindings::codegen::Bindings::HTMLHtmlElementBinding; use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding; use dom::bindings::codegen::Bindings::HTMLImageElementBinding; use dom::bindings::codegen::Bindings::HTMLInputElementBinding; use dom::bindings::codegen::Bindings::HTMLLIElementBinding; use dom::bindings::codegen::Bindings::HTMLLabelElementBinding; use dom::bindings::codegen::Bindings::HTMLLegendElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLMapElementBinding; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding; use dom::bindings::codegen::Bindings::HTMLMeterElementBinding; use dom::bindings::codegen::Bindings::HTMLModElementBinding; use dom::bindings::codegen::Bindings::HTMLOListElementBinding; use dom::bindings::codegen::Bindings::HTMLObjectElementBinding; use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding; use dom::bindings::codegen::Bindings::HTMLOptionElementBinding; use dom::bindings::codegen::Bindings::HTMLOutputElementBinding; use dom::bindings::codegen::Bindings::HTMLParagraphElementBinding; use dom::bindings::codegen::Bindings::HTMLParamElementBinding; use dom::bindings::codegen::Bindings::HTMLPreElementBinding; use dom::bindings::codegen::Bindings::HTMLProgressElementBinding; use dom::bindings::codegen::Bindings::HTMLQuoteElementBinding; use dom::bindings::codegen::Bindings::HTMLScriptElementBinding; use dom::bindings::codegen::Bindings::HTMLSelectElementBinding; use dom::bindings::codegen::Bindings::HTMLSourceElementBinding; use dom::bindings::codegen::Bindings::HTMLSpanElementBinding; use dom::bindings::codegen::Bindings::HTMLStyleElementBinding; use dom::bindings::codegen::Bindings::HTMLTableCaptionElementBinding; use dom::bindings::codegen::Bindings::HTMLTableColElementBinding; use dom::bindings::codegen::Bindings::HTMLTableDataCellElementBinding; use dom::bindings::codegen::Bindings::HTMLTableElementBinding; use dom::bindings::codegen::Bindings::HTMLTableHeaderCellElementBinding; use dom::bindings::codegen::Bindings::HTMLTableRowElementBinding; use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding; use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLTimeElementBinding; use dom::bindings::codegen::Bindings::HTMLTitleElementBinding; use dom::bindings::codegen::Bindings::HTMLTrackElementBinding; use dom::bindings::codegen::Bindings::HTMLUListElementBinding; use dom::bindings::codegen::Bindings::HTMLVideoElementBinding; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::InterfaceObjectMap::Globals; use dom::bindings::codegen::PrototypeList; use dom::bindings::constant::{ConstantSpec, define_constants}; use dom::bindings::conversions::{DOM_OBJECT_SLOT, DerivedFrom, get_dom_class}; use dom::bindings::error::{Error, Fallible}; use dom::bindings::guard::Guard; use dom::bindings::root::DomRoot; use dom::bindings::utils::{DOM_PROTOTYPE_SLOT, ProtoOrIfaceArray, get_proto_or_iface_array}; use dom::create::create_native_html_element; use dom::customelementregistry::ConstructionStackEntry; use dom::element::{CustomElementState, Element, ElementCreator}; use dom::htmlelement::HTMLElement; use dom::window::Window; use html5ever::LocalName; use html5ever::interface::QualName; use js::error::throw_type_error; use js::glue::{RUST_SYMBOL_TO_JSID, UncheckedUnwrapObject, UnwrapObject}; use js::jsapi::{CallArgs, Class, ClassOps, CompartmentOptions, CurrentGlobalOrNull}; use js::jsapi::{GetGlobalForObjectCrossCompartment, GetWellKnownSymbol, HandleObject, HandleValue}; use js::jsapi::{JSAutoCompartment, JSClass, JSContext, JSFUN_CONSTRUCTOR, JSFunctionSpec, JSObject}; use js::jsapi::{JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING}; use js::jsapi::{JSPropertySpec, JSString, JSTracer, JSVersion, JS_AtomizeAndPinString}; use js::jsapi::{JS_DefineProperty, JS_DefineProperty1, JS_DefineProperty2}; use js::jsapi::{JS_DefineProperty4, JS_DefinePropertyById3, JS_FireOnNewGlobalObject}; use js::jsapi::{JS_GetFunctionObject, JS_GetPrototype}; use js::jsapi::{JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewGlobalObject}; use js::jsapi::{JS_NewObject, JS_NewObjectWithUniqueType, JS_NewPlainObject}; use js::jsapi::{JS_NewStringCopyN, JS_SetReservedSlot, MutableHandleObject}; use js::jsapi::{MutableHandleValue, ObjectOps, OnNewGlobalHookOption, SymbolCode}; use js::jsapi::{TrueHandleValue, Value}; use js::jsval::{JSVal, PrivateValue}; use js::rust::{define_methods, define_properties, get_object_class}; use libc; use script_thread::ScriptThread; use std::ptr; /// The class of a non-callback interface object. #[derive(Clone, Copy)] pub struct NonCallbackInterfaceObjectClass { /// The SpiderMonkey Class structure. pub class: Class, /// The prototype id of that interface, used in the hasInstance hook. pub proto_id: PrototypeList::ID, /// The prototype depth of that interface, used in the hasInstance hook. pub proto_depth: u16, /// The string representation of the object. pub representation: &'static [u8], } unsafe impl Sync for NonCallbackInterfaceObjectClass {} impl NonCallbackInterfaceObjectClass { /// Create a new `NonCallbackInterfaceObjectClass` structure. pub const fn new(constructor_behavior: &'static InterfaceConstructorBehavior, string_rep: &'static [u8], proto_id: PrototypeList::ID, proto_depth: u16) -> NonCallbackInterfaceObjectClass { NonCallbackInterfaceObjectClass { class: Class { name: b"Function\0" as *const _ as *const libc::c_char, flags: 0, cOps: &constructor_behavior.0, spec: 0 as *const _, ext: 0 as *const _, oOps: &OBJECT_OPS, }, proto_id: proto_id, proto_depth: proto_depth, representation: string_rep, } } /// cast own reference to `JSClass` reference pub fn as_jsclass(&self) -> &JSClass { unsafe { &*(self as *const _ as *const JSClass) } } } /// A constructor class hook. pub type ConstructorClassHook = unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool; /// The constructor behavior of a non-callback interface object. pub struct InterfaceConstructorBehavior(ClassOps); impl InterfaceConstructorBehavior { /// An interface constructor that unconditionally throws a type error. pub const fn throw() -> Self { InterfaceConstructorBehavior(ClassOps { addProperty: None, delProperty: None, getProperty: None, setProperty: None, enumerate: None, resolve: None, mayResolve: None, finalize: None, call: Some(invalid_constructor), construct: Some(invalid_constructor), hasInstance: Some(has_instance_hook), trace: None, }) } /// An interface constructor that calls a native Rust function. pub const fn call(hook: ConstructorClassHook) -> Self { InterfaceConstructorBehavior(ClassOps { addProperty: None, delProperty: None, getProperty: None, setProperty: None, enumerate: None, resolve: None, mayResolve: None, finalize: None, call: Some(non_new_constructor), construct: Some(hook), hasInstance: Some(has_instance_hook), trace: None, }) } } /// A trace hook. pub type TraceHook = unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject); /// Create a global object with the given class. pub unsafe fn create_global_object( cx: *mut JSContext, class: &'static JSClass, private: *const libc::c_void, trace: TraceHook, rval: MutableHandleObject) { assert!(rval.is_null()); let mut options = CompartmentOptions::default(); options.behaviors_.version_ = JSVersion::JSVERSION_ECMA_5; options.creationOptions_.traceGlobal_ = Some(trace); options.creationOptions_.sharedMemoryAndAtomics_ = true; rval.set(JS_NewGlobalObject(cx, class, ptr::null_mut(), OnNewGlobalHookOption::DontFireOnNewGlobalHook, &options)); assert!(!rval.is_null()); // Initialize the reserved slots before doing anything that can GC, to // avoid getting trace hooks called on a partially initialized object. JS_SetReservedSlot(rval.get(), DOM_OBJECT_SLOT, PrivateValue(private)); let proto_array: Box = Box::new([0 as *mut JSObject; PrototypeList::PROTO_OR_IFACE_LENGTH]); JS_SetReservedSlot(rval.get(), DOM_PROTOTYPE_SLOT, PrivateValue(Box::into_raw(proto_array) as *const libc::c_void)); let _ac = JSAutoCompartment::new(cx, rval.get()); JS_FireOnNewGlobalObject(cx, rval.handle()); } // https://html.spec.whatwg.org/multipage/#htmlconstructor pub unsafe fn html_constructor(window: &Window, call_args: &CallArgs) -> Fallible> where T: DerivedFrom { let document = window.Document(); // Step 1 let registry = window.CustomElements(); // Step 2 is checked in the generated caller code // Step 3 rooted!(in(window.get_cx()) let new_target = call_args.new_target().to_object()); let definition = match registry.lookup_definition_by_constructor(new_target.handle()) { Some(definition) => definition, None => return Err(Error::Type("No custom element definition found for new.target".to_owned())), }; rooted!(in(window.get_cx()) let callee = UnwrapObject(call_args.callee(), 1)); if callee.is_null() { return Err(Error::Security); } { let _ac = JSAutoCompartment::new(window.get_cx(), callee.get()); rooted!(in(window.get_cx()) let mut constructor = ptr::null_mut()); rooted!(in(window.get_cx()) let global_object = CurrentGlobalOrNull(window.get_cx())); if definition.is_autonomous() { // Step 4 // Since this element is autonomous, its active function object must be the HTMLElement // Retrieve the constructor object for HTMLElement HTMLElementBinding::GetConstructorObject(window.get_cx(), global_object.handle(), constructor.handle_mut()); } else { // Step 5 get_constructor_object_from_local_name(definition.local_name.clone(), window.get_cx(), global_object.handle(), constructor.handle_mut()); } // Callee must be the same as the element interface's constructor object. if constructor.get() != callee.get() { return Err(Error::Type("Custom element does not extend the proper interface".to_owned())); } } let entry = definition.construction_stack.borrow().last().cloned(); match entry { // Step 8 None => { // Step 8.1 let name = QualName::new(None, ns!(html), definition.local_name.clone()); let element = if definition.is_autonomous() { DomRoot::upcast(HTMLElement::new(name.local, None, &*document)) } else { create_native_html_element(name, None, &*document, ElementCreator::ScriptCreated) }; // Step 8.2 is performed in the generated caller code. // Step 8.3 element.set_custom_element_state(CustomElementState::Custom); // Step 8.4 element.set_custom_element_definition(definition.clone()); // Step 8.5 DomRoot::downcast(element).ok_or(Error::InvalidState) }, // Step 9 Some(ConstructionStackEntry::Element(element)) => { // Step 11 is performed in the generated caller code. // Step 12 let mut construction_stack = definition.construction_stack.borrow_mut(); construction_stack.pop(); construction_stack.push(ConstructionStackEntry::AlreadyConstructedMarker); // Step 13 DomRoot::downcast(element).ok_or(Error::InvalidState) }, // Step 10 Some(ConstructionStackEntry::AlreadyConstructedMarker) => Err(Error::InvalidState), } } pub fn push_new_element_queue() { ScriptThread::push_new_element_queue(); } pub fn pop_current_element_queue() { ScriptThread::pop_current_element_queue(); } /// Create and define the interface object of a callback interface. pub unsafe fn create_callback_interface_object( cx: *mut JSContext, global: HandleObject, constants: &[Guard<&[ConstantSpec]>], name: &[u8], rval: MutableHandleObject) { assert!(!constants.is_empty()); rval.set(JS_NewObject(cx, ptr::null())); assert!(!rval.ptr.is_null()); define_guarded_constants(cx, rval.handle(), constants); define_name(cx, rval.handle(), name); define_on_global_object(cx, global, name, rval.handle()); } /// Create the interface prototype object of a non-callback interface. pub unsafe fn create_interface_prototype_object( cx: *mut JSContext, proto: HandleObject, class: &'static JSClass, regular_methods: &[Guard<&'static [JSFunctionSpec]>], regular_properties: &[Guard<&'static [JSPropertySpec]>], constants: &[Guard<&[ConstantSpec]>], unscopable_names: &[&[u8]], rval: MutableHandleObject) { create_object(cx, proto, class, regular_methods, regular_properties, constants, rval); if !unscopable_names.is_empty() { rooted!(in(cx) let mut unscopable_obj = ptr::null_mut()); create_unscopable_object(cx, unscopable_names, unscopable_obj.handle_mut()); let unscopable_symbol = GetWellKnownSymbol(cx, SymbolCode::unscopables); assert!(!unscopable_symbol.is_null()); rooted!(in(cx) let unscopable_id = RUST_SYMBOL_TO_JSID(unscopable_symbol)); assert!(JS_DefinePropertyById3( cx, rval.handle(), unscopable_id.handle(), unscopable_obj.handle(), JSPROP_READONLY, None, None)) } } /// Create and define the interface object of a non-callback interface. pub unsafe fn create_noncallback_interface_object( cx: *mut JSContext, global: HandleObject, proto: HandleObject, class: &'static NonCallbackInterfaceObjectClass, static_methods: &[Guard<&'static [JSFunctionSpec]>], static_properties: &[Guard<&'static [JSPropertySpec]>], constants: &[Guard<&[ConstantSpec]>], interface_prototype_object: HandleObject, name: &[u8], length: u32, rval: MutableHandleObject) { create_object(cx, proto, class.as_jsclass(), static_methods, static_properties, constants, rval); assert!(JS_LinkConstructorAndPrototype(cx, rval.handle(), interface_prototype_object)); define_name(cx, rval.handle(), name); define_length(cx, rval.handle(), length); define_on_global_object(cx, global, name, rval.handle()); } /// Create and define the named constructors of a non-callback interface. pub unsafe fn create_named_constructors( cx: *mut JSContext, global: HandleObject, named_constructors: &[(ConstructorClassHook, &[u8], u32)], interface_prototype_object: HandleObject) { rooted!(in(cx) let mut constructor = ptr::null_mut()); for &(native, name, arity) in named_constructors { assert!(*name.last().unwrap() == b'\0'); let fun = JS_NewFunction(cx, Some(native), arity, JSFUN_CONSTRUCTOR, name.as_ptr() as *const libc::c_char); assert!(!fun.is_null()); constructor.set(JS_GetFunctionObject(fun)); assert!(!constructor.is_null()); assert!(JS_DefineProperty1(cx, constructor.handle(), b"prototype\0".as_ptr() as *const libc::c_char, interface_prototype_object, JSPROP_PERMANENT | JSPROP_READONLY, None, None)); define_on_global_object(cx, global, name, constructor.handle()); } } /// Create a new object with a unique type. pub unsafe fn create_object( cx: *mut JSContext, proto: HandleObject, class: &'static JSClass, methods: &[Guard<&'static [JSFunctionSpec]>], properties: &[Guard<&'static [JSPropertySpec]>], constants: &[Guard<&[ConstantSpec]>], rval: MutableHandleObject) { rval.set(JS_NewObjectWithUniqueType(cx, class, proto)); assert!(!rval.ptr.is_null()); define_guarded_methods(cx, rval.handle(), methods); define_guarded_properties(cx, rval.handle(), properties); define_guarded_constants(cx, rval.handle(), constants); } /// Conditionally define constants on an object. pub unsafe fn define_guarded_constants( cx: *mut JSContext, obj: HandleObject, constants: &[Guard<&[ConstantSpec]>]) { for guard in constants { if let Some(specs) = guard.expose(cx, obj) { define_constants(cx, obj, specs); } } } /// Conditionally define methods on an object. pub unsafe fn define_guarded_methods( cx: *mut JSContext, obj: HandleObject, methods: &[Guard<&'static [JSFunctionSpec]>]) { for guard in methods { if let Some(specs) = guard.expose(cx, obj) { define_methods(cx, obj, specs).unwrap(); } } } /// Conditionally define properties on an object. pub unsafe fn define_guarded_properties( cx: *mut JSContext, obj: HandleObject, properties: &[Guard<&'static [JSPropertySpec]>]) { for guard in properties { if let Some(specs) = guard.expose(cx, obj) { define_properties(cx, obj, specs).unwrap(); } } } /// Returns whether an interface with exposure set given by `globals` should /// be exposed in the global object `obj`. pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool { let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0); let dom_class = get_dom_class(unwrapped).unwrap(); globals.contains(dom_class.global) } /// Define a property with a given name on the global object. Should be called /// through the resolve hook. pub unsafe fn define_on_global_object( cx: *mut JSContext, global: HandleObject, name: &[u8], obj: HandleObject) { assert!(*name.last().unwrap() == b'\0'); assert!(JS_DefineProperty1(cx, global, name.as_ptr() as *const libc::c_char, obj, JSPROP_RESOLVING, None, None)); } const OBJECT_OPS: ObjectOps = ObjectOps { lookupProperty: None, defineProperty: None, hasProperty: None, getProperty: None, setProperty: None, getOwnPropertyDescriptor: None, deleteProperty: None, watch: None, unwatch: None, getElements: None, enumerate: None, funToString: Some(fun_to_string_hook), }; unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext, obj: HandleObject, _indent: u32) -> *mut JSString { let js_class = get_object_class(obj.get()); assert!(!js_class.is_null()); let repr = (*(js_class as *const NonCallbackInterfaceObjectClass)).representation; assert!(!repr.is_empty()); let ret = JS_NewStringCopyN(cx, repr.as_ptr() as *const libc::c_char, repr.len()); assert!(!ret.is_null()); ret } /// Hook for instanceof on interface objects. unsafe extern "C" fn has_instance_hook(cx: *mut JSContext, obj: HandleObject, value: MutableHandleValue, rval: *mut bool) -> bool { match has_instance(cx, obj, value.handle()) { Ok(result) => { *rval = result; true } Err(()) => false, } } /// Return whether a value is an instance of a given prototype. /// http://heycam.github.io/webidl/#es-interface-hasinstance unsafe fn has_instance( cx: *mut JSContext, interface_object: HandleObject, value: HandleValue) -> Result { if !value.is_object() { // Step 1. return Ok(false); } rooted!(in(cx) let mut value = value.to_object()); let js_class = get_object_class(interface_object.get()); let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass); if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(value.get(), /* stopAtWindowProxy = */ 0)) { if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id { // Step 4. return Ok(true); } } // Step 2. let global = GetGlobalForObjectCrossCompartment(interface_object.get()); assert!(!global.is_null()); let proto_or_iface_array = get_proto_or_iface_array(global); rooted!(in(cx) let prototype = (*proto_or_iface_array)[object_class.proto_id as usize]); assert!(!prototype.is_null()); // Step 3 only concern legacy callback interface objects (i.e. NodeFilter). while JS_GetPrototype(cx, value.handle(), value.handle_mut()) { if value.is_null() { // Step 5.2. return Ok(false); } else if value.get() as *const _ == prototype.get() { // Step 5.3. return Ok(true); } } // JS_GetPrototype threw an exception. Err(()) } unsafe fn create_unscopable_object( cx: *mut JSContext, names: &[&[u8]], rval: MutableHandleObject) { assert!(!names.is_empty()); assert!(rval.is_null()); rval.set(JS_NewPlainObject(cx)); assert!(!rval.ptr.is_null()); for &name in names { assert!(*name.last().unwrap() == b'\0'); assert!(JS_DefineProperty( cx, rval.handle(), name.as_ptr() as *const libc::c_char, TrueHandleValue, JSPROP_READONLY, None, None)); } } unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) { assert!(*name.last().unwrap() == b'\0'); rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char)); assert!(!name.is_null()); assert!(JS_DefineProperty2(cx, obj, b"name\0".as_ptr() as *const libc::c_char, name.handle(), JSPROP_READONLY, None, None)); } unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: u32) { assert!(JS_DefineProperty4(cx, obj, b"length\0".as_ptr() as *const libc::c_char, length, JSPROP_READONLY, None, None)); } unsafe extern "C" fn invalid_constructor( cx: *mut JSContext, _argc: libc::c_uint, _vp: *mut JSVal) -> bool { throw_type_error(cx, "Illegal constructor."); false } unsafe extern "C" fn non_new_constructor( cx: *mut JSContext, _argc: libc::c_uint, _vp: *mut JSVal) -> bool { throw_type_error(cx, "This constructor needs to be called with `new`."); false } /// Returns the constructor object for the element associated with the given local name. /// This list should only include elements marked with the [HTMLConstructor] extended attribute. pub fn get_constructor_object_from_local_name(name: LocalName, cx: *mut JSContext, global: HandleObject, rval: MutableHandleObject) -> bool { macro_rules! get_constructor( ($binding:ident) => ({ unsafe { $binding::GetConstructorObject(cx, global, rval); } true }) ); match name { local_name!("a") => get_constructor!(HTMLAnchorElementBinding), local_name!("abbr") => get_constructor!(HTMLElementBinding), local_name!("acronym") => get_constructor!(HTMLElementBinding), local_name!("address") => get_constructor!(HTMLElementBinding), local_name!("area") => get_constructor!(HTMLAreaElementBinding), local_name!("article") => get_constructor!(HTMLElementBinding), local_name!("aside") => get_constructor!(HTMLElementBinding), local_name!("audio") => get_constructor!(HTMLAudioElementBinding), local_name!("b") => get_constructor!(HTMLElementBinding), local_name!("base") => get_constructor!(HTMLBaseElementBinding), local_name!("bdi") => get_constructor!(HTMLElementBinding), local_name!("bdo") => get_constructor!(HTMLElementBinding), local_name!("big") => get_constructor!(HTMLElementBinding), local_name!("blockquote") => get_constructor!(HTMLQuoteElementBinding), local_name!("body") => get_constructor!(HTMLBodyElementBinding), local_name!("br") => get_constructor!(HTMLBRElementBinding), local_name!("button") => get_constructor!(HTMLButtonElementBinding), local_name!("canvas") => get_constructor!(HTMLCanvasElementBinding), local_name!("caption") => get_constructor!(HTMLTableCaptionElementBinding), local_name!("center") => get_constructor!(HTMLElementBinding), local_name!("cite") => get_constructor!(HTMLElementBinding), local_name!("code") => get_constructor!(HTMLElementBinding), local_name!("col") => get_constructor!(HTMLTableColElementBinding), local_name!("colgroup") => get_constructor!(HTMLTableColElementBinding), local_name!("data") => get_constructor!(HTMLDataElementBinding), local_name!("datalist") => get_constructor!(HTMLDataListElementBinding), local_name!("dd") => get_constructor!(HTMLElementBinding), local_name!("del") => get_constructor!(HTMLModElementBinding), local_name!("details") => get_constructor!(HTMLDetailsElementBinding), local_name!("dfn") => get_constructor!(HTMLElementBinding), local_name!("dialog") => get_constructor!(HTMLDialogElementBinding), local_name!("dir") => get_constructor!(HTMLDirectoryElementBinding), local_name!("div") => get_constructor!(HTMLDivElementBinding), local_name!("dl") => get_constructor!(HTMLDListElementBinding), local_name!("dt") => get_constructor!(HTMLElementBinding), local_name!("em") => get_constructor!(HTMLElementBinding), local_name!("embed") => get_constructor!(HTMLEmbedElementBinding), local_name!("fieldset") => get_constructor!(HTMLFieldSetElementBinding), local_name!("figcaption") => get_constructor!(HTMLElementBinding), local_name!("figure") => get_constructor!(HTMLElementBinding), local_name!("font") => get_constructor!(HTMLFontElementBinding), local_name!("footer") => get_constructor!(HTMLElementBinding), local_name!("form") => get_constructor!(HTMLFormElementBinding), local_name!("frame") => get_constructor!(HTMLFrameElementBinding), local_name!("frameset") => get_constructor!(HTMLFrameSetElementBinding), local_name!("h1") => get_constructor!(HTMLHeadingElementBinding), local_name!("h2") => get_constructor!(HTMLHeadingElementBinding), local_name!("h3") => get_constructor!(HTMLHeadingElementBinding), local_name!("h4") => get_constructor!(HTMLHeadingElementBinding), local_name!("h5") => get_constructor!(HTMLHeadingElementBinding), local_name!("h6") => get_constructor!(HTMLHeadingElementBinding), local_name!("head") => get_constructor!(HTMLHeadElementBinding), local_name!("header") => get_constructor!(HTMLElementBinding), local_name!("hgroup") => get_constructor!(HTMLElementBinding), local_name!("hr") => get_constructor!(HTMLHRElementBinding), local_name!("html") => get_constructor!(HTMLHtmlElementBinding), local_name!("i") => get_constructor!(HTMLElementBinding), local_name!("iframe") => get_constructor!(HTMLIFrameElementBinding), local_name!("img") => get_constructor!(HTMLImageElementBinding), local_name!("input") => get_constructor!(HTMLInputElementBinding), local_name!("ins") => get_constructor!(HTMLModElementBinding), local_name!("kbd") => get_constructor!(HTMLElementBinding), local_name!("label") => get_constructor!(HTMLLabelElementBinding), local_name!("legend") => get_constructor!(HTMLLegendElementBinding), local_name!("li") => get_constructor!(HTMLLIElementBinding), local_name!("link") => get_constructor!(HTMLLinkElementBinding), local_name!("listing") => get_constructor!(HTMLPreElementBinding), local_name!("main") => get_constructor!(HTMLElementBinding), local_name!("map") => get_constructor!(HTMLMapElementBinding), local_name!("mark") => get_constructor!(HTMLElementBinding), local_name!("marquee") => get_constructor!(HTMLElementBinding), local_name!("meta") => get_constructor!(HTMLMetaElementBinding), local_name!("meter") => get_constructor!(HTMLMeterElementBinding), local_name!("nav") => get_constructor!(HTMLElementBinding), local_name!("nobr") => get_constructor!(HTMLElementBinding), local_name!("noframes") => get_constructor!(HTMLElementBinding), local_name!("noscript") => get_constructor!(HTMLElementBinding), local_name!("object") => get_constructor!(HTMLObjectElementBinding), local_name!("ol") => get_constructor!(HTMLOListElementBinding), local_name!("optgroup") => get_constructor!(HTMLOptGroupElementBinding), local_name!("option") => get_constructor!(HTMLOptionElementBinding), local_name!("output") => get_constructor!(HTMLOutputElementBinding), local_name!("p") => get_constructor!(HTMLParagraphElementBinding), local_name!("param") => get_constructor!(HTMLParamElementBinding), local_name!("plaintext") => get_constructor!(HTMLPreElementBinding), local_name!("pre") => get_constructor!(HTMLPreElementBinding), local_name!("progress") => get_constructor!(HTMLProgressElementBinding), local_name!("q") => get_constructor!(HTMLQuoteElementBinding), local_name!("rp") => get_constructor!(HTMLElementBinding), local_name!("rt") => get_constructor!(HTMLElementBinding), local_name!("ruby") => get_constructor!(HTMLElementBinding), local_name!("s") => get_constructor!(HTMLElementBinding), local_name!("samp") => get_constructor!(HTMLElementBinding), local_name!("script") => get_constructor!(HTMLScriptElementBinding), local_name!("section") => get_constructor!(HTMLElementBinding), local_name!("select") => get_constructor!(HTMLSelectElementBinding), local_name!("small") => get_constructor!(HTMLElementBinding), local_name!("source") => get_constructor!(HTMLSourceElementBinding), local_name!("span") => get_constructor!(HTMLSpanElementBinding), local_name!("strike") => get_constructor!(HTMLElementBinding), local_name!("strong") => get_constructor!(HTMLElementBinding), local_name!("style") => get_constructor!(HTMLStyleElementBinding), local_name!("sub") => get_constructor!(HTMLElementBinding), local_name!("summary") => get_constructor!(HTMLElementBinding), local_name!("sup") => get_constructor!(HTMLElementBinding), local_name!("table") => get_constructor!(HTMLTableElementBinding), local_name!("tbody") => get_constructor!(HTMLTableSectionElementBinding), local_name!("td") => get_constructor!(HTMLTableDataCellElementBinding), local_name!("template") => get_constructor!(HTMLTemplateElementBinding), local_name!("textarea") => get_constructor!(HTMLTextAreaElementBinding), local_name!("tfoot") => get_constructor!(HTMLTableSectionElementBinding), local_name!("th") => get_constructor!(HTMLTableHeaderCellElementBinding), local_name!("thead") => get_constructor!(HTMLTableSectionElementBinding), local_name!("time") => get_constructor!(HTMLTimeElementBinding), local_name!("title") => get_constructor!(HTMLTitleElementBinding), local_name!("tr") => get_constructor!(HTMLTableRowElementBinding), local_name!("tt") => get_constructor!(HTMLElementBinding), local_name!("track") => get_constructor!(HTMLTrackElementBinding), local_name!("u") => get_constructor!(HTMLElementBinding), local_name!("ul") => get_constructor!(HTMLUListElementBinding), local_name!("var") => get_constructor!(HTMLElementBinding), local_name!("video") => get_constructor!(HTMLVideoElementBinding), local_name!("wbr") => get_constructor!(HTMLElementBinding), local_name!("xmp") => get_constructor!(HTMLPreElementBinding), _ => false, } }