Bug 798151. Support stringifier operations (but not yet attributes!) on non-proxy bindings, and fix Object.prototype.toString for proxy bindings. r=peterv

This commit is contained in:
Boris Zbarsky 2012-10-22 13:08:52 -04:00
parent 800cb6581d
commit e435c28e4e
4 changed files with 55 additions and 55 deletions

View File

@ -153,6 +153,11 @@ function testClassList(e) {
// [Stringifies]
ok(DOMTokenList.prototype.hasOwnProperty("toString"),
"Should have own toString on DOMTokenList")
ok(!DOMSettableTokenList.prototype.hasOwnProperty("toString"),
"Should not have own toString on DOMSettableTokenList")
e.removeAttribute("class");
is(e.classList.toString(), "", "wrong classList.toString() value");
is(e.classList + "", "", "wrong classList string conversion value");

View File

@ -1038,6 +1038,19 @@ class MethodDefiner(PropertyDefiner):
"flags": "0",
"pref": None })
if not static:
stringifier = descriptor.operations['Stringifier']
if stringifier:
toStringDesc = { "name": "toString",
"nativeName": stringifier.identifier.name,
"length": 0,
"flags": "JSPROP_ENUMERATE",
"pref": PropertyDefiner.getControllingPref(stringifier) }
if isChromeOnly(stringifier):
self.chrome.append(toStringDesc)
else:
self.regular.append(toStringDesc)
if static:
if not descriptor.interface.hasInterfaceObject():
# static methods go on the interface object
@ -1055,12 +1068,12 @@ class MethodDefiner(PropertyDefiner):
return m["pref"]
def specData(m):
accessor = m.get("nativeName", m["name"])
if m.get("methodInfo", True):
jitinfo = ("&%s_methodinfo" % m["name"])
jitinfo = ("&%s_methodinfo" % accessor)
accessor = "genericMethod"
else:
jitinfo = "nullptr"
accessor = m.get("nativeName", m["name"])
return (m["name"], accessor, jitinfo, m["length"], m["flags"])
return self.generatePrefableArray(
@ -5100,26 +5113,6 @@ class CGDOMJSProxyHandler_obj_toString(ClassMethod):
ClassMethod.__init__(self, "obj_toString", "JSString*", args)
self.descriptor = descriptor
def getBody(self):
stringifier = self.descriptor.operations['Stringifier']
if stringifier:
name = stringifier.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
signature = stringifier.signatures()[0]
returnType = signature[0]
extendedAttributes = self.descriptor.getExtendedAttributes(stringifier)
infallible = 'infallible' in extendedAttributes
if not infallible:
error = CGGeneric(
('ThrowMethodFailedWithDetails(cx, rv, "%s", "toString");\n' +
"return NULL;") % self.descriptor.interface.identifier.name)
else:
error = None
call = CGCallGenerator(error, [], "", returnType, extendedAttributes, self.descriptor, nativeName, False, object="UnwrapProxy(proxy)")
return call.define() + """
JSString* jsresult;
return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;"""
return "return mozilla::dom::DOMProxyHandler::obj_toString(cx, \"%s\");" % self.descriptor.name
class CGDOMJSProxyHandler_finalize(ClassMethod):
@ -5232,7 +5225,8 @@ class CGDescriptor(CGThing):
(hasMethod, hasGetter, hasLenientGetter,
hasSetter, hasLenientSetter) = False, False, False, False, False
for m in descriptor.interface.members:
if m.isMethod() and not m.isStatic() and not m.isIdentifierLess():
if (m.isMethod() and not m.isStatic() and
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True

View File

@ -190,28 +190,33 @@ class Descriptor(DescriptorProvider):
self.concrete = (not self.interface.isExternal() and
not self.interface.isCallback() and
desc.get('concrete', True))
operations = {
'IndexedGetter': None,
'IndexedSetter': None,
'IndexedCreator': None,
'IndexedDeleter': None,
'NamedGetter': None,
'NamedSetter': None,
'NamedCreator': None,
'NamedDeleter': None,
'Stringifier': None
}
if self.concrete:
self.proxy = False
operations = {
'IndexedGetter': None,
'IndexedSetter': None,
'IndexedCreator': None,
'IndexedDeleter': None,
'NamedGetter': None,
'NamedSetter': None,
'NamedCreator': None,
'NamedDeleter': None,
'Stringifier': None
}
iface = self.interface
def addOperation(operation, m):
if not operations[operation]:
operations[operation] = m
# Since stringifiers go on the prototype, we only need to worry
# about our own stringifier, not those of our ancestor interfaces.
for m in iface.members:
if m.isMethod() and m.isStringifier():
addOperation('Stringifier', m)
while iface:
for m in iface.members:
if not m.isMethod():
continue
def addOperation(operation, m):
if not operations[operation]:
operations[operation] = m
def addIndexedOrNamedOperation(operation, m):
self.proxy = True
if m.isIndexed():
@ -220,31 +225,28 @@ class Descriptor(DescriptorProvider):
assert m.isNamed()
operation = 'Named' + operation
addOperation(operation, m)
if m.isStringifier():
addOperation('Stringifier', m)
else:
if m.isGetter():
addIndexedOrNamedOperation('Getter', m)
if m.isSetter():
addIndexedOrNamedOperation('Setter', m)
if m.isCreator():
addIndexedOrNamedOperation('Creator', m)
if m.isDeleter():
addIndexedOrNamedOperation('Deleter', m)
raise TypeError("deleter specified on %s but we "
"don't support deleters yet" %
self.interface.identifier.name)
if m.isGetter():
addIndexedOrNamedOperation('Getter', m)
if m.isSetter():
addIndexedOrNamedOperation('Setter', m)
if m.isCreator():
addIndexedOrNamedOperation('Creator', m)
if m.isDeleter():
addIndexedOrNamedOperation('Deleter', m)
raise TypeError("deleter specified on %s but we "
"don't support deleters yet" %
self.interface.identifier.name)
iface.setUserData('hasConcreteDescendant', True)
iface = iface.parent
if self.proxy:
self.operations = operations
iface = self.interface
while iface:
iface.setUserData('hasProxyDescendant', True)
iface = iface.parent
self.operations = operations
if self.interface.isExternal() and 'prefable' in desc:
raise TypeError("%s is external but has a prefable setting" %

View File

@ -447,6 +447,5 @@
"DOMStringList interface: existence and properties of interface object": true,
"DOMStringList interface: existence and properties of interface prototype object": true,
"DOMStringList interface: existence and properties of interface prototype object's \"constructor\" property": true,
"DOMStringList interface: attribute length": true,
"Stringification of document.body.classList": true
"DOMStringList interface: attribute length": true
}