Always pass InRealm to GlobalScope::from_context to avoid getting null global

This commit is contained in:
CYBAI 2020-01-24 12:43:49 +09:00
parent 795dab71ff
commit 403ffcf1eb
16 changed files with 79 additions and 61 deletions

View file

@ -13,9 +13,9 @@ use crate::dom::bindings::settings_stack::{AutoEntryScript, AutoIncumbentScript}
use crate::dom::bindings::utils::AsCCharPtrPtr;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::JSContext;
use js::jsapi::Heap;
use js::jsapi::JSAutoRealm;
use js::jsapi::{AddRawValueRoot, IsCallable, JSObject};
use js::jsapi::{EnterRealm, LeaveRealm, Realm, RemoveRawValueRoot};
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
@ -270,11 +270,8 @@ impl Drop for CallSetup {
unsafe {
LeaveRealm(*self.cx, self.old_realm);
if self.handling == ExceptionHandling::Report {
let _ac = JSAutoRealm::new(
*self.cx,
self.exception_global.reflector().get_jsobject().get(),
);
report_pending_exception(*self.cx, true);
let ar = enter_realm(&*self.exception_global);
report_pending_exception(*self.cx, true, InRealm::Entered(&ar));
}
drop(self.incumbent_script.take());
drop(self.entry_script.take().unwrap());

View file

@ -57,7 +57,7 @@ DOMInterfaces = {
},
'Window': {
'inRealms': ['Fetch'],
'inRealms': ['Fetch', 'Opener'],
},
'WorkerGlobalScope': {

View file

@ -14,6 +14,7 @@ use crate::dom::bindings::conversions::{
use crate::dom::bindings::str::USVString;
use crate::dom::domexception::{DOMErrorName, DOMException};
use crate::dom::globalscope::GlobalScope;
use crate::realms::InRealm;
use crate::script_runtime::JSContext as SafeJSContext;
#[cfg(feature = "js_backtrace")]
use backtrace::Backtrace;
@ -231,7 +232,7 @@ impl ErrorInfo {
///
/// The `dispatch_event` argument is temporary and non-standard; passing false
/// prevents dispatching the `error` event.
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool) {
pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool, realm: InRealm) {
if !JS_IsExceptionPending(cx) {
return;
}
@ -285,7 +286,7 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
}
if dispatch_event {
GlobalScope::from_context(cx).report_an_error(error_info, value.handle());
GlobalScope::from_context(cx, realm).report_an_error(error_info, value.handle());
}
}

View file

@ -14,7 +14,7 @@ use crate::dom::bindings::transferable::Transferable;
use crate::dom::blob::Blob;
use crate::dom::globalscope::GlobalScope;
use crate::dom::messageport::MessagePort;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use js::glue::CopyJSStructuredCloneData;
use js::glue::DeleteJSAutoStructuredCloneBuffer;
@ -129,8 +129,9 @@ unsafe extern "C" fn read_callback(
"tag should be higher than StructuredCloneTags::Min"
);
if tag == StructuredCloneTags::DomBlob as u32 {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
return read_blob(
&GlobalScope::from_context(cx),
&GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)),
r,
&mut *(closure as *mut StructuredDataHolder),
);
@ -145,8 +146,9 @@ unsafe extern "C" fn write_callback(
closure: *mut raw::c_void,
) -> bool {
if let Ok(blob) = root_from_object::<Blob>(*obj, cx) {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
return write_blob(
&GlobalScope::from_context(cx),
&GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)),
blob,
w,
&mut *(closure as *mut StructuredDataHolder),
@ -166,7 +168,8 @@ unsafe extern "C" fn read_transfer_callback(
) -> bool {
if tag == StructuredCloneTags::MessagePort as u32 {
let mut sc_holder = &mut *(closure as *mut StructuredDataHolder);
let owner = GlobalScope::from_context(cx);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
if let Ok(_) = <MessagePort as Transferable>::transfer_receive(
&owner,
&mut sc_holder,

View file

@ -81,9 +81,9 @@ use crate::dom::htmlulistelement::HTMLUListElement;
use crate::dom::htmlunknownelement::HTMLUnknownElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::svgsvgelement::SVGSVGElement;
use crate::realms::{enter_realm, InRealm};
use crate::script_thread::ScriptThread;
use html5ever::{LocalName, Prefix, QualName};
use js::jsapi::JSAutoRealm;
use servo_config::pref;
fn create_svg_element(
@ -157,10 +157,9 @@ fn create_html_element(
// Step 6.1.1
unsafe {
let _ac =
JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
let ar = enter_realm(&*global);
throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true);
report_pending_exception(*cx, true, InRealm::Entered(&ar));
}
// Step 6.1.2

View file

@ -31,7 +31,7 @@ use crate::dom::node::{document_from_node, window_from_node, Node, ShadowIncludi
use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::microtask::Microtask;
use crate::realms::InRealm;
use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::JSContext;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
@ -652,8 +652,9 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
let global = GlobalScope::current().expect("No current global");
let cx = global.get_cx();
unsafe {
let ar = enter_realm(&*global);
throw_dom_exception(cx, &global, error);
report_pending_exception(*cx, true);
report_pending_exception(*cx, true, InRealm::Entered(&ar));
}
return;

View file

@ -26,7 +26,7 @@ use crate::dom::messageevent::MessageEvent;
use crate::dom::worker::{TrustedWorkerAddress, Worker};
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::fetch::load_whole_resource;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
use crate::script_runtime::{
new_child_runtime, CommonScriptMsg, JSContext as SafeJSContext, Runtime, ScriptChan, ScriptPort,
@ -555,8 +555,10 @@ impl DedicatedWorkerGlobalScope {
#[allow(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
let worker = DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
.expect("global is not a worker scope");
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
let worker =
DomRoot::downcast::<WorkerGlobalScope>(global).expect("global is not a worker scope");
assert!(worker.is::<DedicatedWorkerGlobalScope>());
// A false response causes the script to terminate

View file

@ -34,10 +34,10 @@ use crate::dom::node::document_from_node;
use crate::dom::virtualmethods::VirtualMethods;
use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, InRealm};
use dom_struct::dom_struct;
use fnv::FnvHasher;
use js::jsapi::{JSAutoRealm, JSFunction, JS_GetFunctionObject, SourceText};
use js::jsapi::{JSFunction, JS_GetFunctionObject, SourceText};
use js::rust::wrappers::CompileFunction;
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
use libc::c_char;
@ -552,9 +552,9 @@ impl EventTarget {
if !rv || handler.get().is_null() {
// Step 3.7
unsafe {
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
let ar = enter_realm(&*self);
// FIXME(#13152): dispatch error event.
report_pending_exception(*cx, false);
report_pending_exception(*cx, false, InRealm::Entered(&ar));
}
return None;
}

View file

@ -38,7 +38,7 @@ use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::dom::workletglobalscope::WorkletGlobalScope;
use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
use crate::realms::enter_realm;
use crate::realms::{enter_realm, InRealm};
use crate::script_module::ModuleTree;
use crate::script_runtime::{CommonScriptMsg, JSContext as SafeJSContext, ScriptChan, ScriptPort};
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
@ -61,10 +61,10 @@ use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::glue::{IsWrapper, UnwrapObjectDynamic};
use js::jsapi::JSContext;
use js::jsapi::JSObject;
use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal};
use js::jsapi::{HandleObject, Heap};
use js::jsapi::{JSAutoRealm, JSContext};
use js::jsval::{JSVal, UndefinedValue};
use js::panic::maybe_resume_unwind;
use js::rust::wrappers::EvaluateUtf8;
@ -1449,8 +1449,9 @@ impl GlobalScope {
/// Returns the global scope for the given JSContext
#[allow(unsafe_code)]
pub unsafe fn from_context(cx: *mut JSContext) -> DomRoot<Self> {
pub unsafe fn from_context(cx: *mut JSContext, _realm: InRealm) -> DomRoot<Self> {
let global = CurrentGlobalOrNull(cx);
assert!(!global.is_null());
global_scope_from_global(global, cx)
}
@ -1846,10 +1847,10 @@ impl GlobalScope {
self.time_profiler_chan().clone(),
|| {
let cx = self.get_cx();
let globalhandle = self.reflector().get_jsobject();
let filename = CString::new(filename).unwrap();
let _ac = JSAutoRealm::new(*cx, globalhandle.get());
let ar = enter_realm(&*self);
let _aes = AutoEntryScript::new(self);
let options = CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number);
@ -1866,7 +1867,7 @@ impl GlobalScope {
if !result {
debug!("error evaluating Dom string");
unsafe { report_pending_exception(*cx, true) };
unsafe { report_pending_exception(*cx, true, InRealm::Entered(&ar)) };
}
maybe_resume_unwind();

View file

@ -22,7 +22,7 @@ use crate::dom::messageevent::MessageEvent;
use crate::dom::worker::TrustedWorkerAddress;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::fetch::load_whole_resource;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::{
new_rt_and_cx, CommonScriptMsg, JSContext as SafeJSContext, Runtime, ScriptChan,
};
@ -447,8 +447,10 @@ impl ServiceWorkerGlobalScope {
#[allow(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
let worker = DomRoot::downcast::<WorkerGlobalScope>(GlobalScope::from_context(cx))
.expect("global is not a worker scope");
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
let worker =
DomRoot::downcast::<WorkerGlobalScope>(global).expect("global is not a worker scope");
assert!(worker.is::<ServiceWorkerGlobalScope>());
// A false response causes the script to terminate

View file

@ -48,7 +48,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::url::URL;
use crate::realms::InRealm;
use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use crate::timers::OneshotTimerCallback;
use dom_struct::dom_struct;
@ -1015,7 +1015,10 @@ impl TestBindingMethods for TestBinding {
impl Callback for SimpleHandler {
#[allow(unsafe_code)]
fn callback(&self, cx: *mut JSContext, v: HandleValue) {
let global = unsafe { GlobalScope::from_context(cx) };
let global = unsafe {
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof))
};
let _ = self.handler.Call_(&*global, v, ExceptionHandling::Report);
}
}

View file

@ -673,7 +673,7 @@ impl WindowMethods for Window {
}
// https://html.spec.whatwg.org/multipage/#dom-opener
fn Opener(&self, cx: JSContext) -> JSVal {
fn Opener(&self, cx: JSContext, in_realm_proof: InRealm) -> JSVal {
// Step 1, Let current be this Window object's browsing context.
let current = match self.window_proxy.get() {
Some(proxy) => proxy,
@ -688,7 +688,7 @@ impl WindowMethods for Window {
return NullValue();
}
// Step 3 to 5.
current.opener(*cx)
current.opener(*cx, in_realm_proof)
}
#[allow(unsafe_code)]

View file

@ -17,7 +17,7 @@ use crate::dom::document::Document;
use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use crate::realms::enter_realm;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use crate::script_thread::ScriptThread;
use dom_struct::dom_struct;
@ -370,7 +370,7 @@ impl WindowProxy {
#[allow(unsafe_code)]
// https://html.spec.whatwg.org/multipage/#dom-opener
pub fn opener(&self, cx: *mut JSContext) -> JSVal {
pub fn opener(&self, cx: *mut JSContext, in_realm_proof: InRealm) -> JSVal {
if self.disowned.get() {
return NullValue();
}
@ -387,7 +387,8 @@ impl WindowProxy {
opener_id,
) {
Some(opener_top_id) => {
let global_to_clone_from = unsafe { GlobalScope::from_context(cx) };
let global_to_clone_from =
unsafe { GlobalScope::from_context(cx, in_realm_proof) };
WindowProxy::new_dissimilar_origin(
&*global_to_clone_from,
opener_id,
@ -982,10 +983,11 @@ pub fn new_window_proxy_handler() -> WindowProxyHandler {
// defined in the DissimilarOriginWindow IDL.
#[allow(unsafe_code)]
unsafe fn throw_security_error(cx: *mut JSContext) -> bool {
unsafe fn throw_security_error(cx: *mut JSContext, realm: InRealm) -> bool {
if !JS_IsExceptionPending(cx) {
let global = GlobalScope::from_context(cx);
throw_dom_exception(SafeJSContext::from_ptr(cx), &*global, Error::Security);
let safe_context = SafeJSContext::from_ptr(cx);
let global = GlobalScope::from_context(cx, realm);
throw_dom_exception(safe_context, &*global, Error::Security);
}
false
}
@ -1006,7 +1008,8 @@ unsafe extern "C" fn has_xorigin(
*bp = true;
true
} else {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
}
@ -1032,7 +1035,8 @@ unsafe extern "C" fn set_xorigin(
_: RawHandleValue,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
#[allow(unsafe_code)]
@ -1042,7 +1046,8 @@ unsafe extern "C" fn delete_xorigin(
_: RawHandleId,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
#[allow(unsafe_code, non_snake_case)]
@ -1065,7 +1070,8 @@ unsafe extern "C" fn defineProperty_xorigin(
_: RawHandle<PropertyDescriptor>,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
#[allow(unsafe_code, non_snake_case)]
@ -1074,7 +1080,8 @@ unsafe extern "C" fn preventExtensions_xorigin(
_: RawHandleObject,
_: *mut ObjectOpResult,
) -> bool {
throw_security_error(cx)
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
throw_security_error(cx, InRealm::Already(&in_realm_proof))
}
static XORIGIN_PROXY_HANDLER: ProxyTraps = ProxyTraps {

View file

@ -25,7 +25,7 @@ use crate::dom::window::{base64_atob, base64_btoa};
use crate::dom::workerlocation::WorkerLocation;
use crate::dom::workernavigator::WorkerNavigator;
use crate::fetch;
use crate::realms::InRealm;
use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::JSContext;
use crate::script_runtime::{get_reports, CommonScriptMsg, Runtime, ScriptChan, ScriptPort};
use crate::task::TaskCanceller;
@ -42,7 +42,6 @@ use crossbeam_channel::Receiver;
use devtools_traits::{DevtoolScriptControlMsg, WorkerId};
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use js::jsapi::JSAutoRealm;
use js::jsval::UndefinedValue;
use js::panic::maybe_resume_unwind;
use js::rust::{HandleValue, ParentRuntime};
@ -399,11 +398,8 @@ impl WorkerGlobalScope {
// https://github.com/servo/servo/issues/6422
println!("evaluate_script failed");
unsafe {
let _ac = JSAutoRealm::new(
self.runtime.cx(),
self.reflector().get_jsobject().get(),
);
report_pending_exception(self.runtime.cx(), true);
let ar = enter_realm(&*self);
report_pending_exception(self.runtime.cx(), true, InRealm::Entered(&ar));
}
}
},

View file

@ -32,6 +32,7 @@ use crate::dom::worker::TrustedWorkerAddress;
use crate::network_listener::{self, NetworkListener};
use crate::network_listener::{PreInvoke, ResourceTimingListener};
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::JSContext as SafeJSContext;
use crate::task::TaskBox;
use crate::task_source::TaskSourceName;
use encoding_rs::UTF_8;
@ -473,8 +474,9 @@ impl ModuleTree {
if let Some(exception) = &*module_error {
unsafe {
let ar = enter_realm(&*global);
JS_SetPendingException(*global.get_cx(), exception.handle());
report_pending_exception(*global.get_cx(), true);
report_pending_exception(*global.get_cx(), true, InRealm::Entered(&ar));
}
}
}
@ -1074,7 +1076,8 @@ unsafe extern "C" fn HostResolveImportedModule(
reference_private: RawHandleValue,
specifier: RawHandle<*mut JSString>,
) -> *mut JSObject {
let global_scope = GlobalScope::from_context(cx);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global_scope = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
// Step 2.
let mut base_url = global_scope.api_base_url();

View file

@ -30,6 +30,7 @@ use crate::dom::promise::Promise;
use crate::dom::promiserejectionevent::PromiseRejectionEvent;
use crate::dom::response::Response;
use crate::microtask::{EnqueuedPromiseCallback, Microtask, MicrotaskQueue};
use crate::realms::{AlreadyInRealm, InRealm};
use crate::script_module::EnsureModuleHooksInitialized;
use crate::script_thread::trace_thread;
use crate::task::TaskBox;
@ -232,7 +233,8 @@ unsafe extern "C" fn promise_rejection_tracker(
// Step 3.
let cx = JSContext::from_ptr(cx);
let global = GlobalScope::from_context(*cx);
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
let global = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
wrap_panic(
AssertUnwindSafe(|| {
@ -908,7 +910,8 @@ unsafe extern "C" fn consume_stream(
_consumer: *mut JSStreamConsumer,
) -> bool {
let cx = JSContext::from_ptr(_cx);
let global = GlobalScope::from_context(*cx);
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
let global = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
//Step 2.1 Upon fulfillment of source, store the Response with value unwrappedSource.
if let Ok(unwrapped_source) =