mirror of
https://github.com/servo/servo.git
synced 2025-06-20 15:18:58 +01:00
Fill out various proxy binding traps as part of making setters work. Add named getter and setter and indexed getter support, as well as proxy object expandos. Fixes #660.
This commit is contained in:
parent
a4baa7fc6b
commit
c9bc2046f6
10 changed files with 376 additions and 48 deletions
|
@ -1435,8 +1435,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||||
if not callWrapValue:
|
if not callWrapValue:
|
||||||
tail = successCode
|
tail = successCode
|
||||||
elif haveSuccessCode:
|
elif haveSuccessCode:
|
||||||
tail = ("if (!JS_WrapValue(cx, ${jsvalPtr})) {\n" +
|
tail = ("if JS_WrapValue(cx, ${jsvalPtr}) == 0 {\n" +
|
||||||
" return false;\n" +
|
" return 0;\n" +
|
||||||
"}\n" +
|
"}\n" +
|
||||||
successCode)
|
successCode)
|
||||||
else:
|
else:
|
||||||
|
@ -1527,7 +1527,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
properResult = result + ".as_cacheable_wrapper()"
|
properResult = result + ".as_cacheable_wrapper()"
|
||||||
else:
|
else:
|
||||||
properResult += " as @mut CacheableWrapper"
|
properResult += " as @mut CacheableWrapper"
|
||||||
wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, properResult)
|
wrap = "%s(cx, ${obj}, %s, ${jsvalPtr} as *mut JSVal)" % (wrapMethod, properResult)
|
||||||
# We don't support prefable stuff in workers.
|
# We don't support prefable stuff in workers.
|
||||||
assert(not descriptor.prefable or not descriptor.workers)
|
assert(not descriptor.prefable or not descriptor.workers)
|
||||||
if not descriptor.prefable:
|
if not descriptor.prefable:
|
||||||
|
@ -1547,7 +1547,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
else:
|
else:
|
||||||
#wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
|
#wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
|
||||||
if descriptor.pointerType == '':
|
if descriptor.pointerType == '':
|
||||||
wrap = "%s.wrap(cx, ${obj}, ${jsvalPtr})" % result
|
wrap = "(%s.wrap(cx, ${obj}, ${jsvalPtr}) as bool)" % result
|
||||||
else:
|
else:
|
||||||
wrap = "if WrapNewBindingObject(cx, ${obj}, %s as @mut CacheableWrapper, ${jsvalPtr}) { 1 } else { 0 };" % result
|
wrap = "if WrapNewBindingObject(cx, ${obj}, %s as @mut CacheableWrapper, ${jsvalPtr}) { 1 } else { 0 };" % result
|
||||||
wrappingCode += wrapAndSetPtr(wrap)
|
wrappingCode += wrapAndSetPtr(wrap)
|
||||||
|
@ -2815,13 +2815,13 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
|
||||||
body += """ let traps = ProxyTraps {
|
body += """ let traps = ProxyTraps {
|
||||||
getPropertyDescriptor: getPropertyDescriptor,
|
getPropertyDescriptor: getPropertyDescriptor,
|
||||||
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
|
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
|
||||||
defineProperty: ptr::null(),
|
defineProperty: defineProperty,
|
||||||
getOwnPropertyNames: ptr::null(),
|
getOwnPropertyNames: ptr::null(),
|
||||||
delete_: ptr::null(),
|
delete_: ptr::null(),
|
||||||
enumerate: ptr::null(),
|
enumerate: ptr::null(),
|
||||||
|
|
||||||
has: ptr::null(),
|
has: ptr::null(),
|
||||||
hasOwn: ptr::null(),
|
hasOwn: hasOwn,
|
||||||
get: get,
|
get: get,
|
||||||
set: ptr::null(),
|
set: ptr::null(),
|
||||||
keys: ptr::null(),
|
keys: ptr::null(),
|
||||||
|
@ -3233,8 +3233,8 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
||||||
|
|
||||||
def generate_code(self):
|
def generate_code(self):
|
||||||
return CGIndenter(CGGeneric(
|
return CGIndenter(CGGeneric(
|
||||||
"let _info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"return CallJitPropertyOp(_info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, vp);"))
|
"return CallJitPropertyOp(info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, vp);"))
|
||||||
|
|
||||||
class CGSpecializedGetter(CGAbstractExternMethod):
|
class CGSpecializedGetter(CGAbstractExternMethod):
|
||||||
"""
|
"""
|
||||||
|
@ -3289,7 +3289,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
|
||||||
"let undef = JSVAL_VOID;\n"
|
"let undef = JSVAL_VOID;\n"
|
||||||
"let argv: *JSVal = if argc != 0 { JS_ARGV(cx, cast::transmute(vp)) } else { &undef as *JSVal };\n"
|
"let argv: *JSVal = if argc != 0 { JS_ARGV(cx, cast::transmute(vp)) } else { &undef as *JSVal };\n"
|
||||||
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, cast::transmute(vp)));\n"
|
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, cast::transmute(vp)));\n"
|
||||||
"if CallJitPropertyOp(info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, cast::transmute(vp)) == 0 {"
|
"if CallJitPropertyOp(info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, argv) == 0 {"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"*vp = JSVAL_VOID;\n"
|
"*vp = JSVAL_VOID;\n"
|
||||||
|
@ -3555,10 +3555,33 @@ class CGProxyIndexedGetter(CGProxySpecialOperation):
|
||||||
self.templateValues = templateValues
|
self.templateValues = templateValues
|
||||||
CGProxySpecialOperation.__init__(self, descriptor, 'IndexedGetter')
|
CGProxySpecialOperation.__init__(self, descriptor, 'IndexedGetter')
|
||||||
|
|
||||||
|
class CGProxyIndexedSetter(CGProxySpecialOperation):
|
||||||
|
"""
|
||||||
|
Class to generate a call to an indexed setter.
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
CGProxySpecialOperation.__init__(self, descriptor, 'IndexedSetter')
|
||||||
|
|
||||||
|
class CGProxyNamedGetter(CGProxySpecialOperation):
|
||||||
|
"""
|
||||||
|
Class to generate a call to an named getter. If templateValues is not None
|
||||||
|
the returned value will be wrapped with wrapForType using templateValues.
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor, templateValues=None):
|
||||||
|
self.templateValues = templateValues
|
||||||
|
CGProxySpecialOperation.__init__(self, descriptor, 'NamedGetter')
|
||||||
|
|
||||||
|
class CGProxyNamedSetter(CGProxySpecialOperation):
|
||||||
|
"""
|
||||||
|
Class to generate a call to a named setter.
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter')
|
||||||
|
|
||||||
class CGProxyUnwrap(CGAbstractMethod):
|
class CGProxyUnwrap(CGAbstractMethod):
|
||||||
def __init__(self, descriptor):
|
def __init__(self, descriptor):
|
||||||
args = [Argument('*JSObject', 'obj')]
|
args = [Argument('*JSObject', 'obj')]
|
||||||
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*' + descriptor.nativeType, args, alwaysInline=True)
|
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*' + descriptor.concreteType, args, alwaysInline=True)
|
||||||
def declare(self):
|
def declare(self):
|
||||||
return ""
|
return ""
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
|
@ -3567,7 +3590,241 @@ class CGProxyUnwrap(CGAbstractMethod):
|
||||||
}*/
|
}*/
|
||||||
//MOZ_ASSERT(IsProxy(obj));
|
//MOZ_ASSERT(IsProxy(obj));
|
||||||
let box: *rust_box<%s> = cast::transmute(RUST_JSVAL_TO_PRIVATE(GetProxyPrivate(obj)));
|
let box: *rust_box<%s> = cast::transmute(RUST_JSVAL_TO_PRIVATE(GetProxyPrivate(obj)));
|
||||||
return ptr::to_unsafe_ptr(&(*box).payload);""" % (self.descriptor.nativeType)
|
return ptr::to_unsafe_ptr(&(*box).payload);""" % (self.descriptor.concreteType)
|
||||||
|
|
||||||
|
class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'proxy'),
|
||||||
|
Argument('jsid', 'id'), Argument('JSBool', 'set'),
|
||||||
|
Argument('*mut JSPropertyDescriptor', 'desc')]
|
||||||
|
CGAbstractExternMethod.__init__(self, descriptor, "getOwnPropertyDescriptor",
|
||||||
|
"JSBool", args)
|
||||||
|
self.descriptor = descriptor
|
||||||
|
def getBody(self):
|
||||||
|
indexedGetter = self.descriptor.operations['IndexedGetter']
|
||||||
|
indexedSetter = self.descriptor.operations['IndexedSetter']
|
||||||
|
|
||||||
|
setOrIndexedGet = ""
|
||||||
|
if indexedGetter or indexedSetter:
|
||||||
|
setOrIndexedGet += "let index = GetArrayIndexFromId(cx, id);\n"
|
||||||
|
|
||||||
|
if indexedGetter:
|
||||||
|
readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None)
|
||||||
|
fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly
|
||||||
|
templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_mut_unsafe_ptr(&mut (*desc).value)',
|
||||||
|
'obj': 'proxy', 'successCode': fillDescriptor}
|
||||||
|
get = ("if index.is_some() {\n" +
|
||||||
|
" let index = index.get();\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
|
||||||
|
"}\n") % (self.descriptor.concreteType)
|
||||||
|
|
||||||
|
if indexedSetter or self.descriptor.operations['NamedSetter']:
|
||||||
|
setOrIndexedGet += "if set != 0 {\n"
|
||||||
|
if indexedSetter:
|
||||||
|
setOrIndexedGet += (" if index.is_some() {\n" +
|
||||||
|
" let index = index.get();\n")
|
||||||
|
if not 'IndexedCreator' in self.descriptor.operations:
|
||||||
|
# FIXME need to check that this is a 'supported property index'
|
||||||
|
assert False
|
||||||
|
setOrIndexedGet += (" FillPropertyDescriptor(&mut *desc, proxy, JSVAL_VOID, false);\n" +
|
||||||
|
" return 1;\n" +
|
||||||
|
" }\n")
|
||||||
|
if self.descriptor.operations['NamedSetter']:
|
||||||
|
setOrIndexedGet += " if RUST_JSID_IS_STRING(id) {\n"
|
||||||
|
if not 'NamedCreator' in self.descriptor.operations:
|
||||||
|
# FIXME need to check that this is a 'supported property name'
|
||||||
|
assert False
|
||||||
|
setOrIndexedGet += (" FillPropertyDescriptor(&mut *desc, proxy, JSVAL_VOID, false);\n" +
|
||||||
|
" return 1;\n" +
|
||||||
|
" }\n")
|
||||||
|
setOrIndexedGet += "}"
|
||||||
|
if indexedGetter:
|
||||||
|
setOrIndexedGet += (" else {\n" +
|
||||||
|
CGIndenter(CGGeneric(get)).define() +
|
||||||
|
"}")
|
||||||
|
setOrIndexedGet += "\n\n"
|
||||||
|
elif indexedGetter:
|
||||||
|
setOrIndexedGet += ("if set == 0 {\n" +
|
||||||
|
CGIndenter(CGGeneric(get)).define() +
|
||||||
|
"}\n\n")
|
||||||
|
|
||||||
|
namedGetter = self.descriptor.operations['NamedGetter']
|
||||||
|
if namedGetter:
|
||||||
|
readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None)
|
||||||
|
fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly
|
||||||
|
templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_unsafe_ptr(&(*desc).value)',
|
||||||
|
'obj': 'proxy', 'successCode': fillDescriptor}
|
||||||
|
# Once we start supporting OverrideBuiltins we need to make
|
||||||
|
# ResolveOwnProperty or EnumerateOwnProperties filter out named
|
||||||
|
# properties that shadow prototype properties.
|
||||||
|
namedGet = ("\n" +
|
||||||
|
"if set == 0 && RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
|
||||||
|
" let nameVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||||
|
" //FakeDependentString name;\n"
|
||||||
|
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||||
|
" // eStringify, eStringify, name)) {\n" +
|
||||||
|
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||||
|
" if strval.is_err() {\n" +
|
||||||
|
" return 0;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" let name = str(strval.get());\n" +
|
||||||
|
"\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
|
||||||
|
"}\n") % (self.descriptor.concreteType)
|
||||||
|
else:
|
||||||
|
namedGet = ""
|
||||||
|
|
||||||
|
return setOrIndexedGet + """let expando: *JSObject = GetExpandoObject(proxy);
|
||||||
|
//if (!xpc::WrapperFactory::IsXrayWrapper(proxy) && (expando = GetExpandoObject(proxy))) {
|
||||||
|
if expando.is_not_null() {
|
||||||
|
let flags = if set != 0 { JSRESOLVE_ASSIGNING } else { 0 } | JSRESOLVE_QUALIFIED;
|
||||||
|
if JS_GetPropertyDescriptorById(cx, expando, id, flags, desc as *JSPropertyDescriptor) == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (*desc).obj.is_not_null() {
|
||||||
|
// Pretend the property lives on the wrapper.
|
||||||
|
(*desc).obj = proxy;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""" + namedGet + """
|
||||||
|
(*desc).obj = ptr::null();
|
||||||
|
return 1;"""
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
return self.getBody()
|
||||||
|
|
||||||
|
class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'proxy'),
|
||||||
|
Argument('jsid', 'id'),
|
||||||
|
Argument('*JSPropertyDescriptor', 'desc')]
|
||||||
|
CGAbstractExternMethod.__init__(self, descriptor, "defineProperty", "bool", args)
|
||||||
|
self.descriptor = descriptor
|
||||||
|
def getBody(self):
|
||||||
|
set = ""
|
||||||
|
|
||||||
|
indexedSetter = self.descriptor.operations['IndexedSetter']
|
||||||
|
if indexedSetter:
|
||||||
|
if not (self.descriptor.operations['IndexedCreator'] is indexedSetter):
|
||||||
|
raise TypeError("Can't handle creator that's different from the setter")
|
||||||
|
set += ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
|
"if index.is_some() {\n" +
|
||||||
|
" let index = index.get();\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
|
||||||
|
" return 1;\n" +
|
||||||
|
"}\n") % (self.descriptor.concreteType)
|
||||||
|
elif self.descriptor.operations['IndexedGetter']:
|
||||||
|
set += ("if GetArrayIndexFromId(cx, id).is_some() {\n" +
|
||||||
|
" return 0;\n" +
|
||||||
|
" //return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
|
||||||
|
"}\n") % self.descriptor.name
|
||||||
|
|
||||||
|
namedSetter = self.descriptor.operations['NamedSetter']
|
||||||
|
if namedSetter:
|
||||||
|
if not self.descriptor.operations['NamedCreator'] is namedSetter:
|
||||||
|
raise TypeError("Can't handle creator that's different from the setter")
|
||||||
|
#XXXjdm need to properly support eStringify
|
||||||
|
set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
|
||||||
|
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||||
|
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||||
|
" //FakeDependentString name;\n" +
|
||||||
|
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||||
|
" // eStringify, eStringify, name)) {\n" +
|
||||||
|
" if strval.is_err() {\n" +
|
||||||
|
" return 0;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" let name = str(strval.get());\n" +
|
||||||
|
"\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
|
||||||
|
"}\n") % (self.descriptor.concreteType)
|
||||||
|
elif self.descriptor.operations['NamedGetter']:
|
||||||
|
set += ("if RUST_JSID_IS_STRING(id) {\n" +
|
||||||
|
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||||
|
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||||
|
" //FakeDependentString name;\n"
|
||||||
|
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||||
|
" // eStringify, eStringify, name)) {\n" +
|
||||||
|
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||||
|
" if strval.is_err() {\n" +
|
||||||
|
" return 0;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" let name = str(strval.get());\n" +
|
||||||
|
" let this: %%s = UnwrapProxy(proxy);\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)
|
||||||
|
return set + """return proxyhandler::defineProperty(%s);""" % ", ".join(a.name for a in self.args)
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
return self.getBody()
|
||||||
|
|
||||||
|
class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
|
||||||
|
def __init__(self, descriptor):
|
||||||
|
args = [Argument('*JSContext', 'cx'), Argument('*JSObject', 'proxy'),
|
||||||
|
Argument('jsid', 'id'), Argument('*mut JSBool', 'bp')]
|
||||||
|
CGAbstractExternMethod.__init__(self, descriptor, "hasOwn", "JSBool", args)
|
||||||
|
self.descriptor = descriptor
|
||||||
|
def getBody(self):
|
||||||
|
indexedGetter = self.descriptor.operations['IndexedGetter']
|
||||||
|
if indexedGetter:
|
||||||
|
indexed = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
|
"if index.is_some() {\n" +
|
||||||
|
" let index = index.get();\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
|
||||||
|
" *bp = found as JSBool;\n" +
|
||||||
|
" return 1;\n" +
|
||||||
|
"}\n\n") % (self.descriptor.concreteType)
|
||||||
|
else:
|
||||||
|
indexed = ""
|
||||||
|
|
||||||
|
namedGetter = self.descriptor.operations['NamedGetter']
|
||||||
|
if namedGetter:
|
||||||
|
#XXXjdm support eStringify
|
||||||
|
named = ("if RUST_JSID_IS_STRING(id) != 0 && !HasPropertyOnPrototype(cx, proxy, id) {\n" +
|
||||||
|
" let nameVal: JSVal = RUST_STRING_TO_JSVAL(RUST_JSID_TO_STRING(id));\n" +
|
||||||
|
" let strval = jsval_to_str(cx, nameVal);\n" +
|
||||||
|
" //FakeDependentString name;\n"
|
||||||
|
" //if (!ConvertJSValueToString(cx, nameVal, &nameVal,\n" +
|
||||||
|
" // eStringify, eStringify, name)) {\n" +
|
||||||
|
" if strval.is_err() {\n" +
|
||||||
|
" return 0;\n" +
|
||||||
|
" }\n" +
|
||||||
|
" let name = str(strval.get());\n" +
|
||||||
|
"\n" +
|
||||||
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
|
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
|
||||||
|
" *bp = found as JSBool;\n"
|
||||||
|
" return 1;\n"
|
||||||
|
"}\n" +
|
||||||
|
"\n") % (self.descriptor.concreteType)
|
||||||
|
else:
|
||||||
|
named = ""
|
||||||
|
|
||||||
|
return indexed + """let expando: *JSObject = GetExpandoObject(proxy);
|
||||||
|
if expando.is_not_null() {
|
||||||
|
let b: JSBool = 1;
|
||||||
|
let ok: JSBool = JS_HasPropertyById(cx, expando, id, &b);
|
||||||
|
*bp = !!b;
|
||||||
|
if ok == 0 || *bp != 0 {
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""" + named + """*bp = 0;
|
||||||
|
return 1;"""
|
||||||
|
|
||||||
|
def definition_body(self):
|
||||||
|
return self.getBody()
|
||||||
|
|
||||||
class CGDOMJSProxyHandler_get(CGAbstractExternMethod):
|
class CGDOMJSProxyHandler_get(CGAbstractExternMethod):
|
||||||
def __init__(self, descriptor):
|
def __init__(self, descriptor):
|
||||||
|
@ -3620,7 +3877,7 @@ if expando.is_not_null() {
|
||||||
"\n" +
|
"\n" +
|
||||||
" let this = UnwrapProxy(proxy);\n" +
|
" let this = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
||||||
"}\n") % (self.descriptor.nativeType)
|
"}\n") % (self.descriptor.concreteType)
|
||||||
else:
|
else:
|
||||||
getNamed = ""
|
getNamed = ""
|
||||||
|
|
||||||
|
@ -3773,8 +4030,8 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
|
||||||
|
|
||||||
def generate_code(self):
|
def generate_code(self):
|
||||||
return """ if (!vp.isObject()) {
|
return """ if (!vp.isObject()) {
|
||||||
*bp = false;
|
*bp = 0;
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsval protov;
|
jsval protov;
|
||||||
|
@ -3931,8 +4188,13 @@ class CGDescriptor(CGThing):
|
||||||
#cgThings.append(CGProxyIsProxy(descriptor))
|
#cgThings.append(CGProxyIsProxy(descriptor))
|
||||||
cgThings.append(CGProxyUnwrap(descriptor))
|
cgThings.append(CGProxyUnwrap(descriptor))
|
||||||
cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor))
|
cgThings.append(CGDOMJSProxyHandlerDOMClass(descriptor))
|
||||||
|
cgThings.append(CGDOMJSProxyHandler_getOwnPropertyDescriptor(descriptor))
|
||||||
cgThings.append(CGDOMJSProxyHandler_obj_toString(descriptor))
|
cgThings.append(CGDOMJSProxyHandler_obj_toString(descriptor))
|
||||||
cgThings.append(CGDOMJSProxyHandler_get(descriptor))
|
cgThings.append(CGDOMJSProxyHandler_get(descriptor))
|
||||||
|
cgThings.append(CGDOMJSProxyHandler_hasOwn(descriptor))
|
||||||
|
if descriptor.operations['IndexedSetter'] or descriptor.operations['NamedSetter']:
|
||||||
|
cgThings.append(CGDOMJSProxyHandler_defineProperty(descriptor))
|
||||||
|
|
||||||
#cgThings.append(CGDOMJSProxyHandler(descriptor))
|
#cgThings.append(CGDOMJSProxyHandler(descriptor))
|
||||||
#cgThings.append(CGIsMethod(descriptor))
|
#cgThings.append(CGIsMethod(descriptor))
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -140,6 +140,7 @@ class Descriptor(DescriptorProvider):
|
||||||
|
|
||||||
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
self.nativeType = desc.get('nativeType', nativeTypeDefault)
|
||||||
self.pointerType = desc.get('pointerType', '@mut ')
|
self.pointerType = desc.get('pointerType', '@mut ')
|
||||||
|
self.concreteType = desc.get('concreteType', ifaceName)
|
||||||
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
self.hasInstanceInterface = desc.get('hasInstanceInterface', None)
|
||||||
|
|
||||||
# Do something sane for JSObject
|
# Do something sane for JSObject
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::utils::is_dom_proxy;
|
||||||
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
|
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
|
||||||
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
|
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
|
||||||
use js::glue::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra};
|
use js::jsapi::{JSBool, JS_DefinePropertyById, JS_NewObjectWithGivenProto};
|
||||||
use js::glue::{GetObjectProto};
|
use js::glue::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra, RUST_OBJECT_TO_JSVAL};
|
||||||
|
use js::glue::{GetObjectProto, GetObjectParent, SetProxyExtra, GetProxyHandler};
|
||||||
|
use js::glue::InvokeGetOwnPropertyDescriptor;
|
||||||
|
use js::crust::{JS_StrictPropertyStub};
|
||||||
|
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY, JSRESOLVE_QUALIFIED};
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::libc;
|
use std::libc;
|
||||||
|
@ -15,10 +20,13 @@ use std::sys::size_of;
|
||||||
|
|
||||||
type c_bool = libc::c_int;
|
type c_bool = libc::c_int;
|
||||||
|
|
||||||
|
static JSPROXYSLOT_EXPANDO: u32 = 0;
|
||||||
|
|
||||||
pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||||
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
if _getOwnPropertyDescriptor(cx, proxy, id, set, desc) == 0 {
|
let handler = GetProxyHandler(proxy);
|
||||||
|
if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, set, desc) == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*desc).obj.is_not_null() {
|
if (*desc).obj.is_not_null() {
|
||||||
|
@ -32,34 +40,30 @@ pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_GetPropertyDescriptorById(cx, proto, id, 0x01 /*JSRESOLVE_QUALIFIED*/,
|
JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, cast::transmute(desc))
|
||||||
cast::transmute(desc))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
pub extern fn defineProperty(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||||
_set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
desc: *JSPropertyDescriptor) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = GetProxyExtra(proxy, 0 /*JSPROXYSLOT_EXPANDO*/);
|
if ((*desc).attrs & JSPROP_GETTER) != 0 && (*desc).setter == JS_StrictPropertyStub {
|
||||||
if RUST_JSVAL_IS_VOID(v) == 0 {
|
/*return JS_ReportErrorFlagsAndNumber(cx,
|
||||||
let expando = RUST_JSVAL_TO_OBJECT(v);
|
JSREPORT_WARNING | JSREPORT_STRICT |
|
||||||
if JS_GetPropertyDescriptorById(cx, expando, id, 0x01 /*JSRESOLVE_QUALIFIED*/,
|
JSREPORT_STRICT_MODE_ERROR,
|
||||||
cast::transmute(desc)) == 0 {
|
js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_GETTER_ONLY);*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*desc).obj.is_not_null() {
|
|
||||||
(*desc).obj = proxy;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*desc).obj = ptr::null();
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern fn getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
let expando = EnsureExpandoObject(cx, proxy);
|
||||||
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
if expando.is_null() {
|
||||||
_getOwnPropertyDescriptor(cx, proxy, id, set, desc)
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_DefinePropertyById(cx, expando, id, (*desc).value, (*desc).getter,
|
||||||
|
(*desc).setter, (*desc).attrs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||||
|
@ -84,6 +88,39 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetExpandoObject(_proxy: *JSObject) -> *JSObject {
|
pub fn GetExpandoObject(obj: *JSObject) -> *JSObject {
|
||||||
|
unsafe {
|
||||||
|
assert!(is_dom_proxy(obj));
|
||||||
|
let val = GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||||
|
if RUST_JSVAL_IS_VOID(val) == 1 {
|
||||||
ptr::null()
|
ptr::null()
|
||||||
|
} else {
|
||||||
|
RUST_JSVAL_TO_OBJECT(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn EnsureExpandoObject(cx: *JSContext, obj: *JSObject) -> *JSObject {
|
||||||
|
unsafe {
|
||||||
|
assert!(is_dom_proxy(obj));
|
||||||
|
let mut expando = GetExpandoObject(obj);
|
||||||
|
if expando.is_null() {
|
||||||
|
expando = JS_NewObjectWithGivenProto(cx, ptr::null(), ptr::null(),
|
||||||
|
GetObjectParent(obj));
|
||||||
|
if expando.is_null() {
|
||||||
|
return ptr::null();
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, RUST_OBJECT_TO_JSVAL(expando));
|
||||||
|
}
|
||||||
|
return expando;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn FillPropertyDescriptor(desc: &mut JSPropertyDescriptor, obj: *JSObject, readonly: bool) {
|
||||||
|
desc.obj = obj;
|
||||||
|
desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
|
||||||
|
desc.getter = ptr::null();
|
||||||
|
desc.setter = ptr::null();
|
||||||
|
desc.shortid = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ fn is_dom_class(clasp: *JSClass) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dom_proxy(obj: *JSObject) -> bool {
|
pub fn is_dom_proxy(obj: *JSObject) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) &&
|
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) &&
|
||||||
IsProxyHandlerFamily(obj)
|
IsProxyHandlerFamily(obj)
|
||||||
|
@ -888,3 +888,9 @@ pub fn FindEnumStringIndex(cx: *JSContext,
|
||||||
return Err(()); //XXX pass in behaviour for value not found
|
return Err(()); //XXX pass in behaviour for value not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn HasPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid) -> bool {
|
||||||
|
// MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
|
||||||
|
let mut found = false;
|
||||||
|
return !GetPropertyOnPrototype(cx, proxy, id, &mut found, ptr::null()) || found;
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::codegen::DocumentBinding;
|
use dom::bindings::codegen::DocumentBinding;
|
||||||
use dom::bindings::utils::{DOMString, WrapperCache, ErrorResult, null_string};
|
use dom::bindings::utils::{DOMString, WrapperCache, ErrorResult, null_string, str};
|
||||||
use dom::bindings::utils::{BindingObject, CacheableWrapper, rust_box, DerivedWrapper};
|
use dom::bindings::utils::{BindingObject, CacheableWrapper, rust_box, DerivedWrapper};
|
||||||
use dom::element::{HTMLHtmlElement, HTMLHtmlElementTypeId, Element};
|
use dom::element::{HTMLHtmlElement, HTMLHtmlElementTypeId, Element};
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
|
@ -89,7 +89,8 @@ pub struct Document {
|
||||||
root: AbstractNode<ScriptView>,
|
root: AbstractNode<ScriptView>,
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
window: Option<@mut Window>,
|
window: Option<@mut Window>,
|
||||||
doctype: DocumentType
|
doctype: DocumentType,
|
||||||
|
title: ~str
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
|
@ -106,7 +107,8 @@ impl Document {
|
||||||
root: root,
|
root: root,
|
||||||
wrapper: WrapperCache::new(),
|
wrapper: WrapperCache::new(),
|
||||||
window: window,
|
window: window,
|
||||||
doctype: doctype
|
doctype: doctype,
|
||||||
|
title: ~""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,10 +285,14 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Title(&self) -> DOMString {
|
pub fn Title(&self) -> DOMString {
|
||||||
null_string
|
str(self.title.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn SetTitle(&self, _title: &DOMString, _rv: &mut ErrorResult) {
|
pub fn SetTitle(&mut self, title: &DOMString, _rv: &mut ErrorResult) {
|
||||||
|
self.title = match title {
|
||||||
|
&str(ref s) => s.clone(),
|
||||||
|
&null_string => ~""
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Dir(&self) -> DOMString {
|
pub fn Dir(&self) -> DOMString {
|
||||||
|
|
|
@ -53,6 +53,10 @@ impl HTMLCollection {
|
||||||
*found = true;
|
*found = true;
|
||||||
self.Item(index)
|
self.Item(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn NamedGetter(&self, _cx: *JSContext, _name: &DOMString, _found: &mut bool, _rv: &mut ErrorResult) -> *JSObject {
|
||||||
|
ptr::null()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BindingObject for HTMLCollection {
|
impl BindingObject for HTMLCollection {
|
||||||
|
|
|
@ -49,6 +49,10 @@ impl WrappableDocument for HTMLDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLDocument {
|
impl HTMLDocument {
|
||||||
|
pub fn NamedGetter(&self, _cx: *JSContext, _name: &DOMString, _found: &mut bool, _rv: &mut ErrorResult) -> *JSObject {
|
||||||
|
ptr::null()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn GetDomain(&self, _rv: &mut ErrorResult) -> DOMString {
|
pub fn GetDomain(&self, _rv: &mut ErrorResult) -> DOMString {
|
||||||
null_string
|
null_string
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,10 @@ impl Window {
|
||||||
pub fn ShowModalDialog(&self, _cx: *JSContext, _url: &DOMString, _argument: JSVal) -> JSVal {
|
pub fn ShowModalDialog(&self, _cx: *JSContext, _url: &DOMString, _argument: JSVal) -> JSVal {
|
||||||
JSVAL_NULL
|
JSVAL_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn NamedGetter(&self, _cx: *JSContext, _name: &DOMString, _found: &mut bool) -> *JSObject {
|
||||||
|
ptr::null()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheableWrapper for Window {
|
impl CacheableWrapper for Window {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit df2b9ae514ba76c616e7f58d9de0da545512cfe0
|
Subproject commit 70f74ad3ff1e6a83737569a9520a4b68e7405787
|
|
@ -120,6 +120,10 @@ window.alert(ev2.getModifierState("ctrl"));
|
||||||
window.alert(ev2 instanceof Event);
|
window.alert(ev2 instanceof Event);
|
||||||
window.alert(ev2 instanceof UIEvent);
|
window.alert(ev2 instanceof UIEvent);
|
||||||
|
|
||||||
|
window.alert(document.title);
|
||||||
|
document.title = "foo";
|
||||||
|
window.alert(document.title);
|
||||||
|
|
||||||
//TODO: Doesn't work until we throw proper exceptions instead of returning 0 on
|
//TODO: Doesn't work until we throw proper exceptions instead of returning 0 on
|
||||||
// unwrap failure.
|
// unwrap failure.
|
||||||
/*try {
|
/*try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue