From ac46cc6047a2297bdc578c09dfa290b32f2b61d3 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Mon, 31 Mar 2014 12:13:54 +0200 Subject: [PATCH] Implement FromJSValConvertible for JS. --- .../dom/bindings/codegen/CodegenRust.py | 29 +++++++++++++++++++ .../script/dom/bindings/conversions.rs | 21 ++++++++++++++ src/components/script/dom/bindings/utils.rs | 12 ++++---- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index c1d4ac46aaa..e9a85ac0b23 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1920,6 +1920,32 @@ class CGWrapMethod(CGAbstractMethod): raw.mut_reflector().set_jsobject(obj); return raw;""" % CreateBindingJSObject(self.descriptor) + +class CGIDLInterface(CGThing): + """ + Class for codegen of an implementation of the IDLInterface trait. + """ + def __init__(self, descriptor): + CGThing.__init__(self) + 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(_: Option<${type}>) -> PrototypeList::id::ID { + PrototypeList::id::${type} + } + fn get_prototype_depth(_: Option<${type}>) -> uint { + ${depth} + } +} +""").substitute(replacer) + + class CGAbstractExternMethod(CGAbstractMethod): """ Abstract base class for codegen of implementation-only (no @@ -4080,6 +4106,8 @@ class CGDescriptor(CGThing): cgThings.append(CGWrapMethod(descriptor)) + cgThings.append(CGIDLInterface(descriptor)) + cgThings = CGList(cgThings, "\n") cgThings = CGWrapper(cgThings, pre='\n', post='\n') #self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name), @@ -4496,6 +4524,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::callback::{CallSetup,ExceptionHandling}', 'dom::bindings::callback::{WrapCallThisObject}', 'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}', + 'dom::bindings::conversions::IDLInterface', 'dom::bindings::conversions::{Default, Empty}', 'dom::bindings::codegen::*', 'dom::bindings::codegen::UnionTypes::*', diff --git a/src/components/script/dom/bindings/conversions.rs b/src/components/script/dom/bindings/conversions.rs index 1826782ac84..c658765fb27 100644 --- a/src/components/script/dom/bindings/conversions.rs +++ b/src/components/script/dom/bindings/conversions.rs @@ -5,6 +5,7 @@ use dom::bindings::js::JS; use dom::bindings::utils::Reflectable; use dom::bindings::utils::jsstring_to_str; +use dom::bindings::utils::unwrap_jsmanaged; use servo_util::str::DOMString; use js::jsapi::{JSBool, JSContext}; @@ -20,6 +21,15 @@ use js::glue::RUST_JS_NumberValue; use std::default::Default; use std::libc; +use dom::bindings::codegen::PrototypeList; + +// FIXME (https://github.com/rust-lang/rfcs/pull/4) +// remove Option arguments. +pub trait IDLInterface { + fn get_prototype_id(_: Option) -> PrototypeList::id::ID; + fn get_prototype_depth(_: Option) -> uint; +} + pub trait ToJSValConvertible { fn to_jsval(&self, cx: *JSContext) -> JSVal; } @@ -255,6 +265,17 @@ impl ToJSValConvertible for JS { } } +impl FromJSValConvertible<()> for JS { + fn from_jsval(_cx: *JSContext, value: JSVal, _option: ()) -> Result, ()> { + if !value.is_object() { + return Err(()); + } + unwrap_jsmanaged(value.to_object(), + IDLInterface::get_prototype_id(None::), + IDLInterface::get_prototype_depth(None::)) + } +} + impl ToJSValConvertible for Option { fn to_jsval(&self, cx: *JSContext) -> JSVal { match self { diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 8320d7865aa..46b6175fbfe 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -4,6 +4,7 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; +use dom::bindings::conversions::FromJSValConvertible; use dom::bindings::js::JS; use dom::window; use servo_util::str::DOMString; @@ -34,8 +35,8 @@ use js::jsapi::{JSString}; use js::jsapi::{JS_AllowGC, JS_InhibitGC}; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; use js::jsval::JSVal; -use js::jsval::{PrivateValue, ObjectValue, NullValue, Int32Value}; -use js::jsval::{UInt32Value, DoubleValue, BooleanValue, UndefinedValue}; +use js::jsval::{PrivateValue, ObjectValue, NullValue, ObjectOrNullValue}; +use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue, UndefinedValue}; use js::{JSPROP_ENUMERATE, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS}; use js::JSPROP_PERMANENT; use js::{JSFUN_CONSTRUCTOR, JSPROP_READONLY}; @@ -532,11 +533,8 @@ pub fn global_object_for_js_object(obj: *JSObject) -> JS { let global = GetGlobalForObjectCrossCompartment(obj); let clasp = JS_GetClass(global); assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0); - // FIXME(jdm): Either don't hardcode or sanity assert prototype stuff. - match unwrap_object(global, PrototypeList::id::Window, 1) { - Ok(win) => JS::from_raw(win), - Err(_) => fail!("found DOM global that doesn't unwrap to Window"), - } + FromJSValConvertible::from_jsval(ptr::null(), ObjectOrNullValue(global), ()) + .ok().expect("found DOM global that doesn't unwrap to Window") } }