mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Use JSTraceable everywhere
This commit is contained in:
parent
85f79290a6
commit
cc44a3b064
133 changed files with 325 additions and 278 deletions
|
@ -13,8 +13,6 @@ use js::jsval::{JSVal, UndefinedValue};
|
|||
|
||||
use std::ptr;
|
||||
|
||||
use serialize::{Encodable, Encoder};
|
||||
|
||||
/// The exception handling used for a call.
|
||||
pub enum ExceptionHandling {
|
||||
/// Report any exception and don't throw it to the caller code.
|
||||
|
@ -28,7 +26,8 @@ pub enum ExceptionHandling {
|
|||
}
|
||||
|
||||
/// A common base class for representing IDL callback function types.
|
||||
#[deriving(Clone,PartialEq,Encodable)]
|
||||
#[deriving(Clone,PartialEq)]
|
||||
#[jstraceable]
|
||||
pub struct CallbackFunction {
|
||||
object: CallbackObject
|
||||
}
|
||||
|
@ -44,7 +43,8 @@ impl CallbackFunction {
|
|||
}
|
||||
|
||||
/// A common base class for representing IDL callback interface types.
|
||||
#[deriving(Clone,PartialEq,Encodable)]
|
||||
#[deriving(Clone,PartialEq)]
|
||||
#[jstraceable]
|
||||
pub struct CallbackInterface {
|
||||
object: CallbackObject
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ pub struct CallbackInterface {
|
|||
/// A common base class for representing IDL callback function and
|
||||
/// callback interface types.
|
||||
#[allow(raw_pointer_deriving)]
|
||||
#[deriving(Clone,PartialEq,Encodable)]
|
||||
#[deriving(Clone,PartialEq)]
|
||||
#[jstraceable]
|
||||
struct CallbackObject {
|
||||
/// The underlying `JSObject`.
|
||||
callback: Traceable<*mut JSObject>,
|
||||
|
|
|
@ -2754,7 +2754,8 @@ use js::jsapi::JSContext;
|
|||
use js::jsval::JSVal;
|
||||
|
||||
#[repr(uint)]
|
||||
#[deriving(Encodable, PartialEq)]
|
||||
#[deriving(PartialEq)]
|
||||
#[jstraceable]
|
||||
pub enum valuelist {
|
||||
%s
|
||||
}
|
||||
|
@ -4893,7 +4894,7 @@ class CGCallback(CGClass):
|
|||
bases=[ClassBase(baseName)],
|
||||
constructors=self.getConstructors(),
|
||||
methods=realMethods+getters+setters,
|
||||
decorators="#[deriving(PartialEq,Clone,Encodable)]")
|
||||
decorators="#[deriving(PartialEq,Clone)]#[jstraceable]")
|
||||
|
||||
def getConstructors(self):
|
||||
return [ClassConstructor(
|
||||
|
@ -5438,7 +5439,6 @@ class GlobalGenRoots():
|
|||
CGGeneric("use dom::bindings::js::{JS, JSRef, Temporary};\n"),
|
||||
CGGeneric("use dom::bindings::trace::JSTraceable;\n"),
|
||||
CGGeneric("use dom::bindings::utils::Reflectable;\n"),
|
||||
CGGeneric("use serialize::{Encodable, Encoder};\n"),
|
||||
CGGeneric("use js::jsapi::JSTracer;\n\n")]
|
||||
for descriptor in descriptors:
|
||||
name = descriptor.name
|
||||
|
@ -5500,16 +5500,7 @@ class GlobalGenRoots():
|
|||
'toBound': name + 'Derived'})),
|
||||
CGGeneric("impl %s for %s {}\n\n" % (name + 'Cast', name))]
|
||||
|
||||
trace = [CGGeneric(string.Template('''impl JSTraceable for ${name} {
|
||||
fn trace(&self, tracer: *mut JSTracer) {
|
||||
unsafe {
|
||||
self.encode(&mut *tracer).ok().expect("failed to encode");
|
||||
}
|
||||
}
|
||||
}
|
||||
''').substitute({'name': name}))]
|
||||
|
||||
allprotos += protos + derived + cast + trace
|
||||
allprotos += protos + derived + cast
|
||||
|
||||
curr = CGList(allprotos)
|
||||
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
|
||||
|
|
|
@ -33,7 +33,7 @@ pub enum GlobalRoot<'a, 'b> {
|
|||
|
||||
/// A traced reference to a global object, for use in fields of traced Rust
|
||||
/// structures.
|
||||
#[deriving(Encodable)]
|
||||
#[jstraceable]
|
||||
#[must_root]
|
||||
pub enum GlobalField {
|
||||
WindowField(JS<Window>),
|
||||
|
|
|
@ -10,7 +10,8 @@ use std::path::BytesContainer;
|
|||
use std::str;
|
||||
|
||||
/// Encapsulates the IDL `ByteString` type.
|
||||
#[deriving(Encodable,Clone,Eq,PartialEq)]
|
||||
#[deriving(Clone,Eq,PartialEq)]
|
||||
#[jstraceable]
|
||||
pub struct ByteString(Vec<u8>);
|
||||
|
||||
impl ByteString {
|
||||
|
|
|
@ -11,57 +11,51 @@
|
|||
//! 1. The GC calls `_trace` defined in `FooBinding` during the marking
|
||||
//! phase. (This happens through `JSClass.trace` for non-proxy bindings, and
|
||||
//! through `ProxyTraps.trace` otherwise.)
|
||||
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`,
|
||||
//! defined in `InheritTypes.rs`).
|
||||
//! 3. `Foo::trace()` calls `Foo::encode()` (an implementation of `Encodable`).
|
||||
//! This implementation is typically derived by a `#[deriving(Encodable)]`
|
||||
//! annotation on the Rust struct.
|
||||
//! 4. For all fields (except those wrapped in `Untraceable`), `Foo::encode()`
|
||||
//! calls `encode()` on the field.
|
||||
//!
|
||||
//! For example, for fields of type `JS<T>`, `JS<T>::encode()` calls
|
||||
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
|
||||
//! This is typically derived via a #[jstraceable] annotation
|
||||
//! 4. For all fields (except those wrapped in `Untraceable`), `Foo::trace()`
|
||||
//! calls `trace()` on the field.
|
||||
//! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
|
||||
//! `trace_reflector()`.
|
||||
//! 6. `trace_reflector()` calls `trace_object()` with the `JSObject` for the
|
||||
//! reflector.
|
||||
//! 7. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
|
||||
//! add the object to the graph, and will trace that object as well.
|
||||
//!
|
||||
//! The untraceable!() macro adds an empty implementation of JSTraceable to
|
||||
//! a datatype.
|
||||
|
||||
use dom::bindings::js::JS;
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
|
||||
use js::jsapi::{JSObject, JSTracer, JS_CallTracer, JSTRACE_OBJECT};
|
||||
use js::jsval::JSVal;
|
||||
|
||||
use libc;
|
||||
use url::Url;
|
||||
use std::mem;
|
||||
use std::num;
|
||||
use std::rc::Rc;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use serialize::{Encodable, Encoder};
|
||||
|
||||
use url::Url;
|
||||
use servo_util::atom::Atom;
|
||||
use servo_util::namespace::Namespace;
|
||||
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData};
|
||||
use net::image_cache_task::ImageCacheTask;
|
||||
use script_traits::ScriptControlChan;
|
||||
use std::collections::hashmap::HashMap;
|
||||
use collections::hash::Hash;
|
||||
use style::PropertyDeclarationBlock;
|
||||
|
||||
// IMPORTANT: We rely on the fact that we never attempt to encode DOM objects using
|
||||
// any encoder but JSTracer. Since we derive trace hooks automatically,
|
||||
// we are unfortunately required to use generic types everywhere and
|
||||
// unsafely cast to the concrete JSTracer we actually require.
|
||||
|
||||
fn get_jstracer<'a, S: Encoder<E>, E>(s: &'a mut S) -> &'a mut JSTracer {
|
||||
unsafe {
|
||||
mem::transmute(s)
|
||||
impl<T: Reflectable> JSTraceable for JS<T> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
trace_reflector(trc, "", self.reflector());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflectable+Encodable<S, E>, S: Encoder<E>, E> Encodable<S, E> for JS<T> {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
trace_reflector(get_jstracer(s), "", self.reflector());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E> Encodable<S, E> for Reflector {
|
||||
fn encode(&self, _s: &mut S) -> Result<(), E> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
untraceable!(Reflector)
|
||||
|
||||
/// A trait to allow tracing (only) DOM objects.
|
||||
pub trait JSTraceable {
|
||||
|
@ -122,12 +116,6 @@ impl<T> Untraceable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E, T> Encodable<S, E> for Untraceable<T> {
|
||||
fn encode(&self, _s: &mut S) -> Result<(), E> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref<T> for Untraceable<T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
&self.inner
|
||||
|
@ -167,28 +155,88 @@ impl<T> Deref<T> for Traceable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E, T: Encodable<S, E>> Encodable<S, E> for Traceable<RefCell<T>> {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
self.borrow().encode(s)
|
||||
impl<T: JSTraceable> JSTraceable for RefCell<T> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.borrow().trace(trc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E, T: Encodable<S, E>+Copy> Encodable<S, E> for Traceable<Cell<T>> {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
self.deref().get().encode(s)
|
||||
impl<T: JSTraceable> JSTraceable for Rc<T> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.trace(trc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E> Encodable<S, E> for Traceable<*mut JSObject> {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
trace_object(get_jstracer(s), "object", **self);
|
||||
Ok(())
|
||||
impl<T: JSTraceable> JSTraceable for Box<T> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.trace(trc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder<E>, E> Encodable<S, E> for Traceable<JSVal> {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
trace_jsval(get_jstracer(s), "val", **self);
|
||||
Ok(())
|
||||
impl<T: JSTraceable+Copy> JSTraceable for Traceable<Cell<T>> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.deref().get().trace(trc)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: JSTraceable+Copy> JSTraceable for Cell<T> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.get().trace(trc)
|
||||
}
|
||||
}
|
||||
|
||||
impl JSTraceable for Traceable<*mut JSObject> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
trace_object(trc, "object", **self);
|
||||
}
|
||||
}
|
||||
|
||||
impl JSTraceable for Traceable<JSVal> {
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
trace_jsval(trc, "val", **self);
|
||||
}
|
||||
}
|
||||
|
||||
// XXXManishearth Check if the following three are optimized to no-ops
|
||||
// if e.trace() is a no-op (e.g it is an untraceable type)
|
||||
impl<T: JSTraceable> JSTraceable for Vec<T> {
|
||||
#[inline]
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
for e in self.iter() {
|
||||
e.trace(trc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: JSTraceable> JSTraceable for Option<T> {
|
||||
#[inline]
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
self.as_ref().map(|e| e.trace(trc));
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq+Hash, V: JSTraceable> JSTraceable for HashMap<K, V> {
|
||||
#[inline]
|
||||
fn trace(&self, trc: *mut JSTracer) {
|
||||
for e in self.iter() {
|
||||
e.val1().trace(trc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
untraceable!(bool, f32, f64, String, Url)
|
||||
untraceable!(SubpageId, WindowSizeData, PipelineId)
|
||||
untraceable!(uint, u8, u16, u32, u64)
|
||||
untraceable!(int, i8, i16, i32, i64)
|
||||
untraceable!(Untraceable<T>)
|
||||
untraceable!(ImageCacheTask, ScriptControlChan)
|
||||
untraceable!(Atom, Namespace)
|
||||
untraceable!(PropertyDeclarationBlock)
|
||||
|
||||
impl<'a> JSTraceable for &'a str {
|
||||
#[inline]
|
||||
fn trace(&self, _: *mut JSTracer) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ use js::{JSFUN_CONSTRUCTOR, JSPROP_READONLY};
|
|||
use js;
|
||||
|
||||
#[allow(raw_pointer_deriving)]
|
||||
#[deriving(Encodable)]
|
||||
#[jstraceable]
|
||||
pub struct GlobalStaticData {
|
||||
pub windowproxy_handler: Untraceable<*const libc::c_void>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue