mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
All interface objects now share the same hasInstance
This commit is contained in:
parent
87c6889f44
commit
bb9d3692c7
2 changed files with 39 additions and 47 deletions
|
@ -1892,13 +1892,14 @@ class CGInterfaceObjectJSClass(CGThing):
|
||||||
constructor = "throwing_constructor"
|
constructor = "throwing_constructor"
|
||||||
args = {
|
args = {
|
||||||
"constructor": constructor,
|
"constructor": constructor,
|
||||||
"hasInstance": HASINSTANCE_HOOK_NAME,
|
|
||||||
"name": self.descriptor.interface.identifier.name,
|
"name": self.descriptor.interface.identifier.name,
|
||||||
|
"id": self.descriptor.interface.identifier.name,
|
||||||
|
"depth": self.descriptor.prototypeDepth
|
||||||
}
|
}
|
||||||
return """\
|
return """\
|
||||||
static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
|
static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
|
||||||
NonCallbackInterfaceObjectClass::new(%(constructor)s, %(hasInstance)s,
|
NonCallbackInterfaceObjectClass::new(%(constructor)s, fun_to_string,
|
||||||
fun_to_string);
|
PrototypeList::ID::%(id)s, %(depth)s);
|
||||||
""" % args
|
""" % args
|
||||||
|
|
||||||
|
|
||||||
|
@ -4735,29 +4736,6 @@ let args = CallArgs::from_vp(vp, argc);
|
||||||
return CGList([preamble, callGenerator])
|
return CGList([preamble, callGenerator])
|
||||||
|
|
||||||
|
|
||||||
class CGClassHasInstanceHook(CGAbstractExternMethod):
|
|
||||||
def __init__(self, descriptor):
|
|
||||||
args = [Argument('*mut JSContext', 'cx'),
|
|
||||||
Argument('HandleObject', 'obj'),
|
|
||||||
Argument('MutableHandleValue', 'value'),
|
|
||||||
Argument('*mut bool', 'rval')]
|
|
||||||
assert descriptor.interface.hasInterfaceObject() and not descriptor.interface.isCallback()
|
|
||||||
CGAbstractExternMethod.__init__(self, descriptor, HASINSTANCE_HOOK_NAME,
|
|
||||||
'bool', args)
|
|
||||||
|
|
||||||
def definition_body(self):
|
|
||||||
id = "PrototypeList::ID::%s" % self.descriptor.interface.identifier.name
|
|
||||||
return CGGeneric("""\
|
|
||||||
match has_instance(cx, obj, value.handle(), %(id)s, %(index)s) {
|
|
||||||
Ok(result) => {
|
|
||||||
*rval = result;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
Err(()) => false,
|
|
||||||
}
|
|
||||||
""" % {"id": id, "index": self.descriptor.prototypeDepth})
|
|
||||||
|
|
||||||
|
|
||||||
class CGClassFunToStringHook(CGAbstractExternMethod):
|
class CGClassFunToStringHook(CGAbstractExternMethod):
|
||||||
"""
|
"""
|
||||||
A hook to convert functions to strings.
|
A hook to convert functions to strings.
|
||||||
|
@ -4940,7 +4918,6 @@ class CGDescriptor(CGThing):
|
||||||
cgThings.append(CGClassConstructHook(descriptor, ctor))
|
cgThings.append(CGClassConstructHook(descriptor, ctor))
|
||||||
if not descriptor.interface.isCallback():
|
if not descriptor.interface.isCallback():
|
||||||
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
||||||
cgThings.append(CGClassHasInstanceHook(descriptor))
|
|
||||||
cgThings.append(CGClassFunToStringHook(descriptor))
|
cgThings.append(CGClassFunToStringHook(descriptor))
|
||||||
|
|
||||||
if not descriptor.interface.isCallback():
|
if not descriptor.interface.isCallback():
|
||||||
|
@ -5367,7 +5344,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
|
'dom::bindings::global::{GlobalRef, global_root_from_object, global_root_from_reflector}',
|
||||||
'dom::bindings::interface::{NonCallbackInterfaceObjectClass, create_callback_interface_object}',
|
'dom::bindings::interface::{NonCallbackInterfaceObjectClass, create_callback_interface_object}',
|
||||||
'dom::bindings::interface::{create_interface_prototype_object, create_named_constructors}',
|
'dom::bindings::interface::{create_interface_prototype_object, create_named_constructors}',
|
||||||
'dom::bindings::interface::{create_noncallback_interface_object, has_instance}',
|
'dom::bindings::interface::{create_noncallback_interface_object}',
|
||||||
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
|
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
|
||||||
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
|
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
|
||||||
'dom::bindings::js::{JS, Root, RootedReference}',
|
'dom::bindings::js::{JS, Root, RootedReference}',
|
||||||
|
|
|
@ -11,8 +11,8 @@ use js::glue::UncheckedUnwrapObject;
|
||||||
use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
|
use js::jsapi::{Class, ClassExtension, ClassSpec, GetGlobalForObjectCrossCompartment};
|
||||||
use js::jsapi::{HandleObject, HandleValue, JSClass, JSContext, JSFunctionSpec};
|
use js::jsapi::{HandleObject, HandleValue, JSClass, JSContext, JSFunctionSpec};
|
||||||
use js::jsapi::{JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2};
|
use js::jsapi::{JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2};
|
||||||
use js::jsapi::{JS_DefineProperty4, JS_GetFunctionObject, JS_GetPrototype, JS_InternString};
|
use js::jsapi::{JS_DefineProperty4, JS_GetClass, JS_GetFunctionObject, JS_GetPrototype};
|
||||||
use js::jsapi::{JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject};
|
use js::jsapi::{JS_InternString, JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject};
|
||||||
use js::jsapi::{JS_NewObjectWithUniqueType, JS_DefineProperty, MutableHandleObject};
|
use js::jsapi::{JS_NewObjectWithUniqueType, JS_DefineProperty, MutableHandleObject};
|
||||||
use js::jsapi::{MutableHandleValue, ObjectOps, RootedObject, RootedString, RootedValue, Value};
|
use js::jsapi::{MutableHandleValue, ObjectOps, RootedObject, RootedString, RootedValue, Value};
|
||||||
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
|
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
|
||||||
|
@ -83,14 +83,6 @@ pub fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'stat
|
||||||
pub type ConstructorClassHook =
|
pub type ConstructorClassHook =
|
||||||
unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool;
|
unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool;
|
||||||
|
|
||||||
/// A has_instance class hook.
|
|
||||||
pub type HasInstanceClassHook =
|
|
||||||
unsafe extern "C" fn(cx: *mut JSContext,
|
|
||||||
obj: HandleObject,
|
|
||||||
vp: MutableHandleValue,
|
|
||||||
bp: *mut bool)
|
|
||||||
-> bool;
|
|
||||||
|
|
||||||
/// A fun_to_string class hook.
|
/// A fun_to_string class hook.
|
||||||
pub type FunToStringHook =
|
pub type FunToStringHook =
|
||||||
unsafe extern "C" fn(cx: *mut JSContext,
|
unsafe extern "C" fn(cx: *mut JSContext,
|
||||||
|
@ -103,15 +95,21 @@ pub type FunToStringHook =
|
||||||
pub struct NonCallbackInterfaceObjectClass {
|
pub struct NonCallbackInterfaceObjectClass {
|
||||||
/// The SpiderMonkey Class structure.
|
/// The SpiderMonkey Class structure.
|
||||||
pub class: Class,
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for NonCallbackInterfaceObjectClass {}
|
unsafe impl Sync for NonCallbackInterfaceObjectClass {}
|
||||||
|
|
||||||
impl NonCallbackInterfaceObjectClass {
|
impl NonCallbackInterfaceObjectClass {
|
||||||
/// Create a new `NonCallbackInterfaceObjectClass` structure.
|
/// Create a new `NonCallbackInterfaceObjectClass` structure.
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
constructor: ConstructorClassHook,
|
constructor: ConstructorClassHook,
|
||||||
has_instance: HasInstanceClassHook,
|
fun_to_string: FunToStringHook,
|
||||||
fun_to_string: FunToStringHook)
|
proto_id: PrototypeList::ID,
|
||||||
|
proto_depth: u16)
|
||||||
-> NonCallbackInterfaceObjectClass {
|
-> NonCallbackInterfaceObjectClass {
|
||||||
NonCallbackInterfaceObjectClass {
|
NonCallbackInterfaceObjectClass {
|
||||||
class: Class {
|
class: Class {
|
||||||
|
@ -126,8 +124,8 @@ impl NonCallbackInterfaceObjectClass {
|
||||||
convert: None,
|
convert: None,
|
||||||
finalize: None,
|
finalize: None,
|
||||||
call: Some(constructor),
|
call: Some(constructor),
|
||||||
hasInstance: Some(has_instance),
|
|
||||||
construct: Some(constructor),
|
construct: Some(constructor),
|
||||||
|
hasInstance: Some(has_instance_hook),
|
||||||
trace: None,
|
trace: None,
|
||||||
spec: ClassSpec {
|
spec: ClassSpec {
|
||||||
createConstructor: None,
|
createConstructor: None,
|
||||||
|
@ -162,6 +160,8 @@ impl NonCallbackInterfaceObjectClass {
|
||||||
funToString: Some(fun_to_string),
|
funToString: Some(fun_to_string),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
proto_id: proto_id,
|
||||||
|
proto_depth: proto_depth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,14 +257,26 @@ pub unsafe fn create_named_constructors(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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.
|
/// Return whether a value is an instance of a given prototype.
|
||||||
/// http://heycam.github.io/webidl/#es-interface-hasinstance
|
/// http://heycam.github.io/webidl/#es-interface-hasinstance
|
||||||
pub unsafe fn has_instance(
|
unsafe fn has_instance(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
interface_object: HandleObject,
|
interface_object: HandleObject,
|
||||||
value: HandleValue,
|
value: HandleValue)
|
||||||
id: PrototypeList::ID,
|
|
||||||
index: usize)
|
|
||||||
-> Result<bool, ()> {
|
-> Result<bool, ()> {
|
||||||
if !value.is_object() {
|
if !value.is_object() {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
|
@ -272,8 +284,11 @@ pub unsafe fn has_instance(
|
||||||
}
|
}
|
||||||
let mut value = RootedObject::new(cx, value.to_object());
|
let mut value = RootedObject::new(cx, value.to_object());
|
||||||
|
|
||||||
|
let js_class = JS_GetClass(interface_object.get());
|
||||||
|
let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass);
|
||||||
|
|
||||||
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(value.ptr, /* stopAtOuter = */ 0)) {
|
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(value.ptr, /* stopAtOuter = */ 0)) {
|
||||||
if dom_class.interface_chain[index] == id {
|
if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id {
|
||||||
// Step 4.
|
// Step 4.
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
@ -283,7 +298,7 @@ pub unsafe fn has_instance(
|
||||||
let global = GetGlobalForObjectCrossCompartment(interface_object.get());
|
let global = GetGlobalForObjectCrossCompartment(interface_object.get());
|
||||||
assert!(!global.is_null());
|
assert!(!global.is_null());
|
||||||
let proto_or_iface_array = get_proto_or_iface_array(global);
|
let proto_or_iface_array = get_proto_or_iface_array(global);
|
||||||
let prototype = RootedObject::new(cx, (*proto_or_iface_array)[id as usize]);
|
let prototype = RootedObject::new(cx, (*proto_or_iface_array)[object_class.proto_id as usize]);
|
||||||
assert!(!prototype.ptr.is_null());
|
assert!(!prototype.ptr.is_null());
|
||||||
// Step 3 only concern legacy callback interface objects (i.e. NodeFilter).
|
// Step 3 only concern legacy callback interface objects (i.e. NodeFilter).
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue