Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce trait Castable #8041

Merged
merged 5 commits into from Oct 21, 2015
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Introduce IDLInterface::derives()

This method is given a DOMClass value and returns whether it derives from Self.

Interfaces with no descendants directly check whether the given DOMClass is the
same as their own.
  • Loading branch information
nox committed Oct 21, 2015
commit c77d3b965f6099ffcb2eddc359948f106afca7b5
@@ -2246,20 +2246,24 @@ def __init__(self, descriptor):
self.descriptor = descriptor

def define(self):
replacer = {
'type': self.descriptor.name,
'depth': self.descriptor.interface.inheritanceDepth(),
}
return string.Template("""\
impl IDLInterface for ${type} {
fn get_prototype_id() -> PrototypeList::ID {
PrototypeList::ID::${type}
}
fn get_prototype_depth() -> usize {
${depth}
interface = self.descriptor.interface
name = self.descriptor.name
if (interface.getUserData("hasConcreteDescendant", False) or
interface.getUserData("hasProxyDescendant", False)):
depth = len(self.descriptor.prototypeChain)
check = "class.interface_chain[%s] == PrototypeList::ID::%s" % (depth - 1, name)
elif self.descriptor.proxy:
check = "class as *const _ == &Class as *const _"
else:
check = "class as *const _ == &Class.dom_class as *const _"
return """\
impl IDLInterface for %(name)s {
#[inline]
fn derives(class: &'static DOMClass) -> bool {
%(check)s
}
}
""").substitute(replacer)
""" % {'check': check, 'name': name}


class CGAbstractExternMethod(CGAbstractMethod):
@@ -5820,7 +5824,7 @@ def InheritTypes(config):

descriptors = config.getDescriptors(register=True, isCallback=False)
imports = [CGGeneric("use dom::types::*;\n"),
CGGeneric("use dom::bindings::conversions::get_dom_class;\n"),
CGGeneric("use dom::bindings::conversions::{IDLInterface, get_dom_class};\n"),
CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"),
CGGeneric("use dom::bindings::trace::JSTraceable;\n"),
CGGeneric("use dom::bindings::utils::Reflectable;\n"),
@@ -5886,18 +5890,11 @@ def InheritTypes(config):
# Define a `FooDerived` trait for superclasses to implement,
# as well as the `FooCast::to_*` methods that use it.
baseName = descriptor.prototypeChain[0]
typeIdPat = descriptor.prototypeChain[-1]
if upcast:
typeIdPat += "(_)"
for base in reversed(descriptor.prototypeChain[1:-1]):
typeIdPat = "%s(%sTypeId::%s)" % (base, base, typeIdPat)
typeIdPat = "%sTypeId::%s" % (baseName, typeIdPat)
args = {
'baseName': baseName,
'derivedTrait': name + 'Derived',
'methodName': 'is_' + name.lower(),
'name': name,
'typeIdPat': typeIdPat,
}
allprotos.append(CGGeneric("""\
/// Types which `%(name)s` derives from
@@ -5938,10 +5935,10 @@ def InheritTypes(config):
impl %(derivedTrait)s for %(baseName)s {
fn %(methodName)s(&self) -> bool {
match *self.type_id() {
%(typeIdPat)s => true,
_ => false,
}
let dom_class = unsafe {
get_dom_class(self.reflector().get_jsobject().get()).unwrap()
};
%(name)s::derives(dom_class)
}
}
@@ -33,7 +33,6 @@
//! | union types | `T` |

use core::nonzero::NonZero;
use dom::bindings::codegen::PrototypeList;
use dom::bindings::error::throw_type_error;
use dom::bindings::js::Root;
use dom::bindings::num::Finite;
@@ -101,14 +100,10 @@ impl_as!(u32, u32);
impl_as!(i64, i64);
impl_as!(u64, u64);

/// A trait to retrieve the constants necessary to check if a `JSObject`
/// implements a given interface.
/// A trait to check whether a given `JSObject` implements an IDL interface.
pub trait IDLInterface {
/// Returns the prototype ID.
fn get_prototype_id() -> PrototypeList::ID;
/// Returns the prototype depth, i.e., the number of interfaces this
/// interface inherits from.
fn get_prototype_depth() -> usize;
/// Returns whether the given DOM class derives that interface.
fn derives(&'static DOMClass) -> bool;
}

/// A trait to convert Rust types to `JSVal`s.
@@ -696,9 +691,10 @@ pub unsafe fn get_dom_class(obj: *mut JSObject) -> Result<&'static DOMClass, ()>
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
/// not an object for a DOM object of the given type (as defined by the
/// proto_id and proto_depth).
pub unsafe fn private_from_proto_chain(mut obj: *mut JSObject,
proto_id: u16, proto_depth: u16)
-> Result<*const libc::c_void, ()> {
#[inline]
pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject, proto_check: F)
-> Result<*const libc::c_void, ()>
where F: Fn(&'static DOMClass) -> bool {
let dom_class = try!(get_dom_class(obj).or_else(|_| {
if IsWrapper(obj) {
debug!("found wrapper");
@@ -717,7 +713,7 @@ pub unsafe fn private_from_proto_chain(mut obj: *mut JSObject,
}
}));

if dom_class.interface_chain[proto_depth as usize] as u16 == proto_id {
if proto_check(dom_class) {
debug!("good prototype");
Ok(private_from_reflector(obj))
} else {
@@ -735,10 +731,8 @@ pub unsafe fn private_from_proto_chain(mut obj: *mut JSObject,
pub fn native_from_reflector_jsmanaged<T>(obj: *mut JSObject) -> Result<Root<T>, ()>
where T: Reflectable + IDLInterface
{
let proto_id = <T as IDLInterface>::get_prototype_id() as u16;
let proto_depth = <T as IDLInterface>::get_prototype_depth() as u16;
unsafe {
private_from_proto_chain(obj, proto_id, proto_depth).map(|obj| {
private_from_proto_check(obj, T::derives).map(|obj| {
Root::new(NonZero::new(obj as *const T))
})
}
@@ -8,7 +8,7 @@ use dom::bindings::codegen::InheritTypes::TopTypeId;
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::native_from_handleobject;
use dom::bindings::conversions::private_from_proto_chain;
use dom::bindings::conversions::private_from_proto_check;
use dom::bindings::conversions::{is_dom_class, jsstring_to_str};
use dom::bindings::error::throw_type_error;
use dom::bindings::error::{Error, ErrorResult, Fallible, throw_invalid_this};
@@ -755,7 +755,10 @@ unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal,
let info = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
let proto_id = (*info).protoID;
let depth = (*info).depth;
let this = match private_from_proto_chain(obj.ptr, proto_id, depth) {
let proto_check = |class: &'static DOMClass| {
class.interface_chain[depth as usize] as u16 == proto_id
};
let this = match private_from_proto_check(obj.ptr, proto_check) {
Ok(val) => val,
Err(()) => {
if is_lenient {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.