Auto merge of #29374 - jdm:get-cx-cleanup, r=mrobinson

Assert if DomObject::global is called outside of a JS realm

To avoid crashing in https://github.com/servo/servo/issues/27037, we need to progressively add `InRealm` or `AlreadyInRealm` arguments higher up in the call stack. These changes assert that DomObject::global is only called inside of a realm, which is preferable to segfaulting in the JS engine. Making this a compile-time error requires changing lots of `.global()` callsites, but this PR removes a bunch that are now unnecessary.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix (partially) #27037
- [x] There are tests for these changes
This commit is contained in:
bors-servo 2023-05-21 04:05:58 +02:00 committed by GitHub
commit 1bb713521b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 260 additions and 208 deletions

View file

@ -718,10 +718,8 @@ impl Callback for ConsumeBodyPromiseHandler {
// https://fetch.spec.whatwg.org/#concept-body-consume-body // https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn consume_body<T: BodyMixin + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> { pub fn consume_body<T: BodyMixin + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> {
let global = object.global(); let in_realm_proof = AlreadyInRealm::assert();
let in_realm_proof = AlreadyInRealm::assert(&global); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
let promise =
Promise::new_in_current_realm(&object.global(), InRealm::Already(&in_realm_proof));
// Step 1 // Step 1
if object.is_disturbed() || object.is_locked() { if object.is_disturbed() || object.is_locked() {

View file

@ -33,7 +33,7 @@ use uuid::Uuid;
pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<EvaluateJSReply>) { pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<EvaluateJSReply>) {
// global.get_cx() returns a valid `JSContext` pointer, so this is safe. // global.get_cx() returns a valid `JSContext` pointer, so this is safe.
let result = unsafe { let result = unsafe {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(global); let _ac = enter_realm(global);
rooted!(in(*cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
let source_code = SourceCode::Text(Rc::new(DOMString::from_string(eval))); let source_code = SourceCode::Text(Rc::new(DOMString::from_string(eval)));

View file

@ -9,6 +9,7 @@ use crate::dom::dedicatedworkerglobalscope::{AutoWorkerReset, DedicatedWorkerScr
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::worker::TrustedWorkerAddress; use crate::dom::worker::TrustedWorkerAddress;
use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::enter_realm;
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use crate::task_queue::{QueuedTaskConversion, TaskQueue}; use crate::task_queue::{QueuedTaskConversion, TaskQueue};
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
@ -140,6 +141,7 @@ pub fn run_worker_event_loop<T, WorkerMsg, Event>(
} }
// Step 3 // Step 3
for event in sequential { for event in sequential {
let _realm = enter_realm(&*worker_scope);
if !worker_scope.handle_event(event) { if !worker_scope.handle_event(event) {
// Shutdown // Shutdown
return; return;

View file

@ -9,8 +9,9 @@ use crate::dom::bindings::codegen::Bindings::AudioBufferBinding::{
}; };
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::realms::enter_realm; use crate::realms::enter_realm;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
@ -172,7 +173,7 @@ impl AudioBuffer {
self.length as usize, self.length as usize,
self.sample_rate, self.sample_rate,
); );
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() { for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
// Step 1. // Step 1.
if channel.get().is_null() { if channel.get().is_null() {
@ -271,7 +272,7 @@ impl AudioBufferMethods for AudioBuffer {
} }
let bytes_to_copy = min(self.length - start_in_channel, destination.len() as u32) as usize; let bytes_to_copy = min(self.length - start_in_channel, destination.len() as u32) as usize;
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let channel_number = channel_number as usize; let channel_number = channel_number as usize;
let offset = start_in_channel as usize; let offset = start_in_channel as usize;
let mut dest = Vec::with_capacity(destination.len()); let mut dest = Vec::with_capacity(destination.len());
@ -313,7 +314,7 @@ impl AudioBufferMethods for AudioBuffer {
return Err(Error::IndexSize); return Err(Error::IndexSize);
} }
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
if !self.restore_js_channel_data(cx) { if !self.restore_js_channel_data(cx) {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }

View file

@ -132,7 +132,7 @@ impl AudioContextMethods for AudioContext {
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend // https://webaudio.github.io/web-audio-api/#dom-audiocontext-suspend
fn Suspend(&self, comp: InRealm) -> Rc<Promise> { fn Suspend(&self, comp: InRealm) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {
@ -193,7 +193,7 @@ impl AudioContextMethods for AudioContext {
// https://webaudio.github.io/web-audio-api/#dom-audiocontext-close // https://webaudio.github.io/web-audio-api/#dom-audiocontext-close
fn Close(&self, comp: InRealm) -> Rc<Promise> { fn Close(&self, comp: InRealm) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// Step 2. // Step 2.
if self.context.control_thread_state() == ProcessingState::Closed { if self.context.control_thread_state() == ProcessingState::Closed {

View file

@ -284,7 +284,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-resume
fn Resume(&self, comp: InRealm) -> Rc<Promise> { fn Resume(&self, comp: InRealm) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// Step 2. // Step 2.
if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed { if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed {
@ -440,7 +440,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
comp: InRealm, comp: InRealm,
) -> Rc<Promise> { ) -> Rc<Promise> {
// Step 1. // Step 1.
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
let global = self.global(); let global = self.global();
let window = global.as_window(); let window = global.as_window();

View file

@ -245,7 +245,7 @@ impl CallSetup {
if let Some(window) = global.downcast::<Window>() { if let Some(window) = global.downcast::<Window>() {
window.Document().ensure_safe_to_run_script_or_layout(); window.Document().ensure_safe_to_run_script_or_layout();
} }
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let aes = AutoEntryScript::new(&global); let aes = AutoEntryScript::new(&global);
let ais = callback.incumbent().map(AutoIncumbentScript::new); let ais = callback.incumbent().map(AutoIncumbentScript::new);

View file

@ -9,6 +9,7 @@ use crate::dom::bindings::iterable::{Iterable, IterableIterator};
use crate::dom::bindings::root::{Dom, DomRoot, Root}; use crate::dom::bindings::root::{Dom, DomRoot, Root};
use crate::dom::bindings::trace::JSTraceable; use crate::dom::bindings::trace::JSTraceable;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::realms::AlreadyInRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
use js::jsapi::{Heap, JSObject}; use js::jsapi::{Heap, JSObject};
use js::rust::HandleObject; use js::rust::HandleObject;
@ -22,7 +23,7 @@ where
U: DerivedFrom<GlobalScope>, U: DerivedFrom<GlobalScope>,
{ {
let global_scope = global.upcast(); let global_scope = global.upcast();
unsafe { T::WRAP(global_scope.get_cx(), global_scope, obj) } unsafe { T::WRAP(GlobalScope::get_cx(), global_scope, obj) }
} }
/// A struct to store a reference to the reflector of a DOM object. /// A struct to store a reference to the reflector of a DOM object.
@ -82,7 +83,8 @@ pub trait DomObject: JSTraceable + 'static {
where where
Self: Sized, Self: Sized,
{ {
GlobalScope::from_reflector(self) let realm = AlreadyInRealm::assert_for_cx(GlobalScope::get_cx());
GlobalScope::from_reflector(self, &realm)
} }
} }

View file

@ -352,7 +352,7 @@ pub fn read(
mut data: StructuredSerializedData, mut data: StructuredSerializedData,
rval: MutableHandleValue, rval: MutableHandleValue,
) -> Result<Vec<DomRoot<MessagePort>>, ()> { ) -> Result<Vec<DomRoot<MessagePort>>, ()> {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(&*global); let _ac = enter_realm(&*global);
let mut sc_holder = StructuredDataHolder::Read { let mut sc_holder = StructuredDataHolder::Read {
blobs: None, blobs: None,

View file

@ -238,8 +238,8 @@ impl BlobMethods for Blob {
// https://w3c.github.io/FileAPI/#text-method-algo // https://w3c.github.io/FileAPI/#text-method-algo
fn Text(&self) -> Rc<Promise> { fn Text(&self) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let in_realm_proof = AlreadyInRealm::assert(&global); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(&global, InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
let id = self.get_blob_url_id(); let id = self.get_blob_url_id();
global.read_file_async( global.read_file_async(
id, id,
@ -261,8 +261,8 @@ impl BlobMethods for Blob {
// https://w3c.github.io/FileAPI/#arraybuffer-method-algo // https://w3c.github.io/FileAPI/#arraybuffer-method-algo
fn ArrayBuffer(&self) -> Rc<Promise> { fn ArrayBuffer(&self) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let in_realm_proof = AlreadyInRealm::assert(&global); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(&global, InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
let id = self.get_blob_url_id(); let id = self.get_blob_url_id();
@ -272,7 +272,7 @@ impl BlobMethods for Blob {
Box::new(|promise, bytes| { Box::new(|promise, bytes| {
match bytes { match bytes {
Ok(b) => { Ok(b) => {
let cx = promise.global().get_cx(); let cx = GlobalScope::get_cx();
let result = run_array_buffer_data_algorithm(cx, b); let result = run_array_buffer_data_algorithm(cx, b);
match result { match result {

View file

@ -287,8 +287,8 @@ where
T: AsyncBluetoothListener + DomObject + 'static, T: AsyncBluetoothListener + DomObject + 'static,
F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>, F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID>,
{ {
let in_realm_proof = AlreadyInRealm::assert(&attribute.global()); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(&attribute.global(), InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
let result_uuid = if let Some(u) = uuid { let result_uuid = if let Some(u) = uuid {
// Step 1. // Step 1.
@ -528,7 +528,7 @@ impl From<BluetoothError> for Error {
impl BluetoothMethods for Bluetooth { impl BluetoothMethods for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
fn RequestDevice(&self, option: &RequestDeviceOptions, comp: InRealm) -> Rc<Promise> { fn RequestDevice(&self, option: &RequestDeviceOptions, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if (option.filters.is_some() && option.acceptAllDevices) || if (option.filters.is_some() && option.acceptAllDevices) ||
(option.filters.is_none() && !option.acceptAllDevices) (option.filters.is_none() && !option.acceptAllDevices)
@ -546,7 +546,7 @@ impl BluetoothMethods for Bluetooth {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-getavailability
fn GetAvailability(&self, comp: InRealm) -> Rc<Promise> { fn GetAvailability(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. We did not override the method // Step 1. We did not override the method
// Step 2 - 3. in handle_response // Step 2 - 3. in handle_response
let sender = response_async(&p, self); let sender = response_async(&p, self);

View file

@ -277,7 +277,7 @@ impl BluetoothDeviceMethods for BluetoothDevice {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements
fn WatchAdvertisements(&self, comp: InRealm) -> Rc<Promise> { fn WatchAdvertisements(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 1. // TODO: Step 1.
// Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function // Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function

View file

@ -137,7 +137,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
fn ReadValue(&self, comp: InRealm) -> Rc<Promise> { fn ReadValue(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -170,7 +170,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> { fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {
@ -221,7 +221,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications
fn StartNotifications(&self, comp: InRealm) -> Rc<Promise> { fn StartNotifications(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -258,7 +258,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-stopnotifications
fn StopNotifications(&self, comp: InRealm) -> Rc<Promise> { fn StopNotifications(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic, // TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic,

View file

@ -93,7 +93,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
fn ReadValue(&self, comp: InRealm) -> Rc<Promise> { fn ReadValue(&self, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Reads) {
@ -125,7 +125,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> { fn WriteValue(&self, value: ArrayBufferViewOrArrayBuffer, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) { if uuid_is_blocklisted(self.uuid.as_ref(), Blocklist::Writes) {

View file

@ -71,7 +71,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Connect(&self, comp: InRealm) -> Rc<Promise> { fn Connect(&self, comp: InRealm) -> Rc<Promise> {
// Step 1. // Step 1.
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let sender = response_async(&p, self); let sender = response_async(&p, self);
// TODO: Step 3: Check if the UA is currently using the Bluetooth system. // TODO: Step 3: Check if the UA is currently using the Bluetooth system.

View file

@ -17,7 +17,8 @@ impl Console {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn send_to_devtools(global: &GlobalScope, level: LogLevel, message: DOMString) { fn send_to_devtools(global: &GlobalScope, level: LogLevel, message: DOMString) {
if let Some(chan) = global.devtools_chan() { if let Some(chan) = global.devtools_chan() {
let caller = unsafe { describe_scripted_caller(*global.get_cx()) }.unwrap_or_default(); let caller =
unsafe { describe_scripted_caller(*GlobalScope::get_cx()) }.unwrap_or_default();
let console_message = ConsoleMessage { let console_message = ConsoleMessage {
message: String::from(message), message: String::from(message),
logLevel: level, logLevel: level,

View file

@ -154,7 +154,7 @@ fn create_html_element(
// Step 6. Recovering from exception. // Step 6. Recovering from exception.
let global = let global =
GlobalScope::current().unwrap_or_else(|| document.global()); GlobalScope::current().unwrap_or_else(|| document.global());
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
// Step 6.1.1 // Step 6.1.1
unsafe { unsafe {

View file

@ -140,11 +140,10 @@ impl CustomElementRegistry {
constructor: HandleObject, constructor: HandleObject,
prototype: MutableHandleValue, prototype: MutableHandleValue,
) -> ErrorResult { ) -> ErrorResult {
let global_scope = self.window.upcast::<GlobalScope>();
unsafe { unsafe {
// Step 10.1 // Step 10.1
if !JS_GetProperty( if !JS_GetProperty(
*global_scope.get_cx(), *GlobalScope::get_cx(),
constructor, constructor,
b"prototype\0".as_ptr() as *const _, b"prototype\0".as_ptr() as *const _,
prototype, prototype,
@ -166,7 +165,7 @@ impl CustomElementRegistry {
/// Steps 10.3, 10.4 /// Steps 10.3, 10.4
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_callbacks(&self, prototype: HandleObject) -> Fallible<LifecycleCallbacks> { unsafe fn get_callbacks(&self, prototype: HandleObject) -> Fallible<LifecycleCallbacks> {
let cx = self.window.get_cx(); let cx = GlobalScope::get_cx();
// Step 4 // Step 4
Ok(LifecycleCallbacks { Ok(LifecycleCallbacks {
@ -181,7 +180,7 @@ impl CustomElementRegistry {
/// Step 10.6 /// Step 10.6
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn get_observed_attributes(&self, constructor: HandleObject) -> Fallible<Vec<DOMString>> { fn get_observed_attributes(&self, constructor: HandleObject) -> Fallible<Vec<DOMString>> {
let cx = self.window.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut observed_attributes = UndefinedValue()); rooted!(in(*cx) let mut observed_attributes = UndefinedValue());
if unsafe { if unsafe {
!JS_GetProperty( !JS_GetProperty(
@ -254,7 +253,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
constructor_: Rc<CustomElementConstructor>, constructor_: Rc<CustomElementConstructor>,
options: &ElementDefinitionOptions, options: &ElementDefinitionOptions,
) -> ErrorResult { ) -> ErrorResult {
let cx = self.window.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let constructor = constructor_.callback()); rooted!(in(*cx) let constructor = constructor_.callback());
let name = LocalName::from(&*name); let name = LocalName::from(&*name);
@ -429,7 +428,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
// Step 1 // Step 1
if !is_valid_custom_element_name(&name) { if !is_valid_custom_element_name(&name) {
let promise = Promise::new_in_current_realm(&global_scope, comp); let promise = Promise::new_in_current_realm(comp);
promise.reject_native(&DOMException::new(&global_scope, DOMErrorName::SyntaxError)); promise.reject_native(&DOMException::new(&global_scope, DOMErrorName::SyntaxError));
return promise; return promise;
} }
@ -437,12 +436,12 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
// Step 2 // Step 2
if let Some(definition) = self.definitions.borrow().get(&LocalName::from(&*name)) { if let Some(definition) = self.definitions.borrow().get(&LocalName::from(&*name)) {
unsafe { unsafe {
let cx = global_scope.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut constructor = UndefinedValue()); rooted!(in(*cx) let mut constructor = UndefinedValue());
definition definition
.constructor .constructor
.to_jsval(*cx, constructor.handle_mut()); .to_jsval(*cx, constructor.handle_mut());
let promise = Promise::new_in_current_realm(&global_scope, comp); let promise = Promise::new_in_current_realm(comp);
promise.resolve_native(&constructor.get()); promise.resolve_native(&constructor.get());
return promise; return promise;
} }
@ -453,7 +452,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
// Steps 4, 5 // Steps 4, 5
let promise = map.get(&name).cloned().unwrap_or_else(|| { let promise = map.get(&name).cloned().unwrap_or_else(|| {
let promise = Promise::new_in_current_realm(&global_scope, comp); let promise = Promise::new_in_current_realm(comp);
map.insert(name, promise.clone()); map.insert(name, promise.clone());
promise promise
}); });
@ -543,7 +542,7 @@ impl CustomElementDefinition {
prefix: Option<Prefix>, prefix: Option<Prefix>,
) -> Fallible<DomRoot<Element>> { ) -> Fallible<DomRoot<Element>> {
let window = document.window(); let window = document.window();
let cx = window.get_cx(); let cx = GlobalScope::get_cx();
// Step 2 // Step 2
rooted!(in(*cx) let constructor = ObjectValue(self.constructor.callback())); rooted!(in(*cx) let constructor = ObjectValue(self.constructor.callback()));
rooted!(in(*cx) let mut element = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut element = ptr::null_mut::<JSObject>());
@ -662,7 +661,7 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
// Step 8.exception.3 // Step 8.exception.3
let global = GlobalScope::current().expect("No current global"); let global = GlobalScope::current().expect("No current global");
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
let ar = enter_realm(&*global); let ar = enter_realm(&*global);
throw_dom_exception(cx, &global, error); throw_dom_exception(cx, &global, error);
@ -686,7 +685,7 @@ fn run_upgrade_constructor(
element: &Element, element: &Element,
) -> ErrorResult { ) -> ErrorResult {
let window = window_from_node(element); let window = window_from_node(element);
let cx = window.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let constructor_val = ObjectValue(constructor.callback())); rooted!(in(*cx) let constructor_val = ObjectValue(constructor.callback()));
rooted!(in(*cx) let mut element_val = UndefinedValue()); rooted!(in(*cx) let mut element_val = UndefinedValue());
unsafe { unsafe {
@ -909,7 +908,7 @@ impl CustomElementReactionStack {
return; return;
} }
let cx = element.global().get_cx(); let cx = GlobalScope::get_cx();
// We might be here during HTML parsing, rather than // We might be here during HTML parsing, rather than
// during Javscript execution, and so we typically aren't // during Javscript execution, and so we typically aren't
// already in a realm here. // already in a realm here.

View file

@ -46,7 +46,7 @@ pub struct DissimilarOriginWindow {
impl DissimilarOriginWindow { impl DissimilarOriginWindow {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn new(global_to_clone_from: &GlobalScope, window_proxy: &WindowProxy) -> DomRoot<Self> { pub fn new(global_to_clone_from: &GlobalScope, window_proxy: &WindowProxy) -> DomRoot<Self> {
let cx = global_to_clone_from.get_cx(); let cx = GlobalScope::get_cx();
let win = Box::new(Self { let win = Box::new(Self {
globalscope: GlobalScope::new_inherited( globalscope: GlobalScope::new_inherited(
PipelineId::new(), PipelineId::new(),

View file

@ -3573,9 +3573,8 @@ impl Document {
// https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen // https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
pub fn enter_fullscreen(&self, pending: &Element) -> Rc<Promise> { pub fn enter_fullscreen(&self, pending: &Element) -> Rc<Promise> {
// Step 1 // Step 1
let in_realm_proof = AlreadyInRealm::assert(&self.global()); let in_realm_proof = AlreadyInRealm::assert();
let promise = let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
Promise::new_in_current_realm(&self.global(), InRealm::Already(&in_realm_proof));
let mut error = false; let mut error = false;
// Step 4 // Step 4
@ -3642,8 +3641,8 @@ impl Document {
pub fn exit_fullscreen(&self) -> Rc<Promise> { pub fn exit_fullscreen(&self) -> Rc<Promise> {
let global = self.global(); let global = self.global();
// Step 1 // Step 1
let in_realm_proof = AlreadyInRealm::assert(&global); let in_realm_proof = AlreadyInRealm::assert();
let promise = Promise::new_in_current_realm(&global, InRealm::Already(&in_realm_proof)); let promise = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
// Step 2 // Step 2
if self.fullscreen_element.get().is_none() { if self.fullscreen_element.get().is_none() {
promise.reject_error(Error::Type(String::from("fullscreen is null"))); promise.reject_error(Error::Type(String::from("fullscreen is null")));

View file

@ -222,10 +222,10 @@ impl EventSourceContext {
// Steps 4-5 // Steps 4-5
let event = { let event = {
let _ac = enter_realm(&*event_source); let _ac = enter_realm(&*event_source);
rooted!(in(*event_source.global().get_cx()) let mut data = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut data = UndefinedValue());
unsafe { unsafe {
self.data self.data
.to_jsval(*event_source.global().get_cx(), data.handle_mut()) .to_jsval(*GlobalScope::get_cx(), data.handle_mut())
}; };
MessageEvent::new( MessageEvent::new(
&*event_source.global(), &*event_source.global(),

View file

@ -184,7 +184,7 @@ impl CompiledEventListener {
CommonEventHandler::ErrorEventHandler(ref handler) => { CommonEventHandler::ErrorEventHandler(ref handler) => {
if let Some(event) = event.downcast::<ErrorEvent>() { if let Some(event) = event.downcast::<ErrorEvent>() {
if object.is::<Window>() || object.is::<WorkerGlobalScope>() { if object.is::<Window>() || object.is::<WorkerGlobalScope>() {
let cx = object.global().get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let error = event.Error(cx)); rooted!(in(*cx) let error = event.Error(cx));
let return_value = handler.Call_( let return_value = handler.Call_(
object, object,
@ -242,7 +242,7 @@ impl CompiledEventListener {
CommonEventHandler::EventHandler(ref handler) => { CommonEventHandler::EventHandler(ref handler) => {
if let Ok(value) = handler.Call_(object, event, exception_handle) { if let Ok(value) = handler.Call_(object, event, exception_handle) {
let cx = object.global().get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let value = value); rooted!(in(*cx) let value = value);
let value = value.handle(); let value = value.handle();
@ -525,7 +525,7 @@ impl EventTarget {
let is_error = ty == &atom!("error") && self.is::<Window>(); let is_error = ty == &atom!("error") && self.is::<Window>();
let args = if is_error { ERROR_ARG_NAMES } else { ARG_NAMES }; let args = if is_error { ERROR_ARG_NAMES } else { ARG_NAMES };
let cx = window.get_cx(); let cx = GlobalScope::get_cx();
let options = unsafe { let options = unsafe {
CompileOptionsWrapper::new(*cx, &handler.url.to_string(), handler.line as u32) CompileOptionsWrapper::new(*cx, &handler.url.to_string(), handler.line as u32)
}; };
@ -592,7 +592,7 @@ impl EventTarget {
where where
T: CallbackContainer, T: CallbackContainer,
{ {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let event_listener = listener.map(|listener| { let event_listener = listener.map(|listener| {
InlineEventListener::Compiled(CommonEventHandler::EventHandler(unsafe { InlineEventListener::Compiled(CommonEventHandler::EventHandler(unsafe {
@ -607,7 +607,7 @@ impl EventTarget {
where where
T: CallbackContainer, T: CallbackContainer,
{ {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let event_listener = listener.map(|listener| { let event_listener = listener.map(|listener| {
InlineEventListener::Compiled(CommonEventHandler::ErrorEventHandler(unsafe { InlineEventListener::Compiled(CommonEventHandler::ErrorEventHandler(unsafe {
@ -625,7 +625,7 @@ impl EventTarget {
) where ) where
T: CallbackContainer, T: CallbackContainer,
{ {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let event_listener = listener.map(|listener| { let event_listener = listener.map(|listener| {
InlineEventListener::Compiled(CommonEventHandler::BeforeUnloadEventHandler(unsafe { InlineEventListener::Compiled(CommonEventHandler::BeforeUnloadEventHandler(unsafe {
@ -637,7 +637,7 @@ impl EventTarget {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> { pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let listener = self.get_inline_event_listener(&Atom::from(ty)); let listener = self.get_inline_event_listener(&Atom::from(ty));
unsafe { unsafe {
listener.map(|listener| { listener.map(|listener| {

View file

@ -258,7 +258,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(), GlobalScope::get_cx(),
data, data,
&blob_contents, &blob_contents,
) )

View file

@ -1215,7 +1215,7 @@ impl GlobalScope {
return; return;
} }
rooted!(in(*global.get_cx()) let mut message = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut message = UndefinedValue());
// Step 10.3 StructuredDeserialize(serialized, targetRealm). // Step 10.3 StructuredDeserialize(serialized, targetRealm).
if let Ok(ports) = structuredclone::read(&global, data, message.handle_mut()) { if let Ok(ports) = structuredclone::read(&global, data, message.handle_mut()) {
@ -1269,7 +1269,7 @@ impl GlobalScope {
}; };
if let Some((dom_port, PortMessageTask { origin, data })) = should_dispatch { if let Some((dom_port, PortMessageTask { origin, data })) = should_dispatch {
// Substep 3-4 // Substep 3-4
rooted!(in(*self.get_cx()) let mut message_clone = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut message_clone = UndefinedValue());
if let Ok(ports) = structuredclone::read(self, data, message_clone.handle_mut()) { if let Ok(ports) = structuredclone::read(self, data, message_clone.handle_mut()) {
// Substep 6 // Substep 6
// Dispatch the event, using the dom message-port. // Dispatch the event, using the dom message-port.
@ -2120,7 +2120,7 @@ impl GlobalScope {
/// Returns the global scope of the realm that the given DOM object's reflector /// Returns the global scope of the realm that the given DOM object's reflector
/// was created in. /// was created in.
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn from_reflector<T: DomObject>(reflector: &T) -> DomRoot<Self> { pub fn from_reflector<T: DomObject>(reflector: &T, _realm: &AlreadyInRealm) -> DomRoot<Self> {
unsafe { GlobalScope::from_object(*reflector.reflector().get_jsobject()) } unsafe { GlobalScope::from_object(*reflector.reflector().get_jsobject()) }
} }
@ -2221,7 +2221,7 @@ impl GlobalScope {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn get_cx(&self) -> SafeJSContext { pub fn get_cx() -> SafeJSContext {
unsafe { SafeJSContext::from_ptr(Runtime::get()) } unsafe { SafeJSContext::from_ptr(Runtime::get()) }
} }
@ -2603,7 +2603,7 @@ impl GlobalScope {
Some(metadata), Some(metadata),
self.time_profiler_chan().clone(), self.time_profiler_chan().clone(),
|| { || {
let cx = self.get_cx(); let cx = GlobalScope::get_cx();
let ar = enter_realm(&*self); let ar = enter_realm(&*self);
@ -2733,8 +2733,8 @@ impl GlobalScope {
image: ImageBitmapSource, image: ImageBitmapSource,
options: &ImageBitmapOptions, options: &ImageBitmapOptions,
) -> Rc<Promise> { ) -> Rc<Promise> {
let in_realm_proof = AlreadyInRealm::assert(&self); let in_realm_proof = AlreadyInRealm::assert();
let p = Promise::new_in_current_realm(&self, InRealm::Already(&in_realm_proof)); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
if options.resizeWidth.map_or(false, |w| w == 0) { if options.resizeWidth.map_or(false, |w| w == 0) {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;
@ -2857,7 +2857,7 @@ impl GlobalScope {
// Only perform the checkpoint if we're not shutting down. // Only perform the checkpoint if we're not shutting down.
if self.can_continue_running() { if self.can_continue_running() {
self.microtask_queue.checkpoint( self.microtask_queue.checkpoint(
self.get_cx(), GlobalScope::get_cx(),
|_| Some(DomRoot::from_ref(self)), |_| Some(DomRoot::from_ref(self)),
vec![DomRoot::from_ref(self)], vec![DomRoot::from_ref(self)],
); );
@ -2866,7 +2866,7 @@ impl GlobalScope {
/// Enqueue a microtask for subsequent execution. /// Enqueue a microtask for subsequent execution.
pub fn enqueue_microtask(&self, job: Microtask) { pub fn enqueue_microtask(&self, job: Microtask) {
self.microtask_queue.enqueue(job, self.get_cx()); self.microtask_queue.enqueue(job, GlobalScope::get_cx());
} }
/// Create a new sender/receiver pair that can be used to implement an on-demand /// Create a new sender/receiver pair that can be used to implement an on-demand

View file

@ -100,7 +100,7 @@ impl GPUMethods for GPU {
// https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter // https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter
fn RequestAdapter(&self, options: &GPURequestAdapterOptions, comp: InRealm) -> Rc<Promise> { fn RequestAdapter(&self, options: &GPURequestAdapterOptions, comp: InRealm) -> Rc<Promise> {
let global = &self.global(); let global = &self.global();
let promise = Promise::new_in_current_realm(global, comp); let promise = Promise::new_in_current_realm(comp);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let power_preference = match options.powerPreference { let power_preference = match options.powerPreference {
Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower, Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower,

View file

@ -78,7 +78,7 @@ impl GPUAdapterMethods for GPUAdapter {
/// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice /// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice
fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InRealm) -> Rc<Promise> { fn RequestDevice(&self, descriptor: &GPUDeviceDescriptor, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let mut features = wgt::Features::empty(); let mut features = wgt::Features::empty();
for &ext in descriptor.extensions.iter() { for &ext in descriptor.extensions.iter() {

View file

@ -6,7 +6,6 @@ use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{GPUBufferMethods, GPUSize64}; use crate::dom::bindings::codegen::Bindings::GPUBufferBinding::{GPUBufferMethods, GPUSize64};
use crate::dom::bindings::codegen::Bindings::GPUMapModeBinding::GPUMapModeConstants; use crate::dom::bindings::codegen::Bindings::GPUMapModeBinding::GPUMapModeConstants;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
@ -134,7 +133,7 @@ impl GPUBufferMethods for GPUBuffer {
#[allow(unsafe_code)] #[allow(unsafe_code)]
/// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap /// https://gpuweb.github.io/gpuweb/#dom-gpubuffer-unmap
fn Unmap(&self) { fn Unmap(&self) {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
// Step 1 // Step 1
match self.state.get() { match self.state.get() {
GPUBufferState::Unmapped | GPUBufferState::Destroyed => { GPUBufferState::Unmapped | GPUBufferState::Destroyed => {
@ -209,7 +208,7 @@ impl GPUBufferMethods for GPUBuffer {
size: Option<GPUSize64>, size: Option<GPUSize64>,
comp: InRealm, comp: InRealm,
) -> Rc<Promise> { ) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
let range_size = if let Some(s) = size { let range_size = if let Some(s) = size {
s s
} else if offset >= self.size { } else if offset >= self.size {

View file

@ -357,7 +357,7 @@ impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-lost /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-lost
fn Lost(&self, comp: InRealm) -> Rc<Promise> { fn Lost(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
*self.lost_promise.borrow_mut() = Some(promise.clone()); *self.lost_promise.borrow_mut() = Some(promise.clone());
promise promise
} }
@ -1117,7 +1117,7 @@ impl GPUDeviceMethods for GPUDevice {
/// https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-poperrorscope
fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> { fn PopErrorScope(&self, comp: InRealm) -> Rc<Promise> {
let mut context = self.scope_context.borrow_mut(); let mut context = self.scope_context.borrow_mut();
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
let scope_id = let scope_id =
if let Some(meta) = context.scope_stack.iter().rev().find(|m| !m.popped.get()) { if let Some(meta) = context.scope_stack.iter().rev().find(|m| !m.popped.get()) {
meta.popped.set(true); meta.popped.set(true);

View file

@ -117,7 +117,7 @@ impl History {
blobs: None, blobs: None,
}; };
let global_scope = self.window.upcast::<GlobalScope>(); let global_scope = self.window.upcast::<GlobalScope>();
rooted!(in(*global_scope.get_cx()) let mut state = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut state = UndefinedValue());
if let Err(_) = structuredclone::read(&global_scope, data, state.handle_mut()) { if let Err(_) = structuredclone::read(&global_scope, data, state.handle_mut()) {
warn!("Error reading structuredclone data"); warn!("Error reading structuredclone data");
} }

View file

@ -46,6 +46,7 @@ use crate::fetch::create_a_potential_cors_request;
use crate::image_listener::{generate_cache_listener_for_element, ImageCacheListener}; use crate::image_listener::{generate_cache_listener_for_element, ImageCacheListener};
use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::enter_realm;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
use app_units::{Au, AU_PER_PX}; use app_units::{Au, AU_PER_PX};
@ -56,6 +57,7 @@ use html5ever::{LocalName, Prefix, QualName};
use ipc_channel::ipc; use ipc_channel::ipc;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::jsapi::JSAutoRealm;
use mime::{self, Mime}; use mime::{self, Mime};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image::base::{Image, ImageMetadata};
@ -1353,6 +1355,13 @@ impl MicrotaskRunnable for ImageElementMicrotask {
}, },
} }
} }
fn enter_realm(&self) -> JSAutoRealm {
match self {
&ImageElementMicrotask::StableStateUpdateImageDataTask { ref elem, .. } |
&ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } => enter_realm(&**elem),
}
}
} }
pub trait LayoutHTMLImageElementHelpers { pub trait LayoutHTMLImageElementHelpers {

View file

@ -833,7 +833,7 @@ impl HTMLInputElement {
} }
// Rust's regex is not compatible, we need to use mozjs RegExp. // Rust's regex is not compatible, we need to use mozjs RegExp.
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(self); let _ac = enter_realm(self);
rooted!(in(*cx) let mut pattern = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut pattern = ptr::null_mut::<JSObject>());

View file

@ -62,7 +62,7 @@ use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::{create_a_potential_cors_request, FetchCanceller}; use crate::fetch::{create_a_potential_cors_request, FetchCanceller};
use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::InRealm; use crate::realms::{enter_realm, InRealm};
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -74,6 +74,7 @@ use html5ever::{LocalName, Prefix};
use http::header::{self, HeaderMap, HeaderValue}; use http::header::{self, HeaderMap, HeaderValue};
use ipc_channel::ipc; use ipc_channel::ipc;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use js::jsapi::JSAutoRealm;
use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward, WindowGLContext}; use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward, WindowGLContext};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use net_traits::request::Destination; use net_traits::request::Destination;
@ -2112,7 +2113,7 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
// https://html.spec.whatwg.org/multipage/#dom-media-play // https://html.spec.whatwg.org/multipage/#dom-media-play
fn Play(&self, comp: InRealm) -> Rc<Promise> { fn Play(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// Step 1. // Step 1.
// FIXME(nox): Reject promise if not allowed to play. // FIXME(nox): Reject promise if not allowed to play.
@ -2506,6 +2507,14 @@ impl MicrotaskRunnable for MediaElementMicrotask {
}, },
} }
} }
fn enter_realm(&self) -> JSAutoRealm {
match self {
&MediaElementMicrotask::ResourceSelectionTask { ref elem, .. } |
&MediaElementMicrotask::PauseIfNotInDocumentTask { ref elem } |
&MediaElementMicrotask::SeekedTask { ref elem, .. } => enter_realm(&**elem),
}
}
} }
enum Resource { enum Resource {

View file

@ -110,7 +110,7 @@ unsafe extern "C" fn off_thread_compilation_callback(
task!(off_thread_compile_continue: move || { task!(off_thread_compile_continue: move || {
let elem = script_element.root(); let elem = script_element.root();
let global = elem.global(); let global = elem.global();
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let compiled_script = FinishOffThreadStencil(*cx, token.0, ptr::null_mut()); let compiled_script = FinishOffThreadStencil(*cx, token.0, ptr::null_mut());
@ -418,7 +418,7 @@ impl FetchResponseListener for ClassicContext {
let elem = self.elem.root(); let elem = self.elem.root();
let global = elem.global(); let global = elem.global();
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let options = unsafe { CompileOptionsWrapper::new(*cx, final_url.as_str(), 1) }; let options = unsafe { CompileOptionsWrapper::new(*cx, final_url.as_str(), 1) };
@ -1053,7 +1053,7 @@ impl HTMLScriptElement {
} else { } else {
self.line_number as u32 self.line_number as u32
}; };
rooted!(in(*window.get_cx()) let mut rval = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut rval = UndefinedValue());
let global = window.upcast::<GlobalScope>(); let global = window.upcast::<GlobalScope>();
global.evaluate_script_on_global_with_result( global.evaluate_script_on_global_with_result(
&script.code, &script.code,
@ -1108,7 +1108,7 @@ impl HTMLScriptElement {
.map(|record| record.handle()); .map(|record| record.handle());
if let Some(record) = record { if let Some(record) = record {
rooted!(in(*global.get_cx()) let mut rval = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut rval = UndefinedValue());
let evaluated = let evaluated =
module_tree.execute_module(global, record, rval.handle_mut().into()); module_tree.execute_module(global, record, rval.handle_mut().into());

View file

@ -39,7 +39,7 @@ impl ImageData {
) -> Fallible<DomRoot<ImageData>> { ) -> Fallible<DomRoot<ImageData>> {
let len = width * height * 4; let len = width * height * 4;
unsafe { unsafe {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in (*cx) let mut js_object = ptr::null_mut::<JSObject>()); rooted!(in (*cx) let mut js_object = ptr::null_mut::<JSObject>());
if let Some(ref mut d) = data { if let Some(ref mut d) = data {
d.resize(len as usize, 0); d.resize(len as usize, 0);
@ -60,7 +60,7 @@ impl ImageData {
jsobject: *mut JSObject, jsobject: *mut JSObject,
) -> Fallible<DomRoot<ImageData>> { ) -> Fallible<DomRoot<ImageData>> {
// checking jsobject type // checking jsobject type
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
typedarray!(in(*cx) let array_res: Uint8ClampedArray = jsobject); typedarray!(in(*cx) let array_res: Uint8ClampedArray = jsobject);
let array = array_res.map_err(|_| { let array = array_res.map_err(|_| {
Error::Type("Argument to Image data is not an Uint8ClampedArray".to_owned()) Error::Type("Argument to Image data is not an Uint8ClampedArray".to_owned())
@ -111,7 +111,7 @@ impl ImageData {
}); });
let len = width * height * 4; let len = width * height * 4;
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>()); rooted!(in (*cx) let mut array = ptr::null_mut::<JSObject>());
Uint8ClampedArray::create(*cx, CreateWith::Length(len as usize), array.handle_mut()) Uint8ClampedArray::create(*cx, CreateWith::Length(len as usize), array.handle_mut())
.unwrap(); .unwrap();

View file

@ -44,7 +44,7 @@ impl MediaDevicesMethods for MediaDevices {
/// https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia /// https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn GetUserMedia(&self, constraints: &MediaStreamConstraints, comp: InRealm) -> Rc<Promise> { fn GetUserMedia(&self, constraints: &MediaStreamConstraints, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let media = ServoMedia::get().unwrap(); let media = ServoMedia::get().unwrap();
let stream = MediaStream::new(&self.global()); let stream = MediaStream::new(&self.global());
if let Some(constraints) = convert_constraints(&constraints.audio) { if let Some(constraints) = convert_constraints(&constraints.audio) {
@ -67,9 +67,8 @@ impl MediaDevicesMethods for MediaDevices {
/// https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices /// https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices
fn EnumerateDevices(&self) -> Rc<Promise> { fn EnumerateDevices(&self) -> Rc<Promise> {
// Step 1. // Step 1.
let global = self.global(); let in_realm_proof = AlreadyInRealm::assert();
let in_realm_proof = AlreadyInRealm::assert(&global); let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof));
let p = Promise::new_in_current_realm(&global, InRealm::Already(&in_realm_proof));
// Step 2. // Step 2.
// XXX These steps should be run in parallel. // XXX These steps should be run in parallel.

View file

@ -43,7 +43,7 @@ impl NavigationPreloadManager {
impl NavigationPreloadManagerMethods for NavigationPreloadManager { impl NavigationPreloadManagerMethods for NavigationPreloadManager {
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-enable // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-enable
fn Enable(&self, comp: InRealm) -> Rc<Promise> { fn Enable(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&*self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -65,7 +65,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-disable // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-disable
fn Disable(&self, comp: InRealm) -> Rc<Promise> { fn Disable(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&*self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -87,7 +87,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-setheadervalue // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-setheadervalue
fn SetHeaderValue(&self, value: ByteString, comp: InRealm) -> Rc<Promise> { fn SetHeaderValue(&self, value: ByteString, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&*self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// 2. // 2.
if self.serviceworker_registration.is_active() { if self.serviceworker_registration.is_active() {
@ -109,7 +109,7 @@ impl NavigationPreloadManagerMethods for NavigationPreloadManager {
// https://w3c.github.io/ServiceWorker/#navigation-preload-manager-getstate // https://w3c.github.io/ServiceWorker/#navigation-preload-manager-getstate
fn GetState(&self, comp: InRealm) -> Rc<Promise> { fn GetState(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&*self.global(), comp); let promise = Promise::new_in_current_realm(comp);
// 2. // 2.
let mut state = NavigationPreloadState::empty(); let mut state = NavigationPreloadState::empty();

View file

@ -121,7 +121,7 @@ impl OfflineAudioContextMethods for OfflineAudioContext {
// https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering // https://webaudio.github.io/web-audio-api/#dom-offlineaudiocontext-startrendering
fn StartRendering(&self, comp: InRealm) -> Rc<Promise> { fn StartRendering(&self, comp: InRealm) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(&self.global(), comp); let promise = Promise::new_in_current_realm(comp);
if self.rendering_started.get() { if self.rendering_started.get() {
promise.reject_error(Error::InvalidState); promise.reject_error(Error::InvalidState);
return promise; return promise;

View file

@ -252,7 +252,7 @@ impl PaintWorkletGlobalScope {
name, size_in_px.width, size_in_px.height, device_pixel_ratio name, size_in_px.width, size_in_px.height, device_pixel_ratio
); );
let cx = self.worklet_global.get_cx(); let cx = WorkletGlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, self.worklet_global.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, self.worklet_global.reflector().get_jsobject().get());
// TODO: Steps 1-2.1. // TODO: Steps 1-2.1.
@ -517,7 +517,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
/// <https://drafts.css-houdini.org/css-paint-api/#dom-paintworkletglobalscope-registerpaint> /// <https://drafts.css-houdini.org/css-paint-api/#dom-paintworkletglobalscope-registerpaint>
fn RegisterPaint(&self, name: DOMString, paint_ctor: Rc<VoidFunction>) -> Fallible<()> { fn RegisterPaint(&self, name: DOMString, paint_ctor: Rc<VoidFunction>) -> Fallible<()> {
let name = Atom::from(name); let name = Atom::from(name);
let cx = self.worklet_global.get_cx(); let cx = WorkletGlobalScope::get_cx();
rooted!(in(*cx) let paint_obj = paint_ctor.callback_holder().get()); rooted!(in(*cx) let paint_obj = paint_ctor.callback_holder().get());
rooted!(in(*cx) let paint_val = ObjectValue(paint_obj.get())); rooted!(in(*cx) let paint_val = ObjectValue(paint_obj.get()));

View file

@ -87,8 +87,8 @@ impl Permissions {
let p = match promise { let p = match promise {
Some(promise) => promise, Some(promise) => promise,
None => { None => {
let in_realm_proof = AlreadyInRealm::assert(&self.global()); let in_realm_proof = AlreadyInRealm::assert();
Promise::new_in_current_realm(&self.global(), InRealm::Already(&in_realm_proof)) Promise::new_in_current_realm(InRealm::Already(&in_realm_proof))
}, },
}; };

View file

@ -88,11 +88,11 @@ impl Promise {
pub fn new(global: &GlobalScope) -> Rc<Promise> { pub fn new(global: &GlobalScope) -> Rc<Promise> {
let realm = enter_realm(&*global); let realm = enter_realm(&*global);
let comp = InRealm::Entered(&realm); let comp = InRealm::Entered(&realm);
Promise::new_in_current_realm(global, comp) Promise::new_in_current_realm(comp)
} }
pub fn new_in_current_realm(global: &GlobalScope, _comp: InRealm) -> Rc<Promise> { pub fn new_in_current_realm(_comp: InRealm) -> Rc<Promise> {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>()); rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>());
Promise::create_js_promise(cx, obj.handle_mut()); Promise::create_js_promise(cx, obj.handle_mut());
Promise::new_with_js_promise(obj.handle(), cx) Promise::new_with_js_promise(obj.handle(), cx)
@ -100,7 +100,7 @@ impl Promise {
#[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 = GlobalScope::get_cx();
Promise::new_with_js_promise(self.reflector().get_jsobject(), cx) Promise::new_with_js_promise(self.reflector().get_jsobject(), cx)
} }
@ -172,7 +172,7 @@ impl Promise {
where where
T: ToJSValConvertible, T: ToJSValConvertible,
{ {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(&*self); let _ac = enter_realm(&*self);
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
@ -195,7 +195,7 @@ impl Promise {
where where
T: ToJSValConvertible, T: ToJSValConvertible,
{ {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(&*self); let _ac = enter_realm(&*self);
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
@ -206,7 +206,7 @@ impl Promise {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn reject_error(&self, error: Error) { pub fn reject_error(&self, error: Error) {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let _ac = enter_realm(&*self); let _ac = enter_realm(&*self);
rooted!(in(*cx) let mut v = UndefinedValue()); rooted!(in(*cx) let mut v = UndefinedValue());
unsafe { unsafe {
@ -245,7 +245,7 @@ impl Promise {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn append_native_handler(&self, handler: &PromiseNativeHandler, _comp: InRealm) { pub fn append_native_handler(&self, handler: &PromiseNativeHandler, _comp: InRealm) {
let _ais = AutoEntryScript::new(&*handler.global()); let _ais = AutoEntryScript::new(&*handler.global());
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let resolve_func = rooted!(in(*cx) let resolve_func =
create_native_handler_function(*cx, create_native_handler_function(*cx,
handler.reflector().get_jsobject(), handler.reflector().get_jsobject(),

View file

@ -120,7 +120,7 @@ impl ReadableStream {
) -> DomRoot<ReadableStream> { ) -> DomRoot<ReadableStream> {
let _ar = enter_realm(global); let _ar = enter_realm(global);
let _ais = AutoIncumbentScript::new(global); let _ais = AutoIncumbentScript::new(global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let source = Rc::new(ExternalUnderlyingSourceController::new(source)); let source = Rc::new(ExternalUnderlyingSourceController::new(source));
@ -157,7 +157,7 @@ impl ReadableStream {
pub fn enqueue_native(&self, bytes: Vec<u8>) { pub fn enqueue_native(&self, bytes: Vec<u8>) {
let global = self.global(); let global = self.global();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let handle = unsafe { self.js_stream.handle() }; let handle = unsafe { self.js_stream.handle() };
@ -171,7 +171,7 @@ impl ReadableStream {
pub fn error_native(&self, error: Error) { pub fn error_native(&self, error: Error) {
let global = self.global(); let global = self.global();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let mut js_error = UndefinedValue()); rooted!(in(*cx) let mut js_error = UndefinedValue());
@ -188,7 +188,7 @@ impl ReadableStream {
pub fn close_native(&self) { pub fn close_native(&self) {
let global = self.global(); let global = self.global();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let handle = unsafe { self.js_stream.handle() }; let handle = unsafe { self.js_stream.handle() };
@ -223,7 +223,7 @@ impl ReadableStream {
let global = self.global(); let global = self.global();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let reader = ReadableStreamGetReader( rooted!(in(*cx) let reader = ReadableStreamGetReader(
@ -253,7 +253,7 @@ impl ReadableStream {
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let _aes = AutoEntryScript::new(&*global); let _aes = AutoEntryScript::new(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let promise_obj = ReadableStreamDefaultReaderRead( rooted!(in(*cx) let promise_obj = ReadableStreamDefaultReaderRead(
@ -276,7 +276,7 @@ impl ReadableStream {
let global = self.global(); let global = self.global();
let _ar = enter_realm(&*global); let _ar = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
ReadableStreamReaderReleaseLock(*cx, self.js_reader.handle()); ReadableStreamReaderReleaseLock(*cx, self.js_reader.handle());
@ -293,7 +293,7 @@ impl ReadableStream {
} }
// Otherwise, still double-check that script didn't lock the stream. // Otherwise, still double-check that script didn't lock the stream.
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let mut locked_or_disturbed = false; let mut locked_or_disturbed = false;
unsafe { unsafe {
@ -306,7 +306,7 @@ impl ReadableStream {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn is_disturbed(&self) -> bool { pub fn is_disturbed(&self) -> bool {
// Check that script didn't disturb the stream. // Check that script didn't disturb the stream.
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
let mut locked_or_disturbed = false; let mut locked_or_disturbed = false;
unsafe { unsafe {

View file

@ -135,7 +135,7 @@ impl RTCDataChannel {
pub fn on_error(&self, error: WebRtcError) { pub fn on_error(&self, error: WebRtcError) {
let global = self.global(); let global = self.global();
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
let init = RTCErrorInit { let init = RTCErrorInit {
errorDetail: RTCErrorDetailType::Data_channel_failure, errorDetail: RTCErrorDetailType::Data_channel_failure,
@ -157,7 +157,7 @@ impl RTCDataChannel {
pub fn on_message(&self, channel_message: DataChannelMessage) { pub fn on_message(&self, channel_message: DataChannelMessage) {
unsafe { unsafe {
let global = self.global(); let global = self.global();
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue()); rooted!(in(*cx) let mut message = UndefinedValue());

View file

@ -548,7 +548,7 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addicecandidate
fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> { fn AddIceCandidate(&self, candidate: &RTCIceCandidateInit, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() { if candidate.sdpMid.is_none() && candidate.sdpMLineIndex.is_none() {
p.reject_error(Error::Type(format!( p.reject_error(Error::Type(format!(
"one of sdpMid and sdpMLineIndex must be set" "one of sdpMid and sdpMLineIndex must be set"
@ -583,7 +583,7 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer
fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm) -> Rc<Promise> { fn CreateOffer(&self, _options: &RTCOfferOptions, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;
@ -595,7 +595,7 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer
fn CreateAnswer(&self, _options: &RTCAnswerOptions, comp: InRealm) -> Rc<Promise> { fn CreateAnswer(&self, _options: &RTCAnswerOptions, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
if self.closed.get() { if self.closed.get() {
p.reject_error(Error::InvalidState); p.reject_error(Error::InvalidState);
return p; return p;
@ -618,7 +618,7 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setlocaldescription /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setlocaldescription
fn SetLocalDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> { fn SetLocalDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> {
// XXXManishearth validate the current state // XXXManishearth validate the current state
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let this = Trusted::new(self); let this = Trusted::new(self);
let desc: SessionDescription = desc.into(); let desc: SessionDescription = desc.into();
let trusted_promise = TrustedPromise::new(p.clone()); let trusted_promise = TrustedPromise::new(p.clone());
@ -651,7 +651,7 @@ impl RTCPeerConnectionMethods for RTCPeerConnection {
/// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setremotedescription /// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-setremotedescription
fn SetRemoteDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> { fn SetRemoteDescription(&self, desc: &RTCSessionDescriptionInit, comp: InRealm) -> Rc<Promise> {
// XXXManishearth validate the current state // XXXManishearth validate the current state
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
let this = Trusted::new(self); let this = Trusted::new(self);
let desc: SessionDescription = desc.into(); let desc: SessionDescription = desc.into();
let trusted_promise = TrustedPromise::new(p.clone()); let trusted_promise = TrustedPromise::new(p.clone());

View file

@ -70,7 +70,7 @@ impl ServiceWorkerContainerMethods for ServiceWorkerContainer {
let global = self.client.global(); let global = self.client.global();
// A: Step 1 // A: Step 1
let promise = Promise::new_in_current_realm(&*global, comp); let promise = Promise::new_in_current_realm(comp);
let USVString(ref script_url) = script_url; let USVString(ref script_url) = script_url;
// A: Step 3 // A: Step 3

View file

@ -34,6 +34,7 @@ use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::text::Text; use crate::dom::text::Text;
use crate::dom::virtualmethods::vtable_for; use crate::dom::virtualmethods::vtable_for;
use crate::network_listener::PreInvoke; use crate::network_listener::PreInvoke;
use crate::realms::enter_realm;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use content_security_policy::{self as csp, CspList}; use content_security_policy::{self as csp, CspList};
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -828,6 +829,8 @@ impl FetchResponseListener for ParserContext {
return; return;
} }
let _realm = enter_realm(&*parser.document);
parser.document.set_csp_list(csp_list); parser.document.set_csp_list(csp_list);
self.parser = Some(Trusted::new(&*parser)); self.parser = Some(Trusted::new(&*parser));
self.submit_resource_timing(); self.submit_resource_timing();
@ -916,6 +919,7 @@ impl FetchResponseListener for ParserContext {
if parser.aborted.get() { if parser.aborted.get() {
return; return;
} }
let _realm = enter_realm(&*parser);
parser.parse_bytes_chunk(payload); parser.parse_bytes_chunk(payload);
} }
@ -931,6 +935,8 @@ impl FetchResponseListener for ParserContext {
return; return;
} }
let _realm = enter_realm(&*parser);
match status { match status {
// are we throwing this away or can we use it? // are we throwing this away or can we use it?
Ok(_) => (), Ok(_) => (),

View file

@ -1005,7 +1005,7 @@ impl TestBindingMethods for TestBinding {
resolve.map(SimpleHandler::new), resolve.map(SimpleHandler::new),
reject.map(SimpleHandler::new), reject.map(SimpleHandler::new),
); );
let p = Promise::new_in_current_realm(&global, comp.clone()); let p = Promise::new_in_current_realm(comp.clone());
p.append_native_handler(&handler, comp); p.append_native_handler(&handler, comp);
return p; return p;
@ -1028,7 +1028,7 @@ impl TestBindingMethods for TestBinding {
} }
fn PromiseAttribute(&self, comp: InRealm) -> Rc<Promise> { fn PromiseAttribute(&self, comp: InRealm) -> Rc<Promise> {
Promise::new_in_current_realm(&self.global(), comp) Promise::new_in_current_realm(comp)
} }
fn AcceptPromise(&self, _promise: &Promise) {} fn AcceptPromise(&self, _promise: &Promise) {}

View file

@ -554,9 +554,9 @@ impl TaskOnce for MessageReceivedTask {
// Step 2-5. // Step 2-5.
let global = ws.global(); let global = ws.global();
// global.get_cx() returns a valid `JSContext` pointer, so this is safe. // GlobalScope::get_cx() returns a valid `JSContext` pointer, so this is safe.
unsafe { unsafe {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, ws.reflector().get_jsobject().get()); let _ac = JSAutoRealm::new(*cx, ws.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue()); rooted!(in(*cx) let mut message = UndefinedValue());
match self.message { match self.message {

View file

@ -165,7 +165,7 @@ impl WindowProxy {
let WindowProxyHandler(handler) = window.windowproxy_handler(); let WindowProxyHandler(handler) = window.windowproxy_handler();
assert!(!handler.is_null()); assert!(!handler.is_null());
let cx = window.get_cx(); let cx = GlobalScope::get_cx();
let window_jsobject = window.reflector().get_jsobject(); let window_jsobject = window.reflector().get_jsobject();
assert!(!window_jsobject.get().is_null()); assert!(!window_jsobject.get().is_null());
assert_ne!( assert_ne!(
@ -225,7 +225,7 @@ impl WindowProxy {
let handler = CreateWrapperProxyHandler(&XORIGIN_PROXY_HANDLER); let handler = CreateWrapperProxyHandler(&XORIGIN_PROXY_HANDLER);
assert!(!handler.is_null()); assert!(!handler.is_null());
let cx = global_to_clone_from.get_cx(); let cx = GlobalScope::get_cx();
// Create a new browsing context. // Create a new browsing context.
let window_proxy = Box::new(WindowProxy::new_inherited( let window_proxy = Box::new(WindowProxy::new_inherited(
@ -624,7 +624,7 @@ impl WindowProxy {
let handler = CreateWrapperProxyHandler(traps); let handler = CreateWrapperProxyHandler(traps);
assert!(!handler.is_null()); assert!(!handler.is_null());
let cx = window.get_cx(); let cx = GlobalScope::get_cx();
let window_jsobject = window.reflector().get_jsobject(); let window_jsobject = window.reflector().get_jsobject();
let old_js_proxy = self.reflector.get_jsobject(); let old_js_proxy = self.reflector.get_jsobject();
assert!(!window_jsobject.get().is_null()); assert!(!window_jsobject.get().is_null());

View file

@ -169,7 +169,7 @@ impl Worker {
let global = worker.global(); let global = worker.global();
let target = worker.upcast(); let target = worker.upcast();
let _ac = enter_realm(target); let _ac = enter_realm(target);
rooted!(in(*global.get_cx()) let mut message = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut message = UndefinedValue());
if let Ok(ports) = structuredclone::read(&global, data, message.handle_mut()) { if let Ok(ports) = structuredclone::read(&global, data, message.handle_mut()) {
MessageEvent::dispatch_jsval(target, &global, message.handle(), None, None, ports); MessageEvent::dispatch_jsval(target, &global, message.handle(), None, None, ports);
} else { } else {
@ -247,7 +247,7 @@ impl WorkerMethods for Worker {
self.terminated.set(true); self.terminated.set(true);
// Step 3 // Step 3
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
unsafe { JS_RequestInterruptCallback(*cx) }; unsafe { JS_RequestInterruptCallback(*cx) };
} }

View file

@ -130,8 +130,7 @@ impl WorkletMethods for Worklet {
comp: InRealm, comp: InRealm,
) -> Rc<Promise> { ) -> Rc<Promise> {
// Step 1. // Step 1.
let global = self.window.upcast(); let promise = Promise::new_in_current_realm(comp);
let promise = Promise::new_in_current_realm(&global, comp);
// Step 3. // Step 3.
let module_url_record = match self.window.Document().base_url().join(&module_url.0) { let module_url_record = match self.window.Document().base_url().join(&module_url.0) {

View file

@ -85,14 +85,14 @@ impl WorkletGlobalScope {
} }
/// Get the JS context. /// Get the JS context.
pub fn get_cx(&self) -> JSContext { pub fn get_cx() -> JSContext {
self.globalscope.get_cx() GlobalScope::get_cx()
} }
/// Evaluate a JS script in this global. /// Evaluate a JS script in this global.
pub fn evaluate_js(&self, script: &str) -> bool { pub fn evaluate_js(&self, script: &str) -> bool {
debug!("Evaluating Dom in a worklet."); debug!("Evaluating Dom in a worklet.");
rooted!(in (*self.globalscope.get_cx()) let mut rval = UndefinedValue()); rooted!(in (*GlobalScope::get_cx()) let mut rval = UndefinedValue());
self.globalscope.evaluate_js_on_global_with_result( self.globalscope.evaluate_js_on_global_with_result(
&*script, &*script,
rval.handle_mut(), rval.handle_mut(),

View file

@ -57,7 +57,7 @@ impl XRInputSource {
); );
let _ac = enter_realm(&*global); let _ac = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let mut profiles = UndefinedValue()); rooted!(in(*cx) let mut profiles = UndefinedValue());
source.info.profiles.to_jsval(*cx, profiles.handle_mut()); source.info.profiles.to_jsval(*cx, profiles.handle_mut());

View file

@ -63,7 +63,7 @@ impl XRInputSourcesChangeEvent {
event.init_event(type_, bubbles, cancelable); event.init_event(type_, bubbles, cancelable);
} }
let _ac = enter_realm(&*global); let _ac = enter_realm(&*global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let mut added_val = UndefinedValue()); rooted!(in(*cx) let mut added_val = UndefinedValue());
added.to_jsval(*cx, added_val.handle_mut()); added.to_jsval(*cx, added_val.handle_mut());

View file

@ -116,7 +116,7 @@ impl XRRayMethods for XRRay {
// https://immersive-web.github.io/hit-test/#xrray-obtain-the-matrix // https://immersive-web.github.io/hit-test/#xrray-obtain-the-matrix
// Step 1 // Step 1
if self.matrix.get().is_null() { if self.matrix.get().is_null() {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
// Step 2 // Step 2
let z = Vector3D::new(0., 0., -1.); let z = Vector3D::new(0., 0., -1.);
// Step 3 // Step 3

View file

@ -117,7 +117,7 @@ impl XRRigidTransformMethods for XRRigidTransform {
// https://immersive-web.github.io/webxr/#dom-xrrigidtransform-matrix // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-matrix
fn Matrix(&self, _cx: JSContext) -> NonNull<JSObject> { fn Matrix(&self, _cx: JSContext) -> NonNull<JSObject> {
if self.matrix.get().is_null() { if self.matrix.get().is_null() {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
// According to the spec all matrices are column-major, // According to the spec all matrices are column-major,
// however euclid uses row vectors so we use .to_array() // however euclid uses row vectors so we use .to_array()
let arr = self.transform.to_transform().to_array(); let arr = self.transform.to_transform().to_array();

View file

@ -757,7 +757,7 @@ impl XRSessionMethods for XRSession {
/// https://immersive-web.github.io/webxr/#dom-xrsession-requestreferencespace /// https://immersive-web.github.io/webxr/#dom-xrsession-requestreferencespace
fn RequestReferenceSpace(&self, ty: XRReferenceSpaceType, comp: InRealm) -> Rc<Promise> { fn RequestReferenceSpace(&self, ty: XRReferenceSpaceType, comp: InRealm) -> Rc<Promise> {
let p = Promise::new_in_current_realm(&self.global(), comp); let p = Promise::new_in_current_realm(comp);
// https://immersive-web.github.io/webxr/#create-a-reference-space // https://immersive-web.github.io/webxr/#create-a-reference-space

View file

@ -14,6 +14,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::gamepad::Gamepad; use crate::dom::gamepad::Gamepad;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
@ -158,7 +159,7 @@ impl XRSystemMethods for XRSystem {
) -> Rc<Promise> { ) -> Rc<Promise> {
let global = self.global(); let global = self.global();
let window = global.as_window(); let window = global.as_window();
let promise = Promise::new_in_current_realm(&global, comp); let promise = Promise::new_in_current_realm(comp);
if mode != XRSessionMode::Inline { if mode != XRSessionMode::Inline {
if !ScriptThread::is_user_interacting() { if !ScriptThread::is_user_interacting() {
@ -180,7 +181,7 @@ impl XRSystemMethods for XRSystem {
let mut required_features = vec![]; let mut required_features = vec![];
let mut optional_features = vec![]; let mut optional_features = vec![];
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
// We are supposed to include "viewer" and on immersive devices "local" // We are supposed to include "viewer" and on immersive devices "local"
// by default here, but this is handled directly in requestReferenceSpace() // by default here, but this is handled directly in requestReferenceSpace()

View file

@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods}; use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::utils::create_typed_array; use crate::dom::bindings::utils::create_typed_array;
@ -90,7 +89,7 @@ impl XRViewMethods for XRView {
/// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix /// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix
fn ProjectionMatrix(&self, _cx: JSContext) -> NonNull<JSObject> { fn ProjectionMatrix(&self, _cx: JSContext) -> NonNull<JSObject> {
if self.proj.get().is_null() { if self.proj.get().is_null() {
let cx = self.global().get_cx(); let cx = GlobalScope::get_cx();
// row_major since euclid uses row vectors // row_major since euclid uses row vectors
let proj = self.view.projection.to_array(); let proj = self.view.projection.to_array();
create_typed_array(cx, &proj, &self.proj); create_typed_array(cx, &proj, &self.proj);

View file

@ -154,7 +154,7 @@ impl XRViewerPose {
let transform = XRRigidTransform::new(global, cast_transform(transform)); let transform = XRRigidTransform::new(global, cast_transform(transform));
let pose = reflect_dom_object(Box::new(XRViewerPose::new_inherited(&transform)), global); let pose = reflect_dom_object(Box::new(XRViewerPose::new_inherited(&transform)), global);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
rooted!(in(*cx) let mut jsval = UndefinedValue()); rooted!(in(*cx) let mut jsval = UndefinedValue());
views.to_jsval(*cx, jsval.handle_mut()); views.to_jsval(*cx, jsval.handle_mut());

View file

@ -142,7 +142,7 @@ pub fn Fetch(
let core_resource_thread = global.core_resource_thread(); let core_resource_thread = global.core_resource_thread();
// Step 1 // Step 1
let promise = Promise::new_in_current_realm(global, comp); let promise = Promise::new_in_current_realm(comp);
let response = Response::new(global); let response = Response::new(global);
// Step 2 // Step 2

View file

@ -15,9 +15,10 @@ 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::realms::enter_realm;
use crate::script_runtime::{notify_about_rejected_promises, JSContext}; use crate::script_runtime::{notify_about_rejected_promises, JSContext};
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
use js::jsapi::{JobQueueIsEmpty, JobQueueMayNotBeEmpty}; use js::jsapi::{JSAutoRealm, 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;
@ -44,6 +45,7 @@ pub enum Microtask {
pub trait MicrotaskRunnable { pub trait MicrotaskRunnable {
fn handler(&self) {} fn handler(&self) {}
fn enter_realm(&self) -> JSAutoRealm;
} }
/// A promise callback scheduled to run during the next microtask checkpoint (#4283). /// A promise callback scheduled to run during the next microtask checkpoint (#4283).
@ -108,19 +110,23 @@ impl MicrotaskQueue {
if let Some(target) = target_provider(job.pipeline) { if let Some(target) = target_provider(job.pipeline) {
let was_interacting = ScriptThread::is_user_interacting(); let was_interacting = ScriptThread::is_user_interacting();
ScriptThread::set_user_interacting(job.is_user_interacting); ScriptThread::set_user_interacting(job.is_user_interacting);
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report); let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
ScriptThread::set_user_interacting(was_interacting); ScriptThread::set_user_interacting(was_interacting);
} }
}, },
Microtask::User(ref job) => { Microtask::User(ref job) => {
if let Some(target) = target_provider(job.pipeline) { if let Some(target) = target_provider(job.pipeline) {
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report); let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
} }
}, },
Microtask::MediaElement(ref task) => { Microtask::MediaElement(ref task) => {
let _realm = task.enter_realm();
task.handler(); task.handler();
}, },
Microtask::ImageElement(ref task) => { Microtask::ImageElement(ref task) => {
let _realm = task.enter_realm();
task.handler(); task.handler();
}, },
Microtask::CustomElementReaction => { Microtask::CustomElementReaction => {

View file

@ -11,9 +11,9 @@ pub struct AlreadyInRealm(());
impl AlreadyInRealm { impl AlreadyInRealm {
#![allow(unsafe_code)] #![allow(unsafe_code)]
pub fn assert(global: &GlobalScope) -> AlreadyInRealm { pub fn assert() -> AlreadyInRealm {
unsafe { unsafe {
assert!(!GetCurrentRealmOrNull(*global.get_cx()).is_null()); assert!(!GetCurrentRealmOrNull(*GlobalScope::get_cx()).is_null());
} }
AlreadyInRealm(()) AlreadyInRealm(())
} }
@ -44,7 +44,7 @@ impl<'a> InRealm<'a> {
pub fn enter_realm(object: &impl DomObject) -> JSAutoRealm { pub fn enter_realm(object: &impl DomObject) -> JSAutoRealm {
JSAutoRealm::new( JSAutoRealm::new(
*object.global().get_cx(), *GlobalScope::get_cx(),
object.reflector().get_jsobject().get(), object.reflector().get_jsobject().get(),
) )
} }

View file

@ -81,8 +81,8 @@ use uuid::Uuid;
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn gen_type_error(global: &GlobalScope, string: String) -> RethrowError { unsafe fn gen_type_error(global: &GlobalScope, string: String) -> RethrowError {
rooted!(in(*global.get_cx()) let mut thrown = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut thrown = UndefinedValue());
Error::Type(string).to_jsval(*global.get_cx(), &global, thrown.handle_mut()); Error::Type(string).to_jsval(*GlobalScope::get_cx(), &global, thrown.handle_mut());
return RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get()))); return RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get())));
} }
@ -357,7 +357,7 @@ impl ModuleTree {
match promise.as_ref() { match promise.as_ref() {
Some(promise) => promise.append_native_handler(&handler, comp), Some(promise) => promise.append_native_handler(&handler, comp),
None => { None => {
let new_promise = Promise::new_in_current_realm(&owner.global(), comp); let new_promise = Promise::new_in_current_realm(comp);
new_promise.append_native_handler(&handler, comp); new_promise.append_native_handler(&handler, comp);
*promise = Some(new_promise); *promise = Some(new_promise);
}, },
@ -393,7 +393,7 @@ impl ModuleTree {
match promise.as_ref() { match promise.as_ref() {
Some(promise) => promise.append_native_handler(&handler, comp), Some(promise) => promise.append_native_handler(&handler, comp),
None => { None => {
let new_promise = Promise::new_in_current_realm(&owner.global(), comp); let new_promise = Promise::new_in_current_realm(comp);
new_promise.append_native_handler(&handler, comp); new_promise.append_native_handler(&handler, comp);
*promise = Some(new_promise); *promise = Some(new_promise);
}, },
@ -421,14 +421,14 @@ impl ModuleTree {
url: ServoUrl, url: ServoUrl,
options: ScriptFetchOptions, options: ScriptFetchOptions,
) -> Result<ModuleObject, RethrowError> { ) -> Result<ModuleObject, RethrowError> {
let _ac = JSAutoRealm::new(*global.get_cx(), *global.reflector().get_jsobject()); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
let compile_options = let compile_options = unsafe { CompileOptionsWrapper::new(*cx, url.as_str(), 1) };
unsafe { CompileOptionsWrapper::new(*global.get_cx(), url.as_str(), 1) };
unsafe { unsafe {
rooted!(in(*global.get_cx()) let mut module_script = CompileModule1( rooted!(in(*cx) let mut module_script = CompileModule1(
*global.get_cx(), *cx,
compile_options.ptr, compile_options.ptr,
&mut transform_str_to_source_text(&module_script_text), &mut transform_str_to_source_text(&module_script_text),
)); ));
@ -436,12 +436,9 @@ impl ModuleTree {
if module_script.is_null() { if module_script.is_null() {
warn!("fail to compile module script of {}", url); warn!("fail to compile module script of {}", url);
rooted!(in(*global.get_cx()) let mut exception = UndefinedValue()); rooted!(in(*cx) let mut exception = UndefinedValue());
assert!(JS_GetPendingException( assert!(JS_GetPendingException(*cx, &mut exception.handle_mut()));
*global.get_cx(), JS_ClearPendingException(*cx);
&mut exception.handle_mut()
));
JS_ClearPendingException(*global.get_cx());
return Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed( return Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed(
exception.get(), exception.get(),
@ -474,18 +471,16 @@ impl ModuleTree {
global: &GlobalScope, global: &GlobalScope,
module_record: HandleObject, module_record: HandleObject,
) -> Result<(), RethrowError> { ) -> Result<(), RethrowError> {
let _ac = JSAutoRealm::new(*global.get_cx(), *global.reflector().get_jsobject()); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
unsafe { unsafe {
if !ModuleLink(*global.get_cx(), module_record) { if !ModuleLink(*cx, module_record) {
warn!("fail to link & instantiate module"); warn!("fail to link & instantiate module");
rooted!(in(*global.get_cx()) let mut exception = UndefinedValue()); rooted!(in(*cx) let mut exception = UndefinedValue());
assert!(JS_GetPendingException( assert!(JS_GetPendingException(*cx, &mut exception.handle_mut()));
*global.get_cx(), JS_ClearPendingException(*cx);
&mut exception.handle_mut()
));
JS_ClearPendingException(*global.get_cx());
Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed( Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed(
exception.get(), exception.get(),
@ -505,7 +500,7 @@ impl ModuleTree {
module_record: HandleObject, module_record: HandleObject,
eval_result: MutableHandleValue, eval_result: MutableHandleValue,
) -> Result<(), RethrowError> { ) -> Result<(), RethrowError> {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject()); let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
unsafe { unsafe {
@ -547,11 +542,11 @@ impl ModuleTree {
unsafe { unsafe {
let ar = enter_realm(&*global); let ar = enter_realm(&*global);
JS_SetPendingException( JS_SetPendingException(
*global.get_cx(), *GlobalScope::get_cx(),
exception.handle(), exception.handle(),
ExceptionStackBehavior::Capture, ExceptionStackBehavior::Capture,
); );
report_pending_exception(*global.get_cx(), true, InRealm::Entered(&ar)); report_pending_exception(*GlobalScope::get_cx(), true, InRealm::Entered(&ar));
} }
} }
} }
@ -563,16 +558,17 @@ impl ModuleTree {
module_object: HandleObject, module_object: HandleObject,
base_url: ServoUrl, base_url: ServoUrl,
) -> Result<IndexSet<ServoUrl>, RethrowError> { ) -> Result<IndexSet<ServoUrl>, RethrowError> {
let _ac = JSAutoRealm::new(*global.get_cx(), *global.reflector().get_jsobject()); let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
let mut specifier_urls = IndexSet::new(); let mut specifier_urls = IndexSet::new();
unsafe { unsafe {
rooted!(in(*global.get_cx()) let requested_modules = GetRequestedModules(*global.get_cx(), module_object)); rooted!(in(*cx) let requested_modules = GetRequestedModules(*cx, module_object));
let mut length = 0; let mut length = 0;
if !GetArrayLength(*global.get_cx(), requested_modules.handle(), &mut length) { if !GetArrayLength(*cx, requested_modules.handle(), &mut length) {
let module_length_error = let module_length_error =
gen_type_error(&global, "Wrong length of requested modules".to_owned()); gen_type_error(&global, "Wrong length of requested modules".to_owned());
@ -580,10 +576,10 @@ impl ModuleTree {
} }
for index in 0..length { for index in 0..length {
rooted!(in(*global.get_cx()) let mut element = UndefinedValue()); rooted!(in(*cx) let mut element = UndefinedValue());
if !JS_GetElement( if !JS_GetElement(
*global.get_cx(), *cx,
requested_modules.handle(), requested_modules.handle(),
index, index,
&mut element.handle_mut(), &mut element.handle_mut(),
@ -594,12 +590,12 @@ impl ModuleTree {
return Err(get_element_error); return Err(get_element_error);
} }
rooted!(in(*global.get_cx()) let specifier = GetRequestedModuleSpecifier( rooted!(in(*cx) let specifier = GetRequestedModuleSpecifier(
*global.get_cx(), element.handle() *cx, element.handle()
)); ));
let url = ModuleTree::resolve_module_specifier( let url = ModuleTree::resolve_module_specifier(
*global.get_cx(), *cx,
&base_url, &base_url,
specifier.handle().into_handle(), specifier.handle().into_handle(),
); );
@ -976,7 +972,7 @@ impl ModuleOwner {
let module = global.dynamic_module_list().remove(dynamic_module_id); let module = global.dynamic_module_list().remove(dynamic_module_id);
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
let module_tree = module_identity.get_module_tree(&global); let module_tree = module_identity.get_module_tree(&global);
// In the timing of executing this `finish_dynamic_module` function, // In the timing of executing this `finish_dynamic_module` function,
@ -986,7 +982,7 @@ impl ModuleOwner {
let network_error = module_tree.get_network_error().borrow().as_ref().cloned(); let network_error = module_tree.get_network_error().borrow().as_ref().cloned();
let existing_rethrow_error = module_tree.get_rethrow_error().borrow().as_ref().cloned(); let existing_rethrow_error = module_tree.get_rethrow_error().borrow().as_ref().cloned();
rooted!(in(*global.get_cx()) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
if network_error.is_none() && existing_rethrow_error.is_none() { if network_error.is_none() && existing_rethrow_error.is_none() {
let record = module_tree let record = module_tree
.get_record() .get_record()
@ -1355,7 +1351,7 @@ fn fetch_an_import_module_script_graph(
promise: Rc<Promise>, promise: Rc<Promise>,
) -> Result<(), RethrowError> { ) -> Result<(), RethrowError> {
// Step 1. // Step 1.
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let specifier = unsafe { GetModuleRequestSpecifier(*cx, module_request) }); rooted!(in(*cx) let specifier = unsafe { GetModuleRequestSpecifier(*cx, module_request) });
let url = ModuleTree::resolve_module_specifier(*cx, &base_url, specifier.handle().into()); let url = ModuleTree::resolve_module_specifier(*cx, &base_url, specifier.handle().into());
@ -1428,9 +1424,9 @@ unsafe extern "C" fn HostResolveImportedModule(
} }
// Step 5. // Step 5.
rooted!(in(*global_scope.get_cx()) let specifier = GetModuleRequestSpecifier(cx, specifier)); rooted!(in(*GlobalScope::get_cx()) let specifier = GetModuleRequestSpecifier(cx, specifier));
let url = ModuleTree::resolve_module_specifier( let url = ModuleTree::resolve_module_specifier(
*global_scope.get_cx(), *GlobalScope::get_cx(),
&base_url, &base_url,
specifier.handle().into(), specifier.handle().into(),
); );

View file

@ -297,7 +297,7 @@ unsafe extern "C" fn promise_rejection_tracker(
global.dom_manipulation_task_source().queue( global.dom_manipulation_task_source().queue(
task!(rejection_handled_event: move || { task!(rejection_handled_event: move || {
let target = target.root(); let target = target.root();
let cx = target.global().get_cx(); let cx = GlobalScope::get_cx();
let root_promise = trusted_promise.root(); let root_promise = trusted_promise.root();
rooted!(in(*cx) let mut reason = UndefinedValue()); rooted!(in(*cx) let mut reason = UndefinedValue());
@ -324,7 +324,7 @@ unsafe extern "C" fn promise_rejection_tracker(
#[allow(unsafe_code, unrooted_must_root)] #[allow(unsafe_code, unrooted_must_root)]
/// https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises /// https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises
pub fn notify_about_rejected_promises(global: &GlobalScope) { pub fn notify_about_rejected_promises(global: &GlobalScope) {
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
unsafe { unsafe {
// Step 2. // Step 2.
if global.get_uncaught_rejections().borrow().len() > 0 { if global.get_uncaught_rejections().borrow().len() > 0 {
@ -350,7 +350,7 @@ pub fn notify_about_rejected_promises(global: &GlobalScope) {
global.dom_manipulation_task_source().queue( global.dom_manipulation_task_source().queue(
task!(unhandled_rejection_event: move || { task!(unhandled_rejection_event: move || {
let target = target.root(); let target = target.root();
let cx = target.global().get_cx(); let cx = GlobalScope::get_cx();
for promise in uncaught_rejections { for promise in uncaught_rejections {
let promise = promise.root(); let promise = promise.root();

View file

@ -1473,6 +1473,12 @@ impl ScriptThread {
let mut mouse_move_event_index = None; let mut mouse_move_event_index = None;
let mut animation_ticks = HashSet::new(); let mut animation_ticks = HashSet::new();
loop { loop {
let pipeline_id = self.message_to_pipeline(&event);
let _realm = pipeline_id.map(|id| {
let global = self.documents.borrow().find_global(id);
global.map(|global| enter_realm(&*global))
});
// https://html.spec.whatwg.org/multipage/#event-loop-processing-model step 7 // https://html.spec.whatwg.org/multipage/#event-loop-processing-model step 7
match event { match event {
// This has to be handled before the ResizeMsg below, // This has to be handled before the ResizeMsg below,
@ -1592,6 +1598,11 @@ impl ScriptThread {
let category = self.categorize_msg(&msg); let category = self.categorize_msg(&msg);
let pipeline_id = self.message_to_pipeline(&msg); let pipeline_id = self.message_to_pipeline(&msg);
let _realm = pipeline_id.and_then(|id| {
let global = self.documents.borrow().find_global(id);
global.map(|global| enter_realm(&*global))
});
if self.closing.load(Ordering::SeqCst) { if self.closing.load(Ordering::SeqCst) {
// If we've received the closed signal from the BHM, only handle exit messages. // If we've received the closed signal from the BHM, only handle exit messages.
match msg { match msg {
@ -1638,6 +1649,7 @@ impl ScriptThread {
// https://html.spec.whatwg.org/multipage/#the-end step 6 // https://html.spec.whatwg.org/multipage/#the-end step 6
let mut docs = self.docs_with_no_blocking_loads.borrow_mut(); let mut docs = self.docs_with_no_blocking_loads.borrow_mut();
for document in docs.iter() { for document in docs.iter() {
let _realm = enter_realm(&**document);
document.maybe_queue_document_completion(); document.maybe_queue_document_completion();
} }
docs.clear(); docs.clear();
@ -1656,6 +1668,8 @@ impl ScriptThread {
} }
let window = document.window(); let window = document.window();
let _realm = enter_realm(&*document);
window window
.upcast::<GlobalScope>() .upcast::<GlobalScope>()
.perform_a_dom_garbage_collection_checkpoint(); .perform_a_dom_garbage_collection_checkpoint();
@ -1684,6 +1698,7 @@ impl ScriptThread {
} }
for (_, document) in self.documents.borrow().iter() { for (_, document) in self.documents.borrow().iter() {
let _realm = enter_realm(&*document);
document.animations().send_pending_events(document.window()); document.animations().send_pending_events(document.window());
} }
} }
@ -1756,7 +1771,9 @@ impl ScriptThread {
MixedMessage::FromConstellation(ref inner_msg) => match *inner_msg { MixedMessage::FromConstellation(ref inner_msg) => match *inner_msg {
StopDelayingLoadEventsMode(id) => Some(id), StopDelayingLoadEventsMode(id) => Some(id),
NavigationResponse(id, _) => Some(id), NavigationResponse(id, _) => Some(id),
AttachLayout(ref new_layout_info) => Some(new_layout_info.new_pipeline_id), AttachLayout(ref new_layout_info) => new_layout_info
.parent_info
.or(Some(new_layout_info.new_pipeline_id)),
Resize(id, ..) => Some(id), Resize(id, ..) => Some(id),
ResizeInactive(id, ..) => Some(id), ResizeInactive(id, ..) => Some(id),
UnloadDocument(id) => Some(id), UnloadDocument(id) => Some(id),
@ -1786,7 +1803,7 @@ impl ScriptThread {
DispatchStorageEvent(id, ..) => Some(id), DispatchStorageEvent(id, ..) => Some(id),
ReportCSSError(id, ..) => Some(id), ReportCSSError(id, ..) => Some(id),
Reload(id, ..) => Some(id), Reload(id, ..) => Some(id),
PaintMetric(..) => None, PaintMetric(id, ..) => Some(id),
ExitFullScreen(id, ..) => Some(id), ExitFullScreen(id, ..) => Some(id),
MediaSessionAction(..) => None, MediaSessionAction(..) => None,
SetWebGPUPort(..) => None, SetWebGPUPort(..) => None,
@ -2070,7 +2087,13 @@ impl ScriptThread {
fn handle_msg_from_script(&self, msg: MainThreadScriptMsg) { fn handle_msg_from_script(&self, msg: MainThreadScriptMsg) {
match msg { match msg {
MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task, _, _)) => task.run_box(), MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task, pipeline_id, _)) => {
let _realm = pipeline_id.and_then(|id| {
let global = self.documents.borrow().find_global(id);
global.map(|global| enter_realm(&*global))
});
task.run_box()
},
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => { MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => {
self.collect_reports(chan) self.collect_reports(chan)
}, },
@ -3277,6 +3300,8 @@ impl ScriptThread {
incomplete.inherited_secure_context, incomplete.inherited_secure_context,
); );
let _realm = enter_realm(&*window);
// Initialize the browsing context for the window. // Initialize the browsing context for the window.
let window_proxy = self.local_window_proxy( let window_proxy = self.local_window_proxy(
&window, &window,
@ -3460,6 +3485,8 @@ impl ScriptThread {
); );
} }
let _realm = enter_realm(&*window);
// Assuming all CompositionEvent are generated by user interactions. // Assuming all CompositionEvent are generated by user interactions.
ScriptThread::set_user_interacting(true); ScriptThread::set_user_interacting(true);
match event { match event {
@ -3697,7 +3724,7 @@ impl ScriptThread {
// Script source is ready to be evaluated (11.) // Script source is ready to be evaluated (11.)
let _ac = enter_realm(global_scope); let _ac = enter_realm(global_scope);
rooted!(in(*global_scope.get_cx()) let mut jsval = UndefinedValue()); rooted!(in(*GlobalScope::get_cx()) let mut jsval = UndefinedValue());
global_scope.evaluate_js_on_global_with_result( global_scope.evaluate_js_on_global_with_result(
&script_source, &script_source,
jsval.handle_mut(), jsval.handle_mut(),
@ -3708,7 +3735,7 @@ impl ScriptThread {
load_data.js_eval_result = if jsval.get().is_string() { load_data.js_eval_result = if jsval.get().is_string() {
unsafe { unsafe {
let strval = DOMString::from_jsval( let strval = DOMString::from_jsval(
*global_scope.get_cx(), *GlobalScope::get_cx(),
jsval.handle(), jsval.handle(),
StringificationBehavior::Empty, StringificationBehavior::Empty,
); );
@ -3978,7 +4005,7 @@ impl ScriptThread {
.documents .documents
.borrow() .borrow()
.iter() .iter()
.map(|(_id, document)| document.global()) .map(|(_id, document)| DomRoot::from_ref(document.window().upcast()))
.collect(); .collect();
self.microtask_queue.checkpoint( self.microtask_queue.checkpoint(

View file

@ -540,7 +540,7 @@ impl JsTimerTask {
match self.callback { match self.callback {
InternalTimerCallback::StringTimerCallback(ref code_str) => { InternalTimerCallback::StringTimerCallback(ref code_str) => {
let global = this.global(); let global = this.global();
let cx = global.get_cx(); let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut rval = UndefinedValue()); rooted!(in(*cx) let mut rval = UndefinedValue());
// FIXME(cybai): Use base url properly by saving private reference for timers (#27260) // FIXME(cybai): Use base url properly by saving private reference for timers (#27260)
global.evaluate_js_on_global_with_result( global.evaluate_js_on_global_with_result(