servo/components/script/dom/bindings/reflector.rs
Anthony Ramine a6d59d8714 Replace inheritance_integrity by trait shenanigans
For each derived DomObject impl, we also generate a dummy trait
ShouldNotImplDomObject that is implemented for all T: DomObject.
We then try to implement it for each field type except the first one.
If compilation succeed, this means that field type doesn't implement
DomObject itself otherwise it would break coherence rules.

error[E0119]: conflicting implementations of trait `dom::xmlhttprequest::_IMPL_DOMOBJECT_FOR_XMLHttpRequest::ShouldNotImplDomObject` for type `((), SomeFieldTypeThatShouldNotImplementDomObject)`:
   --> /Users/nox/src/servo/components/script/dom/xmlhttprequest.rs:120:1
    |
120 | #[dom_struct]
    | ^^^^^^^^^^^^^
    | |
    | first implementation here
    | conflicting implementation for `((), SomeFieldTypeThatShouldNotImplementDomObject)`
2017-02-15 22:11:20 +01:00

101 lines
2.9 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! The `Reflector` struct.
use dom::bindings::conversions::DerivedFrom;
use dom::bindings::js::Root;
use dom::globalscope::GlobalScope;
use js::jsapi::{HandleObject, JSContext, JSObject, Heap};
use std::default::Default;
/// Create the reflector for a new DOM object and yield ownership to the
/// reflector.
pub fn reflect_dom_object<T, U>(
obj: Box<T>,
global: &U,
wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> Root<T>)
-> Root<T>
where T: DomObject, U: DerivedFrom<GlobalScope>
{
let global_scope = global.upcast();
unsafe {
wrap_fn(global_scope.get_cx(), global_scope, obj)
}
}
/// A struct to store a reference to the reflector of a DOM object.
#[allow(unrooted_must_root)]
#[derive(HeapSizeOf)]
#[must_root]
// If you're renaming or moving this field, update the path in plugins::reflector as well
pub struct Reflector {
#[ignore_heap_size_of = "defined and measured in rust-mozjs"]
object: Heap<*mut JSObject>,
}
#[allow(unrooted_must_root)]
impl PartialEq for Reflector {
fn eq(&self, other: &Reflector) -> bool {
self.object.get() == other.object.get()
}
}
impl Reflector {
/// Get the reflector.
#[inline]
pub fn get_jsobject(&self) -> HandleObject {
self.object.handle()
}
/// Initialize the reflector. (May be called only once.)
pub fn set_jsobject(&mut self, object: *mut JSObject) {
assert!(self.object.get().is_null());
assert!(!object.is_null());
self.object.set(object);
}
/// Return a pointer to the memory location at which the JS reflector
/// object is stored. Used to root the reflector, as
/// required by the JSAPI rooting APIs.
pub fn rootable(&self) -> &Heap<*mut JSObject> {
&self.object
}
/// Create an uninitialized `Reflector`.
pub fn new() -> Reflector {
Reflector {
object: Heap::default(),
}
}
}
/// A trait to provide access to the `Reflector` for a DOM object.
pub trait DomObject {
/// Returns the receiver's reflector.
fn reflector(&self) -> &Reflector;
/// Returns the global scope of the realm that the DomObject was created in.
fn global(&self) -> Root<GlobalScope> where Self: Sized {
GlobalScope::from_reflector(self)
}
}
impl DomObject for Reflector {
fn reflector(&self) -> &Self {
self
}
}
/// A trait to initialize the `Reflector` for a DOM object.
pub trait MutDomObject: DomObject {
/// Initializes the Reflector
fn init_reflector(&mut self, obj: *mut JSObject);
}
impl MutDomObject for Reflector {
fn init_reflector(&mut self, obj: *mut JSObject) {
self.set_jsobject(obj)
}
}