diff options
author | Josh Matthews <josh@joshmatthews.net> | 2014-03-31 18:41:28 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2014-05-03 14:18:30 -0400 |
commit | d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1 (patch) | |
tree | efd1e7f7ec1dd30467c2a67306e1a639837abead /src/components/script/dom/bindings/codegen | |
parent | ffdc3f5b32a345b88eed774848924e862d47c093 (diff) | |
download | servo-d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1.tar.gz servo-d7b96db33ca8f2b8a162df38e0f00e95f5ea6fa1.zip |
Implement safe rooting strategy via Unrooted, Root, JSRef, and JS.
Diffstat (limited to 'src/components/script/dom/bindings/codegen')
-rw-r--r-- | src/components/script/dom/bindings/codegen/CodegenRust.py | 46 | ||||
-rw-r--r-- | src/components/script/dom/bindings/codegen/Configuration.py | 1 |
2 files changed, 42 insertions, 5 deletions
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 5d4f6cc9bf4..30ff08e21ff 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1008,6 +1008,13 @@ def typeNeedsCx(type, retVal=False): return True return type.isCallback() or type.isAny() or type.isObject() +def typeRetValNeedsRooting(type): + if type is None: + return False + if type.nullable(): + type = type.inner + return type.isGeckoInterface() and not type.isCallback() + def memberIsCreator(member): return member.getExtendedAttribute("Creator") is not None @@ -1039,7 +1046,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType.isGeckoInterface(): descriptor = descriptorProvider.getDescriptor( returnType.unroll().inner.identifier.name) - result = CGGeneric(descriptor.nativeType) + result = CGGeneric(descriptor.returnType) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") return result @@ -2235,6 +2242,14 @@ class CGCallGenerator(CGThing): self.cgRoot.append(CGGeneric("}")) self.cgRoot.append(CGGeneric("result = result_fallible.unwrap();")) + if typeRetValNeedsRooting(returnType): + rooted_value = CGGeneric("result.root(&roots).root_ref().unrooted()") + if returnType.nullable(): + rooted_value = CGWrapper(rooted_value, pre="result.map(|result| ", post=")") + rooted_value = CGWrapper(rooted_value, pre="let result = ", post=";") + + self.cgRoot.append(rooted_value) + def define(self): return self.cgRoot.define() @@ -4306,7 +4321,7 @@ class CGBindingRoot(CGThing): 'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING}', 'dom::types::*', 'dom::bindings', - 'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference}', + 'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted}', 'dom::bindings::utils::{CreateDOMGlobal, CreateInterfaceObjects2}', 'dom::bindings::utils::{ConstantSpec, cx_for_dom_object, Default}', 'dom::bindings::utils::{dom_object_slot, DOM_OBJECT_SLOT, DOMClass}', @@ -5277,8 +5292,9 @@ class GlobalGenRoots(): descriptors = config.getDescriptors(register=True, hasInterfaceObject=True) allprotos = [CGGeneric("#![allow(unused_imports)]\n"), CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::js::{JS, JSRef};\n"), + CGGeneric("use dom::bindings::js::{JS, JSRef, Unrooted};\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: @@ -5310,7 +5326,7 @@ class GlobalGenRoots(): } #[inline(always)] - fn to<T: ${toBound}>(base: &JS<T>) -> Option<JS<Self>> { + fn to<T: ${toBound}+Reflectable>(base: &JS<T>) -> Option<JS<Self>> { match base.get().${checkFn}() { true => unsafe { Some(base.clone().transmute()) }, false => None @@ -5318,7 +5334,23 @@ class GlobalGenRoots(): } #[inline(always)] - unsafe fn to_unchecked<T: ${toBound}>(base: &JS<T>) -> JS<Self> { + fn to_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a JSRef<'b, T>) -> Option<&'a JSRef<'b, Self>> { + match base.get().${checkFn}() { + true => unsafe { Some(base.transmute()) }, + false => None + } + } + + #[inline(always)] + fn to_mut_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a mut JSRef<'b, T>) -> Option<&'a mut JSRef<'b, Self>> { + match base.get().${checkFn}() { + true => unsafe { Some(base.transmute_mut()) }, + false => None + } + } + + #[inline(always)] + unsafe fn to_unchecked<T: ${toBound}+Reflectable>(base: &JS<T>) -> JS<Self> { assert!(base.get().${checkFn}()); base.clone().transmute() } @@ -5330,6 +5362,10 @@ class GlobalGenRoots(): fn from_mut_ref<'a, 'b, T: ${fromBound}>(derived: &'a mut JSRef<'b, T>) -> &'a mut JSRef<'b, Self> { unsafe { derived.transmute_mut() } } + + fn from_unrooted<T: ${fromBound}+Reflectable>(derived: Unrooted<T>) -> Unrooted<Self> { + unsafe { derived.transmute() } + } } ''').substitute({'checkFn': 'is_' + name.lower(), 'castTraitName': name + 'Cast', diff --git a/src/components/script/dom/bindings/codegen/Configuration.py b/src/components/script/dom/bindings/codegen/Configuration.py index a1ccb460ee2..eedb200c75e 100644 --- a/src/components/script/dom/bindings/codegen/Configuration.py +++ b/src/components/script/dom/bindings/codegen/Configuration.py @@ -133,6 +133,7 @@ class Descriptor(DescriptorProvider): else: nativeTypeDefault = 'JS<%s>' % ifaceName + self.returnType = "Unrooted<%s>" % ifaceName self.nativeType = desc.get('nativeType', nativeTypeDefault) self.concreteType = desc.get('concreteType', ifaceName) self.needsAbstract = desc.get('needsAbstract', []) |