mirror of
https://github.com/servo/servo.git
synced 2025-07-30 02:30:21 +01:00
Dynamically check DOMRefCell access from layout in debug builds
This commit is contained in:
parent
0162214b1f
commit
6ec0939a22
9 changed files with 150 additions and 30 deletions
|
@ -5,13 +5,15 @@
|
|||
use dom::bindings::trace::JSTraceable;
|
||||
use js::jsapi::{JSTracer};
|
||||
|
||||
use servo_util::task_state;
|
||||
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::kinds::marker;
|
||||
|
||||
/// A mutable field in the DOM.
|
||||
///
|
||||
/// This extends the API of `core::cell::RefCell` to allow unsafe access in
|
||||
/// certain situations.
|
||||
/// certain situations, with dynamic checking in debug builds.
|
||||
pub struct DOMRefCell<T> {
|
||||
value: UnsafeCell<T>,
|
||||
borrow: Cell<BorrowFlag>,
|
||||
|
@ -27,8 +29,31 @@ impl<T> DOMRefCell<T> {
|
|||
///
|
||||
/// For use in the layout task only.
|
||||
pub unsafe fn borrow_for_layout<'a>(&'a self) -> &'a T {
|
||||
debug_assert!(task_state::get().is_layout());
|
||||
&*self.value.get()
|
||||
}
|
||||
|
||||
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
match self.borrow.get() {
|
||||
WRITING => None,
|
||||
borrow => {
|
||||
self.borrow.set(borrow + 1);
|
||||
Some(Ref { _parent: self })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
|
||||
debug_assert!(task_state::get().is_script());
|
||||
match self.borrow.get() {
|
||||
UNUSED => {
|
||||
self.borrow.set(WRITING);
|
||||
Some(RefMut { _parent: self })
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
|
||||
|
@ -63,16 +88,6 @@ impl<T> DOMRefCell<T> {
|
|||
unsafe{self.value.unwrap()}
|
||||
}
|
||||
|
||||
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
|
||||
match self.borrow.get() {
|
||||
WRITING => None,
|
||||
borrow => {
|
||||
self.borrow.set(borrow + 1);
|
||||
Some(Ref { _parent: self })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
|
||||
match self.try_borrow() {
|
||||
Some(ptr) => ptr,
|
||||
|
@ -80,16 +95,6 @@ impl<T> DOMRefCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
|
||||
match self.borrow.get() {
|
||||
UNUSED => {
|
||||
self.borrow.set(WRITING);
|
||||
Some(RefMut { _parent: self })
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
|
||||
match self.try_borrow_mut() {
|
||||
Some(ptr) => ptr,
|
||||
|
|
|
@ -24,6 +24,8 @@ use script_task::WorkerPostMessage;
|
|||
use script_task::StackRootTLS;
|
||||
|
||||
use servo_net::resource_task::{ResourceTask, load_whole_resource};
|
||||
use servo_util::task_state;
|
||||
use servo_util::task_state::{Script, InWorker};
|
||||
|
||||
use js::glue::JS_STRUCTURED_CLONE_VERSION;
|
||||
use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException};
|
||||
|
@ -90,6 +92,9 @@ impl DedicatedWorkerGlobalScope {
|
|||
.native()
|
||||
.named(format!("Web Worker at {}", worker_url.serialize()))
|
||||
.spawn(proc() {
|
||||
|
||||
task_state::initialize(Script | InWorker);
|
||||
|
||||
let roots = RootCollection::new();
|
||||
let _stack_roots_tls = StackRootTLS::new(&roots);
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ use servo_net::resource_task::ResourceTask;
|
|||
use servo_util::geometry::to_frac_px;
|
||||
use servo_util::smallvec::{SmallVec1, SmallVec};
|
||||
use servo_util::task::spawn_named_with_send_on_failure;
|
||||
use servo_util::task_state;
|
||||
|
||||
use geom::point::Point2D;
|
||||
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
|
||||
|
@ -262,7 +263,7 @@ impl ScriptTaskFactory for ScriptTask {
|
|||
let ConstellationChan(const_chan) = constellation_chan.clone();
|
||||
let (script_chan, script_port) = channel();
|
||||
let layout_chan = LayoutChan(layout_chan.sender());
|
||||
spawn_named_with_send_on_failure("ScriptTask", proc() {
|
||||
spawn_named_with_send_on_failure("ScriptTask", task_state::Script, proc() {
|
||||
let script_task = ScriptTask::new(id,
|
||||
compositor as Box<ScriptListener>,
|
||||
layout_chan,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue