mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Support arbitrary protos when wrapping EventTarget objects.
This commit is contained in:
parent
4ee789a85c
commit
d9600ff50f
8 changed files with 187 additions and 35 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -3752,7 +3752,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "mozjs"
|
||||
version = "0.14.1"
|
||||
source = "git+https://github.com/servo/mozjs#d2a3526611cc123139d01f9ac4ff915f805f9e74"
|
||||
source = "git+https://github.com/servo/mozjs#b9edc816b6662a5986e190cdf53ae295049acb92"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lazy_static",
|
||||
|
@ -3765,7 +3765,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "mozjs_sys"
|
||||
version = "0.68.2"
|
||||
source = "git+https://github.com/servo/mozjs#d2a3526611cc123139d01f9ac4ff915f805f9e74"
|
||||
source = "git+https://github.com/servo/mozjs#b9edc816b6662a5986e190cdf53ae295049acb92"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
|
|
|
@ -2313,10 +2313,11 @@ def DOMClass(descriptor):
|
|||
return """\
|
||||
DOMClass {
|
||||
interface_chain: [ %s ],
|
||||
depth: %d,
|
||||
type_id: %s,
|
||||
malloc_size_of: %s as unsafe fn(&mut _, _) -> _,
|
||||
global: InterfaceObjectMap::Globals::%s,
|
||||
}""" % (prototypeChainString, DOMClassTypeId(descriptor), mallocSizeOf, globals_)
|
||||
}""" % (prototypeChainString, descriptor.prototypeDepth, DOMClassTypeId(descriptor), mallocSizeOf, globals_)
|
||||
|
||||
|
||||
class CGDOMJSClass(CGThing):
|
||||
|
@ -2865,7 +2866,7 @@ ensure_expando_object(*cx, obj.handle().into(), expando.handle_mut());
|
|||
copyFunc = "JS_InitializePropertiesFromCompatibleNativeObject"
|
||||
copyCode += """\
|
||||
let mut slot = UndefinedValue();
|
||||
JS_GetReservedSlot(proto.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, &mut slot);
|
||||
JS_GetReservedSlot(canonical_proto.get(), DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, &mut slot);
|
||||
rooted!(in(*cx) let mut unforgeable_holder = ptr::null_mut::<JSObject>());
|
||||
unforgeable_holder.handle_mut().set(slot.to_object());
|
||||
assert!(%(copyFunc)s(*cx, %(obj)s.handle(), unforgeable_holder.handle()));
|
||||
|
@ -2884,6 +2885,7 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
assert not descriptor.isGlobal()
|
||||
args = [Argument('SafeJSContext', 'cx'),
|
||||
Argument('&GlobalScope', 'scope'),
|
||||
Argument('Option<HandleObject>', 'given_proto'),
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object')]
|
||||
retval = 'DomRoot<%s>' % descriptor.concreteType
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args,
|
||||
|
@ -2896,7 +2898,7 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
proto = "ptr::null_mut()"
|
||||
lazyProto = "true" # Our proxy handler will manage the prototype
|
||||
else:
|
||||
proto = "proto.get()"
|
||||
proto = "canonical_proto.get()"
|
||||
lazyProto = "false"
|
||||
|
||||
create = """
|
||||
|
@ -2924,6 +2926,15 @@ SetProxyReservedSlot(
|
|||
else:
|
||||
lazyProto = None
|
||||
create = """
|
||||
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
|
||||
if let Some(given) = given_proto {
|
||||
*proto = *given;
|
||||
if get_context_realm(*cx) != get_object_realm(*given) {
|
||||
assert!(JS_WrapObject(*cx, proto.handle_mut()));
|
||||
}
|
||||
} else {
|
||||
*proto = *canonical_proto;
|
||||
}
|
||||
rooted!(in(*cx) let obj = JS_NewObjectWithGivenProto(
|
||||
*cx,
|
||||
&Class.base,
|
||||
|
@ -2951,9 +2962,9 @@ assert!(!scope.get().is_null());
|
|||
assert!(((*get_object_class(scope.get())).flags & JSCLASS_IS_GLOBAL) != 0);
|
||||
let _ac = JSAutoRealm::new(*cx, scope.get());
|
||||
|
||||
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
|
||||
GetProtoObject(cx, scope, proto.handle_mut());
|
||||
assert!(!proto.is_null());
|
||||
rooted!(in(*cx) let mut canonical_proto = ptr::null_mut::<JSObject>());
|
||||
GetProtoObject(cx, scope, canonical_proto.handle_mut());
|
||||
assert!(!canonical_proto.is_null());
|
||||
|
||||
%(createObject)s
|
||||
let root = raw.reflect_with(obj.get());
|
||||
|
@ -3010,9 +3021,9 @@ assert!(!obj.is_null());
|
|||
let root = raw.reflect_with(obj.get());
|
||||
|
||||
let _ac = JSAutoRealm::new(*cx, obj.get());
|
||||
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
|
||||
GetProtoObject(cx, obj.handle(), proto.handle_mut());
|
||||
assert!(JS_SetPrototype(*cx, obj.handle(), proto.handle()));
|
||||
rooted!(in(*cx) let mut canonical_proto = ptr::null_mut::<JSObject>());
|
||||
GetProtoObject(cx, obj.handle(), canonical_proto.handle_mut());
|
||||
assert!(JS_SetPrototype(*cx, obj.handle(), canonical_proto.handle()));
|
||||
let mut immutable = false;
|
||||
assert!(JS_SetImmutablePrototype(*cx, obj.handle(), &mut immutable));
|
||||
assert!(immutable);
|
||||
|
@ -3076,6 +3087,7 @@ impl DomObjectWrap for %s {
|
|||
const WRAP: unsafe fn(
|
||||
SafeJSContext,
|
||||
&GlobalScope,
|
||||
Option<HandleObject>,
|
||||
Box<Self>,
|
||||
) -> Root<Dom<Self>> = Wrap;
|
||||
}
|
||||
|
@ -3098,6 +3110,7 @@ impl DomObjectIteratorWrap for %s {
|
|||
const ITER_WRAP: unsafe fn(
|
||||
SafeJSContext,
|
||||
&GlobalScope,
|
||||
Option<HandleObject>,
|
||||
Box<IterableIterator<Self>>,
|
||||
) -> Root<Dom<IterableIterator<Self>>> = Wrap;
|
||||
}
|
||||
|
@ -6102,13 +6115,25 @@ class CGClassConstructHook(CGAbstractExternMethod):
|
|||
|
||||
def definition_body(self):
|
||||
preamble = """let cx = SafeJSContext::from_ptr(cx);
|
||||
let args = CallArgs::from_vp(vp, argc);
|
||||
let global = GlobalScope::from_object(JS_CALLEE(*cx, vp).to_object());
|
||||
"""
|
||||
rooted!(in(*cx) let mut desired_proto = ptr::null_mut::<JSObject>());
|
||||
let proto_result = get_desired_proto(
|
||||
cx,
|
||||
&args,
|
||||
PrototypeList::ID::%s,
|
||||
CreateInterfaceObjects,
|
||||
desired_proto.handle_mut(),
|
||||
);
|
||||
assert!(proto_result.is_ok());
|
||||
if proto_result.is_err() {
|
||||
return false;
|
||||
}
|
||||
""" % (MakeNativeName(self.descriptor.name))
|
||||
if len(self.exposureSet) == 1:
|
||||
preamble += """\
|
||||
let global = DomRoot::downcast::<dom::types::%s>(global).unwrap();
|
||||
""" % list(self.exposureSet)[0]
|
||||
preamble += """let args = CallArgs::from_vp(vp, argc);\n"""
|
||||
preamble = CGGeneric(preamble)
|
||||
if self.constructor.isHTMLConstructor():
|
||||
signatures = self.constructor.signatures()
|
||||
|
@ -6122,7 +6147,10 @@ let global = DomRoot::downcast::<dom::types::%s>(global).unwrap();
|
|||
else:
|
||||
name = self.constructor.identifier.name
|
||||
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
|
||||
constructorCall = CGMethodCall(["&global"], nativeName, True,
|
||||
args = ["&global"]
|
||||
if self.descriptor.interface.identifier.name == "EventTarget":
|
||||
args += ["desired_proto.handle()"]
|
||||
constructorCall = CGMethodCall(args, nativeName, True,
|
||||
self.descriptor, self.constructor)
|
||||
return CGList([preamble, constructorCall])
|
||||
|
||||
|
@ -6295,6 +6323,8 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'js::jsapi::CallArgs',
|
||||
'js::jsapi::CurrentGlobalOrNull',
|
||||
'js::rust::wrappers::GetPropertyKeys',
|
||||
'js::rust::get_object_realm',
|
||||
'js::rust::get_context_realm',
|
||||
'js::jsapi::GCContext',
|
||||
'js::jsapi::GetWellKnownSymbol',
|
||||
'js::rust::Handle',
|
||||
|
@ -6439,6 +6469,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'crate::dom::bindings::interface::define_guarded_properties',
|
||||
'crate::dom::bindings::interface::is_exposed_in',
|
||||
'crate::dom::bindings::interface::get_per_interface_object_handle',
|
||||
'crate::dom::bindings::interface::get_desired_proto',
|
||||
'crate::dom::bindings::htmlconstructor::pop_current_element_queue',
|
||||
'crate::dom::bindings::htmlconstructor::push_new_element_queue',
|
||||
'crate::dom::bindings::iterable::Iterable',
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::dom::bindings::guard::Guard;
|
|||
use crate::dom::bindings::principals::ServoJSPrincipals;
|
||||
use crate::dom::bindings::utils::{
|
||||
get_proto_or_iface_array, ProtoOrIfaceArray, DOM_PROTOTYPE_SLOT, JSCLASS_DOM_GLOBAL,
|
||||
DOMJSClass,
|
||||
};
|
||||
use crate::script_runtime::JSContext as SafeJSContext;
|
||||
use js::error::throw_type_error;
|
||||
|
@ -21,7 +22,7 @@ use js::jsapi::HandleObject as RawHandleObject;
|
|||
use js::jsapi::{jsid, JSClass, JSClassOps};
|
||||
use js::jsapi::{
|
||||
Compartment, CompartmentSpecifier, IsSharableCompartment, IsSystemCompartment,
|
||||
JS_IterateCompartments, JS::CompartmentIterResult,
|
||||
JS_IterateCompartments, JS::CompartmentIterResult, CallArgs,
|
||||
};
|
||||
use js::jsapi::{JSAutoRealm, JSContext, JSFunctionSpec, JSObject, JSFUN_CONSTRUCTOR};
|
||||
use js::jsapi::{JSPropertySpec, JSString, JSTracer, JS_AtomizeAndPinString};
|
||||
|
@ -31,13 +32,22 @@ use js::jsapi::{JS_NewStringCopyN, JS_SetReservedSlot};
|
|||
use js::jsapi::{ObjectOps, OnNewGlobalHookOption, SymbolCode};
|
||||
use js::jsapi::{TrueHandleValue, Value};
|
||||
use js::jsapi::{JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING};
|
||||
use js::jsapi::CheckedUnwrapStatic;
|
||||
use js::jsapi::JS_GetProperty;
|
||||
use js::jsapi::GetFunctionRealm;
|
||||
use js::jsapi::GetRealmGlobalOrNull;
|
||||
use js::jsapi::GetNonCCWObjectGlobal;
|
||||
use js::jsapi::JS_WrapObject;
|
||||
use js::jsapi::CurrentGlobalOrNull;
|
||||
use js::jsval::{JSVal, PrivateValue};
|
||||
use js::jsval::NullValue;
|
||||
use js::rust::is_dom_class;
|
||||
use js::rust::wrappers::JS_FireOnNewGlobalObject;
|
||||
use js::rust::wrappers::RUST_SYMBOL_TO_JSID;
|
||||
use js::rust::wrappers::{JS_DefineProperty, JS_DefineProperty5};
|
||||
use js::rust::wrappers::{JS_DefineProperty3, JS_DefineProperty4, JS_DefinePropertyById5};
|
||||
use js::rust::wrappers::{JS_LinkConstructorAndPrototype, JS_NewObjectWithGivenProto};
|
||||
use js::rust::{define_methods, define_properties, get_object_class};
|
||||
use js::rust::{define_methods, define_properties, get_object_class, maybe_wrap_object};
|
||||
use js::rust::{HandleObject, HandleValue, MutableHandleObject, RealmOptions};
|
||||
use servo_url::MutableOrigin;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -592,3 +602,111 @@ pub fn define_dom_interface(
|
|||
get_per_interface_object_handle(cx, global, id, creator, proto.handle_mut());
|
||||
assert!(!proto.is_null());
|
||||
}
|
||||
|
||||
fn get_proto_id_for_new_target(
|
||||
new_target: HandleObject,
|
||||
) -> Option<PrototypeList::ID> {
|
||||
unsafe {
|
||||
let new_target_class = get_object_class(*new_target);
|
||||
if is_dom_class(&*new_target_class) {
|
||||
let domjsclass: *const DOMJSClass = new_target_class as *const DOMJSClass;
|
||||
let dom_class = &(*domjsclass).dom_class;
|
||||
return Some(dom_class.interface_chain[dom_class.depth as usize]);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_desired_proto(
|
||||
cx: SafeJSContext,
|
||||
args: &CallArgs,
|
||||
proto_id: PrototypeList::ID,
|
||||
creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
|
||||
mut desired_proto: MutableHandleObject,
|
||||
) -> Result<(), ()> {
|
||||
unsafe {
|
||||
// This basically implements
|
||||
// https://heycam.github.io/webidl/#internally-create-a-new-object-implementing-the-interface
|
||||
// step 3.
|
||||
|
||||
//assert!(args.is_constructing())
|
||||
|
||||
// The desired prototype depends on the actual constructor that was invoked,
|
||||
// which is passed to us as the newTarget in the callargs. We want to do
|
||||
// something akin to the ES6 specification's GetProtototypeFromConstructor (so
|
||||
// get .prototype on the newTarget, with a fallback to some sort of default).
|
||||
|
||||
// First, a fast path for the case when the the constructor is in fact one of
|
||||
// our DOM constructors. This is safe because on those the "constructor"
|
||||
// property is non-configurable and non-writable, so we don't have to do the
|
||||
// slow JS_GetProperty call.
|
||||
rooted!(in(*cx) let mut new_target = args.new_target().to_object());
|
||||
rooted!(in(*cx) let original_new_target = *new_target);
|
||||
// See whether we have a known DOM constructor here, such that we can take a
|
||||
// fast path.
|
||||
let target_proto_id = get_proto_id_for_new_target(new_target.handle())
|
||||
.or_else(|| {
|
||||
// We might still have a cross-compartment wrapper for a known DOM
|
||||
// constructor. CheckedUnwrapStatic is fine here, because we're looking for
|
||||
// DOM constructors and those can't be cross-origin objects.
|
||||
*new_target = CheckedUnwrapStatic(*new_target);
|
||||
if !new_target.is_null() && &*new_target != &*original_new_target {
|
||||
get_proto_id_for_new_target(new_target.handle())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(proto_id) = target_proto_id {
|
||||
let global = GetNonCCWObjectGlobal(*new_target);
|
||||
let proto_or_iface_cache = get_proto_or_iface_array(global);
|
||||
desired_proto.set((*proto_or_iface_cache)[proto_id as usize]);
|
||||
if &*new_target != &*original_new_target {
|
||||
if !JS_WrapObject(*cx, desired_proto.into()) {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Slow path. This basically duplicates the ES6 spec's
|
||||
// GetPrototypeFromConstructor except that instead of taking a string naming
|
||||
// the fallback prototype we determine the fallback based on the proto id we
|
||||
// were handed.
|
||||
rooted!(in(*cx) let mut proto_val = NullValue());
|
||||
if !JS_GetProperty(*cx, original_new_target.handle().into(), b"prototype\0".as_ptr() as *const libc::c_char, proto_val.handle_mut().into()) {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if proto_val.is_object() {
|
||||
desired_proto.set(proto_val.to_object());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Fall back to getting the proto for our given proto id in the realm that
|
||||
// GetFunctionRealm(newTarget) returns.
|
||||
rooted!(in(*cx) let realm = GetFunctionRealm(*cx, new_target.handle().into()));
|
||||
|
||||
if (*realm).is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
{
|
||||
let _realm = JSAutoRealm::new(*cx, GetRealmGlobalOrNull(*realm));
|
||||
rooted!(in(*cx) let global = CurrentGlobalOrNull(*cx));
|
||||
get_per_interface_object_handle(
|
||||
cx,
|
||||
global.handle(),
|
||||
ProtoOrIfaceIndex::ID(proto_id),
|
||||
creator,
|
||||
desired_proto
|
||||
);
|
||||
if desired_proto.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
maybe_wrap_object(*cx, desired_proto);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use dom_struct::dom_struct;
|
|||
use js::conversions::ToJSValConvertible;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::{HandleValue, MutableHandleObject};
|
||||
use js::rust::{HandleValue, MutableHandleObject, HandleObject};
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::ptr::NonNull;
|
||||
|
@ -118,7 +118,7 @@ impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> IterableIterator<T> {
|
|||
}
|
||||
|
||||
impl<T: DomObjectIteratorWrap + JSTraceable + Iterable> DomObjectWrap for IterableIterator<T> {
|
||||
const WRAP: unsafe fn(JSContext, &GlobalScope, Box<Self>) -> Root<Dom<Self>> = T::ITER_WRAP;
|
||||
const WRAP: unsafe fn(JSContext, &GlobalScope, Option<HandleObject>, Box<Self>) -> Root<Dom<Self>> = T::ITER_WRAP;
|
||||
}
|
||||
|
||||
fn dict_return(
|
||||
|
|
|
@ -23,7 +23,16 @@ where
|
|||
U: DerivedFrom<GlobalScope>,
|
||||
{
|
||||
let global_scope = global.upcast();
|
||||
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, obj) }
|
||||
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, None, obj) }
|
||||
}
|
||||
|
||||
pub fn reflect_dom_object2<T, U>(obj: Box<T>, global: &U, proto: HandleObject) -> DomRoot<T>
|
||||
where
|
||||
T: DomObject + DomObjectWrap,
|
||||
U: DerivedFrom<GlobalScope>,
|
||||
{
|
||||
let global_scope = global.upcast();
|
||||
unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, Some(proto), obj) }
|
||||
}
|
||||
|
||||
/// A struct to store a reference to the reflector of a DOM object.
|
||||
|
@ -109,7 +118,7 @@ impl MutDomObject for Reflector {
|
|||
/// A trait to provide a function pointer to wrap function for DOM objects.
|
||||
pub trait DomObjectWrap: Sized + DomObject {
|
||||
/// Function pointer to the general wrap function type
|
||||
const WRAP: unsafe fn(JSContext, &GlobalScope, Box<Self>) -> Root<Dom<Self>>;
|
||||
const WRAP: unsafe fn(JSContext, &GlobalScope, Option<HandleObject>, Box<Self>) -> Root<Dom<Self>>;
|
||||
}
|
||||
|
||||
/// A trait to provide a function pointer to wrap function for
|
||||
|
@ -119,6 +128,7 @@ pub trait DomObjectIteratorWrap: DomObjectWrap + JSTraceable + Iterable {
|
|||
const ITER_WRAP: unsafe fn(
|
||||
JSContext,
|
||||
&GlobalScope,
|
||||
Option<HandleObject>,
|
||||
Box<IterableIterator<Self>>,
|
||||
) -> Root<Dom<IterableIterator<Self>>>;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,9 @@ pub struct DOMClass {
|
|||
/// derivedness.
|
||||
pub interface_chain: [PrototypeList::ID; MAX_PROTO_CHAIN_LENGTH],
|
||||
|
||||
/// The last valid index of `interface_chain`.
|
||||
pub depth: u8,
|
||||
|
||||
/// The type ID of that interface.
|
||||
pub type_id: TopTypeId,
|
||||
|
||||
|
@ -112,6 +115,7 @@ unsafe impl Sync for DOMClass {}
|
|||
|
||||
/// The JSClass used for DOM object reflectors.
|
||||
#[derive(Copy)]
|
||||
#[repr(C)]
|
||||
pub struct DOMJSClass {
|
||||
/// The actual JSClass.
|
||||
pub base: js::jsapi::JSClass,
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::dom::bindings::codegen::UnionTypes::EventListenerOptionsOrBoolean;
|
|||
use crate::dom::bindings::codegen::UnionTypes::EventOrString;
|
||||
use crate::dom::bindings::error::{report_pending_exception, Error, Fallible};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, reflect_dom_object2, DomObject, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::element::Element;
|
||||
|
@ -39,7 +39,7 @@ use fnv::FnvHasher;
|
|||
use js::jsapi::JS_GetFunctionObject;
|
||||
use js::rust::transform_u16_to_source_text;
|
||||
use js::rust::wrappers::CompileFunction;
|
||||
use js::rust::{CompileOptionsWrapper, RootedObjectVectorWrapper};
|
||||
use js::rust::{CompileOptionsWrapper, RootedObjectVectorWrapper, HandleObject};
|
||||
use libc::c_char;
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -360,8 +360,8 @@ impl EventTarget {
|
|||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Constructor(global: &GlobalScope) -> Fallible<DomRoot<EventTarget>> {
|
||||
Ok(EventTarget::new(global))
|
||||
pub fn Constructor(global: &GlobalScope, proto: HandleObject) -> Fallible<DomRoot<EventTarget>> {
|
||||
Ok(reflect_dom_object2(Box::new(EventTarget::new_inherited()), global, proto))
|
||||
}
|
||||
|
||||
pub fn has_listeners_for(&self, type_: &Atom) -> bool {
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[EventTarget-constructible.any.worker.html]
|
||||
type: testharness
|
||||
[EventTarget can be subclassed]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[EventTarget-constructible.any.html]
|
||||
type: testharness
|
||||
[EventTarget can be subclassed]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue