Auto merge of #23872 - marmeladema:issue-20377, r=jdm

Make DOM bindings methods not take raw JSContext pointers. Part 2.

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #20377

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23872)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-08-08 22:21:19 -04:00 committed by GitHub
commit da559d47b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 543 additions and 558 deletions

View file

@ -50,7 +50,7 @@ fn main() {
let mut phf = File::create(&phf).unwrap(); let mut phf = File::create(&phf).unwrap();
write!( write!(
&mut phf, &mut phf,
"pub static MAP: phf::Map<&'static [u8], unsafe fn(JSContext, HandleObject)> = " "pub static MAP: phf::Map<&'static [u8], fn(JSContext, HandleObject)> = "
) )
.unwrap(); .unwrap();
map.build(&mut phf).unwrap(); map.build(&mut phf).unwrap();

View file

@ -4,7 +4,8 @@
use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::DomObject;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use js::jsapi::{GetCurrentRealmOrNull, JSAutoRealm, JSContext}; use crate::script_runtime::JSContext;
use js::jsapi::{GetCurrentRealmOrNull, JSAutoRealm};
pub struct AlreadyInCompartment(()); pub struct AlreadyInCompartment(());
@ -17,9 +18,9 @@ impl AlreadyInCompartment {
AlreadyInCompartment(()) AlreadyInCompartment(())
} }
pub fn assert_for_cx(cx: *mut JSContext) -> AlreadyInCompartment { pub fn assert_for_cx(cx: JSContext) -> AlreadyInCompartment {
unsafe { unsafe {
assert!(!GetCurrentRealmOrNull(cx).is_null()); assert!(!GetCurrentRealmOrNull(*cx).is_null());
} }
AlreadyInCompartment(()) AlreadyInCompartment(())
} }

View file

@ -13,10 +13,10 @@ use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::jsapi::JS_GetArrayBufferViewBuffer; use js::jsapi::JS_GetArrayBufferViewBuffer;
use js::jsapi::{Heap, JSContext, JSObject}; use js::jsapi::{Heap, JSObject};
use js::rust::wrappers::DetachArrayBuffer; use js::rust::wrappers::DetachArrayBuffer;
use js::rust::CustomAutoRooterGuard; use js::rust::CustomAutoRooterGuard;
use js::typedarray::{CreateWith, Float32Array}; use js::typedarray::{CreateWith, Float32Array};
@ -127,7 +127,7 @@ impl AudioBuffer {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool { fn restore_js_channel_data(&self, cx: JSContext) -> bool {
let _ac = enter_realm(&*self); let _ac = enter_realm(&*self);
for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() { for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
if !channel.get().is_null() { if !channel.get().is_null() {
@ -135,14 +135,15 @@ impl AudioBuffer {
continue; continue;
} }
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>()); rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>());
if let Some(ref shared_channels) = *self.shared_channels.borrow() { if let Some(ref shared_channels) = *self.shared_channels.borrow() {
// Step 4. of // Step 4. of
// https://webaudio.github.io/web-audio-api/#acquire-the-content // https://webaudio.github.io/web-audio-api/#acquire-the-content
// "Attach ArrayBuffers containing copies of the data to the AudioBuffer, // "Attach ArrayBuffers containing copies of the data to the AudioBuffer,
// to be returned by the next call to getChannelData()". // to be returned by the next call to getChannelData()".
unsafe {
if Float32Array::create( if Float32Array::create(
cx, *cx,
CreateWith::Slice(&shared_channels.buffers[i]), CreateWith::Slice(&shared_channels.buffers[i]),
array.handle_mut(), array.handle_mut(),
) )
@ -151,6 +152,7 @@ impl AudioBuffer {
return false; return false;
} }
} }
}
channel.set(array.get()); channel.set(array.get());
} }
@ -231,16 +233,15 @@ impl AudioBufferMethods for AudioBuffer {
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn GetChannelData(&self, cx: SafeJSContext, channel: u32) -> Fallible<NonNull<JSObject>> { fn GetChannelData(&self, cx: JSContext, channel: u32) -> Fallible<NonNull<JSObject>> {
if channel >= self.number_of_channels { if channel >= self.number_of_channels {
return Err(Error::IndexSize); return Err(Error::IndexSize);
} }
unsafe { if !self.restore_js_channel_data(cx) {
if !self.restore_js_channel_data(*cx) {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }
unsafe {
Ok(NonNull::new_unchecked( Ok(NonNull::new_unchecked(
self.js_channels.borrow()[channel as usize].get(), self.js_channels.borrow()[channel as usize].get(),
)) ))
@ -307,7 +308,7 @@ impl AudioBufferMethods for AudioBuffer {
} }
let cx = self.global().get_cx(); let cx = self.global().get_cx();
if unsafe { !self.restore_js_channel_data(*cx) } { if !self.restore_js_channel_data(cx) {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }

View file

@ -13,10 +13,10 @@ use crate::dom::bindings::settings_stack::{AutoEntryScript, AutoIncumbentScript}
use crate::dom::bindings::utils::AsCCharPtrPtr; use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use js::jsapi::Heap; use js::jsapi::Heap;
use js::jsapi::JSAutoRealm; use js::jsapi::JSAutoRealm;
use js::jsapi::{AddRawValueRoot, IsCallable, JSContext, JSObject}; use js::jsapi::{AddRawValueRoot, IsCallable, JSObject};
use js::jsapi::{EnterRealm, LeaveRealm, Realm, RemoveRawValueRoot}; use js::jsapi::{EnterRealm, LeaveRealm, Realm, RemoveRawValueRoot};
use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use js::jsval::{JSVal, ObjectValue, UndefinedValue};
use js::rust::wrappers::{JS_GetProperty, JS_WrapObject}; use js::rust::wrappers::{JS_GetProperty, JS_WrapObject};
@ -82,11 +82,11 @@ impl CallbackObject {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) { unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
self.callback.set(callback); self.callback.set(callback);
self.permanent_js_root.set(ObjectValue(callback)); self.permanent_js_root.set(ObjectValue(callback));
assert!(AddRawValueRoot( assert!(AddRawValueRoot(
cx, *cx,
self.permanent_js_root.get_unsafe(), self.permanent_js_root.get_unsafe(),
b"CallbackObject::root\n".as_c_char_ptr() b"CallbackObject::root\n".as_c_char_ptr()
)); ));
@ -113,7 +113,7 @@ impl PartialEq for CallbackObject {
/// callback interface types. /// callback interface types.
pub trait CallbackContainer { pub trait CallbackContainer {
/// Create a new CallbackContainer object for the given `JSObject`. /// Create a new CallbackContainer object for the given `JSObject`.
unsafe fn new(cx: SafeJSContext, callback: *mut JSObject) -> Rc<Self>; unsafe fn new(cx: JSContext, callback: *mut JSObject) -> Rc<Self>;
/// Returns the underlying `CallbackObject`. /// Returns the underlying `CallbackObject`.
fn callback_holder(&self) -> &CallbackObject; fn callback_holder(&self) -> &CallbackObject;
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
@ -152,8 +152,8 @@ impl CallbackFunction {
/// Initialize the callback function with a value. /// Initialize the callback function with a value.
/// Should be called once this object is done moving. /// Should be called once this object is done moving.
pub unsafe fn init(&mut self, cx: SafeJSContext, callback: *mut JSObject) { pub unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
self.object.init(*cx, callback); self.object.init(cx, callback);
} }
} }
@ -179,18 +179,18 @@ impl CallbackInterface {
/// Initialize the callback function with a value. /// Initialize the callback function with a value.
/// Should be called once this object is done moving. /// Should be called once this object is done moving.
pub unsafe fn init(&mut self, cx: SafeJSContext, callback: *mut JSObject) { pub unsafe fn init(&mut self, cx: JSContext, callback: *mut JSObject) {
self.object.init(*cx, callback); self.object.init(cx, callback);
} }
/// Returns the property with the given `name`, if it is a callable object, /// Returns the property with the given `name`, if it is a callable object,
/// or an error otherwise. /// or an error otherwise.
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str) -> Fallible<JSVal> { pub fn get_callable_property(&self, cx: JSContext, name: &str) -> Fallible<JSVal> {
rooted!(in(cx) let mut callable = UndefinedValue()); rooted!(in(*cx) let mut callable = UndefinedValue());
rooted!(in(cx) let obj = self.callback_holder().get()); rooted!(in(*cx) let obj = self.callback_holder().get());
unsafe { unsafe {
let c_name = CString::new(name).unwrap(); let c_name = CString::new(name).unwrap();
if !JS_GetProperty(cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) { if !JS_GetProperty(*cx, obj.handle(), c_name.as_ptr(), callable.handle_mut()) {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }
@ -206,16 +206,12 @@ impl CallbackInterface {
} }
/// Wraps the reflector for `p` into the compartment of `cx`. /// Wraps the reflector for `p` into the compartment of `cx`.
pub fn wrap_call_this_object<T: DomObject>( pub fn wrap_call_this_object<T: DomObject>(cx: JSContext, p: &T, mut rval: MutableHandleObject) {
cx: *mut JSContext,
p: &T,
mut rval: MutableHandleObject,
) {
rval.set(p.reflector().get_jsobject().get()); rval.set(p.reflector().get_jsobject().get());
assert!(!rval.get().is_null()); assert!(!rval.get().is_null());
unsafe { unsafe {
if !JS_WrapObject(cx, rval) { if !JS_WrapObject(*cx, rval) {
rval.set(ptr::null_mut()); rval.set(ptr::null_mut());
} }
} }
@ -228,7 +224,7 @@ pub struct CallSetup {
/// (possibly wrapped) callback object. /// (possibly wrapped) callback object.
exception_global: DomRoot<GlobalScope>, exception_global: DomRoot<GlobalScope>,
/// The `JSContext` used for the call. /// The `JSContext` used for the call.
cx: *mut JSContext, cx: JSContext,
/// The compartment we were in before the call. /// The compartment we were in before the call.
old_realm: *mut Realm, old_realm: *mut Realm,
/// The exception handling used for the call. /// The exception handling used for the call.
@ -255,7 +251,7 @@ impl CallSetup {
let ais = callback.incumbent().map(AutoIncumbentScript::new); let ais = callback.incumbent().map(AutoIncumbentScript::new);
CallSetup { CallSetup {
exception_global: global, exception_global: global,
cx: *cx, cx: cx,
old_realm: unsafe { EnterRealm(*cx, callback.callback()) }, old_realm: unsafe { EnterRealm(*cx, callback.callback()) },
handling: handling, handling: handling,
entry_script: Some(aes), entry_script: Some(aes),
@ -264,7 +260,7 @@ impl CallSetup {
} }
/// Returns the `JSContext` used for the call. /// Returns the `JSContext` used for the call.
pub fn get_context(&self) -> *mut JSContext { pub fn get_context(&self) -> JSContext {
self.cx self.cx
} }
} }
@ -272,13 +268,13 @@ impl CallSetup {
impl Drop for CallSetup { impl Drop for CallSetup {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
LeaveRealm(self.cx, self.old_realm); LeaveRealm(*self.cx, self.old_realm);
if self.handling == ExceptionHandling::Report { if self.handling == ExceptionHandling::Report {
let _ac = JSAutoRealm::new( let _ac = JSAutoRealm::new(
self.cx, *self.cx,
self.exception_global.reflector().get_jsobject().get(), self.exception_global.reflector().get_jsobject().get(),
); );
report_pending_exception(self.cx, true); report_pending_exception(*self.cx, true);
} }
drop(self.incumbent_script.take()); drop(self.incumbent_script.take());
drop(self.entry_script.take().unwrap()); drop(self.entry_script.take().unwrap());

View file

@ -810,10 +810,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if !JS_WrapValue(*cx, valueToResolve.handle_mut()) { if !JS_WrapValue(*cx, valueToResolve.handle_mut()) {
$*{exceptionCode} $*{exceptionCode}
} }
match Promise::new_resolved(&promiseGlobal, *cx, valueToResolve.handle()) { match Promise::new_resolved(&promiseGlobal, cx, valueToResolve.handle()) {
Ok(value) => value, Ok(value) => value,
Err(error) => { Err(error) => {
throw_dom_exception(*cx, &promiseGlobal, error); throw_dom_exception(cx, &promiseGlobal, error);
$*{exceptionCode} $*{exceptionCode}
} }
} }
@ -2588,8 +2588,7 @@ class CGConstructorEnabled(CGAbstractMethod):
CGAbstractMethod.__init__(self, descriptor, CGAbstractMethod.__init__(self, descriptor,
'ConstructorEnabled', 'bool', 'ConstructorEnabled', 'bool',
[Argument("SafeJSContext", "aCx"), [Argument("SafeJSContext", "aCx"),
Argument("HandleObject", "aObj")], Argument("HandleObject", "aObj")])
unsafe=True)
def definition_body(self): def definition_body(self):
conditions = [] conditions = []
@ -2651,8 +2650,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 +2761,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 +2771,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 +2910,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 +2923,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 +2975,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 +3010,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 +3092,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
@ -3137,23 +3136,25 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
Argument('HandleObject', 'global'), Argument('HandleObject', 'global'),
Argument('MutableHandleObject', 'mut rval')] Argument('MutableHandleObject', 'mut rval')]
CGAbstractMethod.__init__(self, descriptor, name, CGAbstractMethod.__init__(self, descriptor, name,
'void', args, pub=pub, unsafe=True) 'void', args, pub=pub)
self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name) self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name)
def definition_body(self): def definition_body(self):
return CGGeneric(""" return CGGeneric("""
assert!(((*get_object_class(global.get())).flags & JSCLASS_DOM_GLOBAL) != 0); unsafe {
assert!(((*get_object_class(global.get())).flags & JSCLASS_DOM_GLOBAL) != 0);
/* Check to see whether the interface objects are already installed */ /* Check to see whether the interface objects are already installed */
let proto_or_iface_array = get_proto_or_iface_array(global.get()); let proto_or_iface_array = get_proto_or_iface_array(global.get());
rval.set((*proto_or_iface_array)[%(id)s as usize]); rval.set((*proto_or_iface_array)[%(id)s as usize]);
if !rval.get().is_null() { if !rval.get().is_null() {
return; return;
} }
CreateInterfaceObjects(cx, global, proto_or_iface_array); CreateInterfaceObjects(cx, global, proto_or_iface_array);
rval.set((*proto_or_iface_array)[%(id)s as usize]); rval.set((*proto_or_iface_array)[%(id)s as usize]);
assert!(!rval.get().is_null()); assert!(!rval.get().is_null());
}
""" % {"id": self.id}) """ % {"id": self.id})
@ -3274,7 +3275,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
Argument('HandleObject', 'global'), Argument('HandleObject', 'global'),
] ]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface',
'void', args, pub=True, unsafe=True) 'void', args, pub=True)
def define(self): def define(self):
return CGAbstractMethod.define(self) return CGAbstractMethod.define(self)
@ -3335,7 +3336,7 @@ class CGCallGenerator(CGThing):
if "cx" not in argsPre and needsCx: if "cx" not in argsPre and needsCx:
args.prepend(CGGeneric("cx")) args.prepend(CGGeneric("cx"))
if nativeMethodName in descriptor.inCompartmentMethods: if nativeMethodName in descriptor.inCompartmentMethods:
args.append(CGGeneric("InCompartment::in_compartment(&AlreadyInCompartment::assert_for_cx(*cx))")) args.append(CGGeneric("InCompartment::in_compartment(&AlreadyInCompartment::assert_for_cx(cx))"))
# Build up our actual call # Build up our actual call
self.cgRoot = CGList([], "\n") self.cgRoot = CGList([], "\n")
@ -3371,7 +3372,7 @@ class CGCallGenerator(CGThing):
"let result = match result {\n" "let result = match result {\n"
" Ok(result) => result,\n" " Ok(result) => result,\n"
" Err(e) => {\n" " Err(e) => {\n"
" throw_dom_exception(*cx, %s, e);\n" " throw_dom_exception(cx, %s, e);\n"
" return%s;\n" " return%s;\n"
" },\n" " },\n"
"};" % (glob, errorResult))) "};" % (glob, errorResult)))
@ -5555,12 +5556,12 @@ let global = DomRoot::downcast::<dom::types::%s>(global).unwrap();
// so we can do the spec's object-identity checks. // so we can do the spec's object-identity checks.
rooted!(in(*cx) let new_target = UnwrapObjectDynamic(args.new_target().to_object(), *cx, 1)); rooted!(in(*cx) let new_target = UnwrapObjectDynamic(args.new_target().to_object(), *cx, 1));
if new_target.is_null() { if new_target.is_null() {
throw_dom_exception(*cx, global.upcast::<GlobalScope>(), Error::Type("new.target is null".to_owned())); throw_dom_exception(cx, global.upcast::<GlobalScope>(), Error::Type("new.target is null".to_owned()));
return false; return false;
} }
if args.callee() == new_target.get() { if args.callee() == new_target.get() {
throw_dom_exception(*cx, global.upcast::<GlobalScope>(), throw_dom_exception(cx, global.upcast::<GlobalScope>(),
Error::Type("new.target must not be the active function object".to_owned())); Error::Type("new.target must not be the active function object".to_owned()));
return false; return false;
} }
@ -5601,7 +5602,7 @@ let result: Result<DomRoot<%s>, Error> = html_constructor(&global, &args);
let result = match result { let result = match result {
Ok(result) => result, Ok(result) => result,
Err(e) => { Err(e) => {
throw_dom_exception(*cx, global.upcast::<GlobalScope>(), e); throw_dom_exception(cx, global.upcast::<GlobalScope>(), e);
return false; return false;
}, },
}; };
@ -6355,8 +6356,9 @@ class CGDictionary(CGThing):
return string.Template( return string.Template(
"impl ${selfName} {\n" "impl ${selfName} {\n"
"${empty}\n" "${empty}\n"
" pub unsafe fn new(cx: SafeJSContext, val: HandleValue) \n" " pub fn new(cx: SafeJSContext, val: HandleValue) \n"
" -> Result<ConversionResult<${actualType}>, ()> {\n" " -> Result<ConversionResult<${actualType}>, ()> {\n"
" unsafe {\n"
" let object = if val.get().is_null_or_undefined() {\n" " let object = if val.get().is_null_or_undefined() {\n"
" ptr::null_mut()\n" " ptr::null_mut()\n"
" } else if val.get().is_object() {\n" " } else if val.get().is_object() {\n"
@ -6371,6 +6373,7 @@ class CGDictionary(CGThing):
"${postInitial}" "${postInitial}"
" Ok(ConversionResult::Success(dictionary))\n" " Ok(ConversionResult::Success(dictionary))\n"
" }\n" " }\n"
" }\n"
"}\n" "}\n"
"\n" "\n"
"impl FromJSValConvertible for ${actualType} {\n" "impl FromJSValConvertible for ${actualType} {\n"
@ -6391,11 +6394,11 @@ class CGDictionary(CGThing):
"selfName": selfName, "selfName": selfName,
"actualType": actualType, "actualType": actualType,
"empty": CGIndenter(CGGeneric(self.makeEmpty()), indentLevel=4).define(), "empty": CGIndenter(CGGeneric(self.makeEmpty()), indentLevel=4).define(),
"initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(), "initParent": CGIndenter(CGGeneric(initParent), indentLevel=16).define(),
"initMembers": CGIndenter(memberInits, indentLevel=12).define(), "initMembers": CGIndenter(memberInits, indentLevel=16).define(),
"insertMembers": CGIndenter(memberInserts, indentLevel=8).define(), "insertMembers": CGIndenter(memberInserts, indentLevel=8).define(),
"preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=12).define(), "preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=16).define(),
"postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=12).define(), "postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=16).define(),
}) })
def membersNeedTracing(self): def membersNeedTracing(self):
@ -6825,8 +6828,8 @@ class CGCallback(CGClass):
# Record the names of all the arguments, so we can use them when we call # Record the names of all the arguments, so we can use them when we call
# the private method. # the private method.
argnames = [arg.name for arg in args] argnames = [arg.name for arg in args]
argnamesWithThis = ["SafeJSContext::from_ptr(s.get_context())", "thisObjJS.handle()"] + argnames argnamesWithThis = ["s.get_context()", "thisObjJS.handle()"] + argnames
argnamesWithoutThis = ["SafeJSContext::from_ptr(s.get_context())", "thisObjJS.handle()"] + argnames argnamesWithoutThis = ["s.get_context()", "thisObjJS.handle()"] + argnames
# Now that we've recorded the argnames for our call to our private # Now that we've recorded the argnames for our call to our private
# method, insert our optional argument for deciding whether the # method, insert our optional argument for deciding whether the
# CallSetup should re-throw exceptions on aRv. # CallSetup should re-throw exceptions on aRv.
@ -6846,7 +6849,7 @@ class CGCallback(CGClass):
bodyWithThis = string.Template( bodyWithThis = string.Template(
setupCall + setupCall +
"rooted!(in(s.get_context()) let mut thisObjJS = ptr::null_mut::<JSObject>());\n" "rooted!(in(*s.get_context()) let mut thisObjJS = ptr::null_mut::<JSObject>());\n"
"wrap_call_this_object(s.get_context(), thisObj, thisObjJS.handle_mut());\n" "wrap_call_this_object(s.get_context(), thisObj, thisObjJS.handle_mut());\n"
"if thisObjJS.is_null() {\n" "if thisObjJS.is_null() {\n"
" return Err(JSFailed);\n" " return Err(JSFailed);\n"
@ -6857,7 +6860,7 @@ class CGCallback(CGClass):
}) })
bodyWithoutThis = string.Template( bodyWithoutThis = string.Template(
setupCall + setupCall +
"rooted!(in(s.get_context()) let thisObjJS = ptr::null_mut::<JSObject>());\n" "rooted!(in(*s.get_context()) let thisObjJS = ptr::null_mut::<JSObject>());\n"
"unsafe { ${methodName}(${callArgs}) }").substitute({ "unsafe { ${methodName}(${callArgs}) }").substitute({
"callArgs": ", ".join(argnamesWithoutThis), "callArgs": ", ".join(argnamesWithoutThis),
"methodName": 'self.' + method.name, "methodName": 'self.' + method.name,
@ -7115,7 +7118,7 @@ class CallbackMember(CGNativeMember):
return "" return ""
return ( return (
"CallSetup s(CallbackPreserveColor(), aRv, aExceptionHandling);\n" "CallSetup s(CallbackPreserveColor(), aRv, aExceptionHandling);\n"
"JSContext* cx = s.get_context();\n" "JSContext* cx = *s.get_context();\n"
"if (!cx) {\n" "if (!cx) {\n"
" return Err(JSFailed);\n" " return Err(JSFailed);\n"
"}\n") "}\n")
@ -7216,7 +7219,7 @@ class CallbackOperationBase(CallbackMethod):
"methodName": self.methodName "methodName": self.methodName
} }
getCallableFromProp = string.Template( getCallableFromProp = string.Template(
'r#try!(self.parent.get_callable_property(*cx, "${methodName}"))' 'r#try!(self.parent.get_callable_property(cx, "${methodName}"))'
).substitute(replacements) ).substitute(replacements)
if not self.singleOperation: if not self.singleOperation:
return 'rooted!(in(*cx) let callable =\n' + getCallableFromProp + ');\n' return 'rooted!(in(*cx) let callable =\n' + getCallableFromProp + ');\n'

View file

@ -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());
unsafe {
assert!(JS_DefineProperty( assert!(JS_DefineProperty(
cx, *cx,
obj, obj,
spec.name.as_ptr() as *const libc::c_char, spec.name.as_ptr() as *const libc::c_char,
value.handle(), value.handle(),
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32 (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) as u32
)); ));
} }
}
} }

View file

@ -15,6 +15,7 @@ use crate::dom::bindings::conversions::{
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
use crate::dom::domexception::{DOMErrorName, DOMException}; use crate::dom::domexception::{DOMErrorName, DOMException};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::JSContext as SafeJSContext;
#[cfg(feature = "js_backtrace")] #[cfg(feature = "js_backtrace")]
use backtrace::Backtrace; use backtrace::Backtrace;
use js::error::{throw_range_error, throw_type_error}; use js::error::{throw_range_error, throw_type_error};
@ -104,10 +105,10 @@ pub type Fallible<T> = Result<T, Error>;
pub type ErrorResult = Fallible<()>; pub type ErrorResult = Fallible<()>;
/// Set a pending exception for the given `result` on `cx`. /// Set a pending exception for the given `result` on `cx`.
pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, result: Error) { pub fn throw_dom_exception(cx: SafeJSContext, global: &GlobalScope, result: Error) {
#[cfg(feature = "js_backtrace")] #[cfg(feature = "js_backtrace")]
{ {
capture_stack!(in(cx) let stack); capture_stack!(in(*cx) let stack);
let js_stack = stack.and_then(|s| s.as_string(None)); let js_stack = stack.and_then(|s| s.as_string(None));
let rust_stack = Backtrace::new(); let rust_stack = Backtrace::new();
LAST_EXCEPTION_BACKTRACE.with(|backtrace| { LAST_EXCEPTION_BACKTRACE.with(|backtrace| {
@ -139,27 +140,29 @@ pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, resu
Error::InvalidModification => DOMErrorName::InvalidModificationError, Error::InvalidModification => DOMErrorName::InvalidModificationError,
Error::NotReadable => DOMErrorName::NotReadableError, Error::NotReadable => DOMErrorName::NotReadableError,
Error::Operation => DOMErrorName::OperationError, Error::Operation => DOMErrorName::OperationError,
Error::Type(message) => { Error::Type(message) => unsafe {
assert!(!JS_IsExceptionPending(cx)); assert!(!JS_IsExceptionPending(*cx));
throw_type_error(cx, &message); throw_type_error(*cx, &message);
return; return;
}, },
Error::Range(message) => { Error::Range(message) => unsafe {
assert!(!JS_IsExceptionPending(cx)); assert!(!JS_IsExceptionPending(*cx));
throw_range_error(cx, &message); throw_range_error(*cx, &message);
return; return;
}, },
Error::JSFailed => { Error::JSFailed => unsafe {
assert!(JS_IsExceptionPending(cx)); assert!(JS_IsExceptionPending(*cx));
return; return;
}, },
}; };
assert!(!JS_IsExceptionPending(cx)); unsafe {
assert!(!JS_IsExceptionPending(*cx));
let exception = DOMException::new(global, code); let exception = DOMException::new(global, code);
rooted!(in(cx) let mut thrown = UndefinedValue()); rooted!(in(*cx) let mut thrown = UndefinedValue());
exception.to_jsval(cx, thrown.handle_mut()); exception.to_jsval(*cx, thrown.handle_mut());
JS_SetPendingException(cx, thrown.handle()); JS_SetPendingException(*cx, thrown.handle());
}
} }
/// A struct encapsulating information about a runtime script error. /// A struct encapsulating information about a runtime script error.
@ -310,7 +313,7 @@ impl Error {
Error::JSFailed => (), Error::JSFailed => (),
_ => assert!(!JS_IsExceptionPending(cx)), _ => assert!(!JS_IsExceptionPending(cx)),
} }
throw_dom_exception(cx, global, self); throw_dom_exception(SafeJSContext::from_ptr(cx), global, self);
assert!(JS_IsExceptionPending(cx)); assert!(JS_IsExceptionPending(cx));
assert!(JS_GetPendingException(cx, rval)); assert!(JS_GetPendingException(cx, rval));
JS_ClearPendingException(cx); JS_ClearPendingException(cx);

View file

@ -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),

View file

@ -76,13 +76,13 @@ use crate::dom::customelementregistry::{ConstructionStackEntry, CustomElementSta
use crate::dom::element::{Element, ElementCreator}; use crate::dom::element::{Element, ElementCreator};
use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlelement::HTMLElement;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use html5ever::interface::QualName; use html5ever::interface::QualName;
use html5ever::LocalName; use html5ever::LocalName;
use js::glue::UnwrapObjectStatic; use js::glue::UnwrapObjectStatic;
use js::jsapi::{CallArgs, CurrentGlobalOrNull}; use js::jsapi::{CallArgs, CurrentGlobalOrNull};
use js::jsapi::{JSAutoRealm, JSContext, JSObject}; use js::jsapi::{JSAutoRealm, JSObject};
use js::rust::HandleObject; use js::rust::HandleObject;
use js::rust::MutableHandleObject; use js::rust::MutableHandleObject;
use std::ptr; use std::ptr;
@ -134,7 +134,7 @@ where
// Step 5 // Step 5
get_constructor_object_from_local_name( get_constructor_object_from_local_name(
definition.local_name.clone(), definition.local_name.clone(),
*window.get_cx(), window.get_cx(),
global_object.handle(), global_object.handle(),
constructor.handle_mut(), constructor.handle_mut(),
); );
@ -196,13 +196,13 @@ where
/// This list should only include elements marked with the [HTMLConstructor] extended attribute. /// This list should only include elements marked with the [HTMLConstructor] extended attribute.
pub fn get_constructor_object_from_local_name( pub fn get_constructor_object_from_local_name(
name: LocalName, name: LocalName,
cx: *mut JSContext, cx: JSContext,
global: HandleObject, global: HandleObject,
rval: MutableHandleObject, rval: MutableHandleObject,
) -> bool { ) -> bool {
macro_rules! get_constructor( macro_rules! get_constructor(
($binding:ident) => ({ ($binding:ident) => ({
unsafe { $binding::GetConstructorObject(SafeJSContext::from_ptr(cx), global, rval); } $binding::GetConstructorObject(cx, global, rval);
true true
}) })
); );

View file

@ -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); let unscopable_symbol = GetWellKnownSymbol(*cx, SymbolCode::unscopables);
assert!(!unscopable_symbol.is_null()); assert!(!unscopable_symbol.is_null());
rooted!(in(cx) let mut unscopable_id: jsid); rooted!(in(*cx) let mut unscopable_id: jsid);
RUST_SYMBOL_TO_JSID(unscopable_symbol, unscopable_id.handle_mut()); RUST_SYMBOL_TO_JSID(unscopable_symbol, unscopable_id.handle_mut());
assert!(JS_DefinePropertyById5( assert!(JS_DefinePropertyById5(
cx, *cx,
rval.handle(), rval.handle(),
unscopable_id.handle(), unscopable_id.handle(),
unscopable_obj.handle(), unscopable_obj.handle(),
JSPROP_READONLY as u32 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,30 +250,33 @@ pub unsafe fn create_noncallback_interface_object(
constants, constants,
rval, rval,
); );
unsafe {
assert!(JS_LinkConstructorAndPrototype( assert!(JS_LinkConstructorAndPrototype(
cx, *cx,
rval.handle(), rval.handle(),
interface_prototype_object 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');
unsafe {
let fun = JS_NewFunction( let fun = JS_NewFunction(
cx, *cx,
Some(native), Some(native),
arity, arity,
JSFUN_CONSTRUCTOR, JSFUN_CONSTRUCTOR,
@ -279,20 +287,21 @@ pub unsafe fn create_named_constructors(
assert!(!constructor.is_null()); 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 {
unsafe {
let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0); let unwrapped = UncheckedUnwrapObject(object.get(), /* stopAtWindowProxy = */ 0);
let dom_class = get_dom_class(unwrapped).unwrap(); let dom_class = get_dom_class(unwrapped).unwrap();
globals.contains(dom_class.global) 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');
unsafe {
assert!(JS_DefineProperty3( assert!(JS_DefineProperty3(
cx, *cx,
global, global,
name.as_ptr() as *const libc::c_char, name.as_ptr() as *const libc::c_char,
obj, obj,
JSPROP_RESOLVING 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,9 +452,10 @@ 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());
unsafe {
let js_class = get_object_class(interface_object.get()); let js_class = get_object_class(interface_object.get());
let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass); let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass);
@ -442,7 +463,8 @@ unsafe fn has_instance(
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. // Step 4.
return Ok(true); return Ok(true);
} }
@ -452,11 +474,11 @@ unsafe fn has_instance(
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.
@ -466,52 +488,55 @@ unsafe fn has_instance(
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 {
rval.set(JS_NewPlainObject(*cx));
assert!(!rval.is_null()); assert!(!rval.is_null());
for &name in names { for &name in names {
assert_eq!(*name.last().unwrap(), b'\0'); assert_eq!(*name.last().unwrap(), b'\0');
assert!(JS_DefineProperty( assert!(JS_DefineProperty(
cx, *cx,
rval.handle(), rval.handle(),
name.as_ptr() as *const libc::c_char, name.as_ptr() as *const libc::c_char,
HandleValue::from_raw(TrueHandleValue), HandleValue::from_raw(TrueHandleValue),
JSPROP_READONLY as u32, JSPROP_READONLY as u32,
)); ));
} }
}
} }
unsafe fn define_name(cx: *mut JSContext, obj: HandleObject, name: &[u8]) { fn define_name(cx: SafeJSContext, obj: HandleObject, name: &[u8]) {
assert_eq!(*name.last().unwrap(), b'\0'); assert_eq!(*name.last().unwrap(), b'\0');
rooted!(in(cx) let name = JS_AtomizeAndPinString(cx, name.as_ptr() as *const libc::c_char)); unsafe {
rooted!(in(*cx) let name = JS_AtomizeAndPinString(*cx, name.as_ptr() as *const libc::c_char));
assert!(!name.is_null()); assert!(!name.is_null());
assert!(JS_DefineProperty4( assert!(JS_DefineProperty4(
cx, *cx,
obj, obj,
b"name\0".as_ptr() as *const libc::c_char, b"name\0".as_ptr() as *const libc::c_char,
name.handle().into(), name.handle().into(),
JSPROP_READONLY as u32 JSPROP_READONLY as u32
)); ));
}
} }
unsafe fn define_length(cx: *mut JSContext, obj: HandleObject, length: i32) { fn define_length(cx: SafeJSContext, obj: HandleObject, length: i32) {
unsafe {
assert!(JS_DefineProperty5( assert!(JS_DefineProperty5(
cx, *cx,
obj, obj,
b"length\0".as_ptr() as *const libc::c_char, b"length\0".as_ptr() as *const libc::c_char,
length, length,
JSPROP_READONLY as u32 JSPROP_READONLY as u32
)); ));
}
} }
unsafe extern "C" fn invalid_constructor( unsafe extern "C" fn invalid_constructor(

View file

@ -13,10 +13,10 @@ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::trace::{JSTraceable, RootedTraceableBox}; use crate::dom::bindings::trace::{JSTraceable, RootedTraceableBox};
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible; use js::conversions::ToJSValConvertible;
use js::jsapi::{Heap, JSContext, JSObject}; use js::jsapi::{Heap, JSObject};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use js::rust::{HandleValue, MutableHandleObject}; use js::rust::{HandleValue, MutableHandleObject};
use std::cell::Cell; use std::cell::Cell;
@ -63,7 +63,7 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
pub fn new( pub fn new(
iterable: &T, iterable: &T,
type_: IteratorType, type_: IteratorType,
wrap: unsafe fn(SafeJSContext, &GlobalScope, Box<IterableIterator<T>>) -> DomRoot<Self>, wrap: unsafe fn(JSContext, &GlobalScope, Box<IterableIterator<T>>) -> DomRoot<Self>,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
let iterator = Box::new(IterableIterator { let iterator = Box::new(IterableIterator {
reflector: Reflector::new(), reflector: Reflector::new(),
@ -76,12 +76,12 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
/// Return the next value from the iterable object. /// Return the next value from the iterable object.
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn Next(&self, cx: SafeJSContext) -> Fallible<NonNull<JSObject>> { pub fn Next(&self, cx: JSContext) -> Fallible<NonNull<JSObject>> {
let index = self.index.get(); let index = self.index.get();
rooted!(in(*cx) let mut value = UndefinedValue()); rooted!(in(*cx) let mut value = UndefinedValue());
rooted!(in(*cx) let mut rval = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut rval = ptr::null_mut::<JSObject>());
let result = if index >= self.iterable.get_iterable_length() { let result = if index >= self.iterable.get_iterable_length() {
dict_return(*cx, rval.handle_mut(), true, value.handle()) dict_return(cx, rval.handle_mut(), true, value.handle())
} else { } else {
match self.type_ { match self.type_ {
IteratorType::Keys => { IteratorType::Keys => {
@ -90,7 +90,7 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
.get_key_at_index(index) .get_key_at_index(index)
.to_jsval(*cx, value.handle_mut()); .to_jsval(*cx, value.handle_mut());
} }
dict_return(*cx, rval.handle_mut(), false, value.handle()) dict_return(cx, rval.handle_mut(), false, value.handle())
}, },
IteratorType::Values => { IteratorType::Values => {
unsafe { unsafe {
@ -98,7 +98,7 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
.get_value_at_index(index) .get_value_at_index(index)
.to_jsval(*cx, value.handle_mut()); .to_jsval(*cx, value.handle_mut());
} }
dict_return(*cx, rval.handle_mut(), false, value.handle()) dict_return(cx, rval.handle_mut(), false, value.handle())
}, },
IteratorType::Entries => { IteratorType::Entries => {
rooted!(in(*cx) let mut key = UndefinedValue()); rooted!(in(*cx) let mut key = UndefinedValue());
@ -110,7 +110,7 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
.get_value_at_index(index) .get_value_at_index(index)
.to_jsval(*cx, value.handle_mut()); .to_jsval(*cx, value.handle_mut());
} }
key_and_value_return(*cx, rval.handle_mut(), key.handle(), value.handle()) key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle())
}, },
} }
}; };
@ -120,7 +120,7 @@ impl<T: DomObject + JSTraceable + Iterable> IterableIterator<T> {
} }
fn dict_return( fn dict_return(
cx: *mut JSContext, cx: JSContext,
mut result: MutableHandleObject, mut result: MutableHandleObject,
done: bool, done: bool,
value: HandleValue, value: HandleValue,
@ -128,16 +128,16 @@ fn dict_return(
let mut dict = IterableKeyOrValueResult::empty(); let mut dict = IterableKeyOrValueResult::empty();
dict.done = done; dict.done = done;
dict.value.set(value.get()); dict.value.set(value.get());
rooted!(in(cx) let mut dict_value = UndefinedValue()); rooted!(in(*cx) let mut dict_value = UndefinedValue());
unsafe { unsafe {
dict.to_jsval(cx, dict_value.handle_mut()); dict.to_jsval(*cx, dict_value.handle_mut());
} }
result.set(dict_value.to_object()); result.set(dict_value.to_object());
Ok(()) Ok(())
} }
fn key_and_value_return( fn key_and_value_return(
cx: *mut JSContext, cx: JSContext,
mut result: MutableHandleObject, mut result: MutableHandleObject,
key: HandleValue, key: HandleValue,
value: HandleValue, value: HandleValue,
@ -150,9 +150,9 @@ fn key_and_value_return(
.map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get()))) .map(|handle| RootedTraceableBox::from_box(Heap::boxed(handle.get())))
.collect(), .collect(),
); );
rooted!(in(cx) let mut dict_value = UndefinedValue()); rooted!(in(*cx) let mut dict_value = UndefinedValue());
unsafe { unsafe {
dict.to_jsval(cx, dict_value.handle_mut()); dict.to_jsval(*cx, dict_value.handle_mut());
} }
result.set(dict_value.to_object()); result.set(dict_value.to_object());
Ok(()) Ok(())

View file

@ -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,

View file

@ -30,13 +30,13 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::permissions::{get_descriptor_permission_state, PermissionAlgorithm}; use crate::dom::permissions::{get_descriptor_permission_state, PermissionAlgorithm};
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use crate::task::TaskOnce; use crate::task::TaskOnce;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::conversions::ConversionResult; use js::conversions::ConversionResult;
use js::jsapi::{JSContext, JSObject}; use js::jsapi::JSObject;
use js::jsval::{ObjectValue, UndefinedValue}; use js::jsval::{ObjectValue, UndefinedValue};
use profile_traits::ipc as ProfiledIpc; use profile_traits::ipc as ProfiledIpc;
use std::cell::Ref; use std::cell::Ref;
@ -616,28 +616,24 @@ impl PermissionAlgorithm for Bluetooth {
type Descriptor = BluetoothPermissionDescriptor; type Descriptor = BluetoothPermissionDescriptor;
type Status = BluetoothPermissionResult; type Status = BluetoothPermissionResult;
#[allow(unsafe_code)]
fn create_descriptor( fn create_descriptor(
cx: *mut JSContext, cx: JSContext,
permission_descriptor_obj: *mut JSObject, permission_descriptor_obj: *mut JSObject,
) -> Result<BluetoothPermissionDescriptor, Error> { ) -> Result<BluetoothPermissionDescriptor, Error> {
rooted!(in(cx) let mut property = UndefinedValue()); rooted!(in(*cx) let mut property = UndefinedValue());
property property
.handle_mut() .handle_mut()
.set(ObjectValue(permission_descriptor_obj)); .set(ObjectValue(permission_descriptor_obj));
unsafe { match BluetoothPermissionDescriptor::new(cx, property.handle()) {
match BluetoothPermissionDescriptor::new(SafeJSContext::from_ptr(cx), property.handle())
{
Ok(ConversionResult::Success(descriptor)) => Ok(descriptor), Ok(ConversionResult::Success(descriptor)) => Ok(descriptor),
Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())), Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
Err(_) => Err(Error::Type(String::from(BT_DESC_CONVERSION_ERROR))), Err(_) => Err(Error::Type(String::from(BT_DESC_CONVERSION_ERROR))),
} }
} }
}
// https://webbluetoothcg.github.io/web-bluetooth/#query-the-bluetooth-permission // https://webbluetoothcg.github.io/web-bluetooth/#query-the-bluetooth-permission
fn permission_query( fn permission_query(
_cx: *mut JSContext, _cx: JSContext,
promise: &Rc<Promise>, promise: &Rc<Promise>,
descriptor: &BluetoothPermissionDescriptor, descriptor: &BluetoothPermissionDescriptor,
status: &BluetoothPermissionResult, status: &BluetoothPermissionResult,
@ -727,7 +723,7 @@ impl PermissionAlgorithm for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission // https://webbluetoothcg.github.io/web-bluetooth/#request-the-bluetooth-permission
fn permission_request( fn permission_request(
_cx: *mut JSContext, _cx: JSContext,
promise: &Rc<Promise>, promise: &Rc<Promise>,
descriptor: &BluetoothPermissionDescriptor, descriptor: &BluetoothPermissionDescriptor,
status: &BluetoothPermissionResult, status: &BluetoothPermissionResult,

View file

@ -158,7 +158,7 @@ fn create_html_element(
unsafe { unsafe {
let _ac = let _ac =
JSAutoRealm::new(*cx, global.reflector().get_jsobject().get()); JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
throw_dom_exception(*cx, &global, error); throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true); report_pending_exception(*cx, true);
} }

View file

@ -31,14 +31,14 @@ use crate::dom::node::{document_from_node, window_from_node, Node, ShadowIncludi
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::microtask::Microtask; use crate::microtask::Microtask;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{LocalName, Namespace, Prefix}; use html5ever::{LocalName, Namespace, Prefix};
use js::conversions::ToJSValConvertible; use js::conversions::ToJSValConvertible;
use js::glue::UnwrapObjectStatic; use js::glue::UnwrapObjectStatic;
use js::jsapi::{HandleValueArray, Heap, IsCallable, IsConstructor}; use js::jsapi::{HandleValueArray, Heap, IsCallable, IsConstructor};
use js::jsapi::{JSAutoRealm, JSContext, JSObject}; use js::jsapi::{JSAutoRealm, JSObject};
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue}; use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
use js::rust::wrappers::{Construct1, JS_GetProperty, SameValue}; use js::rust::wrappers::{Construct1, JS_GetProperty, SameValue};
use js::rust::{HandleObject, HandleValue, MutableHandleValue}; use js::rust::{HandleObject, HandleValue, MutableHandleValue};
@ -171,14 +171,10 @@ impl CustomElementRegistry {
// Step 4 // Step 4
Ok(LifecycleCallbacks { Ok(LifecycleCallbacks {
connected_callback: get_callback(*cx, prototype, b"connectedCallback\0")?, connected_callback: get_callback(cx, prototype, b"connectedCallback\0")?,
disconnected_callback: get_callback(*cx, prototype, b"disconnectedCallback\0")?, disconnected_callback: get_callback(cx, prototype, b"disconnectedCallback\0")?,
adopted_callback: get_callback(*cx, prototype, b"adoptedCallback\0")?, adopted_callback: get_callback(cx, prototype, b"adoptedCallback\0")?,
attribute_changed_callback: get_callback( attribute_changed_callback: get_callback(cx, prototype, b"attributeChangedCallback\0")?,
*cx,
prototype,
b"attributeChangedCallback\0",
)?,
}) })
} }
@ -221,16 +217,16 @@ impl CustomElementRegistry {
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define> /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define>
/// Step 10.4 /// Step 10.4
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_callback( fn get_callback(
cx: *mut JSContext, cx: JSContext,
prototype: HandleObject, prototype: HandleObject,
name: &[u8], name: &[u8],
) -> Fallible<Option<Rc<Function>>> { ) -> Fallible<Option<Rc<Function>>> {
rooted!(in(cx) let mut callback = UndefinedValue()); rooted!(in(*cx) let mut callback = UndefinedValue());
unsafe {
// Step 10.4.1 // Step 10.4.1
if !JS_GetProperty( if !JS_GetProperty(
cx, *cx,
prototype, prototype,
name.as_ptr() as *const _, name.as_ptr() as *const _,
callback.handle_mut(), callback.handle_mut(),
@ -243,13 +239,11 @@ unsafe fn get_callback(
if !callback.is_object() || !IsCallable(callback.to_object()) { if !callback.is_object() || !IsCallable(callback.to_object()) {
return Err(Error::Type("Lifecycle callback is not callable".to_owned())); return Err(Error::Type("Lifecycle callback is not callable".to_owned()));
} }
Ok(Some(Function::new( Ok(Some(Function::new(cx, callback.to_object())))
SafeJSContext::from_ptr(cx),
callback.to_object(),
)))
} else { } else {
Ok(None) Ok(None)
} }
}
} }
impl CustomElementRegistryMethods for CustomElementRegistry { impl CustomElementRegistryMethods for CustomElementRegistry {
@ -409,7 +403,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-get> /// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-get>
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Get(&self, cx: SafeJSContext, name: DOMString) -> JSVal { fn Get(&self, cx: JSContext, name: DOMString) -> JSVal {
match self.definitions.borrow().get(&LocalName::from(&*name)) { match self.definitions.borrow().get(&LocalName::from(&*name)) {
Some(definition) => unsafe { Some(definition) => unsafe {
rooted!(in(*cx) let mut constructor = UndefinedValue()); rooted!(in(*cx) let mut constructor = UndefinedValue());
@ -631,7 +625,7 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
let global = GlobalScope::current().expect("No current global"); let global = GlobalScope::current().expect("No current global");
let cx = global.get_cx(); let cx = global.get_cx();
unsafe { unsafe {
throw_dom_exception(*cx, &global, error); throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true); report_pending_exception(*cx, true);
} }
return; return;

View file

@ -22,7 +22,7 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::progressevent::ProgressEvent; use crate::dom::progressevent::ProgressEvent;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use crate::task::TaskCanceller; use crate::task::TaskCanceller;
use crate::task_source::file_reading::{FileReadingTask, FileReadingTaskSource}; use crate::task_source::file_reading::{FileReadingTask, FileReadingTaskSource};
use crate::task_source::{TaskSource, TaskSourceName}; use crate::task_source::{TaskSource, TaskSourceName};
@ -30,7 +30,6 @@ use base64;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::{Encoding, UTF_8}; use encoding_rs::{Encoding, UTF_8};
use js::jsapi::Heap; use js::jsapi::Heap;
use js::jsapi::JSContext;
use js::jsapi::JSObject; use js::jsapi::JSObject;
use js::jsval::{self, JSVal}; use js::jsval::{self, JSVal};
use js::typedarray::{ArrayBuffer, CreateWith}; use js::typedarray::{ArrayBuffer, CreateWith};
@ -233,7 +232,6 @@ impl FileReader {
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
#[allow(unsafe_code)]
pub fn process_read_eof( pub fn process_read_eof(
filereader: TrustedFileReader, filereader: TrustedFileReader,
gen_id: GenerationId, gen_id: GenerationId,
@ -266,7 +264,7 @@ impl FileReader {
let _ac = enter_realm(&*fr); let _ac = enter_realm(&*fr);
FileReader::perform_readasarraybuffer( FileReader::perform_readasarraybuffer(
&fr.result, &fr.result,
*fr.global().get_cx(), fr.global().get_cx(),
data, data,
&blob_contents, &blob_contents,
) )
@ -313,14 +311,14 @@ impl FileReader {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn perform_readasarraybuffer( fn perform_readasarraybuffer(
result: &DomRefCell<Option<FileReaderResult>>, result: &DomRefCell<Option<FileReaderResult>>,
cx: *mut JSContext, cx: JSContext,
_: ReadMetaData, _: ReadMetaData,
bytes: &[u8], bytes: &[u8],
) { ) {
unsafe { unsafe {
rooted!(in(cx) let mut array_buffer = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
assert!( assert!(
ArrayBuffer::create(cx, CreateWith::Slice(bytes), array_buffer.handle_mut()) ArrayBuffer::create(*cx, CreateWith::Slice(bytes), array_buffer.handle_mut())
.is_ok() .is_ok()
); );
@ -392,7 +390,7 @@ impl FileReaderMethods for FileReader {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://w3c.github.io/FileAPI/#dfn-result // https://w3c.github.io/FileAPI/#dfn-result
fn GetResult(&self, _: SafeJSContext) -> Option<StringOrObject> { fn GetResult(&self, _: JSContext) -> Option<StringOrObject> {
self.result.borrow().as_ref().map(|r| match *r { self.result.borrow().as_ref().map(|r| match *r {
FileReaderResult::String(ref string) => StringOrObject::String(string.clone()), FileReaderResult::String(ref string) => StringOrObject::String(string.clone()),
FileReaderResult::ArrayBuffer(ref arr_buffer) => { FileReaderResult::ArrayBuffer(ref arr_buffer) => {

View file

@ -677,23 +677,17 @@ impl GlobalScope {
} }
/// Perform a microtask checkpoint. /// Perform a microtask checkpoint.
#[allow(unsafe_code)]
pub fn perform_a_microtask_checkpoint(&self) { pub fn perform_a_microtask_checkpoint(&self) {
unsafe {
self.microtask_queue.checkpoint( self.microtask_queue.checkpoint(
*self.get_cx(), self.get_cx(),
|_| Some(DomRoot::from_ref(self)), |_| Some(DomRoot::from_ref(self)),
vec![DomRoot::from_ref(self)], vec![DomRoot::from_ref(self)],
); );
} }
}
/// Enqueue a microtask for subsequent execution. /// Enqueue a microtask for subsequent execution.
#[allow(unsafe_code)]
pub fn enqueue_microtask(&self, job: Microtask) { pub fn enqueue_microtask(&self, job: Microtask) {
unsafe { self.microtask_queue.enqueue(job, self.get_cx());
self.microtask_queue.enqueue(job, *self.get_cx());
}
} }
/// Create a new sender/receiver pair that can be used to implement an on-demand /// Create a new sender/receiver pair that can be used to implement an on-demand

View file

@ -18,9 +18,9 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::hashchangeevent::HashChangeEvent; use crate::dom::hashchangeevent::HashChangeEvent;
use crate::dom::popstateevent::PopStateEvent; use crate::dom::popstateevent::PopStateEvent;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::jsapi::{Heap, JSContext}; use js::jsapi::Heap;
use js::jsval::{JSVal, NullValue, UndefinedValue}; use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::HandleValue; use js::rust::HandleValue;
use msg::constellation_msg::{HistoryStateId, TraversalDirection}; use msg::constellation_msg::{HistoryStateId, TraversalDirection};
@ -165,7 +165,7 @@ impl History {
// https://html.spec.whatwg.org/multipage/#dom-history-replacestate // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
fn push_or_replace_state( fn push_or_replace_state(
&self, &self,
cx: *mut JSContext, cx: JSContext,
data: HandleValue, data: HandleValue,
_title: DOMString, _title: DOMString,
url: Option<USVString>, url: Option<USVString>,
@ -185,7 +185,7 @@ impl History {
// TODO: Step 4 // TODO: Step 4
// Step 5 // Step 5
let serialized_data = StructuredCloneData::write(cx, data)?.move_to_arraybuffer(); let serialized_data = StructuredCloneData::write(*cx, data)?.move_to_arraybuffer();
let new_url: ServoUrl = match url { let new_url: ServoUrl = match url {
// Step 6 // Step 6
@ -265,7 +265,7 @@ impl History {
// Step 11 // Step 11
let global_scope = self.window.upcast::<GlobalScope>(); let global_scope = self.window.upcast::<GlobalScope>();
rooted!(in(cx) let mut state = UndefinedValue()); rooted!(in(*cx) let mut state = UndefinedValue());
StructuredCloneData::Vector(serialized_data).read(&global_scope, state.handle_mut()); StructuredCloneData::Vector(serialized_data).read(&global_scope, state.handle_mut());
// Step 12 // Step 12
@ -280,7 +280,7 @@ impl History {
impl HistoryMethods for History { impl HistoryMethods for History {
// https://html.spec.whatwg.org/multipage/#dom-history-state // https://html.spec.whatwg.org/multipage/#dom-history-state
fn GetState(&self, _cx: SafeJSContext) -> Fallible<JSVal> { fn GetState(&self, _cx: JSContext) -> Fallible<JSVal> {
if !self.window.Document().is_fully_active() { if !self.window.Document().is_fully_active() {
return Err(Error::Security); return Err(Error::Security);
} }
@ -329,22 +329,22 @@ impl HistoryMethods for History {
// https://html.spec.whatwg.org/multipage/#dom-history-pushstate // https://html.spec.whatwg.org/multipage/#dom-history-pushstate
fn PushState( fn PushState(
&self, &self,
cx: SafeJSContext, cx: JSContext,
data: HandleValue, data: HandleValue,
title: DOMString, title: DOMString,
url: Option<USVString>, url: Option<USVString>,
) -> ErrorResult { ) -> ErrorResult {
self.push_or_replace_state(*cx, data, title, url, PushOrReplace::Push) self.push_or_replace_state(cx, data, title, url, PushOrReplace::Push)
} }
// https://html.spec.whatwg.org/multipage/#dom-history-replacestate // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
fn ReplaceState( fn ReplaceState(
&self, &self,
cx: SafeJSContext, cx: JSContext,
data: HandleValue, data: HandleValue,
title: DOMString, title: DOMString,
url: Option<USVString>, url: Option<USVString>,
) -> ErrorResult { ) -> ErrorResult {
self.push_or_replace_state(*cx, data, title, url, PushOrReplace::Replace) self.push_or_replace_state(cx, data, title, url, PushOrReplace::Replace)
} }
} }

View file

@ -28,7 +28,7 @@ use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
use crate::dom::webglrenderingcontext::{ use crate::dom::webglrenderingcontext::{
LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext,
}; };
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use base64; use base64;
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg}; use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg};
use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; use canvas_traits::webgl::{GLContextAttributes, WebGLVersion};
@ -39,7 +39,6 @@ use image::png::PNGEncoder;
use image::ColorType; use image::ColorType;
use ipc_channel::ipc::IpcSharedMemory; use ipc_channel::ipc::IpcSharedMemory;
use js::error::throw_type_error; use js::error::throw_type_error;
use js::jsapi::JSContext;
use js::rust::HandleValue; use js::rust::HandleValue;
use profile_traits::ipc; use profile_traits::ipc;
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource}; use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
@ -207,10 +206,9 @@ impl HTMLCanvasElement {
Some(context) Some(context)
} }
#[allow(unsafe_code)] fn get_or_init_webgl_context(
unsafe fn get_or_init_webgl_context(
&self, &self,
cx: *mut JSContext, cx: JSContext,
options: HandleValue, options: HandleValue,
) -> Option<DomRoot<WebGLRenderingContext>> { ) -> Option<DomRoot<WebGLRenderingContext>> {
if let Some(ctx) = self.context() { if let Some(ctx) = self.context() {
@ -227,10 +225,9 @@ impl HTMLCanvasElement {
Some(context) Some(context)
} }
#[allow(unsafe_code)] fn get_or_init_webgl2_context(
unsafe fn get_or_init_webgl2_context(
&self, &self,
cx: *mut JSContext, cx: JSContext,
options: HandleValue, options: HandleValue,
) -> Option<DomRoot<WebGL2RenderingContext>> { ) -> Option<DomRoot<WebGL2RenderingContext>> {
if !pref!(dom.webgl2.enabled) { if !pref!(dom.webgl2.enabled) {
@ -260,14 +257,12 @@ impl HTMLCanvasElement {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_gl_attributes( fn get_gl_attributes(cx: JSContext, options: HandleValue) -> Option<GLContextAttributes> {
cx: *mut JSContext, unsafe {
options: HandleValue, match WebGLContextAttributes::new(cx, options) {
) -> Option<GLContextAttributes> {
match WebGLContextAttributes::new(SafeJSContext::from_ptr(cx), options) {
Ok(ConversionResult::Success(ref attrs)) => Some(From::from(attrs)), Ok(ConversionResult::Success(ref attrs)) => Some(From::from(attrs)),
Ok(ConversionResult::Failure(ref error)) => { Ok(ConversionResult::Failure(ref error)) => {
throw_type_error(cx, &error); throw_type_error(*cx, &error);
None None
}, },
_ => { _ => {
@ -276,6 +271,7 @@ impl HTMLCanvasElement {
}, },
} }
} }
}
pub fn is_valid(&self) -> bool { pub fn is_valid(&self) -> bool {
self.Height() != 0 && self.Width() != 0 self.Height() != 0 && self.Width() != 0
@ -329,10 +325,9 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
make_uint_setter!(SetHeight, "height", DEFAULT_HEIGHT); make_uint_setter!(SetHeight, "height", DEFAULT_HEIGHT);
// https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
#[allow(unsafe_code)]
fn GetContext( fn GetContext(
&self, &self,
cx: SafeJSContext, cx: JSContext,
id: DOMString, id: DOMString,
options: HandleValue, options: HandleValue,
) -> Option<RenderingContext> { ) -> Option<RenderingContext> {
@ -340,14 +335,12 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
"2d" => self "2d" => self
.get_or_init_2d_context() .get_or_init_2d_context()
.map(RenderingContext::CanvasRenderingContext2D), .map(RenderingContext::CanvasRenderingContext2D),
"webgl" | "experimental-webgl" => unsafe { "webgl" | "experimental-webgl" => self
self.get_or_init_webgl_context(*cx, options) .get_or_init_webgl_context(cx, options)
.map(RenderingContext::WebGLRenderingContext) .map(RenderingContext::WebGLRenderingContext),
}, "webgl2" | "experimental-webgl2" => self
"webgl2" | "experimental-webgl2" => unsafe { .get_or_init_webgl2_context(cx, options)
self.get_or_init_webgl2_context(*cx, options) .map(RenderingContext::WebGL2RenderingContext),
.map(RenderingContext::WebGL2RenderingContext)
},
_ => None, _ => None,
} }
} }
@ -355,7 +348,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
// https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl
fn ToDataURL( fn ToDataURL(
&self, &self,
_context: SafeJSContext, _context: JSContext,
_mime_type: Option<DOMString>, _mime_type: Option<DOMString>,
_quality: HandleValue, _quality: HandleValue,
) -> Fallible<USVString> { ) -> Fallible<USVString> {

View file

@ -17,10 +17,10 @@ use crate::dom::bluetoothpermissionresult::BluetoothPermissionResult;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::permissionstatus::PermissionStatus; use crate::dom::permissionstatus::PermissionStatus;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::conversions::ConversionResult; use js::conversions::ConversionResult;
use js::jsapi::{JSContext, JSObject}; use js::jsapi::JSObject;
use js::jsval::{ObjectValue, UndefinedValue}; use js::jsval::{ObjectValue, UndefinedValue};
use servo_config::pref; use servo_config::pref;
use std::rc::Rc; use std::rc::Rc;
@ -37,17 +37,17 @@ pub trait PermissionAlgorithm {
type Descriptor; type Descriptor;
type Status; type Status;
fn create_descriptor( fn create_descriptor(
cx: *mut JSContext, cx: JSContext,
permission_descriptor_obj: *mut JSObject, permission_descriptor_obj: *mut JSObject,
) -> Result<Self::Descriptor, Error>; ) -> Result<Self::Descriptor, Error>;
fn permission_query( fn permission_query(
cx: *mut JSContext, cx: JSContext,
promise: &Rc<Promise>, promise: &Rc<Promise>,
descriptor: &Self::Descriptor, descriptor: &Self::Descriptor,
status: &Self::Status, status: &Self::Status,
); );
fn permission_request( fn permission_request(
cx: *mut JSContext, cx: JSContext,
promise: &Rc<Promise>, promise: &Rc<Promise>,
descriptor: &Self::Descriptor, descriptor: &Self::Descriptor,
status: &Self::Status, status: &Self::Status,
@ -88,7 +88,7 @@ impl Permissions {
fn manipulate( fn manipulate(
&self, &self,
op: Operation, op: Operation,
cx: *mut JSContext, cx: JSContext,
permissionDesc: *mut JSObject, permissionDesc: *mut JSObject,
promise: Option<Rc<Promise>>, promise: Option<Rc<Promise>>,
) -> Rc<Promise> { ) -> Rc<Promise> {
@ -201,18 +201,18 @@ impl Permissions {
impl PermissionsMethods for Permissions { impl PermissionsMethods for Permissions {
// https://w3c.github.io/permissions/#dom-permissions-query // https://w3c.github.io/permissions/#dom-permissions-query
fn Query(&self, cx: SafeJSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Query(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
self.manipulate(Operation::Query, *cx, permissionDesc, None) self.manipulate(Operation::Query, cx, permissionDesc, None)
} }
// https://w3c.github.io/permissions/#dom-permissions-request // https://w3c.github.io/permissions/#dom-permissions-request
fn Request(&self, cx: SafeJSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Request(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
self.manipulate(Operation::Request, *cx, permissionDesc, None) self.manipulate(Operation::Request, cx, permissionDesc, None)
} }
// https://w3c.github.io/permissions/#dom-permissions-revoke // https://w3c.github.io/permissions/#dom-permissions-revoke
fn Revoke(&self, cx: SafeJSContext, permissionDesc: *mut JSObject) -> Rc<Promise> { fn Revoke(&self, cx: JSContext, permissionDesc: *mut JSObject) -> Rc<Promise> {
self.manipulate(Operation::Revoke, *cx, permissionDesc, None) self.manipulate(Operation::Revoke, cx, permissionDesc, None)
} }
} }
@ -220,27 +220,24 @@ impl PermissionAlgorithm for Permissions {
type Descriptor = PermissionDescriptor; type Descriptor = PermissionDescriptor;
type Status = PermissionStatus; type Status = PermissionStatus;
#[allow(unsafe_code)]
fn create_descriptor( fn create_descriptor(
cx: *mut JSContext, cx: JSContext,
permission_descriptor_obj: *mut JSObject, permission_descriptor_obj: *mut JSObject,
) -> Result<PermissionDescriptor, Error> { ) -> Result<PermissionDescriptor, Error> {
rooted!(in(cx) let mut property = UndefinedValue()); rooted!(in(*cx) let mut property = UndefinedValue());
property property
.handle_mut() .handle_mut()
.set(ObjectValue(permission_descriptor_obj)); .set(ObjectValue(permission_descriptor_obj));
unsafe { match PermissionDescriptor::new(cx, property.handle()) {
match PermissionDescriptor::new(SafeJSContext::from_ptr(cx), property.handle()) {
Ok(ConversionResult::Success(descriptor)) => Ok(descriptor), Ok(ConversionResult::Success(descriptor)) => Ok(descriptor),
Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())), Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
Err(_) => Err(Error::JSFailed), Err(_) => Err(Error::JSFailed),
} }
} }
}
// https://w3c.github.io/permissions/#boolean-permission-query-algorithm // https://w3c.github.io/permissions/#boolean-permission-query-algorithm
fn permission_query( fn permission_query(
_cx: *mut JSContext, _cx: JSContext,
_promise: &Rc<Promise>, _promise: &Rc<Promise>,
_descriptor: &PermissionDescriptor, _descriptor: &PermissionDescriptor,
status: &PermissionStatus, status: &PermissionStatus,
@ -251,7 +248,7 @@ impl PermissionAlgorithm for Permissions {
// https://w3c.github.io/permissions/#boolean-permission-request-algorithm // https://w3c.github.io/permissions/#boolean-permission-request-algorithm
fn permission_request( fn permission_request(
cx: *mut JSContext, cx: JSContext,
promise: &Rc<Promise>, promise: &Rc<Promise>,
descriptor: &PermissionDescriptor, descriptor: &PermissionDescriptor,
status: &PermissionStatus, status: &PermissionStatus,

View file

@ -18,6 +18,7 @@ use crate::dom::bindings::reflector::{DomObject, MutDomObject, Reflector};
use crate::dom::bindings::utils::AsCCharPtrPtr; use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::promisenativehandler::PromiseNativeHandler; use crate::dom::promisenativehandler::PromiseNativeHandler;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible; use js::conversions::ToJSValConvertible;
use js::jsapi::{AddRawValueRoot, CallArgs, GetFunctionNativeReserved}; use js::jsapi::{AddRawValueRoot, CallArgs, GetFunctionNativeReserved};
@ -49,21 +50,22 @@ pub struct Promise {
/// Private helper to enable adding new methods to Rc<Promise>. /// Private helper to enable adding new methods to Rc<Promise>.
trait PromiseHelper { trait PromiseHelper {
#[allow(unsafe_code)] fn initialize(&self, cx: SafeJSContext);
unsafe fn initialize(&self, cx: *mut JSContext);
} }
impl PromiseHelper for Rc<Promise> { impl PromiseHelper for Rc<Promise> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn initialize(&self, cx: *mut JSContext) { fn initialize(&self, cx: SafeJSContext) {
let obj = self.reflector().get_jsobject(); let obj = self.reflector().get_jsobject();
self.permanent_js_root.set(ObjectValue(*obj)); self.permanent_js_root.set(ObjectValue(*obj));
unsafe {
assert!(AddRawValueRoot( assert!(AddRawValueRoot(
cx, *cx,
self.permanent_js_root.get_unsafe(), self.permanent_js_root.get_unsafe(),
b"Promise::root\0".as_c_char_ptr() b"Promise::root\0".as_c_char_ptr()
)); ));
} }
}
} }
impl Drop for Promise { impl Drop for Promise {
@ -86,24 +88,22 @@ impl Promise {
Promise::new_in_current_compartment(global, comp) Promise::new_in_current_compartment(global, comp)
} }
#[allow(unsafe_code)]
pub fn new_in_current_compartment(global: &GlobalScope, _comp: InCompartment) -> Rc<Promise> { pub fn new_in_current_compartment(global: &GlobalScope, _comp: InCompartment) -> Rc<Promise> {
let cx = global.get_cx(); let cx = global.get_cx();
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
unsafe { Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut());
Promise::create_js_promise(*cx, HandleObject::null(), obj.handle_mut()); Promise::new_with_js_promise(obj.handle(), cx)
Promise::new_with_js_promise(obj.handle(), *cx)
}
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn duplicate(&self) -> Rc<Promise> { pub fn duplicate(&self) -> Rc<Promise> {
let cx = self.global().get_cx(); let cx = self.global().get_cx();
unsafe { Promise::new_with_js_promise(self.reflector().get_jsobject(), *cx) } Promise::new_with_js_promise(self.reflector().get_jsobject(), cx)
} }
#[allow(unsafe_code, unrooted_must_root)] #[allow(unsafe_code, unrooted_must_root)]
pub unsafe fn new_with_js_promise(obj: HandleObject, cx: *mut JSContext) -> Rc<Promise> { pub fn new_with_js_promise(obj: HandleObject, cx: SafeJSContext) -> Rc<Promise> {
unsafe {
assert!(IsPromiseObject(obj)); assert!(IsPromiseObject(obj));
let promise = Promise { let promise = Promise {
reflector: Reflector::new(), reflector: Reflector::new(),
@ -114,47 +114,46 @@ impl Promise {
promise.initialize(cx); promise.initialize(cx);
promise promise
} }
}
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn create_js_promise( fn create_js_promise(cx: SafeJSContext, proto: HandleObject, mut obj: MutableHandleObject) {
cx: *mut JSContext, unsafe {
proto: HandleObject,
mut obj: MutableHandleObject,
) {
let do_nothing_func = JS_NewFunction( let do_nothing_func = JS_NewFunction(
cx, *cx,
Some(do_nothing_promise_executor), Some(do_nothing_promise_executor),
/* nargs = */ 2, /* nargs = */ 2,
/* flags = */ 0, /* flags = */ 0,
ptr::null(), ptr::null(),
); );
assert!(!do_nothing_func.is_null()); assert!(!do_nothing_func.is_null());
rooted!(in(cx) let do_nothing_obj = JS_GetFunctionObject(do_nothing_func)); rooted!(in(*cx) let do_nothing_obj = JS_GetFunctionObject(do_nothing_func));
assert!(!do_nothing_obj.is_null()); assert!(!do_nothing_obj.is_null());
obj.set(NewPromiseObject(cx, do_nothing_obj.handle(), proto)); obj.set(NewPromiseObject(*cx, do_nothing_obj.handle(), proto));
assert!(!obj.is_null()); assert!(!obj.is_null());
} }
}
#[allow(unrooted_must_root, unsafe_code)] #[allow(unrooted_must_root, unsafe_code)]
pub unsafe fn new_resolved( pub fn new_resolved(
global: &GlobalScope, global: &GlobalScope,
cx: *mut JSContext, cx: SafeJSContext,
value: HandleValue, value: HandleValue,
) -> Fallible<Rc<Promise>> { ) -> Fallible<Rc<Promise>> {
let _ac = JSAutoRealm::new(cx, global.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
rooted!(in(cx) let p = CallOriginalPromiseResolve(cx, value)); rooted!(in(*cx) let p = unsafe { CallOriginalPromiseResolve(*cx, value) });
assert!(!p.handle().is_null()); assert!(!p.handle().is_null());
Ok(Promise::new_with_js_promise(p.handle(), cx)) Ok(Promise::new_with_js_promise(p.handle(), cx))
} }
#[allow(unrooted_must_root, unsafe_code)] #[allow(unrooted_must_root, unsafe_code)]
pub unsafe fn new_rejected( pub fn new_rejected(
global: &GlobalScope, global: &GlobalScope,
cx: *mut JSContext, cx: SafeJSContext,
value: HandleValue, value: HandleValue,
) -> Fallible<Rc<Promise>> { ) -> Fallible<Rc<Promise>> {
let _ac = JSAutoRealm::new(cx, global.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
rooted!(in(cx) let p = CallOriginalPromiseReject(cx, value)); rooted!(in(*cx) let p = unsafe { CallOriginalPromiseReject(*cx, value) });
assert!(!p.handle().is_null()); assert!(!p.handle().is_null());
Ok(Promise::new_with_js_promise(p.handle(), cx)) Ok(Promise::new_with_js_promise(p.handle(), cx))
} }
@ -169,14 +168,16 @@ impl Promise {
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
val.to_jsval(*cx, v.handle_mut()); val.to_jsval(*cx, v.handle_mut());
self.resolve(*cx, v.handle());
} }
self.resolve(cx, v.handle());
} }
#[allow(unrooted_must_root, unsafe_code)] #[allow(unrooted_must_root, unsafe_code)]
pub unsafe fn resolve(&self, cx: *mut JSContext, value: HandleValue) { pub fn resolve(&self, cx: SafeJSContext, value: HandleValue) {
if !ResolvePromise(cx, self.promise_obj(), value) { unsafe {
JS_ClearPendingException(cx); if !ResolvePromise(*cx, self.promise_obj(), value) {
JS_ClearPendingException(*cx);
}
} }
} }
@ -190,8 +191,8 @@ impl Promise {
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
val.to_jsval(*cx, v.handle_mut()); val.to_jsval(*cx, v.handle_mut());
self.reject(*cx, v.handle());
} }
self.reject(cx, v.handle());
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
@ -201,14 +202,16 @@ impl Promise {
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
error.to_jsval(*cx, &self.global(), v.handle_mut()); error.to_jsval(*cx, &self.global(), v.handle_mut());
self.reject(*cx, v.handle());
} }
self.reject(cx, v.handle());
} }
#[allow(unrooted_must_root, unsafe_code)] #[allow(unrooted_must_root, unsafe_code)]
pub unsafe fn reject(&self, cx: *mut JSContext, value: HandleValue) { pub fn reject(&self, cx: SafeJSContext, value: HandleValue) {
if !RejectPromise(cx, self.promise_obj(), value) { unsafe {
JS_ClearPendingException(cx); if !RejectPromise(*cx, self.promise_obj(), value) {
JS_ClearPendingException(*cx);
}
} }
} }

View file

@ -941,29 +941,21 @@ impl TestBindingMethods for TestBinding {
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
#[allow(unsafe_code)]
fn ReturnResolvedPromise(&self, cx: SafeJSContext, v: HandleValue) -> Fallible<Rc<Promise>> { fn ReturnResolvedPromise(&self, cx: SafeJSContext, v: HandleValue) -> Fallible<Rc<Promise>> {
unsafe { Promise::new_resolved(&self.global(), *cx, v) } Promise::new_resolved(&self.global(), cx, v)
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
#[allow(unsafe_code)]
fn ReturnRejectedPromise(&self, cx: SafeJSContext, v: HandleValue) -> Fallible<Rc<Promise>> { fn ReturnRejectedPromise(&self, cx: SafeJSContext, v: HandleValue) -> Fallible<Rc<Promise>> {
unsafe { Promise::new_rejected(&self.global(), *cx, v) } Promise::new_rejected(&self.global(), cx, v)
} }
#[allow(unsafe_code)]
fn PromiseResolveNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) { fn PromiseResolveNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) {
unsafe { p.resolve(cx, v);
p.resolve(*cx, v);
}
} }
#[allow(unsafe_code)]
fn PromiseRejectNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) { fn PromiseRejectNative(&self, cx: SafeJSContext, p: &Promise, v: HandleValue) {
unsafe { p.reject(cx, v);
p.reject(*cx, v);
}
} }
fn PromiseRejectWithTypeError(&self, p: &Promise, s: USVString) { fn PromiseRejectWithTypeError(&self, p: &Promise, s: USVString) {
@ -1098,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
} }
} }

View file

@ -18,6 +18,7 @@ use crate::dom::document::Document;
use crate::dom::element::Element; use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use embedder_traits::EmbedderMsg; use embedder_traits::EmbedderMsg;
@ -959,7 +960,7 @@ pub fn new_window_proxy_handler() -> WindowProxyHandler {
unsafe fn throw_security_error(cx: *mut JSContext) -> bool { unsafe fn throw_security_error(cx: *mut JSContext) -> bool {
if !JS_IsExceptionPending(cx) { if !JS_IsExceptionPending(cx) {
let global = GlobalScope::from_context(cx); let global = GlobalScope::from_context(cx);
throw_dom_exception(cx, &*global, Error::Security); throw_dom_exception(SafeJSContext::from_ptr(cx), &*global, Error::Security);
} }
false false
} }

View file

@ -38,7 +38,7 @@ use crate::dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
use crate::dom::xmlhttprequestupload::XMLHttpRequestUpload; use crate::dom::xmlhttprequestupload::XMLHttpRequestUpload;
use crate::fetch::FetchCanceller; use crate::fetch::FetchCanceller;
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::script_runtime::JSContext as SafeJSContext; use crate::script_runtime::JSContext;
use crate::task_source::networking::NetworkingTaskSource; use crate::task_source::networking::NetworkingTaskSource;
use crate::task_source::TaskSourceName; use crate::task_source::TaskSourceName;
use crate::timers::{OneshotTimerCallback, OneshotTimerHandle}; use crate::timers::{OneshotTimerCallback, OneshotTimerHandle};
@ -54,7 +54,7 @@ use hyper_serde::Serde;
use ipc_channel::ipc; use ipc_channel::ipc;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::jsapi::JS_ClearPendingException; use js::jsapi::JS_ClearPendingException;
use js::jsapi::{Heap, JSContext, JSObject}; use js::jsapi::{Heap, JSObject};
use js::jsval::{JSVal, NullValue, UndefinedValue}; use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::wrappers::JS_ParseJSON; use js::rust::wrappers::JS_ParseJSON;
use js::typedarray::{ArrayBuffer, CreateWith}; use js::typedarray::{ArrayBuffer, CreateWith};
@ -878,7 +878,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://xhr.spec.whatwg.org/#the-response-attribute // https://xhr.spec.whatwg.org/#the-response-attribute
fn Response(&self, cx: SafeJSContext) -> JSVal { fn Response(&self, cx: JSContext) -> JSVal {
rooted!(in(*cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
match self.response_type.get() { match self.response_type.get() {
XMLHttpRequestResponseType::_empty | XMLHttpRequestResponseType::Text => unsafe { XMLHttpRequestResponseType::_empty | XMLHttpRequestResponseType::Text => unsafe {
@ -902,16 +902,14 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
self.document_response().to_jsval(*cx, rval.handle_mut()); self.document_response().to_jsval(*cx, rval.handle_mut());
}, },
XMLHttpRequestResponseType::Json => unsafe { XMLHttpRequestResponseType::Json => unsafe {
self.json_response(*cx).to_jsval(*cx, rval.handle_mut()); self.json_response(cx).to_jsval(*cx, rval.handle_mut());
}, },
XMLHttpRequestResponseType::Blob => unsafe { XMLHttpRequestResponseType::Blob => unsafe {
self.blob_response().to_jsval(*cx, rval.handle_mut()); self.blob_response().to_jsval(*cx, rval.handle_mut());
}, },
XMLHttpRequestResponseType::Arraybuffer => unsafe { XMLHttpRequestResponseType::Arraybuffer => match self.arraybuffer_response(cx) {
match self.arraybuffer_response(*cx) { Some(js_object) => unsafe { js_object.to_jsval(*cx, rval.handle_mut()) },
Some(js_object) => js_object.to_jsval(*cx, rval.handle_mut()),
None => return NullValue(), None => return NullValue(),
}
}, },
} }
rval.get() rval.get()
@ -1278,7 +1276,7 @@ impl XMLHttpRequest {
// https://xhr.spec.whatwg.org/#arraybuffer-response // https://xhr.spec.whatwg.org/#arraybuffer-response
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn arraybuffer_response(&self, cx: *mut JSContext) -> Option<NonNull<JSObject>> { fn arraybuffer_response(&self, cx: JSContext) -> Option<NonNull<JSObject>> {
// Step 1 // Step 1
let created = self.response_arraybuffer.get(); let created = self.response_arraybuffer.get();
if let Some(nonnull) = NonNull::new(created) { if let Some(nonnull) = NonNull::new(created) {
@ -1287,14 +1285,16 @@ impl XMLHttpRequest {
// Step 2 // Step 2
let bytes = self.response.borrow(); let bytes = self.response.borrow();
rooted!(in(cx) let mut array_buffer = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer.handle_mut()) unsafe {
ArrayBuffer::create(*cx, CreateWith::Slice(&bytes), array_buffer.handle_mut())
.ok() .ok()
.and_then(|()| { .and_then(|()| {
self.response_arraybuffer.set(array_buffer.get()); self.response_arraybuffer.set(array_buffer.get());
Some(NonNull::new_unchecked(array_buffer.get())) Some(NonNull::new_unchecked(array_buffer.get()))
}) })
} }
}
// https://xhr.spec.whatwg.org/#document-response // https://xhr.spec.whatwg.org/#document-response
fn document_response(&self) -> Option<DomRoot<Document>> { fn document_response(&self) -> Option<DomRoot<Document>> {
@ -1345,7 +1345,7 @@ impl XMLHttpRequest {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://xhr.spec.whatwg.org/#json-response // https://xhr.spec.whatwg.org/#json-response
fn json_response(&self, cx: *mut JSContext) -> JSVal { fn json_response(&self, cx: JSContext) -> JSVal {
// Step 1 // Step 1
let response_json = self.response_json.get(); let response_json = self.response_json.get();
if !response_json.is_null_or_undefined() { if !response_json.is_null_or_undefined() {
@ -1378,15 +1378,15 @@ impl XMLHttpRequest {
// if present, but UTF-16BE/LE BOM must not be honored. // if present, but UTF-16BE/LE BOM must not be honored.
let json_text = decode_to_utf16_with_bom_removal(&bytes, UTF_8); let json_text = decode_to_utf16_with_bom_removal(&bytes, UTF_8);
// Step 5 // Step 5
rooted!(in(cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
unsafe { unsafe {
if !JS_ParseJSON( if !JS_ParseJSON(
cx, *cx,
json_text.as_ptr(), json_text.as_ptr(),
json_text.len() as u32, json_text.len() as u32,
rval.handle_mut(), rval.handle_mut(),
) { ) {
JS_ClearPendingException(cx); JS_ClearPendingException(*cx);
return NullValue(); return NullValue();
} }
} }

View file

@ -14,9 +14,9 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlimageelement::ImageElementMicrotask; use crate::dom::htmlimageelement::ImageElementMicrotask;
use crate::dom::htmlmediaelement::MediaElementMicrotask; use crate::dom::htmlmediaelement::MediaElementMicrotask;
use crate::dom::mutationobserver::MutationObserver; use crate::dom::mutationobserver::MutationObserver;
use crate::script_runtime::notify_about_rejected_promises; use crate::script_runtime::{notify_about_rejected_promises, JSContext};
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use js::jsapi::{JSContext, JobQueueIsEmpty, JobQueueMayNotBeEmpty}; use js::jsapi::{JobQueueIsEmpty, JobQueueMayNotBeEmpty};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use std::cell::Cell; use std::cell::Cell;
use std::mem; use std::mem;
@ -56,17 +56,17 @@ impl MicrotaskQueue {
/// Add a new microtask to this queue. It will be invoked as part of the next /// Add a new microtask to this queue. It will be invoked as part of the next
/// microtask checkpoint. /// microtask checkpoint.
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe fn enqueue(&self, job: Microtask, cx: *mut JSContext) { pub fn enqueue(&self, job: Microtask, cx: JSContext) {
self.microtask_queue.borrow_mut().push(job); self.microtask_queue.borrow_mut().push(job);
JobQueueMayNotBeEmpty(cx); unsafe { JobQueueMayNotBeEmpty(*cx) };
} }
/// <https://html.spec.whatwg.org/multipage/#perform-a-microtask-checkpoint> /// <https://html.spec.whatwg.org/multipage/#perform-a-microtask-checkpoint>
/// Perform a microtask checkpoint, executing all queued microtasks until the queue is empty. /// Perform a microtask checkpoint, executing all queued microtasks until the queue is empty.
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe fn checkpoint<F>( pub fn checkpoint<F>(
&self, &self,
cx: *mut JSContext, cx: JSContext,
target_provider: F, target_provider: F,
globalscopes: Vec<DomRoot<GlobalScope>>, globalscopes: Vec<DomRoot<GlobalScope>>,
) where ) where
@ -86,7 +86,7 @@ impl MicrotaskQueue {
for (idx, job) in pending_queue.iter().enumerate() { for (idx, job) in pending_queue.iter().enumerate() {
if idx == pending_queue.len() - 1 && self.microtask_queue.borrow().is_empty() { if idx == pending_queue.len() - 1 && self.microtask_queue.borrow().is_empty() {
JobQueueIsEmpty(cx); unsafe { JobQueueIsEmpty(*cx) };
} }
match *job { match *job {

View file

@ -172,6 +172,7 @@ unsafe extern "C" fn enqueue_promise_job(
_allocation_site: HandleObject, _allocation_site: HandleObject,
incumbent_global: HandleObject, incumbent_global: HandleObject,
) -> bool { ) -> bool {
let cx = JSContext::from_ptr(cx);
wrap_panic( wrap_panic(
AssertUnwindSafe(|| { AssertUnwindSafe(|| {
let microtask_queue = &*(extra as *const MicrotaskQueue); let microtask_queue = &*(extra as *const MicrotaskQueue);
@ -179,7 +180,7 @@ unsafe extern "C" fn enqueue_promise_job(
let pipeline = global.pipeline_id(); let pipeline = global.pipeline_id();
microtask_queue.enqueue( microtask_queue.enqueue(
Microtask::Promise(EnqueuedPromiseCallback { Microtask::Promise(EnqueuedPromiseCallback {
callback: PromiseJobCallback::new(JSContext::from_ptr(cx), job.get()), callback: PromiseJobCallback::new(cx, job.get()),
pipeline, pipeline,
}), }),
cx, cx,
@ -201,7 +202,8 @@ unsafe extern "C" fn promise_rejection_tracker(
// TODO: Step 2 - If script's muted errors is true, terminate these steps. // TODO: Step 2 - If script's muted errors is true, terminate these steps.
// Step 3. // Step 3.
let global = GlobalScope::from_context(cx); let cx = JSContext::from_ptr(cx);
let global = GlobalScope::from_context(*cx);
wrap_panic( wrap_panic(
AssertUnwindSafe(|| { AssertUnwindSafe(|| {
@ -281,7 +283,7 @@ pub fn notify_about_rejected_promises(global: &GlobalScope) {
.iter() .iter()
.map(|promise| { .map(|promise| {
let promise = let promise =
Promise::new_with_js_promise(Handle::from_raw(promise.handle()), *cx); Promise::new_with_js_promise(Handle::from_raw(promise.handle()), cx);
TrustedPromise::new(promise) TrustedPromise::new(promise)
}) })

View file

@ -910,16 +910,13 @@ impl ScriptThread {
} }
// https://html.spec.whatwg.org/multipage/#await-a-stable-state // https://html.spec.whatwg.org/multipage/#await-a-stable-state
#[allow(unsafe_code)]
pub fn await_stable_state(task: Microtask) { pub fn await_stable_state(task: Microtask) {
SCRIPT_THREAD_ROOT.with(|root| { SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() { if let Some(script_thread) = root.get() {
unsafe { let script_thread = unsafe { &*script_thread };
let script_thread = &*script_thread;
script_thread script_thread
.microtask_queue .microtask_queue
.enqueue(task, *script_thread.get_cx()); .enqueue(task, script_thread.get_cx());
}
} }
}); });
} }
@ -3776,17 +3773,15 @@ impl ScriptThread {
} }
} }
#[allow(unsafe_code)]
pub fn enqueue_microtask(job: Microtask) { pub fn enqueue_microtask(job: Microtask) {
SCRIPT_THREAD_ROOT.with(|root| unsafe { SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = &*root.get().unwrap(); let script_thread = unsafe { &*root.get().unwrap() };
script_thread script_thread
.microtask_queue .microtask_queue
.enqueue(job, *script_thread.get_cx()); .enqueue(job, script_thread.get_cx());
}); });
} }
#[allow(unsafe_code)]
fn perform_a_microtask_checkpoint(&self) { fn perform_a_microtask_checkpoint(&self) {
let globals = self let globals = self
.documents .documents
@ -3795,14 +3790,12 @@ impl ScriptThread {
.map(|(_id, document)| document.global()) .map(|(_id, document)| document.global())
.collect(); .collect();
unsafe {
self.microtask_queue.checkpoint( self.microtask_queue.checkpoint(
*self.get_cx(), self.get_cx(),
|id| self.documents.borrow().find_global(id), |id| self.documents.borrow().find_global(id),
globals, globals,
) )
} }
}
} }
impl Drop for ScriptThread { impl Drop for ScriptThread {

View file

@ -739,7 +739,7 @@ pub fn handle_get_property(
Err(_) => Ok(WebDriverJSValue::Undefined), Err(_) => Ok(WebDriverJSValue::Undefined),
}, },
Err(error) => { Err(error) => {
unsafe { throw_dom_exception(*cx, &node.reflector().global(), error) }; throw_dom_exception(cx, &node.reflector().global(), error);
Ok(WebDriverJSValue::Undefined) Ok(WebDriverJSValue::Undefined)
}, },
} }