mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #10819 - nox:call-without-new, r=Ms2ger
Refactor the `call` hook on non-callback interface objects (fixes #10744) <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10819) <!-- Reviewable:end -->
This commit is contained in:
commit
a92a6360cf
6 changed files with 67 additions and 49 deletions
|
@ -1897,20 +1897,24 @@ class CGInterfaceObjectJSClass(CGThing):
|
||||||
|
|
||||||
def define(self):
|
def define(self):
|
||||||
if self.descriptor.interface.ctor():
|
if self.descriptor.interface.ctor():
|
||||||
constructor = CONSTRUCT_HOOK_NAME
|
constructorBehavior = "InterfaceConstructorBehavior::call(%s)" % CONSTRUCT_HOOK_NAME
|
||||||
else:
|
else:
|
||||||
constructor = "throwing_constructor"
|
constructorBehavior = "InterfaceConstructorBehavior::throw()"
|
||||||
name = self.descriptor.interface.identifier.name
|
name = self.descriptor.interface.identifier.name
|
||||||
args = {
|
args = {
|
||||||
"constructor": constructor,
|
"constructorBehavior": constructorBehavior,
|
||||||
"id": name,
|
"id": name,
|
||||||
"representation": str_to_const_array("function %s() {\\n [native code]\\n}" % name),
|
"representation": str_to_const_array("function %s() {\\n [native code]\\n}" % name),
|
||||||
"depth": self.descriptor.prototypeDepth
|
"depth": self.descriptor.prototypeDepth
|
||||||
}
|
}
|
||||||
return """\
|
return """\
|
||||||
static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
|
static InterfaceObjectClass: NonCallbackInterfaceObjectClass = unsafe {
|
||||||
NonCallbackInterfaceObjectClass::new(%(constructor)s, %(representation)s,
|
NonCallbackInterfaceObjectClass::new(
|
||||||
PrototypeList::ID::%(id)s, %(depth)s);
|
%(constructorBehavior)s,
|
||||||
|
%(representation)s,
|
||||||
|
PrototypeList::ID::%(id)s,
|
||||||
|
%(depth)s)
|
||||||
|
};
|
||||||
""" % args
|
""" % args
|
||||||
|
|
||||||
|
|
||||||
|
@ -2449,10 +2453,8 @@ if <*mut JSObject>::needs_post_barrier(prototype.ptr) {
|
||||||
if self.descriptor.interface.hasInterfaceObject():
|
if self.descriptor.interface.hasInterfaceObject():
|
||||||
properties["name"] = str_to_const_array(name)
|
properties["name"] = str_to_const_array(name)
|
||||||
if self.descriptor.interface.ctor():
|
if self.descriptor.interface.ctor():
|
||||||
properties["constructor"] = CONSTRUCT_HOOK_NAME
|
|
||||||
properties["length"] = methodLength(self.descriptor.interface.ctor())
|
properties["length"] = methodLength(self.descriptor.interface.ctor())
|
||||||
else:
|
else:
|
||||||
properties["constructor"] = "throwing_constructor"
|
|
||||||
properties["length"] = 0
|
properties["length"] = 0
|
||||||
if self.descriptor.interface.parent:
|
if self.descriptor.interface.parent:
|
||||||
parentName = toBindingNamespace(self.descriptor.getParentName())
|
parentName = toBindingNamespace(self.descriptor.getParentName())
|
||||||
|
@ -5400,9 +5402,9 @@ class CGBindingRoot(CGThing):
|
||||||
'js::rust::{GCMethods, define_methods, define_properties}',
|
'js::rust::{GCMethods, define_methods, define_properties}',
|
||||||
'dom::bindings',
|
'dom::bindings',
|
||||||
'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::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
|
||||||
'dom::bindings::interface::{create_interface_prototype_object, create_named_constructors}',
|
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
|
||||||
'dom::bindings::interface::{create_noncallback_interface_object}',
|
'dom::bindings::interface::{create_named_constructors, 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}',
|
||||||
|
@ -5416,8 +5418,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
|
'dom::bindings::utils::{generic_method, generic_setter, get_array_index_from_id}',
|
||||||
'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
|
'dom::bindings::utils::{get_dictionary_property, get_property_on_prototype}',
|
||||||
'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
|
'dom::bindings::utils::{get_proto_or_iface_array, has_property_on_prototype}',
|
||||||
'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property}',
|
'dom::bindings::utils::{is_platform_object, resolve_global, set_dictionary_property, trace_global}',
|
||||||
'dom::bindings::utils::{throwing_constructor, trace_global}',
|
|
||||||
'dom::bindings::trace::{JSTraceable, RootedTraceable}',
|
'dom::bindings::trace::{JSTraceable, RootedTraceable}',
|
||||||
'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
|
'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
|
||||||
'dom::bindings::callback::{CallSetup,ExceptionHandling}',
|
'dom::bindings::callback::{CallSetup,ExceptionHandling}',
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
use dom::bindings::codegen::PrototypeList;
|
use dom::bindings::codegen::PrototypeList;
|
||||||
use dom::bindings::conversions::get_dom_class;
|
use dom::bindings::conversions::get_dom_class;
|
||||||
use dom::bindings::utils::get_proto_or_iface_array;
|
use dom::bindings::utils::get_proto_or_iface_array;
|
||||||
|
use js::error::throw_type_error;
|
||||||
use js::glue::UncheckedUnwrapObject;
|
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::{JSNative, JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2};
|
||||||
use js::jsapi::{JS_DefineProperty4, JS_GetClass, JS_GetFunctionObject, JS_GetPrototype};
|
use js::jsapi::{JS_DefineProperty4, JS_GetClass, JS_GetFunctionObject, JS_GetPrototype};
|
||||||
use js::jsapi::{JS_InternString, JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject};
|
use js::jsapi::{JS_InternString, JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject};
|
||||||
use js::jsapi::{JS_NewObjectWithUniqueType, JS_NewStringCopyZ, JS_DefineProperty};
|
use js::jsapi::{JS_NewObjectWithUniqueType, JS_NewStringCopyZ, JS_DefineProperty};
|
||||||
|
@ -93,10 +94,6 @@ unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext,
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A constructor class hook.
|
|
||||||
pub type ConstructorClassHook =
|
|
||||||
unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool;
|
|
||||||
|
|
||||||
/// The class of a non-callback interface object.
|
/// The class of a non-callback interface object.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct NonCallbackInterfaceObjectClass {
|
pub struct NonCallbackInterfaceObjectClass {
|
||||||
|
@ -114,8 +111,8 @@ 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 unsafe fn new(
|
||||||
constructor: ConstructorClassHook,
|
constructor_behavior: InterfaceConstructorBehavior,
|
||||||
string_rep: &'static [u8],
|
string_rep: &'static [u8],
|
||||||
proto_id: PrototypeList::ID,
|
proto_id: PrototypeList::ID,
|
||||||
proto_depth: u16)
|
proto_depth: u16)
|
||||||
|
@ -132,8 +129,8 @@ impl NonCallbackInterfaceObjectClass {
|
||||||
resolve: None,
|
resolve: None,
|
||||||
convert: None,
|
convert: None,
|
||||||
finalize: None,
|
finalize: None,
|
||||||
call: Some(constructor),
|
call: constructor_behavior.call,
|
||||||
construct: Some(constructor),
|
construct: constructor_behavior.construct,
|
||||||
hasInstance: Some(has_instance_hook),
|
hasInstance: Some(has_instance_hook),
|
||||||
trace: None,
|
trace: None,
|
||||||
spec: ClassSpec {
|
spec: ClassSpec {
|
||||||
|
@ -183,6 +180,34 @@ impl NonCallbackInterfaceObjectClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
call: JSNative,
|
||||||
|
construct: JSNative,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InterfaceConstructorBehavior {
|
||||||
|
/// An interface constructor that unconditionally throws a type error.
|
||||||
|
pub const fn throw() -> InterfaceConstructorBehavior {
|
||||||
|
InterfaceConstructorBehavior {
|
||||||
|
call: Some(invalid_constructor),
|
||||||
|
construct: Some(invalid_constructor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An interface constructor that calls a native Rust function.
|
||||||
|
pub const fn call(hook: ConstructorClassHook) -> InterfaceConstructorBehavior {
|
||||||
|
InterfaceConstructorBehavior {
|
||||||
|
call: Some(non_new_constructor),
|
||||||
|
construct: Some(hook),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create and define the interface object of a callback interface.
|
/// Create and define the interface object of a callback interface.
|
||||||
pub unsafe fn create_callback_interface_object(
|
pub unsafe fn create_callback_interface_object(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
|
@ -380,3 +405,21 @@ unsafe fn define_on_global_object(
|
||||||
0,
|
0,
|
||||||
None, None));
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use dom::browsingcontext;
|
||||||
use dom::window;
|
use dom::window;
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use js;
|
use js;
|
||||||
use js::error::throw_type_error;
|
|
||||||
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
||||||
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
|
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
|
||||||
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
|
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
|
||||||
|
@ -35,7 +34,7 @@ use js::jsval::{JSVal};
|
||||||
use js::jsval::{PrivateValue, UndefinedValue};
|
use js::jsval::{PrivateValue, UndefinedValue};
|
||||||
use js::rust::{GCMethods, ToString};
|
use js::rust::{GCMethods, ToString};
|
||||||
use js::{JS_CALLEE};
|
use js::{JS_CALLEE};
|
||||||
use libc::{self, c_uint};
|
use libc;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
@ -123,16 +122,6 @@ pub fn get_proto_or_iface_array(global: *mut JSObject) -> *mut ProtoOrIfaceArray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A throwing constructor, for those interfaces that have neither
|
|
||||||
/// `NoInterfaceObject` nor `Constructor`.
|
|
||||||
pub unsafe extern "C" fn throwing_constructor(cx: *mut JSContext,
|
|
||||||
_argc: c_uint,
|
|
||||||
_vp: *mut JSVal)
|
|
||||||
-> bool {
|
|
||||||
throw_type_error(cx, "Illegal constructor.");
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An array of *mut JSObject of size PROTO_OR_IFACE_LENGTH.
|
/// An array of *mut JSObject of size PROTO_OR_IFACE_LENGTH.
|
||||||
pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH];
|
pub type ProtoOrIfaceArray = [*mut JSObject; PROTO_OR_IFACE_LENGTH];
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,3 @@
|
||||||
[Array with mixed types]
|
[Array with mixed types]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Blob constructor with no arguments, without 'new']
|
|
||||||
bug: https://github.com/servo/servo/issues/10744
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[Event-constructors.html]
|
|
||||||
type: testharness
|
|
||||||
[Event constructors 4]
|
|
||||||
expected: FAIL
|
|
||||||
bug: https://github.com/servo/servo/issues/10744
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[urlsearchparams-constructor.html]
|
|
||||||
type: testharness
|
|
||||||
[URLSearchParams constructor, empty.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue