mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
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:
commit
da559d47b9
28 changed files with 543 additions and 558 deletions
|
@ -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();
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue