mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Use safe JSContext when possible in interface.rs
This commit is contained in:
parent
8b070fef52
commit
78034a90d0
6 changed files with 194 additions and 176 deletions
|
@ -2651,8 +2651,8 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties):
|
||||||
"""
|
"""
|
||||||
unforgeables = []
|
unforgeables = []
|
||||||
|
|
||||||
defineUnforgeableAttrs = "define_guarded_properties(*cx, unforgeable_holder.handle(), %s, global);"
|
defineUnforgeableAttrs = "define_guarded_properties(cx, unforgeable_holder.handle(), %s, global);"
|
||||||
defineUnforgeableMethods = "define_guarded_methods(*cx, unforgeable_holder.handle(), %s, global);"
|
defineUnforgeableMethods = "define_guarded_methods(cx, unforgeable_holder.handle(), %s, global);"
|
||||||
|
|
||||||
unforgeableMembers = [
|
unforgeableMembers = [
|
||||||
(defineUnforgeableAttrs, properties.unforgeable_attrs),
|
(defineUnforgeableAttrs, properties.unforgeable_attrs),
|
||||||
|
@ -2762,7 +2762,7 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||||
("define_guarded_methods", self.properties.methods),
|
("define_guarded_methods", self.properties.methods),
|
||||||
("define_guarded_constants", self.properties.consts)
|
("define_guarded_constants", self.properties.consts)
|
||||||
]
|
]
|
||||||
members = ["%s(*cx, obj.handle(), %s, obj.handle());" % (function, array.variableName())
|
members = ["%s(cx, obj.handle(), %s, obj.handle());" % (function, array.variableName())
|
||||||
for (function, array) in pairs if array.length() > 0]
|
for (function, array) in pairs if array.length() > 0]
|
||||||
values["members"] = "\n".join(members)
|
values["members"] = "\n".join(members)
|
||||||
|
|
||||||
|
@ -2772,7 +2772,7 @@ let _rt = RootedTraceable::new(&*raw);
|
||||||
|
|
||||||
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
|
||||||
create_global_object(
|
create_global_object(
|
||||||
*cx,
|
cx,
|
||||||
&Class.base,
|
&Class.base,
|
||||||
raw as *const libc::c_void,
|
raw as *const libc::c_void,
|
||||||
_trace,
|
_trace,
|
||||||
|
@ -2911,7 +2911,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||||
rooted!(in(*cx) let proto = %(proto)s);
|
rooted!(in(*cx) let proto = %(proto)s);
|
||||||
assert!(!proto.is_null());
|
assert!(!proto.is_null());
|
||||||
rooted!(in(*cx) let mut namespace = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut namespace = ptr::null_mut::<JSObject>());
|
||||||
create_namespace_object(*cx, global, proto.handle(), &NAMESPACE_OBJECT_CLASS,
|
create_namespace_object(cx, global, proto.handle(), &NAMESPACE_OBJECT_CLASS,
|
||||||
%(methods)s, %(name)s, namespace.handle_mut());
|
%(methods)s, %(name)s, namespace.handle_mut());
|
||||||
assert!(!namespace.is_null());
|
assert!(!namespace.is_null());
|
||||||
assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
||||||
|
@ -2924,7 +2924,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
||||||
assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
|
assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
|
||||||
return CGGeneric("""\
|
return CGGeneric("""\
|
||||||
rooted!(in(*cx) let mut interface = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut interface = ptr::null_mut::<JSObject>());
|
||||||
create_callback_interface_object(*cx, global, sConstants, %(name)s, interface.handle_mut());
|
create_callback_interface_object(cx, global, sConstants, %(name)s, interface.handle_mut());
|
||||||
assert!(!interface.is_null());
|
assert!(!interface.is_null());
|
||||||
assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
||||||
(*cache)[PrototypeList::Constructor::%(id)s as usize] = interface.get();
|
(*cache)[PrototypeList::Constructor::%(id)s as usize] = interface.get();
|
||||||
|
@ -2976,7 +2976,7 @@ assert!(!prototype_proto.is_null());""" % getPrototypeProto)]
|
||||||
|
|
||||||
code.append(CGGeneric("""
|
code.append(CGGeneric("""
|
||||||
rooted!(in(*cx) let mut prototype = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut prototype = ptr::null_mut::<JSObject>());
|
||||||
create_interface_prototype_object(*cx,
|
create_interface_prototype_object(cx,
|
||||||
global.into(),
|
global.into(),
|
||||||
prototype_proto.handle().into(),
|
prototype_proto.handle().into(),
|
||||||
&PrototypeClass,
|
&PrototypeClass,
|
||||||
|
@ -3011,7 +3011,7 @@ assert!((*cache)[PrototypeList::ID::%(id)s as usize].is_null());
|
||||||
assert!(!interface_proto.is_null());
|
assert!(!interface_proto.is_null());
|
||||||
|
|
||||||
rooted!(in(*cx) let mut interface = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut interface = ptr::null_mut::<JSObject>());
|
||||||
create_noncallback_interface_object(*cx,
|
create_noncallback_interface_object(cx,
|
||||||
global.into(),
|
global.into(),
|
||||||
interface_proto.handle(),
|
interface_proto.handle(),
|
||||||
&INTERFACE_OBJECT_CLASS,
|
&INTERFACE_OBJECT_CLASS,
|
||||||
|
@ -3093,7 +3093,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
||||||
specs.append(CGGeneric("(%s as ConstructorClassHook, %s, %d)" % (hook, name, length)))
|
specs.append(CGGeneric("(%s as ConstructorClassHook, %s, %d)" % (hook, name, length)))
|
||||||
values = CGIndenter(CGList(specs, "\n"), 4)
|
values = CGIndenter(CGList(specs, "\n"), 4)
|
||||||
code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];"))
|
code.append(CGWrapper(values, pre="%s = [\n" % decl, post="\n];"))
|
||||||
code.append(CGGeneric("create_named_constructors(*cx, global, &named_constructors, prototype.handle());"))
|
code.append(CGGeneric("create_named_constructors(cx, global, &named_constructors, prototype.handle());"))
|
||||||
|
|
||||||
if self.descriptor.hasUnforgeableMembers:
|
if self.descriptor.hasUnforgeableMembers:
|
||||||
# We want to use the same JSClass and prototype as the object we'll
|
# We want to use the same JSClass and prototype as the object we'll
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
//! WebIDL constants.
|
//! WebIDL constants.
|
||||||
|
|
||||||
|
use crate::script_runtime::JSContext;
|
||||||
use js::jsapi::JSPROP_READONLY;
|
use js::jsapi::JSPROP_READONLY;
|
||||||
use js::jsapi::{JSContext, JSPROP_ENUMERATE, JSPROP_PERMANENT};
|
use js::jsapi::{JSPROP_ENUMERATE, JSPROP_PERMANENT};
|
||||||
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
|
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
|
||||||
use js::rust::wrappers::JS_DefineProperty;
|
use js::rust::wrappers::JS_DefineProperty;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
@ -50,15 +51,17 @@ impl ConstantSpec {
|
||||||
|
|
||||||
/// Defines constants on `obj`.
|
/// Defines constants on `obj`.
|
||||||
/// Fails on JSAPI failure.
|
/// Fails on JSAPI failure.
|
||||||
pub unsafe fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &[ConstantSpec]) {
|
pub fn define_constants(cx: JSContext, obj: HandleObject, constants: &[ConstantSpec]) {
|
||||||
for spec in constants {
|
for spec in constants {
|
||||||
rooted!(in(cx) let value = spec.get_value());
|
rooted!(in(*cx) let value = spec.get_value());
|
||||||
assert!(JS_DefineProperty(
|
unsafe {
|
||||||
cx,
|
assert!(JS_DefineProperty(
|
||||||
obj,
|
*cx,
|
||||||
spec.name.as_ptr() as *const libc::c_char,
|
obj,
|
||||||
value.handle(),
|
spec.name.as_ptr() as *const libc::c_char,
|
||||||
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
|
value.handle(),
|
||||||
));
|
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::InterfaceObjectMap;
|
use crate::dom::bindings::codegen::InterfaceObjectMap;
|
||||||
use crate::dom::bindings::interface::is_exposed_in;
|
use crate::dom::bindings::interface::is_exposed_in;
|
||||||
use js::jsapi::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
use servo_config::prefs;
|
use servo_config::prefs;
|
||||||
|
|
||||||
|
@ -28,12 +28,7 @@ impl<T: Clone + Copy> Guard<T> {
|
||||||
/// Expose the value if the condition is satisfied.
|
/// Expose the value if the condition is satisfied.
|
||||||
///
|
///
|
||||||
/// The passed handle is the object on which the value may be exposed.
|
/// The passed handle is the object on which the value may be exposed.
|
||||||
pub unsafe fn expose(
|
pub fn expose(&self, cx: JSContext, obj: HandleObject, global: HandleObject) -> Option<T> {
|
||||||
&self,
|
|
||||||
cx: *mut JSContext,
|
|
||||||
obj: HandleObject,
|
|
||||||
global: HandleObject,
|
|
||||||
) -> Option<T> {
|
|
||||||
if self.condition.is_satisfied(cx, obj, global) {
|
if self.condition.is_satisfied(cx, obj, global) {
|
||||||
Some(self.value)
|
Some(self.value)
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,7 +40,7 @@ impl<T: Clone + Copy> Guard<T> {
|
||||||
/// A condition to expose things.
|
/// A condition to expose things.
|
||||||
pub enum Condition {
|
pub enum Condition {
|
||||||
/// The condition is satisfied if the function returns true.
|
/// The condition is satisfied if the function returns true.
|
||||||
Func(unsafe fn(*mut JSContext, HandleObject) -> bool),
|
Func(fn(JSContext, HandleObject) -> bool),
|
||||||
/// The condition is satisfied if the preference is set.
|
/// The condition is satisfied if the preference is set.
|
||||||
Pref(&'static str),
|
Pref(&'static str),
|
||||||
// The condition is satisfied if the interface is exposed in the global.
|
// The condition is satisfied if the interface is exposed in the global.
|
||||||
|
@ -55,12 +50,7 @@ pub enum Condition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Condition {
|
impl Condition {
|
||||||
unsafe fn is_satisfied(
|
fn is_satisfied(&self, cx: JSContext, obj: HandleObject, global: HandleObject) -> bool {
|
||||||
&self,
|
|
||||||
cx: *mut JSContext,
|
|
||||||
obj: HandleObject,
|
|
||||||
global: HandleObject,
|
|
||||||
) -> bool {
|
|
||||||
match *self {
|
match *self {
|
||||||
Condition::Pref(name) => prefs::pref_map().get(name).as_bool().unwrap_or(false),
|
Condition::Pref(name) => prefs::pref_map().get(name).as_bool().unwrap_or(false),
|
||||||
Condition::Func(f) => f(cx, obj),
|
Condition::Func(f) => f(cx, obj),
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::dom::bindings::guard::Guard;
|
||||||
use crate::dom::bindings::utils::{
|
use crate::dom::bindings::utils::{
|
||||||
get_proto_or_iface_array, ProtoOrIfaceArray, DOM_PROTOTYPE_SLOT,
|
get_proto_or_iface_array, ProtoOrIfaceArray, DOM_PROTOTYPE_SLOT,
|
||||||
};
|
};
|
||||||
|
use crate::script_runtime::JSContext as SafeJSContext;
|
||||||
use js::error::throw_type_error;
|
use js::error::throw_type_error;
|
||||||
use js::glue::UncheckedUnwrapObject;
|
use js::glue::UncheckedUnwrapObject;
|
||||||
use js::jsapi::HandleObject as RawHandleObject;
|
use js::jsapi::HandleObject as RawHandleObject;
|
||||||
|
@ -129,7 +130,7 @@ pub type TraceHook = unsafe extern "C" fn(trc: *mut JSTracer, obj: *mut JSObject
|
||||||
|
|
||||||
/// Create a global object with the given class.
|
/// Create a global object with the given class.
|
||||||
pub unsafe fn create_global_object(
|
pub unsafe fn create_global_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
class: &'static JSClass,
|
class: &'static JSClass,
|
||||||
private: *const libc::c_void,
|
private: *const libc::c_void,
|
||||||
trace: TraceHook,
|
trace: TraceHook,
|
||||||
|
@ -142,7 +143,7 @@ pub unsafe fn create_global_object(
|
||||||
options.creationOptions_.sharedMemoryAndAtomics_ = true;
|
options.creationOptions_.sharedMemoryAndAtomics_ = true;
|
||||||
|
|
||||||
rval.set(JS_NewGlobalObject(
|
rval.set(JS_NewGlobalObject(
|
||||||
cx,
|
*cx,
|
||||||
class,
|
class,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
|
OnNewGlobalHookOption::DontFireOnNewGlobalHook,
|
||||||
|
@ -159,20 +160,22 @@ pub unsafe fn create_global_object(
|
||||||
let val = PrivateValue(Box::into_raw(proto_array) as *const libc::c_void);
|
let val = PrivateValue(Box::into_raw(proto_array) as *const libc::c_void);
|
||||||
JS_SetReservedSlot(rval.get(), DOM_PROTOTYPE_SLOT, &val);
|
JS_SetReservedSlot(rval.get(), DOM_PROTOTYPE_SLOT, &val);
|
||||||
|
|
||||||
let _ac = JSAutoRealm::new(cx, rval.get());
|
let _ac = JSAutoRealm::new(*cx, rval.get());
|
||||||
JS_FireOnNewGlobalObject(cx, rval.handle());
|
JS_FireOnNewGlobalObject(*cx, rval.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 fn create_callback_interface_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
constants: &[Guard<&[ConstantSpec]>],
|
constants: &[Guard<&[ConstantSpec]>],
|
||||||
name: &[u8],
|
name: &[u8],
|
||||||
mut rval: MutableHandleObject,
|
mut rval: MutableHandleObject,
|
||||||
) {
|
) {
|
||||||
assert!(!constants.is_empty());
|
assert!(!constants.is_empty());
|
||||||
rval.set(JS_NewObject(cx, ptr::null()));
|
unsafe {
|
||||||
|
rval.set(JS_NewObject(*cx, ptr::null()));
|
||||||
|
}
|
||||||
assert!(!rval.is_null());
|
assert!(!rval.is_null());
|
||||||
define_guarded_constants(cx, rval.handle(), constants, global);
|
define_guarded_constants(cx, rval.handle(), constants, global);
|
||||||
define_name(cx, rval.handle(), name);
|
define_name(cx, rval.handle(), name);
|
||||||
|
@ -180,8 +183,8 @@ pub unsafe fn create_callback_interface_object(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the interface prototype object of a non-callback interface.
|
/// Create the interface prototype object of a non-callback interface.
|
||||||
pub unsafe fn create_interface_prototype_object(
|
pub fn create_interface_prototype_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static JSClass,
|
class: &'static JSClass,
|
||||||
|
@ -203,27 +206,29 @@ pub unsafe fn create_interface_prototype_object(
|
||||||
);
|
);
|
||||||
|
|
||||||
if !unscopable_names.is_empty() {
|
if !unscopable_names.is_empty() {
|
||||||
rooted!(in(cx) let mut unscopable_obj = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut unscopable_obj = ptr::null_mut::<JSObject>());
|
||||||
create_unscopable_object(cx, unscopable_names, unscopable_obj.handle_mut());
|
create_unscopable_object(cx, unscopable_names, unscopable_obj.handle_mut());
|
||||||
|
unsafe {
|
||||||
|
let unscopable_symbol = GetWellKnownSymbol(*cx, SymbolCode::unscopables);
|
||||||
|
assert!(!unscopable_symbol.is_null());
|
||||||
|
|
||||||
let unscopable_symbol = GetWellKnownSymbol(cx, SymbolCode::unscopables);
|
rooted!(in(*cx) let mut unscopable_id: jsid);
|
||||||
assert!(!unscopable_symbol.is_null());
|
RUST_SYMBOL_TO_JSID(unscopable_symbol, unscopable_id.handle_mut());
|
||||||
|
|
||||||
rooted!(in(cx) let mut unscopable_id: jsid);
|
assert!(JS_DefinePropertyById5(
|
||||||
RUST_SYMBOL_TO_JSID(unscopable_symbol, unscopable_id.handle_mut());
|
*cx,
|
||||||
assert!(JS_DefinePropertyById5(
|
rval.handle(),
|
||||||
cx,
|
unscopable_id.handle(),
|
||||||
rval.handle(),
|
unscopable_obj.handle(),
|
||||||
unscopable_id.handle(),
|
JSPROP_READONLY as u32
|
||||||
unscopable_obj.handle(),
|
))
|
||||||
JSPROP_READONLY as u32
|
}
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and define the interface object of a non-callback interface.
|
/// Create and define the interface object of a non-callback interface.
|
||||||
pub unsafe fn create_noncallback_interface_object(
|
pub fn create_noncallback_interface_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static NonCallbackInterfaceObjectClass,
|
class: &'static NonCallbackInterfaceObjectClass,
|
||||||
|
@ -245,54 +250,58 @@ pub unsafe fn create_noncallback_interface_object(
|
||||||
constants,
|
constants,
|
||||||
rval,
|
rval,
|
||||||
);
|
);
|
||||||
assert!(JS_LinkConstructorAndPrototype(
|
unsafe {
|
||||||
cx,
|
assert!(JS_LinkConstructorAndPrototype(
|
||||||
rval.handle(),
|
*cx,
|
||||||
interface_prototype_object
|
rval.handle(),
|
||||||
));
|
interface_prototype_object
|
||||||
|
));
|
||||||
|
}
|
||||||
define_name(cx, rval.handle(), name);
|
define_name(cx, rval.handle(), name);
|
||||||
define_length(cx, rval.handle(), i32::try_from(length).expect("overflow"));
|
define_length(cx, rval.handle(), i32::try_from(length).expect("overflow"));
|
||||||
define_on_global_object(cx, global, name, rval.handle());
|
define_on_global_object(cx, global, name, rval.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and define the named constructors of a non-callback interface.
|
/// Create and define the named constructors of a non-callback interface.
|
||||||
pub unsafe fn create_named_constructors(
|
pub fn create_named_constructors(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
named_constructors: &[(ConstructorClassHook, &[u8], u32)],
|
named_constructors: &[(ConstructorClassHook, &[u8], u32)],
|
||||||
interface_prototype_object: HandleObject,
|
interface_prototype_object: HandleObject,
|
||||||
) {
|
) {
|
||||||
rooted!(in(cx) let mut constructor = ptr::null_mut::<JSObject>());
|
rooted!(in(*cx) let mut constructor = ptr::null_mut::<JSObject>());
|
||||||
|
|
||||||
for &(native, name, arity) in named_constructors {
|
for &(native, name, arity) in named_constructors {
|
||||||
assert_eq!(*name.last().unwrap(), b'\0');
|
assert_eq!(*name.last().unwrap(), b'\0');
|
||||||
|
|
||||||
let fun = JS_NewFunction(
|
unsafe {
|
||||||
cx,
|
let fun = JS_NewFunction(
|
||||||
Some(native),
|
*cx,
|
||||||
arity,
|
Some(native),
|
||||||
JSFUN_CONSTRUCTOR,
|
arity,
|
||||||
name.as_ptr() as *const libc::c_char,
|
JSFUN_CONSTRUCTOR,
|
||||||
);
|
name.as_ptr() as *const libc::c_char,
|
||||||
assert!(!fun.is_null());
|
);
|
||||||
constructor.set(JS_GetFunctionObject(fun));
|
assert!(!fun.is_null());
|
||||||
assert!(!constructor.is_null());
|
constructor.set(JS_GetFunctionObject(fun));
|
||||||
|
assert!(!constructor.is_null());
|
||||||
|
|
||||||
assert!(JS_DefineProperty3(
|
assert!(JS_DefineProperty3(
|
||||||
cx,
|
*cx,
|
||||||
constructor.handle(),
|
constructor.handle(),
|
||||||
b"prototype\0".as_ptr() as *const libc::c_char,
|
b"prototype\0".as_ptr() as *const libc::c_char,
|
||||||
interface_prototype_object,
|
interface_prototype_object,
|
||||||
(JSPROP_PERMANENT | JSPROP_READONLY) as u32
|
(JSPROP_PERMANENT | JSPROP_READONLY) as u32
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
define_on_global_object(cx, global, name, constructor.handle());
|
define_on_global_object(cx, global, name, constructor.handle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new object with a unique type.
|
/// Create a new object with a unique type.
|
||||||
pub unsafe fn create_object(
|
pub fn create_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static JSClass,
|
class: &'static JSClass,
|
||||||
|
@ -301,7 +310,9 @@ pub unsafe fn create_object(
|
||||||
constants: &[Guard<&[ConstantSpec]>],
|
constants: &[Guard<&[ConstantSpec]>],
|
||||||
mut rval: MutableHandleObject,
|
mut rval: MutableHandleObject,
|
||||||
) {
|
) {
|
||||||
rval.set(JS_NewObjectWithUniqueType(cx, class, proto));
|
unsafe {
|
||||||
|
rval.set(JS_NewObjectWithUniqueType(*cx, class, proto));
|
||||||
|
}
|
||||||
assert!(!rval.is_null());
|
assert!(!rval.is_null());
|
||||||
define_guarded_methods(cx, rval.handle(), methods, global);
|
define_guarded_methods(cx, rval.handle(), methods, global);
|
||||||
define_guarded_properties(cx, rval.handle(), properties, global);
|
define_guarded_properties(cx, rval.handle(), properties, global);
|
||||||
|
@ -309,8 +320,8 @@ pub unsafe fn create_object(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conditionally define constants on an object.
|
/// Conditionally define constants on an object.
|
||||||
pub unsafe fn define_guarded_constants(
|
pub fn define_guarded_constants(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
obj: HandleObject,
|
obj: HandleObject,
|
||||||
constants: &[Guard<&[ConstantSpec]>],
|
constants: &[Guard<&[ConstantSpec]>],
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
|
@ -323,57 +334,65 @@ pub unsafe fn define_guarded_constants(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conditionally define methods on an object.
|
/// Conditionally define methods on an object.
|
||||||
pub unsafe fn define_guarded_methods(
|
pub fn define_guarded_methods(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
obj: HandleObject,
|
obj: HandleObject,
|
||||||
methods: &[Guard<&'static [JSFunctionSpec]>],
|
methods: &[Guard<&'static [JSFunctionSpec]>],
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
) {
|
) {
|
||||||
for guard in methods {
|
for guard in methods {
|
||||||
if let Some(specs) = guard.expose(cx, obj, global) {
|
if let Some(specs) = guard.expose(cx, obj, global) {
|
||||||
define_methods(cx, obj, specs).unwrap();
|
unsafe {
|
||||||
|
define_methods(*cx, obj, specs).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conditionally define properties on an object.
|
/// Conditionally define properties on an object.
|
||||||
pub unsafe fn define_guarded_properties(
|
pub fn define_guarded_properties(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
obj: HandleObject,
|
obj: HandleObject,
|
||||||
properties: &[Guard<&'static [JSPropertySpec]>],
|
properties: &[Guard<&'static [JSPropertySpec]>],
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
) {
|
) {
|
||||||
for guard in properties {
|
for guard in properties {
|
||||||
if let Some(specs) = guard.expose(cx, obj, global) {
|
if let Some(specs) = guard.expose(cx, obj, global) {
|
||||||
define_properties(cx, obj, specs).unwrap();
|
unsafe {
|
||||||
|
define_properties(*cx, obj, specs).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether an interface with exposure set given by `globals` should
|
/// Returns whether an interface with exposure set given by `globals` should
|
||||||
/// be exposed in the global object `obj`.
|
/// be exposed in the global object `obj`.
|
||||||
pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
|
pub fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
|
||||||
let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
|
unsafe {
|
||||||
let dom_class = get_dom_class(unwrapped).unwrap();
|
let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
|
||||||
globals.contains(dom_class.global)
|
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
|
/// Define a property with a given name on the global object. Should be called
|
||||||
/// through the resolve hook.
|
/// through the resolve hook.
|
||||||
pub unsafe fn define_on_global_object(
|
pub fn define_on_global_object(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
name: &[u8],
|
name: &[u8],
|
||||||
obj: HandleObject,
|
obj: HandleObject,
|
||||||
) {
|
) {
|
||||||
assert_eq!(*name.last().unwrap(), b'\0');
|
assert_eq!(*name.last().unwrap(), b'\0');
|
||||||
assert!(JS_DefineProperty3(
|
unsafe {
|
||||||
cx,
|
assert!(JS_DefineProperty3(
|
||||||
global,
|
*cx,
|
||||||
name.as_ptr() as *const libc::c_char,
|
global,
|
||||||
obj,
|
name.as_ptr() as *const libc::c_char,
|
||||||
JSPROP_RESOLVING
|
obj,
|
||||||
));
|
JSPROP_RESOLVING
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const OBJECT_OPS: ObjectOps = ObjectOps {
|
const OBJECT_OPS: ObjectOps = ObjectOps {
|
||||||
|
@ -409,6 +428,7 @@ unsafe extern "C" fn has_instance_hook(
|
||||||
value: RawMutableHandleValue,
|
value: RawMutableHandleValue,
|
||||||
rval: *mut bool,
|
rval: *mut bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let cx = SafeJSContext::from_ptr(cx);
|
||||||
let obj_raw = HandleObject::from_raw(obj);
|
let obj_raw = HandleObject::from_raw(obj);
|
||||||
let val_raw = HandleValue::from_raw(value.handle());
|
let val_raw = HandleValue::from_raw(value.handle());
|
||||||
match has_instance(cx, obj_raw, val_raw) {
|
match has_instance(cx, obj_raw, val_raw) {
|
||||||
|
@ -422,8 +442,8 @@ unsafe extern "C" fn has_instance_hook(
|
||||||
|
|
||||||
/// 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>
|
||||||
unsafe fn has_instance(
|
fn has_instance(
|
||||||
cx: *mut JSContext,
|
cx: SafeJSContext,
|
||||||
interface_object: HandleObject,
|
interface_object: HandleObject,
|
||||||
value: HandleValue,
|
value: HandleValue,
|
||||||
) -> Result<bool, ()> {
|
) -> Result<bool, ()> {
|
||||||
|
@ -432,86 +452,91 @@ unsafe fn has_instance(
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
rooted!(in(cx) let mut value_out = value.to_object());
|
rooted!(in(*cx) let mut value_out = value.to_object());
|
||||||
rooted!(in(cx) let mut value = value.to_object());
|
rooted!(in(*cx) let mut value = value.to_object());
|
||||||
|
|
||||||
let js_class = get_object_class(interface_object.get());
|
unsafe {
|
||||||
let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass);
|
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(
|
if let Ok(dom_class) = get_dom_class(UncheckedUnwrapObject(
|
||||||
value.get(),
|
value.get(),
|
||||||
/* stopAtWindowProxy = */ 0,
|
/* stopAtWindowProxy = */ 0,
|
||||||
)) {
|
)) {
|
||||||
if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id {
|
if dom_class.interface_chain[object_class.proto_depth as usize] == object_class.proto_id
|
||||||
// Step 4.
|
{
|
||||||
return Ok(true);
|
// Step 4.
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let global = GetNonCCWObjectGlobal(interface_object.get());
|
let global = GetNonCCWObjectGlobal(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);
|
||||||
rooted!(in(cx) let prototype = (*proto_or_iface_array)[object_class.proto_id as usize]);
|
rooted!(in(*cx) let prototype = (*proto_or_iface_array)[object_class.proto_id as usize]);
|
||||||
assert!(!prototype.is_null());
|
assert!(!prototype.is_null());
|
||||||
// Step 3 only concern legacy callback interface objects (i.e. NodeFilter).
|
// Step 3 only concern legacy callback interface objects (i.e. NodeFilter).
|
||||||
|
|
||||||
while JS_GetPrototype(cx, value.handle(), value_out.handle_mut()) {
|
while JS_GetPrototype(*cx, value.handle(), value_out.handle_mut()) {
|
||||||
*value = *value_out;
|
*value = *value_out;
|
||||||
if value.is_null() {
|
if value.is_null() {
|
||||||
// Step 5.2.
|
// Step 5.2.
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
} else if value.get() as *const _ == prototype.get() {
|
} else if value.get() as *const _ == prototype.get() {
|
||||||
// Step 5.3.
|
// Step 5.3.
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// JS_GetPrototype threw an exception.
|
// JS_GetPrototype threw an exception.
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_unscopable_object(
|
fn create_unscopable_object(cx: SafeJSContext, names: &[&[u8]], mut rval: MutableHandleObject) {
|
||||||
cx: *mut JSContext,
|
|
||||||
names: &[&[u8]],
|
|
||||||
mut rval: MutableHandleObject,
|
|
||||||
) {
|
|
||||||
assert!(!names.is_empty());
|
assert!(!names.is_empty());
|
||||||
assert!(rval.is_null());
|
assert!(rval.is_null());
|
||||||
rval.set(JS_NewPlainObject(cx));
|
unsafe {
|
||||||
assert!(!rval.is_null());
|
rval.set(JS_NewPlainObject(*cx));
|
||||||
for &name in names {
|
assert!(!rval.is_null());
|
||||||
assert_eq!(*name.last().unwrap(), b'\0');
|
for &name in names {
|
||||||
assert!(JS_DefineProperty(
|
assert_eq!(*name.last().unwrap(), b'\0');
|
||||||
cx,
|
assert!(JS_DefineProperty(
|
||||||
rval.handle(),
|
*cx,
|
||||||
name.as_ptr() as *const libc::c_char,
|
rval.handle(),
|
||||||
HandleValue::from_raw(TrueHandleValue),
|
name.as_ptr() as *const libc::c_char,
|
||||||
JSPROP_READONLY as u32,
|
HandleValue::from_raw(TrueHandleValue),
|
||||||
|
JSPROP_READONLY as u32,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_name(cx: SafeJSContext, obj: HandleObject, name: &[u8]) {
|
||||||
|
assert_eq!(*name.last().unwrap(), b'\0');
|
||||||
|
unsafe {
|
||||||
|
rooted!(in(*cx) let name = JS_AtomizeAndPinString(*cx, name.as_ptr() as *const libc::c_char));
|
||||||
|
assert!(!name.is_null());
|
||||||
|
assert!(JS_DefineProperty4(
|
||||||
|
*cx,
|
||||||
|
obj,
|
||||||
|
b"name\0".as_ptr() as *const libc::c_char,
|
||||||
|
name.handle().into(),
|
||||||
|
JSPROP_READONLY as u32
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) {
|
fn define_length(cx: SafeJSContext, obj: HandleObject, length: i32) {
|
||||||
assert_eq!(*name.last().unwrap(), b'\0');
|
unsafe {
|
||||||
rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char));
|
assert!(JS_DefineProperty5(
|
||||||
assert!(!name.is_null());
|
*cx,
|
||||||
assert!(JS_DefineProperty4(
|
obj,
|
||||||
cx,
|
b"length\0".as_ptr() as *const libc::c_char,
|
||||||
obj,
|
length,
|
||||||
b"name\0".as_ptr() as *const libc::c_char,
|
JSPROP_READONLY as u32
|
||||||
name.handle().into(),
|
));
|
||||||
JSPROP_READONLY as u32
|
}
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: i32) {
|
|
||||||
assert!(JS_DefineProperty5(
|
|
||||||
cx,
|
|
||||||
obj,
|
|
||||||
b"length\0".as_ptr() as *const libc::c_char,
|
|
||||||
length,
|
|
||||||
JSPROP_READONLY as u32
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn invalid_constructor(
|
unsafe extern "C" fn invalid_constructor(
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
use crate::dom::bindings::guard::Guard;
|
use crate::dom::bindings::guard::Guard;
|
||||||
use crate::dom::bindings::interface::{create_object, define_on_global_object};
|
use crate::dom::bindings::interface::{create_object, define_on_global_object};
|
||||||
use js::jsapi::{JSClass, JSContext, JSFunctionSpec};
|
use crate::script_runtime::JSContext;
|
||||||
|
use js::jsapi::{JSClass, JSFunctionSpec};
|
||||||
use js::rust::{HandleObject, MutableHandleObject};
|
use js::rust::{HandleObject, MutableHandleObject};
|
||||||
|
|
||||||
/// The class of a namespace object.
|
/// The class of a namespace object.
|
||||||
|
@ -28,8 +29,8 @@ impl NamespaceObjectClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new namespace object.
|
/// Create a new namespace object.
|
||||||
pub unsafe fn create_namespace_object(
|
pub fn create_namespace_object(
|
||||||
cx: *mut JSContext,
|
cx: JSContext,
|
||||||
global: HandleObject,
|
global: HandleObject,
|
||||||
proto: HandleObject,
|
proto: HandleObject,
|
||||||
class: &'static NamespaceObjectClass,
|
class: &'static NamespaceObjectClass,
|
||||||
|
|
|
@ -1090,12 +1090,11 @@ impl TestBinding {
|
||||||
pub fn FuncControlledStaticMethodEnabled(_: &GlobalScope) {}
|
pub fn FuncControlledStaticMethodEnabled(_: &GlobalScope) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
impl TestBinding {
|
impl TestBinding {
|
||||||
pub unsafe fn condition_satisfied(_: *mut JSContext, _: HandleObject) -> bool {
|
pub fn condition_satisfied(_: SafeJSContext, _: HandleObject) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
pub unsafe fn condition_unsatisfied(_: *mut JSContext, _: HandleObject) -> bool {
|
pub fn condition_unsatisfied(_: SafeJSContext, _: HandleObject) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue