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

Implement a safe, mostly-sound rooting rooting strategy. #2101

Merged
merged 16 commits into from May 3, 2014
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Move WebIDL methods to traits implemented by JSRef types.

  • Loading branch information
jdm committed May 3, 2014
commit 76783b029e5e10da7fd61ab356a8f80a1eaf32e0
@@ -91,31 +91,40 @@ impl Attr {
}
}

impl Attr {
pub fn LocalName(&self) -> DOMString {
pub trait AttrMethods {
fn LocalName(&self) -> DOMString;
fn Value(&self) -> DOMString;
fn SetValue(&mut self, value: DOMString);
fn Name(&self) -> DOMString;
fn GetNamespaceURI(&self) -> Option<DOMString>;
fn GetPrefix(&self) -> Option<DOMString>;
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
fn LocalName(&self) -> DOMString {
self.local_name.clone()
}

pub fn Value(&self) -> DOMString {
fn Value(&self) -> DOMString {
self.value.clone()
}

pub fn SetValue(&mut self, value: DOMString) {
fn SetValue(&mut self, value: DOMString) {
self.set_value(ReplacedAttr, value);
}

pub fn Name(&self) -> DOMString {
fn Name(&self) -> DOMString {
self.name.clone()
}

pub fn GetNamespaceURI(&self) -> Option<DOMString> {
fn GetNamespaceURI(&self) -> Option<DOMString> {
match self.namespace.to_str() {
"" => None,
url => Some(url.to_owned()),
}
}

pub fn GetPrefix(&self) -> Option<DOMString> {
fn GetPrefix(&self) -> Option<DOMString> {
self.prefix.clone()
}
}
@@ -29,18 +29,26 @@ impl AttrList {
reflect_dom_object(~AttrList::new_inherited(window.unrooted(), elem.unrooted()),
window, AttrListBinding::Wrap)
}
}

pub trait AttrListMethods {
fn Length(&self) -> u32;
fn Item(&self, index: u32) -> Option<Unrooted<Attr>>;
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Attr>>;
}

pub fn Length(&self) -> u32 {
impl<'a> AttrListMethods for JSRef<'a, AttrList> {
fn Length(&self) -> u32 {
let roots = RootCollection::new();
self.owner.root(&roots).attrs.len() as u32
}

pub fn Item(&self, index: u32) -> Option<Unrooted<Attr>> {
fn Item(&self, index: u32) -> Option<Unrooted<Attr>> {
let roots = RootCollection::new();
self.owner.root(&roots).attrs.as_slice().get(index as uint).map(|x| Unrooted::new(x.clone()))
}

pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Attr>> {
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Attr>> {
let item = self.Item(index);
*found = item.is_some();
item
@@ -1395,7 +1395,7 @@ class CGImports(CGWrapper):
"""
Generates the appropriate import/use statements.
"""
def __init__(self, child, imports):
def __init__(self, child, descriptors, imports):
"""
Adds a set of imports.
"""
@@ -1415,6 +1415,10 @@ def __init__(self, child, imports):
'dead_code',
]

for d in descriptors:
name = d.interface.identifier.name
imports.append('dom::%s::%sMethods' % (name.lower(), name))

statements = ['#![allow(%s)]' % ','.join(ignored_warnings)]
statements.extend('use %s;' % i for i in sorted(imports))

@@ -2499,7 +2503,8 @@ def definition_body(self):
return CGWrapper(CGMethodCall(argsPre, nativeName, self.method.isStatic(),
self.descriptor, self.method),
pre=extraPre +
" let this = &mut *this;\n").define()
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n").define()

class CGGenericGetter(CGAbstractBindingMethod):
"""
@@ -2558,7 +2563,8 @@ def definition_body(self):
return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName,
self.descriptor, self.attr)),
pre=extraPre +
" let this = &mut *this;\n").define()
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n").define()

class CGGenericSetter(CGAbstractBindingMethod):
"""
@@ -2617,7 +2623,8 @@ def definition_body(self):
return CGWrapper(CGIndenter(CGSetterCall(argsPre, self.attr.type, nativeName,
self.descriptor, self.attr)),
pre=extraPre +
" let this = &mut *this;\n").define()
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n").define()


class CGMemberJITInfo(CGThing):
@@ -3508,14 +3515,14 @@ def __init__(self, descriptor):
class CGProxyUnwrap(CGAbstractMethod):
def __init__(self, descriptor):
args = [Argument('*JSObject', 'obj')]
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*' + descriptor.concreteType, args, alwaysInline=True)
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*mut ' + descriptor.concreteType, args, alwaysInline=True)

def definition_body(self):
return """ /*if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
obj = js::UnwrapObject(obj);
}*/
//MOZ_ASSERT(IsProxy(obj));
let box_: *%s = cast::transmute(GetProxyPrivate(obj).to_private());
let box_: *mut %s = cast::transmute(GetProxyPrivate(obj).to_private());
return box_;""" % (self.descriptor.concreteType)

class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
@@ -3540,9 +3547,11 @@ def getBody(self):
templateValues = {'jsvalRef': '(*desc).value', 'successCode': fillDescriptor}
get = ("if index.is_some() {\n" +
" let index = index.unwrap();\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
"}\n") % (self.descriptor.concreteType)
"}\n")

if indexedSetter or self.descriptor.operations['NamedSetter']:
setOrIndexedGet += "if set != 0 {\n"
@@ -3585,9 +3594,11 @@ def getBody(self):
namedGet = ("\n" +
"if set == 0 && RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
" let name = Some(jsid_to_str(cx, id));\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
"}\n") % (self.descriptor.concreteType)
"}\n")
else:
namedGet = ""

@@ -3628,10 +3639,12 @@ def getBody(self):
set += ("let index = GetArrayIndexFromId(cx, id);\n" +
"if index.is_some() {\n" +
" let index = index.unwrap();\n" +
" let this: *mut %s = UnwrapProxy(proxy) as *mut %s;\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
" return 1;\n" +
"}\n") % (self.descriptor.concreteType, self.descriptor.concreteType)
"}\n")
elif self.descriptor.operations['IndexedGetter']:
set += ("if GetArrayIndexFromId(cx, id).is_some() {\n" +
" return 0;\n" +
@@ -3644,20 +3657,24 @@ def getBody(self):
raise TypeError("Can't handle creator that's different from the setter")
set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
" let name = Some(jsid_to_str(cx, id));\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
"}\n") % (self.descriptor.concreteType)
"}\n")
elif self.descriptor.operations['NamedGetter']:
set += ("if RUST_JSID_IS_STRING(id) {\n" +
" let name = Some(jsid_to_str(cx, id));\n" +
" let this: %%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
" if (found) {\n"
" return 0;\n" +
" //return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
" }\n" +
" return 1;\n"
"}\n") % (self.descriptor.concreteType, self.descriptor.name)
"}\n") % (self.descriptor.name)
return set + """return proxyhandler::defineProperty_(%s);""" % ", ".join(a.name for a in self.args)

def definition_body(self):
@@ -3675,24 +3692,28 @@ def getBody(self):
indexed = ("let index = GetArrayIndexFromId(cx, id);\n" +
"if index.is_some() {\n" +
" let index = index.unwrap();\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
" *bp = found as JSBool;\n" +
" return 1;\n" +
"}\n\n") % (self.descriptor.concreteType)
"}\n\n")
else:
indexed = ""

namedGetter = self.descriptor.operations['NamedGetter']
if namedGetter:
named = ("if RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
" let name = Some(jsid_to_str(cx, id));\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
" *bp = found as JSBool;\n"
" return 1;\n"
"}\n" +
"\n") % (self.descriptor.concreteType)
"\n")
else:
named = ""

@@ -3740,6 +3761,8 @@ def getBody(self):
"if index.is_some() {\n" +
" let index = index.unwrap();\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define())
getIndexedOrExpando += """
// Even if we don't have this index, we don't forward the
@@ -3756,6 +3779,8 @@ def getBody(self):
getNamed = ("if (JSID_IS_STRING(id)) {\n" +
" let name = Some(jsid_to_str(cx, id));\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = JS::from_raw(this);\n" +
" let mut this = this.root(&roots);\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
"}\n") % (self.descriptor.concreteType)
else:
@@ -4288,7 +4313,7 @@ def __init__(self, config, prefix, webIDLFile):
# Add imports
#XXXjdm This should only import the namespace for the current binding,
# not every binding ever.
curr = CGImports(curr, [
curr = CGImports(curr, descriptors, [
'js',
'js::{JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}',
@@ -5253,7 +5278,7 @@ def PrototypeList(config):
@staticmethod
def RegisterBindings(config):
# TODO - Generate the methods we want
return CGImports(CGRegisterProtos(config), [
return CGImports(CGRegisterProtos(config), [], [
'dom::bindings::codegen',
'dom::bindings::js::{JS, JSRef}',
'dom::window::Window',
@@ -5372,7 +5397,7 @@ def UnionTypes(config):

curr = UnionTypes(config.getDescriptors())

curr = CGImports(curr, [
curr = CGImports(curr, [], [
'dom::bindings::utils::unwrap_jsmanaged',
'dom::bindings::codegen::PrototypeList',
'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}',
@@ -28,28 +28,35 @@ impl Blob {
window,
BlobBinding::Wrap)
}
}

impl Blob {
pub fn Constructor(window: &JSRef<Window>) -> Fallible<Unrooted<Blob>> {
Ok(Blob::new(window))
}
}

pub trait BlobMethods {
fn Size(&self) -> u64;
fn Type(&self) -> DOMString;
fn Slice(&self, _start: Option<i64>, _end: Option<i64>, _contentType: Option<DOMString>) -> Unrooted<Blob>;
fn Close(&self);
}

pub fn Size(&self) -> u64 {
impl<'a> BlobMethods for JSRef<'a, Blob> {
fn Size(&self) -> u64 {
0
}

pub fn Type(&self) -> DOMString {
fn Type(&self) -> DOMString {
~""
}

pub fn Slice(&self, _start: Option<i64>, _end: Option<i64>, _contentType: Option<DOMString>) -> Unrooted<Blob> {
fn Slice(&self, _start: Option<i64>, _end: Option<i64>, _contentType: Option<DOMString>) -> Unrooted<Blob> {
let roots = RootCollection::new();
let window = self.window.root(&roots);
Blob::new(&window.root_ref())
}

pub fn Close(&self) {}
fn Close(&self) {}
}

impl Reflectable for Blob {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.