mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Upgrade to Spidermonkey 67.
This commit is contained in:
parent
ce9f35e0e3
commit
63714c90fb
19 changed files with 260 additions and 139 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -2827,21 +2827,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mozjs"
|
name = "mozjs"
|
||||||
version = "0.11.0"
|
version = "0.12.0"
|
||||||
source = "git+https://github.com/servo/rust-mozjs#bea7b5cca9448ca10f8f710b7ad75567424f73b4"
|
source = "git+https://github.com/servo/rust-mozjs#124e5243a02ddaa879f2988313cee738c435f8b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mozjs_sys 0.66.1 (git+https://github.com/servo/mozjs?rev=05c7d307811f88ca263f1861ccca0a81ffb0b58d)",
|
"mozjs_sys 0.67.0 (git+https://github.com/servo/mozjs?rev=b2f83932fe9d361face14efd03f2465b9262e687)",
|
||||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mozjs_sys"
|
name = "mozjs_sys"
|
||||||
version = "0.66.1"
|
version = "0.67.0"
|
||||||
source = "git+https://github.com/servo/mozjs?rev=05c7d307811f88ca263f1861ccca0a81ffb0b58d#05c7d307811f88ca263f1861ccca0a81ffb0b58d"
|
source = "git+https://github.com/servo/mozjs?rev=b2f83932fe9d361face14efd03f2465b9262e687#b2f83932fe9d361face14efd03f2465b9262e687"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3755,7 +3755,7 @@ dependencies = [
|
||||||
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mozangle 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mozangle 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mozjs 0.11.0 (git+https://github.com/servo/rust-mozjs)",
|
"mozjs 0.12.0 (git+https://github.com/servo/rust-mozjs)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"net_traits 0.0.1",
|
"net_traits 0.0.1",
|
||||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -5771,8 +5771,8 @@ dependencies = [
|
||||||
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
||||||
"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
|
"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
|
||||||
"checksum mozangle 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1dc10080cc8b83bfb5580de720f00c768ec1b365c75fbc4c57324118a38a618d"
|
"checksum mozangle 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1dc10080cc8b83bfb5580de720f00c768ec1b365c75fbc4c57324118a38a618d"
|
||||||
"checksum mozjs 0.11.0 (git+https://github.com/servo/rust-mozjs)" = "<none>"
|
"checksum mozjs 0.12.0 (git+https://github.com/servo/rust-mozjs)" = "<none>"
|
||||||
"checksum mozjs_sys 0.66.1 (git+https://github.com/servo/mozjs?rev=05c7d307811f88ca263f1861ccca0a81ffb0b58d)" = "<none>"
|
"checksum mozjs_sys 0.67.0 (git+https://github.com/servo/mozjs?rev=b2f83932fe9d361face14efd03f2465b9262e687)" = "<none>"
|
||||||
"checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
|
"checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
|
||||||
"checksum muldiv 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "451a9a05d2a32c566c897835e0ea95cf79ed2fdfe957924045a1721a36c9980f"
|
"checksum muldiv 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "451a9a05d2a32c566c897835e0ea95cf79ed2fdfe957924045a1721a36c9980f"
|
||||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use js::jsapi::JS_GetArrayBufferViewBuffer;
|
use js::jsapi::JS_GetArrayBufferViewBuffer;
|
||||||
use js::jsapi::{Heap, JSAutoRealm, JSContext, JSObject};
|
use js::jsapi::{Heap, JSAutoRealm, JSContext, JSObject};
|
||||||
use js::rust::wrappers::JS_DetachArrayBuffer;
|
use js::rust::wrappers::DetachArrayBuffer;
|
||||||
use js::rust::CustomAutoRooterGuard;
|
use js::rust::CustomAutoRooterGuard;
|
||||||
use js::typedarray::{CreateWith, Float32Array};
|
use js::typedarray::{CreateWith, Float32Array};
|
||||||
use servo_media::audio::buffer_source_node::AudioBuffer as ServoMediaAudioBuffer;
|
use servo_media::audio::buffer_source_node::AudioBuffer as ServoMediaAudioBuffer;
|
||||||
|
@ -180,7 +180,7 @@ impl AudioBuffer {
|
||||||
JS_GetArrayBufferViewBuffer(cx, channel.handle(), &mut is_shared));
|
JS_GetArrayBufferViewBuffer(cx, channel.handle(), &mut is_shared));
|
||||||
// This buffer is always created unshared
|
// This buffer is always created unshared
|
||||||
debug_assert!(!is_shared);
|
debug_assert!(!is_shared);
|
||||||
let _ = JS_DetachArrayBuffer(cx, view_buffer.handle());
|
let _ = DetachArrayBuffer(cx, view_buffer.handle());
|
||||||
data
|
data
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -466,7 +466,7 @@ class CGMethodCall(CGThing):
|
||||||
|
|
||||||
# Check for vanilla JS objects
|
# Check for vanilla JS objects
|
||||||
# XXXbz Do we need to worry about security wrappers?
|
# XXXbz Do we need to worry about security wrappers?
|
||||||
pickFirstSignature("%s.get().is_object() && !is_platform_object(%s.get().to_object())" %
|
pickFirstSignature("%s.get().is_object() && !is_platform_object(%s.get().to_object(), cx)" %
|
||||||
(distinguishingArg, distinguishingArg),
|
(distinguishingArg, distinguishingArg),
|
||||||
lambda s: (s[1][distinguishingIndex].type.isCallback() or
|
lambda s: (s[1][distinguishingIndex].type.isCallback() or
|
||||||
s[1][distinguishingIndex].type.isCallbackInterface() or
|
s[1][distinguishingIndex].type.isCallbackInterface() or
|
||||||
|
@ -798,7 +798,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
{ // Scope for our JSAutoRealm.
|
{ // Scope for our JSAutoRealm.
|
||||||
|
|
||||||
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
|
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
|
||||||
let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get());
|
let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get(), cx);
|
||||||
|
|
||||||
rooted!(in(cx) let mut valueToResolve = $${val}.get());
|
rooted!(in(cx) let mut valueToResolve = $${val}.get());
|
||||||
if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
|
if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
|
||||||
|
@ -866,7 +866,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
|
|
||||||
templateBody = fill(
|
templateBody = fill(
|
||||||
"""
|
"""
|
||||||
match ${function}($${val}) {
|
match ${function}($${val}, cx) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
$*{failureCode}
|
$*{failureCode}
|
||||||
|
@ -2158,8 +2158,8 @@ class CGDOMJSClass(CGThing):
|
||||||
static CLASS_OPS: js::jsapi::JSClassOps = js::jsapi::JSClassOps {
|
static CLASS_OPS: js::jsapi::JSClassOps = js::jsapi::JSClassOps {
|
||||||
addProperty: None,
|
addProperty: None,
|
||||||
delProperty: None,
|
delProperty: None,
|
||||||
enumerate: %(enumerateHook)s,
|
enumerate: None,
|
||||||
newEnumerate: None,
|
newEnumerate: %(enumerateHook)s,
|
||||||
resolve: %(resolveHook)s,
|
resolve: %(resolveHook)s,
|
||||||
mayResolve: None,
|
mayResolve: None,
|
||||||
finalize: Some(%(finalizeHook)s),
|
finalize: Some(%(finalizeHook)s),
|
||||||
|
@ -3223,7 +3223,6 @@ let traps = ProxyTraps {
|
||||||
set: None,
|
set: None,
|
||||||
call: None,
|
call: None,
|
||||||
construct: None,
|
construct: None,
|
||||||
getPropertyDescriptor: Some(get_property_descriptor),
|
|
||||||
hasOwn: Some(hasOwn),
|
hasOwn: Some(hasOwn),
|
||||||
getOwnEnumerablePropertyKeys: Some(%(getOwnEnumerablePropertyKeys)s),
|
getOwnEnumerablePropertyKeys: Some(%(getOwnEnumerablePropertyKeys)s),
|
||||||
nativeCall: None,
|
nativeCall: None,
|
||||||
|
@ -4980,10 +4979,6 @@ class CGProxyUnwrap(CGAbstractMethod):
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
return CGGeneric("""\
|
return CGGeneric("""\
|
||||||
/*if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
|
|
||||||
obj = js::UnwrapObject(obj);
|
|
||||||
}*/
|
|
||||||
//MOZ_ASSERT(IsProxy(obj));
|
|
||||||
let mut slot = UndefinedValue();
|
let mut slot = UndefinedValue();
|
||||||
GetProxyReservedSlot(obj.get(), 0, &mut slot);
|
GetProxyReservedSlot(obj.get(), 0, &mut slot);
|
||||||
let box_ = slot.to_private() as *const %s;
|
let box_ = slot.to_private() as *const %s;
|
||||||
|
@ -5430,7 +5425,7 @@ class CGAbstractClassHook(CGAbstractExternMethod):
|
||||||
|
|
||||||
def definition_body_prologue(self):
|
def definition_body_prologue(self):
|
||||||
return CGGeneric("""
|
return CGGeneric("""
|
||||||
let this = native_from_object::<%s>(obj).unwrap();
|
let this = native_from_object_static::<%s>(obj).unwrap();
|
||||||
""" % self.descriptor.concreteType)
|
""" % self.descriptor.concreteType)
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
|
@ -5530,7 +5525,7 @@ let global = DomRoot::downcast::<dom::types::%s>(global).unwrap();
|
||||||
|
|
||||||
// The new_target might be a cross-compartment wrapper. Get the underlying object
|
// The new_target might be a cross-compartment wrapper. Get the underlying object
|
||||||
// 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 = UnwrapObject(args.new_target().to_object(), 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;
|
||||||
|
@ -5877,7 +5872,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
||||||
'js::glue::RUST_JSID_IS_STRING',
|
'js::glue::RUST_JSID_IS_STRING',
|
||||||
'js::glue::RUST_SYMBOL_TO_JSID',
|
'js::glue::RUST_SYMBOL_TO_JSID',
|
||||||
'js::glue::int_to_jsid',
|
'js::glue::int_to_jsid',
|
||||||
'js::glue::UnwrapObject',
|
'js::glue::UnwrapObjectDynamic',
|
||||||
'js::panic::maybe_resume_unwind',
|
'js::panic::maybe_resume_unwind',
|
||||||
'js::panic::wrap_panic',
|
'js::panic::wrap_panic',
|
||||||
'js::rust::GCMethods',
|
'js::rust::GCMethods',
|
||||||
|
@ -5959,6 +5954,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
||||||
'crate::dom::bindings::conversions::is_array_like',
|
'crate::dom::bindings::conversions::is_array_like',
|
||||||
'crate::dom::bindings::conversions::native_from_handlevalue',
|
'crate::dom::bindings::conversions::native_from_handlevalue',
|
||||||
'crate::dom::bindings::conversions::native_from_object',
|
'crate::dom::bindings::conversions::native_from_object',
|
||||||
|
'crate::dom::bindings::conversions::native_from_object_static',
|
||||||
'crate::dom::bindings::conversions::private_from_object',
|
'crate::dom::bindings::conversions::private_from_object',
|
||||||
'crate::dom::bindings::conversions::root_from_handleobject',
|
'crate::dom::bindings::conversions::root_from_handleobject',
|
||||||
'crate::dom::bindings::conversions::root_from_handlevalue',
|
'crate::dom::bindings::conversions::root_from_handlevalue',
|
||||||
|
@ -5979,7 +5975,6 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
||||||
'crate::dom::bindings::proxyhandler::ensure_expando_object',
|
'crate::dom::bindings::proxyhandler::ensure_expando_object',
|
||||||
'crate::dom::bindings::proxyhandler::fill_property_descriptor',
|
'crate::dom::bindings::proxyhandler::fill_property_descriptor',
|
||||||
'crate::dom::bindings::proxyhandler::get_expando_object',
|
'crate::dom::bindings::proxyhandler::get_expando_object',
|
||||||
'crate::dom::bindings::proxyhandler::get_property_descriptor',
|
|
||||||
'crate::dom::bindings::mozmap::MozMap',
|
'crate::dom::bindings::mozmap::MozMap',
|
||||||
'std::ptr::NonNull',
|
'std::ptr::NonNull',
|
||||||
'crate::dom::bindings::num::Finite',
|
'crate::dom::bindings::num::Finite',
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub use js::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvert
|
||||||
use js::error::throw_type_error;
|
use js::error::throw_type_error;
|
||||||
use js::glue::GetProxyReservedSlot;
|
use js::glue::GetProxyReservedSlot;
|
||||||
use js::glue::JS_GetReservedSlot;
|
use js::glue::JS_GetReservedSlot;
|
||||||
use js::glue::{IsWrapper, UnwrapObject};
|
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
||||||
use js::glue::{RUST_JSID_IS_INT, RUST_JSID_TO_INT};
|
use js::glue::{RUST_JSID_IS_INT, RUST_JSID_TO_INT};
|
||||||
use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING};
|
use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING};
|
||||||
use js::jsapi::{Heap, JSContext, JSObject, JSString};
|
use js::jsapi::{Heap, JSContext, JSObject, JSString};
|
||||||
|
@ -113,11 +113,11 @@ impl<T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> {
|
||||||
type Config = ();
|
type Config = ();
|
||||||
|
|
||||||
unsafe fn from_jsval(
|
unsafe fn from_jsval(
|
||||||
_cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
value: HandleValue,
|
value: HandleValue,
|
||||||
_config: Self::Config,
|
_config: Self::Config,
|
||||||
) -> Result<ConversionResult<DomRoot<T>>, ()> {
|
) -> Result<ConversionResult<DomRoot<T>>, ()> {
|
||||||
Ok(match root_from_handlevalue(value) {
|
Ok(match root_from_handlevalue(value, cx) {
|
||||||
Ok(result) => ConversionResult::Success(result),
|
Ok(result) => ConversionResult::Success(result),
|
||||||
Err(()) => ConversionResult::Failure("value is not an object".into()),
|
Err(()) => ConversionResult::Failure("value is not an object".into()),
|
||||||
})
|
})
|
||||||
|
@ -411,6 +411,7 @@ pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<&'static DOMClass, ()>
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn private_from_proto_check<F>(
|
pub unsafe fn private_from_proto_check<F>(
|
||||||
mut obj: *mut JSObject,
|
mut obj: *mut JSObject,
|
||||||
|
cx: *mut JSContext,
|
||||||
proto_check: F,
|
proto_check: F,
|
||||||
) -> Result<*const libc::c_void, ()>
|
) -> Result<*const libc::c_void, ()>
|
||||||
where
|
where
|
||||||
|
@ -419,7 +420,7 @@ where
|
||||||
let dom_class = get_dom_class(obj).or_else(|_| {
|
let dom_class = get_dom_class(obj).or_else(|_| {
|
||||||
if IsWrapper(obj) {
|
if IsWrapper(obj) {
|
||||||
trace!("found wrapper");
|
trace!("found wrapper");
|
||||||
obj = UnwrapObject(obj, /* stopAtWindowProxy = */ 0);
|
obj = UnwrapObjectDynamic(obj, cx, /* stopAtWindowProxy = */ 0);
|
||||||
if obj.is_null() {
|
if obj.is_null() {
|
||||||
trace!("unwrapping security wrapper failed");
|
trace!("unwrapping security wrapper failed");
|
||||||
Err(())
|
Err(())
|
||||||
|
@ -443,12 +444,44 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a `*const libc::c_void` for the given DOM object, unless it is a DOM
|
||||||
|
/// wrapper, and checking if the object is of the correct type.
|
||||||
|
///
|
||||||
|
/// Returns Err(()) if `obj` is a wrapper or if the object is not an object
|
||||||
|
/// for a DOM object of the given type (as defined by the proto_id and proto_depth).
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn private_from_proto_check_static<F>(
|
||||||
|
obj: *mut JSObject,
|
||||||
|
proto_check: F,
|
||||||
|
) -> Result<*const libc::c_void, ()>
|
||||||
|
where
|
||||||
|
F: Fn(&'static DOMClass) -> bool,
|
||||||
|
{
|
||||||
|
let dom_class = get_dom_class(obj).map_err(|_| ())?;
|
||||||
|
if proto_check(dom_class) {
|
||||||
|
trace!("good prototype");
|
||||||
|
Ok(private_from_object(obj))
|
||||||
|
} else {
|
||||||
|
trace!("bad prototype");
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a `*const T` for a DOM object accessible from a `JSObject`.
|
/// Get a `*const T` for a DOM object accessible from a `JSObject`.
|
||||||
pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()>
|
pub fn native_from_object<T>(obj: *mut JSObject, cx: *mut JSContext) -> Result<*const T, ()>
|
||||||
where
|
where
|
||||||
T: DomObject + IDLInterface,
|
T: DomObject + IDLInterface,
|
||||||
{
|
{
|
||||||
unsafe { private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T) }
|
unsafe { private_from_proto_check(obj, cx, T::derives).map(|ptr| ptr as *const T) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a `*const T` for a DOM object accessible from a `JSObject`, where the DOM object
|
||||||
|
/// is guaranteed not to be a wrapper.
|
||||||
|
pub fn native_from_object_static<T>(obj: *mut JSObject) -> Result<*const T, ()>
|
||||||
|
where
|
||||||
|
T: DomObject + IDLInterface,
|
||||||
|
{
|
||||||
|
unsafe { private_from_proto_check_static(obj, T::derives).map(|ptr| ptr as *const T) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
|
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
|
||||||
|
@ -457,43 +490,56 @@ where
|
||||||
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
|
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
|
||||||
/// not a reflector for a DOM object of the given type (as defined by the
|
/// not a reflector for a DOM object of the given type (as defined by the
|
||||||
/// proto_id and proto_depth).
|
/// proto_id and proto_depth).
|
||||||
pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
|
pub fn root_from_object<T>(obj: *mut JSObject, cx: *mut JSContext) -> Result<DomRoot<T>, ()>
|
||||||
where
|
where
|
||||||
T: DomObject + IDLInterface,
|
T: DomObject + IDLInterface,
|
||||||
{
|
{
|
||||||
native_from_object(obj).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) })
|
native_from_object(obj, cx).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a `DomRoot<T>` for the given DOM object, unwrapping any wrapper
|
||||||
|
/// around it first, and checking if the object is of the correct type.
|
||||||
|
///
|
||||||
|
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
|
||||||
|
/// not a reflector for a DOM object of the given type (as defined by the
|
||||||
|
/// proto_id and proto_depth).
|
||||||
|
pub fn root_from_object_static<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()>
|
||||||
|
where
|
||||||
|
T: DomObject + IDLInterface,
|
||||||
|
{
|
||||||
|
native_from_object_static(obj).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `*const T` for a DOM object accessible from a `HandleValue`.
|
/// Get a `*const T` for a DOM object accessible from a `HandleValue`.
|
||||||
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
||||||
pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()>
|
pub fn native_from_handlevalue<T>(v: HandleValue, cx: *mut JSContext) -> Result<*const T, ()>
|
||||||
where
|
where
|
||||||
T: DomObject + IDLInterface,
|
T: DomObject + IDLInterface,
|
||||||
{
|
{
|
||||||
if !v.get().is_object() {
|
if !v.get().is_object() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
native_from_object(v.get().to_object())
|
native_from_object(v.get().to_object(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleValue`.
|
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleValue`.
|
||||||
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
/// Caller is responsible for throwing a JS exception if needed in case of error.
|
||||||
pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()>
|
pub fn root_from_handlevalue<T>(v: HandleValue, cx: *mut JSContext) -> Result<DomRoot<T>, ()>
|
||||||
where
|
where
|
||||||
T: DomObject + IDLInterface,
|
T: DomObject + IDLInterface,
|
||||||
{
|
{
|
||||||
if !v.get().is_object() {
|
if !v.get().is_object() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
root_from_object(v.get().to_object())
|
root_from_object(v.get().to_object(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleObject`.
|
/// Get a `DomRoot<T>` for a DOM object accessible from a `HandleObject`.
|
||||||
pub fn root_from_handleobject<T>(obj: HandleObject) -> Result<DomRoot<T>, ()>
|
pub fn root_from_handleobject<T>(obj: HandleObject, cx: *mut JSContext) -> Result<DomRoot<T>, ()>
|
||||||
where
|
where
|
||||||
T: DomObject + IDLInterface,
|
T: DomObject + IDLInterface,
|
||||||
{
|
{
|
||||||
root_from_object(obj.get())
|
root_from_object(obj.get(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DomObject> ToJSValConvertible for DomRoot<T> {
|
impl<T: DomObject> ToJSValConvertible for DomRoot<T> {
|
||||||
|
|
|
@ -207,8 +207,8 @@ impl ErrorInfo {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_dom_exception(object: HandleObject) -> Option<ErrorInfo> {
|
fn from_dom_exception(object: HandleObject, cx: *mut JSContext) -> Option<ErrorInfo> {
|
||||||
let exception = match root_from_object::<DOMException>(object.get()) {
|
let exception = match root_from_object::<DOMException>(object.get(), cx) {
|
||||||
Ok(exception) => exception,
|
Ok(exception) => exception,
|
||||||
Err(_) => return None,
|
Err(_) => return None,
|
||||||
};
|
};
|
||||||
|
@ -242,7 +242,7 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
||||||
let error_info = if value.is_object() {
|
let error_info = if value.is_object() {
|
||||||
rooted!(in(cx) let object = value.to_object());
|
rooted!(in(cx) let object = value.to_object());
|
||||||
ErrorInfo::from_native_error(cx, object.handle())
|
ErrorInfo::from_native_error(cx, object.handle())
|
||||||
.or_else(|| ErrorInfo::from_dom_exception(object.handle()))
|
.or_else(|| ErrorInfo::from_dom_exception(object.handle(), cx))
|
||||||
.unwrap_or_else(|| ErrorInfo {
|
.unwrap_or_else(|| ErrorInfo {
|
||||||
message: format!("uncaught exception: unknown (can't convert to string)"),
|
message: format!("uncaught exception: unknown (can't convert to string)"),
|
||||||
filename: String::new(),
|
filename: String::new(),
|
||||||
|
|
|
@ -79,7 +79,7 @@ use crate::dom::window::Window;
|
||||||
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::UnwrapObject;
|
use js::glue::UnwrapObjectStatic;
|
||||||
use js::jsapi::{CallArgs, CurrentGlobalOrNull};
|
use js::jsapi::{CallArgs, CurrentGlobalOrNull};
|
||||||
use js::jsapi::{JSAutoRealm, JSContext, JSObject};
|
use js::jsapi::{JSAutoRealm, JSContext, JSObject};
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
|
@ -109,7 +109,7 @@ where
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
rooted!(in(window.get_cx()) let callee = UnwrapObject(call_args.callee(), 1));
|
rooted!(in(window.get_cx()) let callee = UnwrapObjectStatic(call_args.callee()));
|
||||||
if callee.is_null() {
|
if callee.is_null() {
|
||||||
return Err(Error::Security);
|
return Err(Error::Security);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,13 @@
|
||||||
|
|
||||||
use crate::dom::bindings::conversions::is_dom_proxy;
|
use crate::dom::bindings::conversions::is_dom_proxy;
|
||||||
use crate::dom::bindings::utils::delete_property_by_id;
|
use crate::dom::bindings::utils::delete_property_by_id;
|
||||||
use js::glue::InvokeGetOwnPropertyDescriptor;
|
use js::glue::GetProxyHandlerFamily;
|
||||||
use js::glue::{GetProxyHandler, GetProxyHandlerFamily};
|
|
||||||
use js::glue::{GetProxyPrivate, SetProxyPrivate};
|
use js::glue::{GetProxyPrivate, SetProxyPrivate};
|
||||||
use js::jsapi::GetObjectProto;
|
|
||||||
use js::jsapi::GetStaticPrototype;
|
use js::jsapi::GetStaticPrototype;
|
||||||
use js::jsapi::Handle as RawHandle;
|
use js::jsapi::Handle as RawHandle;
|
||||||
use js::jsapi::HandleId as RawHandleId;
|
use js::jsapi::HandleId as RawHandleId;
|
||||||
use js::jsapi::HandleObject as RawHandleObject;
|
use js::jsapi::HandleObject as RawHandleObject;
|
||||||
use js::jsapi::JS_DefinePropertyById;
|
use js::jsapi::JS_DefinePropertyById;
|
||||||
use js::jsapi::JS_GetPropertyDescriptorById;
|
|
||||||
use js::jsapi::MutableHandle as RawMutableHandle;
|
|
||||||
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
||||||
use js::jsapi::ObjectOpResult;
|
use js::jsapi::ObjectOpResult;
|
||||||
use js::jsapi::{DOMProxyShadowsResult, JSContext, JSObject, PropertyDescriptor};
|
use js::jsapi::{DOMProxyShadowsResult, JSContext, JSObject, PropertyDescriptor};
|
||||||
|
@ -62,34 +58,6 @@ pub unsafe fn init() {
|
||||||
SetDOMProxyInformation(GetProxyHandlerFamily(), Some(shadow_check_callback));
|
SetDOMProxyInformation(GetProxyHandlerFamily(), Some(shadow_check_callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
|
|
||||||
/// with argument `id` and return the result, if it is not `undefined`.
|
|
||||||
/// Otherwise, walk along the prototype chain to find a property with that
|
|
||||||
/// name.
|
|
||||||
pub unsafe extern "C" fn get_property_descriptor(
|
|
||||||
cx: *mut JSContext,
|
|
||||||
proxy: RawHandleObject,
|
|
||||||
id: RawHandleId,
|
|
||||||
desc: RawMutableHandle<PropertyDescriptor>,
|
|
||||||
) -> bool {
|
|
||||||
let handler = GetProxyHandler(proxy.get());
|
|
||||||
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if !desc.obj.is_null() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
rooted!(in(cx) let mut proto = ptr::null_mut::<JSObject>());
|
|
||||||
if !GetObjectProto(cx, proxy, proto.handle_mut().into()) {
|
|
||||||
// FIXME(#11868) Should assign to desc.obj, desc.get() is a copy.
|
|
||||||
desc.get().obj = ptr::null_mut();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_GetPropertyDescriptorById(cx, proto.handle().into(), id, desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Defines an expando on the given `proxy`.
|
/// Defines an expando on the given `proxy`.
|
||||||
pub unsafe extern "C" fn define_property(
|
pub unsafe extern "C" fn define_property(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
|
|
|
@ -176,12 +176,12 @@ unsafe extern "C" fn read_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn write_callback(
|
unsafe extern "C" fn write_callback(
|
||||||
_cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
w: *mut JSStructuredCloneWriter,
|
w: *mut JSStructuredCloneWriter,
|
||||||
obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
_closure: *mut raw::c_void,
|
_closure: *mut raw::c_void,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Ok(blob) = root_from_handleobject::<Blob>(Handle::from_raw(obj)) {
|
if let Ok(blob) = root_from_handleobject::<Blob>(Handle::from_raw(obj), cx) {
|
||||||
return write_blob(blob, w).is_ok();
|
return write_blob(blob, w).is_ok();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -68,7 +68,7 @@ use hyper::StatusCode;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use js::glue::{CallObjectTracer, CallValueTracer};
|
use js::glue::{CallObjectTracer, CallValueTracer};
|
||||||
use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind};
|
use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, JobQueue, TraceKind};
|
||||||
use js::jsval::JSVal;
|
use js::jsval::JSVal;
|
||||||
use js::rust::{GCMethods, Handle, Runtime};
|
use js::rust::{GCMethods, Handle, Runtime};
|
||||||
use js::typedarray::TypedArray;
|
use js::typedarray::TypedArray;
|
||||||
|
@ -162,6 +162,8 @@ unsafe_no_jsmanaged_fields!(Duration);
|
||||||
|
|
||||||
unsafe_no_jsmanaged_fields!(TexDataType, TexFormat);
|
unsafe_no_jsmanaged_fields!(TexDataType, TexFormat);
|
||||||
|
|
||||||
|
unsafe_no_jsmanaged_fields!(*mut JobQueue);
|
||||||
|
|
||||||
/// Trace a `JSVal`.
|
/// Trace a `JSVal`.
|
||||||
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) {
|
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -15,12 +15,12 @@ use crate::dom::bindings::trace::trace_object;
|
||||||
use crate::dom::windowproxy;
|
use crate::dom::windowproxy;
|
||||||
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
|
||||||
use js::glue::{GetCrossCompartmentWrapper, JS_GetReservedSlot, WrapperNew};
|
use js::glue::{GetCrossCompartmentWrapper, JS_GetReservedSlot, WrapperNew};
|
||||||
use js::glue::{UnwrapObject, RUST_JSID_TO_INT, RUST_JSID_TO_STRING};
|
use js::glue::{UnwrapObjectDynamic, RUST_JSID_TO_INT, RUST_JSID_TO_STRING};
|
||||||
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
|
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
|
||||||
use js::jsapi::HandleId as RawHandleId;
|
use js::jsapi::HandleId as RawHandleId;
|
||||||
use js::jsapi::HandleObject as RawHandleObject;
|
use js::jsapi::HandleObject as RawHandleObject;
|
||||||
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
use js::jsapi::MutableHandleObject as RawMutableHandleObject;
|
||||||
use js::jsapi::{CallArgs, DOMCallbacks, GetNonCCWObjectGlobal};
|
use js::jsapi::{AutoIdVector, CallArgs, DOMCallbacks, GetNonCCWObjectGlobal};
|
||||||
use js::jsapi::{Heap, JSAutoRealm, JSContext};
|
use js::jsapi::{Heap, JSAutoRealm, JSContext};
|
||||||
use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
|
use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
|
||||||
use js::jsapi::{JS_EnumerateStandardClasses, JS_GetLatin1StringCharsAndLength};
|
use js::jsapi::{JS_EnumerateStandardClasses, JS_GetLatin1StringCharsAndLength};
|
||||||
|
@ -210,7 +210,7 @@ pub unsafe fn find_enum_value<'a, T>(
|
||||||
|
|
||||||
/// Returns wether `obj` is a platform object
|
/// Returns wether `obj` is a platform object
|
||||||
/// <https://heycam.github.io/webidl/#dfn-platform-object>
|
/// <https://heycam.github.io/webidl/#dfn-platform-object>
|
||||||
pub fn is_platform_object(obj: *mut JSObject) -> bool {
|
pub fn is_platform_object(obj: *mut JSObject, cx: *mut JSContext) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Fast-path the common case
|
// Fast-path the common case
|
||||||
let mut clasp = get_object_class(obj);
|
let mut clasp = get_object_class(obj);
|
||||||
|
@ -219,7 +219,7 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
|
||||||
}
|
}
|
||||||
// Now for simplicity check for security wrappers before anything else
|
// Now for simplicity check for security wrappers before anything else
|
||||||
if IsWrapper(obj) {
|
if IsWrapper(obj) {
|
||||||
let unwrapped_obj = UnwrapObject(obj, /* stopAtWindowProxy = */ 0);
|
let unwrapped_obj = UnwrapObjectDynamic(obj, cx, /* stopAtWindowProxy = */ 0);
|
||||||
if unwrapped_obj.is_null() {
|
if unwrapped_obj.is_null() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,12 @@ pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerate lazy properties of a global object.
|
/// Enumerate lazy properties of a global object.
|
||||||
pub unsafe extern "C" fn enumerate_global(cx: *mut JSContext, obj: RawHandleObject) -> bool {
|
pub unsafe extern "C" fn enumerate_global(
|
||||||
|
cx: *mut JSContext,
|
||||||
|
obj: RawHandleObject,
|
||||||
|
_props: *mut AutoIdVector,
|
||||||
|
_enumerable_only: bool,
|
||||||
|
) -> bool {
|
||||||
assert!(JS_IsGlobalObject(obj.get()));
|
assert!(JS_IsGlobalObject(obj.get()));
|
||||||
if !JS_EnumerateStandardClasses(cx, obj) {
|
if !JS_EnumerateStandardClasses(cx, obj) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -463,7 +468,7 @@ unsafe fn generic_call(
|
||||||
let depth = (*info).depth;
|
let depth = (*info).depth;
|
||||||
let proto_check =
|
let proto_check =
|
||||||
|class: &'static DOMClass| class.interface_chain[depth as usize] as u16 == proto_id;
|
|class: &'static DOMClass| class.interface_chain[depth as usize] as u16 == proto_id;
|
||||||
let this = match private_from_proto_check(obj.get(), proto_check) {
|
let this = match private_from_proto_check(obj.get(), cx, proto_check) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
if is_lenient {
|
if is_lenient {
|
||||||
|
|
|
@ -35,7 +35,7 @@ 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::UnwrapObject;
|
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, JSContext, JSObject};
|
||||||
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
|
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
|
||||||
|
@ -259,7 +259,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
|
|
||||||
// Step 1
|
// Step 1
|
||||||
// We must unwrap the constructor as all wrappers are constructable if they are callable.
|
// We must unwrap the constructor as all wrappers are constructable if they are callable.
|
||||||
rooted!(in(cx) let unwrapped_constructor = unsafe { UnwrapObject(constructor.get(), 1) });
|
rooted!(in(cx) let unwrapped_constructor = unsafe { UnwrapObjectStatic(constructor.get()) });
|
||||||
|
|
||||||
if unwrapped_constructor.is_null() {
|
if unwrapped_constructor.is_null() {
|
||||||
// We do not have permission to access the unwrapped constructor.
|
// We do not have permission to access the unwrapped constructor.
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSourceBinding::EventSourceMethods;
|
use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSourceBinding::EventSourceMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||||
use crate::dom::bindings::conversions::root_from_object;
|
use crate::dom::bindings::conversions::{root_from_object, root_from_object_static};
|
||||||
use crate::dom::bindings::error::{report_pending_exception, ErrorInfo};
|
use crate::dom::bindings::error::{report_pending_exception, ErrorInfo};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
|
@ -41,7 +41,7 @@ use crate::timers::{OneshotTimers, TimerCallback};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use js::glue::{IsWrapper, UnwrapObject};
|
use js::glue::{IsWrapper, UnwrapObjectDynamic};
|
||||||
use js::jsapi::JSObject;
|
use js::jsapi::JSObject;
|
||||||
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
|
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
|
||||||
use js::jsapi::{HandleObject, Heap};
|
use js::jsapi::{HandleObject, Heap};
|
||||||
|
@ -233,22 +233,25 @@ impl GlobalScope {
|
||||||
pub unsafe fn from_object(obj: *mut JSObject) -> DomRoot<Self> {
|
pub unsafe fn from_object(obj: *mut JSObject) -> DomRoot<Self> {
|
||||||
assert!(!obj.is_null());
|
assert!(!obj.is_null());
|
||||||
let global = GetNonCCWObjectGlobal(obj);
|
let global = GetNonCCWObjectGlobal(obj);
|
||||||
global_scope_from_global(global)
|
global_scope_from_global_static(global)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the global scope for the given JSContext
|
/// Returns the global scope for the given JSContext
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub unsafe fn from_context(cx: *mut JSContext) -> DomRoot<Self> {
|
pub unsafe fn from_context(cx: *mut JSContext) -> DomRoot<Self> {
|
||||||
let global = CurrentGlobalOrNull(cx);
|
let global = CurrentGlobalOrNull(cx);
|
||||||
global_scope_from_global(global)
|
global_scope_from_global(global, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the global object of the realm that the given JS object
|
/// Returns the global object of the realm that the given JS object
|
||||||
/// was created in, after unwrapping any wrappers.
|
/// was created in, after unwrapping any wrappers.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub unsafe fn from_object_maybe_wrapped(mut obj: *mut JSObject) -> DomRoot<Self> {
|
pub unsafe fn from_object_maybe_wrapped(
|
||||||
|
mut obj: *mut JSObject,
|
||||||
|
cx: *mut JSContext,
|
||||||
|
) -> DomRoot<Self> {
|
||||||
if IsWrapper(obj) {
|
if IsWrapper(obj) {
|
||||||
obj = UnwrapObject(obj, /* stopAtWindowProxy = */ 0);
|
obj = UnwrapObjectDynamic(obj, cx, /* stopAtWindowProxy = */ 0);
|
||||||
assert!(!obj.is_null());
|
assert!(!obj.is_null());
|
||||||
}
|
}
|
||||||
GlobalScope::from_object(obj)
|
GlobalScope::from_object(obj)
|
||||||
|
@ -663,16 +666,23 @@ 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(),
|
||||||
|_| 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) {
|
||||||
self.microtask_queue.enqueue(job);
|
unsafe {
|
||||||
|
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
|
||||||
|
@ -749,7 +759,7 @@ impl GlobalScope {
|
||||||
if global.is_null() {
|
if global.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(global_scope_from_global(global))
|
Some(global_scope_from_global(global, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,12 +807,27 @@ fn timestamp_in_ms(time: Timespec) -> u64 {
|
||||||
|
|
||||||
/// Returns the Rust global scope from a JS global object.
|
/// Returns the Rust global scope from a JS global object.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn global_scope_from_global(global: *mut JSObject) -> DomRoot<GlobalScope> {
|
unsafe fn global_scope_from_global(
|
||||||
|
global: *mut JSObject,
|
||||||
|
cx: *mut JSContext,
|
||||||
|
) -> DomRoot<GlobalScope> {
|
||||||
assert!(!global.is_null());
|
assert!(!global.is_null());
|
||||||
let clasp = get_object_class(global);
|
let clasp = get_object_class(global);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)),
|
((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
root_from_object(global).unwrap()
|
root_from_object(global, cx).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Rust global scope from a JS global object.
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe fn global_scope_from_global_static(global: *mut JSObject) -> DomRoot<GlobalScope> {
|
||||||
|
assert!(!global.is_null());
|
||||||
|
let clasp = get_object_class(global);
|
||||||
|
assert_ne!(
|
||||||
|
((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
root_from_object_static(global).unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ unsafe extern "C" fn native_handler_callback(
|
||||||
rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER));
|
rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER));
|
||||||
assert!(v.get().is_object());
|
assert!(v.get().is_object());
|
||||||
|
|
||||||
let handler = root_from_object::<PromiseNativeHandler>(v.to_object())
|
let handler = root_from_object::<PromiseNativeHandler>(v.to_object(), cx)
|
||||||
.expect("unexpected value for native handler in promise native handler callback");
|
.expect("unexpected value for native handler in promise native handler callback");
|
||||||
|
|
||||||
rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER_TASK));
|
rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER_TASK));
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::conversions::{root_from_handleobject, ToJSValConvertible};
|
use crate::dom::bindings::conversions::{root_from_handleobject, ToJSValConvertible};
|
||||||
use crate::dom::bindings::error::{throw_dom_exception, Error};
|
use crate::dom::bindings::error::{throw_dom_exception, Error};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
|
use crate::dom::bindings::proxyhandler::fill_property_descriptor;
|
||||||
use crate::dom::bindings::reflector::{DomObject, Reflector};
|
use crate::dom::bindings::reflector::{DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
@ -712,7 +712,7 @@ unsafe fn GetSubframeWindowProxy(
|
||||||
let mut slot = UndefinedValue();
|
let mut slot = UndefinedValue();
|
||||||
GetProxyPrivate(*proxy, &mut slot);
|
GetProxyPrivate(*proxy, &mut slot);
|
||||||
rooted!(in(cx) let target = slot.to_object());
|
rooted!(in(cx) let target = slot.to_object());
|
||||||
if let Ok(win) = root_from_handleobject::<Window>(target.handle()) {
|
if let Ok(win) = root_from_handleobject::<Window>(target.handle(), cx) {
|
||||||
let browsing_context_id = win.window_proxy().browsing_context_id();
|
let browsing_context_id = win.window_proxy().browsing_context_id();
|
||||||
let (result_sender, result_receiver) = ipc::channel().unwrap();
|
let (result_sender, result_receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
|
@ -730,7 +730,9 @@ unsafe fn GetSubframeWindowProxy(
|
||||||
.and_then(|maybe_bcid| maybe_bcid)
|
.and_then(|maybe_bcid| maybe_bcid)
|
||||||
.and_then(ScriptThread::find_window_proxy)
|
.and_then(ScriptThread::find_window_proxy)
|
||||||
.map(|proxy| (proxy, (JSPROP_ENUMERATE | JSPROP_READONLY) as u32));
|
.map(|proxy| (proxy, (JSPROP_ENUMERATE | JSPROP_READONLY) as u32));
|
||||||
} else if let Ok(win) = root_from_handleobject::<DissimilarOriginWindow>(target.handle()) {
|
} else if let Ok(win) =
|
||||||
|
root_from_handleobject::<DissimilarOriginWindow>(target.handle(), cx)
|
||||||
|
{
|
||||||
let browsing_context_id = win.window_proxy().browsing_context_id();
|
let browsing_context_id = win.window_proxy().browsing_context_id();
|
||||||
let (result_sender, result_receiver) = ipc::channel().unwrap();
|
let (result_sender, result_receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
|
@ -912,7 +914,6 @@ static PROXY_HANDLER: ProxyTraps = ProxyTraps {
|
||||||
set: Some(set),
|
set: Some(set),
|
||||||
call: None,
|
call: None,
|
||||||
construct: None,
|
construct: None,
|
||||||
getPropertyDescriptor: Some(get_property_descriptor),
|
|
||||||
hasOwn: None,
|
hasOwn: None,
|
||||||
getOwnEnumerablePropertyKeys: None,
|
getOwnEnumerablePropertyKeys: None,
|
||||||
nativeCall: None,
|
nativeCall: None,
|
||||||
|
@ -1049,7 +1050,6 @@ static XORIGIN_PROXY_HANDLER: ProxyTraps = ProxyTraps {
|
||||||
set: Some(set_xorigin),
|
set: Some(set_xorigin),
|
||||||
call: None,
|
call: None,
|
||||||
construct: None,
|
construct: None,
|
||||||
getPropertyDescriptor: Some(getOwnPropertyDescriptor_xorigin),
|
|
||||||
hasOwn: Some(has_xorigin),
|
hasOwn: Some(has_xorigin),
|
||||||
getOwnEnumerablePropertyKeys: None,
|
getOwnEnumerablePropertyKeys: None,
|
||||||
nativeCall: None,
|
nativeCall: None,
|
||||||
|
|
|
@ -131,7 +131,7 @@ impl WorkerGlobalScope {
|
||||||
init.resource_threads,
|
init.resource_threads,
|
||||||
timer_event_chan,
|
timer_event_chan,
|
||||||
MutableOrigin::new(init.origin),
|
MutableOrigin::new(init.origin),
|
||||||
Default::default(),
|
runtime.microtask_queue.clone(),
|
||||||
),
|
),
|
||||||
worker_id: init.worker_id,
|
worker_id: init.worker_id,
|
||||||
worker_name,
|
worker_name,
|
||||||
|
|
|
@ -16,6 +16,7 @@ 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;
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
|
use js::jsapi::{JSContext, 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;
|
||||||
|
@ -54,14 +55,21 @@ pub struct EnqueuedPromiseCallback {
|
||||||
impl MicrotaskQueue {
|
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.
|
||||||
pub fn enqueue(&self, job: Microtask) {
|
#[allow(unsafe_code)]
|
||||||
|
pub unsafe fn enqueue(&self, job: Microtask, cx: *mut JSContext) {
|
||||||
self.microtask_queue.borrow_mut().push(job);
|
self.microtask_queue.borrow_mut().push(job);
|
||||||
|
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.
|
||||||
pub fn checkpoint<F>(&self, target_provider: F, globalscopes: Vec<DomRoot<GlobalScope>>)
|
#[allow(unsafe_code)]
|
||||||
where
|
pub unsafe fn checkpoint<F>(
|
||||||
|
&self,
|
||||||
|
cx: *mut JSContext,
|
||||||
|
target_provider: F,
|
||||||
|
globalscopes: Vec<DomRoot<GlobalScope>>,
|
||||||
|
) where
|
||||||
F: Fn(PipelineId) -> Option<DomRoot<GlobalScope>>,
|
F: Fn(PipelineId) -> Option<DomRoot<GlobalScope>>,
|
||||||
{
|
{
|
||||||
if self.performing_a_microtask_checkpoint.get() {
|
if self.performing_a_microtask_checkpoint.get() {
|
||||||
|
@ -76,7 +84,11 @@ impl MicrotaskQueue {
|
||||||
rooted_vec!(let mut pending_queue);
|
rooted_vec!(let mut pending_queue);
|
||||||
mem::swap(&mut *pending_queue, &mut *self.microtask_queue.borrow_mut());
|
mem::swap(&mut *pending_queue, &mut *self.microtask_queue.borrow_mut());
|
||||||
|
|
||||||
for job in pending_queue.iter() {
|
for (idx, job) in pending_queue.iter().enumerate() {
|
||||||
|
if idx == pending_queue.len() - 1 && self.microtask_queue.borrow().is_empty() {
|
||||||
|
JobQueueIsEmpty(cx);
|
||||||
|
}
|
||||||
|
|
||||||
match *job {
|
match *job {
|
||||||
Microtask::Promise(ref job) => {
|
Microtask::Promise(ref job) => {
|
||||||
if let Some(target) = target_provider(job.pipeline) {
|
if let Some(target) = target_provider(job.pipeline) {
|
||||||
|
@ -109,4 +121,8 @@ impl MicrotaskQueue {
|
||||||
// Step 5
|
// Step 5
|
||||||
self.performing_a_microtask_checkpoint.set(false);
|
self.performing_a_microtask_checkpoint.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty(&self) -> bool {
|
||||||
|
self.microtask_queue.borrow().is_empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,14 @@ use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::promiserejectionevent::PromiseRejectionEvent;
|
use crate::dom::promiserejectionevent::PromiseRejectionEvent;
|
||||||
use crate::microtask::{EnqueuedPromiseCallback, Microtask};
|
use crate::microtask::{EnqueuedPromiseCallback, Microtask, MicrotaskQueue};
|
||||||
use crate::script_thread::trace_thread;
|
use crate::script_thread::trace_thread;
|
||||||
use crate::task::TaskBox;
|
use crate::task::TaskBox;
|
||||||
use crate::task_source::{TaskSource, TaskSourceName};
|
use crate::task_source::{TaskSource, TaskSourceName};
|
||||||
use js::glue::CollectServoSizes;
|
use js::glue::{CollectServoSizes, CreateJobQueue, DeleteJobQueue, JobQueueTraps, SetBuildId};
|
||||||
use js::glue::SetBuildId;
|
|
||||||
use js::jsapi::ContextOptionsRef;
|
use js::jsapi::ContextOptionsRef;
|
||||||
use js::jsapi::{BuildIdCharVector, DisableIncrementalGC, GCDescription, GCProgress};
|
use js::jsapi::{BuildIdCharVector, DisableIncrementalGC, GCDescription, GCProgress};
|
||||||
use js::jsapi::{HandleObject, Heap};
|
use js::jsapi::{HandleObject, Heap, JobQueue};
|
||||||
use js::jsapi::{JSContext, JSTracer, SetDOMCallbacks, SetGCSliceCallback};
|
use js::jsapi::{JSContext, JSTracer, SetDOMCallbacks, SetGCSliceCallback};
|
||||||
use js::jsapi::{JSGCInvocationKind, JSGCStatus, JS_AddExtraGCRootsTracer, JS_SetGCCallback};
|
use js::jsapi::{JSGCInvocationKind, JSGCStatus, JS_AddExtraGCRootsTracer, JS_SetGCCallback};
|
||||||
use js::jsapi::{JSGCMode, JSGCParamKey, JS_SetGCParameter, JS_SetGlobalJitCompilerOption};
|
use js::jsapi::{JSGCMode, JSGCParamKey, JS_SetGCParameter, JS_SetGlobalJitCompilerOption};
|
||||||
|
@ -37,9 +36,7 @@ use js::jsapi::{
|
||||||
JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled,
|
JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled,
|
||||||
};
|
};
|
||||||
use js::jsapi::{JSObject, PromiseRejectionHandlingState, SetPreserveWrapperCallback};
|
use js::jsapi::{JSObject, PromiseRejectionHandlingState, SetPreserveWrapperCallback};
|
||||||
use js::jsapi::{
|
use js::jsapi::{SetJobQueue, SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback};
|
||||||
SetEnqueuePromiseJobCallback, SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback,
|
|
||||||
};
|
|
||||||
use js::panic::wrap_panic;
|
use js::panic::wrap_panic;
|
||||||
use js::rust::wrappers::{GetPromiseIsHandled, GetPromiseResult};
|
use js::rust::wrappers::{GetPromiseIsHandled, GetPromiseResult};
|
||||||
use js::rust::Handle;
|
use js::rust::Handle;
|
||||||
|
@ -60,10 +57,17 @@ use std::os;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::panic::AssertUnwindSafe;
|
use std::panic::AssertUnwindSafe;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::thread_state::{self, ThreadState};
|
use style::thread_state::{self, ThreadState};
|
||||||
use time::{now, Tm};
|
use time::{now, Tm};
|
||||||
|
|
||||||
|
static JOB_QUEUE_TRAPS: JobQueueTraps = JobQueueTraps {
|
||||||
|
getIncumbentGlobal: Some(get_incumbent_global),
|
||||||
|
enqueuePromiseJob: Some(enqueue_promise_job),
|
||||||
|
empty: Some(empty),
|
||||||
|
};
|
||||||
|
|
||||||
/// Common messages used to control the event loops in both the script and the worker
|
/// Common messages used to control the event loops in both the script and the worker
|
||||||
pub enum CommonScriptMsg {
|
pub enum CommonScriptMsg {
|
||||||
/// Requests that the script thread measure its memory usage. The results are sent back via the
|
/// Requests that the script thread measure its memory usage. The results are sent back via the
|
||||||
|
@ -134,25 +138,52 @@ pub trait ScriptPort {
|
||||||
fn recv(&self) -> Result<CommonScriptMsg, ()>;
|
fn recv(&self) -> Result<CommonScriptMsg, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe extern "C" fn get_incumbent_global(_: *const c_void, _: *mut JSContext) -> *mut JSObject {
|
||||||
|
wrap_panic(
|
||||||
|
AssertUnwindSafe(|| {
|
||||||
|
GlobalScope::incumbent()
|
||||||
|
.map(|g| g.reflector().get_jsobject().get())
|
||||||
|
.unwrap_or(ptr::null_mut())
|
||||||
|
}),
|
||||||
|
ptr::null_mut(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe extern "C" fn empty(extra: *const c_void) -> bool {
|
||||||
|
wrap_panic(
|
||||||
|
AssertUnwindSafe(|| {
|
||||||
|
let microtask_queue = &*(extra as *const MicrotaskQueue);
|
||||||
|
microtask_queue.empty()
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// SM callback for promise job resolution. Adds a promise callback to the current
|
/// SM callback for promise job resolution. Adds a promise callback to the current
|
||||||
/// global's microtask queue.
|
/// global's microtask queue.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe extern "C" fn enqueue_job(
|
unsafe extern "C" fn enqueue_promise_job(
|
||||||
|
extra: *const c_void,
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
_promise: HandleObject,
|
_promise: HandleObject,
|
||||||
job: HandleObject,
|
job: HandleObject,
|
||||||
_allocation_site: HandleObject,
|
_allocation_site: HandleObject,
|
||||||
incumbent_global: HandleObject,
|
incumbent_global: HandleObject,
|
||||||
_data: *mut c_void,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
wrap_panic(
|
wrap_panic(
|
||||||
AssertUnwindSafe(|| {
|
AssertUnwindSafe(|| {
|
||||||
|
let microtask_queue = &*(extra as *const MicrotaskQueue);
|
||||||
let global = GlobalScope::from_object(incumbent_global.get());
|
let global = GlobalScope::from_object(incumbent_global.get());
|
||||||
let pipeline = global.pipeline_id();
|
let pipeline = global.pipeline_id();
|
||||||
global.enqueue_microtask(Microtask::Promise(EnqueuedPromiseCallback {
|
microtask_queue.enqueue(
|
||||||
|
Microtask::Promise(EnqueuedPromiseCallback {
|
||||||
callback: PromiseJobCallback::new(cx, job.get()),
|
callback: PromiseJobCallback::new(cx, job.get()),
|
||||||
pipeline: pipeline,
|
pipeline,
|
||||||
}));
|
}),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
|
@ -309,10 +340,18 @@ pub fn notify_about_rejected_promises(global: &GlobalScope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JSTraceable)]
|
#[derive(JSTraceable)]
|
||||||
pub struct Runtime(RustRuntime);
|
pub struct Runtime {
|
||||||
|
rt: RustRuntime,
|
||||||
|
pub microtask_queue: Rc<MicrotaskQueue>,
|
||||||
|
job_queue: *mut JobQueue,
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for Runtime {
|
impl Drop for Runtime {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
DeleteJobQueue(self.job_queue);
|
||||||
|
}
|
||||||
THREAD_ACTIVE.with(|t| {
|
THREAD_ACTIVE.with(|t| {
|
||||||
LiveDOMReferences::destruct();
|
LiveDOMReferences::destruct();
|
||||||
t.set(false);
|
t.set(false);
|
||||||
|
@ -323,7 +362,7 @@ impl Drop for Runtime {
|
||||||
impl Deref for Runtime {
|
impl Deref for Runtime {
|
||||||
type Target = RustRuntime;
|
type Target = RustRuntime;
|
||||||
fn deref(&self) -> &RustRuntime {
|
fn deref(&self) -> &RustRuntime {
|
||||||
&self.0
|
&self.rt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +409,12 @@ unsafe fn new_rt_and_cx_with_parent(parent: Option<ParentRuntime>) -> Runtime {
|
||||||
// Pre barriers aren't working correctly at the moment
|
// Pre barriers aren't working correctly at the moment
|
||||||
DisableIncrementalGC(cx);
|
DisableIncrementalGC(cx);
|
||||||
|
|
||||||
SetEnqueuePromiseJobCallback(cx, Some(enqueue_job), ptr::null_mut());
|
let microtask_queue = Rc::new(MicrotaskQueue::default());
|
||||||
|
let job_queue = CreateJobQueue(
|
||||||
|
&JOB_QUEUE_TRAPS,
|
||||||
|
&*microtask_queue as *const _ as *const c_void,
|
||||||
|
);
|
||||||
|
SetJobQueue(cx, job_queue);
|
||||||
SetPromiseRejectionTrackerCallback(cx, Some(promise_rejection_tracker), ptr::null_mut());
|
SetPromiseRejectionTrackerCallback(cx, Some(promise_rejection_tracker), ptr::null_mut());
|
||||||
|
|
||||||
set_gc_zeal_options(cx);
|
set_gc_zeal_options(cx);
|
||||||
|
@ -407,7 +451,7 @@ unsafe fn new_rt_and_cx_with_parent(parent: Option<ParentRuntime>) -> Runtime {
|
||||||
);
|
);
|
||||||
JS_SetGlobalJitCompilerOption(
|
JS_SetGlobalJitCompilerOption(
|
||||||
cx,
|
cx,
|
||||||
JSJitCompilerOption::JSJITCOMPILER_ION_WARMUP_TRIGGER,
|
JSJitCompilerOption::JSJITCOMPILER_ION_NORMAL_WARMUP_TRIGGER,
|
||||||
if pref!(js.ion.unsafe_eager_compilation.enabled) {
|
if pref!(js.ion.unsafe_eager_compilation.enabled) {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
@ -511,7 +555,11 @@ unsafe fn new_rt_and_cx_with_parent(parent: Option<ParentRuntime>) -> Runtime {
|
||||||
JS_SetGCParameter(cx, JSGCParamKey::JSGC_MAX_EMPTY_CHUNK_COUNT, val as u32);
|
JS_SetGCParameter(cx, JSGCParamKey::JSGC_MAX_EMPTY_CHUNK_COUNT, val as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Runtime(runtime)
|
Runtime {
|
||||||
|
rt: runtime,
|
||||||
|
microtask_queue,
|
||||||
|
job_queue,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_range<T: PartialOrd + Copy>(val: T, min: T, max: T) -> Option<T> {
|
fn in_range<T: PartialOrd + Copy>(val: T, min: T, max: T) -> Option<T> {
|
||||||
|
|
|
@ -845,11 +845,16 @@ 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() {
|
||||||
let script_thread = unsafe { &*script_thread };
|
unsafe {
|
||||||
script_thread.microtask_queue.enqueue(task);
|
let script_thread = &*script_thread;
|
||||||
|
script_thread
|
||||||
|
.microtask_queue
|
||||||
|
.enqueue(task, script_thread.get_cx());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1123,6 +1128,8 @@ impl ScriptThread {
|
||||||
devtools_port: devtools_port,
|
devtools_port: devtools_port,
|
||||||
devtools_sender: ipc_devtools_sender,
|
devtools_sender: ipc_devtools_sender,
|
||||||
|
|
||||||
|
microtask_queue: runtime.microtask_queue.clone(),
|
||||||
|
|
||||||
js_runtime: Rc::new(runtime),
|
js_runtime: Rc::new(runtime),
|
||||||
topmost_mouse_over_target: MutNullableDom::new(Default::default()),
|
topmost_mouse_over_target: MutNullableDom::new(Default::default()),
|
||||||
closed_pipelines: DomRefCell::new(HashSet::new()),
|
closed_pipelines: DomRefCell::new(HashSet::new()),
|
||||||
|
@ -1133,8 +1140,6 @@ impl ScriptThread {
|
||||||
|
|
||||||
content_process_shutdown_chan: state.content_process_shutdown_chan,
|
content_process_shutdown_chan: state.content_process_shutdown_chan,
|
||||||
|
|
||||||
microtask_queue: Default::default(),
|
|
||||||
|
|
||||||
mutation_observer_microtask_queued: Default::default(),
|
mutation_observer_microtask_queued: Default::default(),
|
||||||
|
|
||||||
mutation_observers: Default::default(),
|
mutation_observers: Default::default(),
|
||||||
|
@ -3541,13 +3546,17 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
pub fn enqueue_microtask(job: Microtask) {
|
pub fn enqueue_microtask(job: Microtask) {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| unsafe {
|
||||||
let script_thread = unsafe { &*root.get().unwrap() };
|
let script_thread = &*root.get().unwrap();
|
||||||
script_thread.microtask_queue.enqueue(job);
|
script_thread
|
||||||
|
.microtask_queue
|
||||||
|
.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
|
||||||
|
@ -3556,8 +3565,13 @@ impl ScriptThread {
|
||||||
.map(|(_id, document)| document.global())
|
.map(|(_id, document)| document.global())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.microtask_queue
|
unsafe {
|
||||||
.checkpoint(|id| self.documents.borrow().find_global(id), globals)
|
self.microtask_queue.checkpoint(
|
||||||
|
self.get_cx(),
|
||||||
|
|id| self.documents.borrow().find_global(id),
|
||||||
|
globals,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ RUN \
|
||||||
#
|
#
|
||||||
# Bindgen (for SpiderMonkey bindings)
|
# Bindgen (for SpiderMonkey bindings)
|
||||||
clang \
|
clang \
|
||||||
|
llvm \
|
||||||
|
llvm-dev \
|
||||||
#
|
#
|
||||||
# GStreamer
|
# GStreamer
|
||||||
libgstreamer-plugins-bad1.0-dev \
|
libgstreamer-plugins-bad1.0-dev \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue