diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-06-24 03:54:56 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-06-24 03:54:56 -0600 |
commit | 6247a96761279979412fb49fa4fbca2fd9a82e1b (patch) | |
tree | 6503e916806f73b0434073a7e2a22f32993f3e1f | |
parent | 469b9550f6feec56d87ea5c772cb76453c13036a (diff) | |
parent | a90983553b78e3450cc91d810eb3d053398169d0 (diff) | |
download | servo-6247a96761279979412fb49fa4fbca2fd9a82e1b.tar.gz servo-6247a96761279979412fb49fa4fbca2fd9a82e1b.zip |
Auto merge of #6223 - nox:merge-generic-functions, r=Ms2ger
Merge generic funs to share them across all bindings (fixes #2684)
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6223)
<!-- Reviewable:end -->
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 157 | ||||
-rw-r--r-- | components/script/dom/bindings/conversions.rs | 107 | ||||
-rw-r--r-- | components/script/dom/bindings/error.rs | 10 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 108 | ||||
-rw-r--r-- | tests/wpt/metadata/html/dom/interfaces.html.ini | 3 |
5 files changed, 185 insertions, 200 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index f9e929c68da..832dd564736 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1441,7 +1441,7 @@ class MethodDefiner(PropertyDefiner): if m.get("methodInfo", True): identifier = m.get("nativeName", m["name"]) jitinfo = "&%s_methodinfo" % identifier - accessor = "Some(genericMethod)" + accessor = "Some(generic_method)" else: jitinfo = "0 as *const JSJitInfo" accessor = 'Some(%s)' % m.get("nativeName", m["name"]) @@ -1481,9 +1481,9 @@ class AttrDefiner(PropertyDefiner): jitinfo = "0 as *const JSJitInfo" else: if attr.hasLenientThis(): - accessor = "genericLenientGetter" + accessor = "generic_lenient_getter" else: - accessor = "genericGetter" + accessor = "generic_getter" jitinfo = "&%s_getterinfo" % attr.identifier.name return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" @@ -1499,9 +1499,9 @@ class AttrDefiner(PropertyDefiner): jitinfo = "0 as *const JSJitInfo" else: if attr.hasLenientThis(): - accessor = "genericLenientSetter" + accessor = "generic_lenient_setter" else: - accessor = "genericSetter" + accessor = "generic_setter" jitinfo = "&%s_setterinfo" % attr.identifier.name return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" @@ -2696,52 +2696,6 @@ class CGSetterCall(CGPerSignatureCall): # We just get our stuff from our last arg no matter what return "" -class CGAbstractBindingMethod(CGAbstractExternMethod): - """ - Common class to generate the JSNatives for all our methods, getters, and - setters. This will generate the function declaration and unwrap the - |this| object. Subclasses are expected to override the generate_code - function to do the rest of the work. This function should return a - CGThing which is already properly indented. - """ - def __init__(self, descriptor, name, args, unwrapFailureCode=None): - CGAbstractExternMethod.__init__(self, descriptor, name, "u8", args) - - if unwrapFailureCode is None: - self.unwrapFailureCode = ( - 'throw_type_error(cx, "\\"this\\" object does not ' - 'implement interface %s.");\n' - 'return 0;' % descriptor.interface.identifier.name) - else: - self.unwrapFailureCode = unwrapFailureCode - - def definition_body(self): - # Our descriptor might claim that we're not castable, simply because - # we're someone's consequential interface. But for this-unwrapping, we - # know that we're the real deal. So fake a descriptor here for - # consumption by FailureFatalCastableObjectUnwrapper. - unwrapThis = str(CastableObjectUnwrapper( - FakeCastableDescriptor(self.descriptor), - "obj.handle()", self.unwrapFailureCode, "object")) - unwrapThis = CGGeneric( - "let args = CallArgs::from_vp(vp, argc);\n" - "let thisobj = args.thisv();\n" - "if !thisobj.get().is_null_or_undefined() && !thisobj.get().is_object() {\n" - " return JSFalse;\n" - "}\n" - "let obj = if thisobj.get().is_object() {\n" - " RootedObject::new(cx, thisobj.get().to_object())\n" - "} else {\n" - " RootedObject::new(cx, GetGlobalForObjectCrossCompartment(JS_CALLEE(cx, vp).to_object_or_null()))\n" - "};\n" - "\n" - "let this: Root<%s> = %s;\n" % (self.descriptor.concreteType, unwrapThis)) - return CGList([ unwrapThis, self.generate_code() ], "\n") - - def generate_code(self): - assert(False) # Override me - - class CGAbstractStaticBindingMethod(CGAbstractMethod): """ Common class to generate the JSNatives for all our static methods, getters @@ -2767,21 +2721,6 @@ let global = global_object_for_js_object(JS_CALLEE(cx, vp).to_object()); def generate_code(self): assert False # Override me - -class CGGenericMethod(CGAbstractBindingMethod): - """ - A class for generating the C++ code for an IDL method.. - """ - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', 'vp')] - CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args) - - def generate_code(self): - return CGGeneric( - "let _info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "return CallJitMethodOp(_info, cx, obj.handle(), this.r() as *const _ as *const libc::c_void as *mut libc::c_void, argc, vp);") - class CGSpecializedMethod(CGAbstractExternMethod): """ A class for generating the C++ code for a specialized method that the JIT @@ -2825,30 +2764,6 @@ class CGStaticMethod(CGAbstractStaticBindingMethod): call = CGMethodCall(["global.r()"], nativeName, True, self.descriptor, self.method) return CGList([setupArgs, call]) -class CGGenericGetter(CGAbstractBindingMethod): - """ - A class for generating the C++ code for an IDL attribute getter. - """ - def __init__(self, descriptor, lenientThis=False): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', 'vp')] - if lenientThis: - name = "genericLenientGetter" - unwrapFailureCode = ( - "assert!(JS_IsExceptionPending(cx) == 0);\n" - "*vp = UndefinedValue();\n" - "return 1;") - else: - name = "genericGetter" - unwrapFailureCode = None - CGAbstractBindingMethod.__init__(self, descriptor, name, args, - unwrapFailureCode) - - def generate_code(self): - return CGGeneric( - "let info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "return CallJitGetterOp(info, cx, obj.handle(), this.r() as *const _ as *const libc::c_void as *mut libc::c_void, argc, vp);") - class CGSpecializedGetter(CGAbstractExternMethod): """ A class for generating the code for a specialized attribute getter @@ -2900,34 +2815,6 @@ class CGStaticGetter(CGAbstractStaticBindingMethod): self.attr) return CGList([setupArgs, call]) - -class CGGenericSetter(CGAbstractBindingMethod): - """ - A class for generating the Rust code for an IDL attribute setter. - """ - def __init__(self, descriptor, lenientThis=False): - args = [Argument('*mut JSContext', 'cx'), Argument('libc::c_uint', 'argc'), - Argument('*mut JSVal', 'vp')] - if lenientThis: - name = "genericLenientSetter" - unwrapFailureCode = ( - "assert!(JS_IsExceptionPending(cx) == 0);\n" - "return 1;") - else: - name = "genericSetter" - unwrapFailureCode = None - CGAbstractBindingMethod.__init__(self, descriptor, name, args, - unwrapFailureCode) - - def generate_code(self): - return CGGeneric( - "let info: *const JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" - "if CallJitSetterOp(info, cx, obj.handle(), this.r() as *const _ as *const libc::c_void as *mut libc::c_void, argc, vp) == 0 {\n" - " return 0;\n" - "}\n" - "*vp = UndefinedValue();\n" - "return 1;") - class CGSpecializedSetter(CGAbstractExternMethod): """ A class for generating the code for a specialized attribute setter @@ -4641,8 +4528,6 @@ class CGDescriptor(CGThing): # cgThings.append(CGGetConstructorObjectMethod(descriptor)) pass - (hasMethod, hasGetter, hasLenientGetter, - hasSetter, hasLenientSetter) = False, False, False, False, False for m in descriptor.interface.members: if (m.isMethod() and (not m.isIdentifierLess() or m == descriptor.operations["Stringifier"])): @@ -4652,7 +4537,6 @@ class CGDescriptor(CGThing): elif not descriptor.interface.isCallback(): cgThings.append(CGSpecializedMethod(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m)) - hasMethod = True elif m.isAttr(): if m.stringifier: raise TypeError("Stringifier attributes not supported yet. " @@ -4664,10 +4548,6 @@ class CGDescriptor(CGThing): cgThings.append(CGStaticGetter(descriptor, m)) elif not descriptor.interface.isCallback(): cgThings.append(CGSpecializedGetter(descriptor, m)) - if m.hasLenientThis(): - hasLenientGetter = True - else: - hasGetter = True if not m.readonly: if m.isStatic(): @@ -4675,27 +4555,12 @@ class CGDescriptor(CGThing): cgThings.append(CGStaticSetter(descriptor, m)) elif not descriptor.interface.isCallback(): cgThings.append(CGSpecializedSetter(descriptor, m)) - if m.hasLenientThis(): - hasLenientSetter = True - else: - hasSetter = True elif m.getExtendedAttribute("PutForwards"): cgThings.append(CGSpecializedForwardingSetter(descriptor, m)) - hasSetter = True if (not m.isStatic() and not descriptor.interface.isCallback()): cgThings.append(CGMemberJITInfo(descriptor, m)) - if hasMethod: - cgThings.append(CGGenericMethod(descriptor)) - if hasGetter: - cgThings.append(CGGenericGetter(descriptor)) - if hasLenientGetter: - cgThings.append(CGGenericGetter(descriptor, lenientThis=True)) - if hasSetter: - cgThings.append(CGGenericSetter(descriptor)) - if hasLenientSetter: - cgThings.append(CGGenericSetter(descriptor, lenientThis=True)) if descriptor.concrete: cgThings.append(CGClassFinalizeHook(descriptor)) @@ -5128,6 +4993,9 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{NativeProperties, NativePropertyHooks}', 'dom::bindings::utils::ConstantVal::{IntVal, UintVal}', 'dom::bindings::utils::NonNullJSNative', + 'dom::bindings::utils::{generic_getter, generic_lenient_getter}', + 'dom::bindings::utils::{generic_lenient_setter, generic_method}', + 'dom::bindings::utils::generic_setter', 'dom::bindings::trace::{JSTraceable, RootedTraceable}', 'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}', 'dom::bindings::callback::{CallSetup,ExceptionHandling}', @@ -5756,6 +5624,15 @@ class GlobalGenRoots(): CGGeneric(AUTOGENERATED_WARNING_COMMENT), CGGeneric("pub const MAX_PROTO_CHAIN_LENGTH: usize = %d;\n\n" % config.maxProtoChainLength), CGNonNamespacedEnum('ID', protos, [0], deriving="PartialEq, Copy, Clone", repr="u16"), + CGWrapper(CGIndenter(CGList([CGGeneric('"' + name + '"') for name in protos], + ",\n"), + indentLevel=4), + pre="static INTERFACES: [&'static str; %d] = [\n" % len(protos), + post="\n];\n\n"), + CGGeneric("pub fn proto_id_to_name(proto_id: u16) -> &'static str {\n" + " debug_assert!(proto_id < ID::Count as u16);\n" + " INTERFACES[proto_id as usize]\n" + "}\n\n"), CGNonNamespacedEnum('Proxies', proxies, [0], deriving="PartialEq, Copy, Clone"), ]) diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index 317744907c7..1f29eeb687d 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -41,17 +41,16 @@ use dom::bindings::utils::{Reflectable, Reflector, DOMClass}; use util::str::DOMString; use js; -use js::glue::{RUST_JSID_TO_STRING, RUST_JSID_IS_STRING}; -use js::glue::RUST_JS_NumberValue; +use js::glue::{GetProxyPrivate, IsWrapper, RUST_JS_NumberValue}; +use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING, UnwrapObject}; use js::rust::{ToUint64, ToInt64}; use js::rust::{ToUint32, ToInt32}; use js::rust::{ToUint16, ToNumber, ToBoolean, ToString}; -use js::jsapi::{JSContext, JSObject, JSString}; -use js::jsapi::{JS_StringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, JS_GetTwoByteStringCharsAndLength}; -use js::jsapi::{JS_NewUCStringCopyN, JS_NewStringCopyN}; -use js::jsapi::{JS_WrapValue}; -use js::jsapi::{JSClass, JS_GetClass}; -use js::jsapi::{HandleId, HandleValue, HandleObject, MutableHandleValue}; +use js::jsapi::{HandleId, HandleObject, HandleValue, JS_GetClass}; +use js::jsapi::{JS_GetLatin1StringCharsAndLength, JS_GetReservedSlot}; +use js::jsapi::{JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyN}; +use js::jsapi::{JS_NewUCStringCopyN, JS_StringHasLatin1Chars, JS_WrapValue}; +use js::jsapi::{JSClass, JSContext, JSObject, JSString, MutableHandleValue}; use js::jsval::JSVal; use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value}; use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue}; @@ -504,25 +503,27 @@ pub fn is_dom_proxy(obj: *mut JSObject) -> bool { // globals and non-globals. pub const DOM_OBJECT_SLOT: u32 = 0; -/// Get the DOM object from the given reflector. -pub unsafe fn native_from_reflector<T>(obj: *mut JSObject) -> *const T { - use js::jsapi::JS_GetReservedSlot; - use js::glue::GetProxyPrivate; - +/// Get the private pointer of a DOM object from a given reflector. +unsafe fn private_from_reflector(obj: *mut JSObject) -> *const libc::c_void { let clasp = JS_GetClass(obj); let value = if is_dom_class(clasp) { JS_GetReservedSlot(obj, DOM_OBJECT_SLOT) } else { - assert!(is_dom_proxy(obj)); + debug_assert!(is_dom_proxy(obj)); GetProxyPrivate(obj) }; if value.is_undefined() { ptr::null() } else { - value.to_private() as *const T + value.to_private() } } +/// Get the DOM object from the given reflector. +pub unsafe fn native_from_reflector<T>(obj: *mut JSObject) -> *const T { + private_from_reflector(obj) as *const T +} + /// Get the `DOMClass` from `obj`, or `Err(())` if `obj` is not a DOM object. unsafe fn get_dom_class(obj: *mut JSObject) -> Result<DOMClass, ()> { use dom::bindings::utils::DOMJSClass; @@ -543,47 +544,57 @@ unsafe fn get_dom_class(obj: *mut JSObject) -> Result<DOMClass, ()> { return Err(()); } -/// Get an `Unrooted<T>` for the given DOM object, unwrapping any wrapper -/// around it first, and checking if the object is of the correct type. +/// Get a `*const libc::c_void` for the given DOM object, unwrapping any +/// wrapper around it first, and checking if the object is of the correct type. /// /// Returns Err(()) if `obj` is an opaque security wrapper or if the object is -/// not a reflector for a DOM object of the given type (as defined by the +/// not an object for a DOM object of the given type (as defined by the /// proto_id and proto_depth). -pub fn native_from_reflector_jsmanaged<T>(mut obj: *mut JSObject) -> Result<Root<T>, ()> - where T: Reflectable + IDLInterface -{ - use js::glue::{IsWrapper, UnwrapObject}; - - unsafe { - let dom_class = try!(get_dom_class(obj).or_else(|_| { - if IsWrapper(obj) == 1 { - debug!("found wrapper"); - obj = UnwrapObject(obj, /* stopAtOuter = */ 0); - if obj.is_null() { - debug!("unwrapping security wrapper failed"); - Err(()) - } else { - assert!(IsWrapper(obj) == 0); - debug!("unwrapped successfully"); - get_dom_class(obj) - } - } else { - debug!("not a dom wrapper"); +pub unsafe fn private_from_proto_chain(mut obj: *mut JSObject, + proto_id: u16, proto_depth: u16) + -> Result<*const libc::c_void, ()> { + let dom_class = try!(get_dom_class(obj).or_else(|_| { + if IsWrapper(obj) == 1 { + debug!("found wrapper"); + obj = UnwrapObject(obj, /* stopAtOuter = */ 0); + if obj.is_null() { + debug!("unwrapping security wrapper failed"); Err(()) + } else { + assert!(IsWrapper(obj) == 0); + debug!("unwrapped successfully"); + get_dom_class(obj) } - })); - - let proto_id = <T as IDLInterface>::get_prototype_id(); - let proto_depth = <T as IDLInterface>::get_prototype_depth(); - if dom_class.interface_chain[proto_depth] == proto_id { - debug!("good prototype"); - let native = native_from_reflector(obj); - assert!(!native.is_null()); - Ok(Root::new(NonZero::new(native))) } else { - debug!("bad prototype"); + debug!("not a dom wrapper"); Err(()) } + })); + + if dom_class.interface_chain[proto_depth as usize] as u16 == proto_id { + debug!("good prototype"); + Ok(private_from_reflector(obj)) + } else { + debug!("bad prototype"); + Err(()) + } +} + +/// Get a `Root<T>` for the given DOM object, unwrapping any wrapper +/// around it first, and checking if the object is of the correct type. +/// +/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is +/// not a reflector for a DOM object of the given type (as defined by the +/// proto_id and proto_depth). +pub fn native_from_reflector_jsmanaged<T>(obj: *mut JSObject) -> Result<Root<T>, ()> + where T: Reflectable + IDLInterface +{ + let proto_id = <T as IDLInterface>::get_prototype_id() as u16; + let proto_depth = <T as IDLInterface>::get_prototype_depth() as u16; + unsafe { + private_from_proto_chain(obj, proto_id, proto_depth).map(|obj| { + Root::new(NonZero::new(obj as *const T)) + }) } } diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs index 683e5e19feb..9c0567067db 100644 --- a/components/script/dom/bindings/error.rs +++ b/components/script/dom/bindings/error.rs @@ -4,6 +4,7 @@ //! Utilities to throw exceptions from Rust bindings. +use dom::bindings::codegen::PrototypeList::proto_id_to_name; use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::global::GlobalRef; use dom::domexception::{DOMException, DOMErrorName}; @@ -149,6 +150,15 @@ pub fn throw_not_in_union(cx: *mut JSContext, names: &'static str) { throw_type_error(cx, &error); } +/// Throw an exception to signal that a `JSObject` can not be converted to a +/// given DOM type. +pub fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) { + debug_assert!(unsafe { JS_IsExceptionPending(cx) } == 0); + let error = format!("\"this\" object does not implement interface {}.", + proto_id_to_name(proto_id)); + throw_type_error(cx, &error); +} + /// Format string used to throw javascript errors. static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [ '{' as libc::c_char, diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 43f920a4f02..c57de127dfc 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -6,8 +6,11 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; -use dom::bindings::conversions::{native_from_handleobject, is_dom_class, jsstring_to_str}; -use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error}; +use dom::bindings::conversions::{is_dom_class, jsstring_to_str}; +use dom::bindings::conversions::native_from_handleobject; +use dom::bindings::conversions::private_from_proto_chain; +use dom::bindings::error::{Error, ErrorResult, Fallible, throw_invalid_this}; +use dom::bindings::error::throw_type_error; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::trace::trace_object; @@ -24,8 +27,11 @@ use std::ptr; use std::cmp::PartialEq; use std::default::Default; use std::cell::UnsafeCell; -use js::glue::UnwrapObject; -use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT}; +use js::glue::{CallJitMethodOp, CallJitGetterOp, CallJitSetterOp, IsWrapper}; +use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT}; +use js::glue::{RUST_JSID_TO_INT, UnwrapObject}; +use js::jsapi::{CallArgs, GetGlobalForObjectCrossCompartment, JSJitInfo}; +use js::jsapi::JS_IsExceptionPending; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction, JSTraceOp}; use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype}; @@ -47,13 +53,12 @@ use js::jsapi::{ObjectOpResult, RootedObject, RootedValue, Heap, MutableHandleOb use js::jsapi::PropertyDefinitionBehavior; use js::jsapi::JSAutoCompartment; use js::jsapi::{DOMCallbacks, JSWrapObjectCallbacks}; -use js::jsval::JSVal; -use js::jsval::{PrivateValue, NullValue}; -use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue}; +use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue}; +use js::jsval::{PrivateValue, UInt32Value, UndefinedValue}; use js::rust::{GCMethods, ToString}; use js::glue::{WrapperNew, GetCrossCompartmentWrapper}; -use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT}; -use js::JSFUN_CONSTRUCTOR; +use js::{JS_ARGV, JS_CALLEE, JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE}; +use js::{JSPROP_PERMANENT, JSPROP_READONLY}; use js; use string_cache::{Atom, Namespace}; @@ -670,6 +675,91 @@ pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: HandleObject, JS_DeletePropertyById1(cx, object, id, bp) } +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) + -> u8 { + let args = CallArgs::from_vp(vp, argc); + let thisobj = args.thisv(); + if !thisobj.get().is_null_or_undefined() && !thisobj.get().is_object() { + return 0; + } + let obj = if thisobj.get().is_object() { + thisobj.get().to_object() + } else { + GetGlobalForObjectCrossCompartment(JS_CALLEE(cx, vp).to_object_or_null()) + }; + let obj = RootedObject::new(cx, obj); + let info = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp)); + let proto_id = (*info).protoID; + let depth = (*info).depth; + let this = match private_from_proto_chain(obj.ptr, proto_id, depth) { + Ok(val) => val, + Err(()) => { + if is_lenient { + debug_assert!(JS_IsExceptionPending(cx) == 0); + *vp = UndefinedValue(); + return 1; + } else { + throw_invalid_this(cx, proto_id); + return 0; + } + } + }; + call(info, cx, obj.handle(), this as *mut libc::c_void, argc, vp) +} + +/// Generic method of IDL interface. +pub unsafe extern fn generic_method(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, CallJitMethodOp) +} + +/// Generic getter of IDL interface. +pub unsafe extern fn generic_getter(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, CallJitGetterOp) +} + +/// Generic lenient getter of IDL interface. +pub unsafe extern fn generic_lenient_getter(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, true, CallJitGetterOp) +} + +unsafe extern fn call_setter(info: *const JSJitInfo, cx: *mut JSContext, + handle: HandleObject, this: *mut libc::c_void, + argc: u32, vp: *mut JSVal) + -> u8 { + if CallJitSetterOp(info, cx, handle, this, argc, vp) == 0 { + return 0; + } + *vp = UndefinedValue(); + 1 +} + +/// Generic setter of IDL interface. +pub unsafe extern fn generic_setter(cx: *mut JSContext, + argc: libc::c_uint, vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, false, call_setter) +} + +/// Generic lenient setter of IDL interface. +pub unsafe extern fn generic_lenient_setter(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal) + -> u8 { + generic_call(cx, argc, vp, true, call_setter) +} + /// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { match xml_name_type(qualified_name) { diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index b1228b4171f..02a810d184b 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -57,9 +57,6 @@ [Document interface: attribute commands] expected: FAIL - [Document interface: attribute onreadystatechange] - expected: FAIL - [Document interface: attribute fgColor] expected: FAIL |