Bug 1052139 - Perform proper failure handling in interfaces' CreateInterfaceObjects method, after dom::CreateInterfaceObjects has been called and possibly created the interface's constructor and prototype. r=bz

--HG--
extra : rebase_source : 683614405bb61ff078e5504d9c2717a92ed2976e
This commit is contained in:
Jeff Walden 2015-09-29 09:31:42 -07:00
parent 1876c2cd4f
commit ddc5b08c61

View File

@ -2820,6 +2820,19 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
chromeProperties=chromeProperties,
name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
# If we fail after here, we must clear interface and prototype caches
# using this code: intermediate failure must not expose the interface in
# partially-constructed state. Note that every case after here needs an
# interface prototype object.
failureCode = dedent(
"""
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
""")
aliasedMembers = [m for m in self.descriptor.interface.members if m.isMethod() and m.aliases]
if aliasedMembers:
assert needInterfacePrototypeObject
@ -2839,17 +2852,18 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
prop = '"%s"' % alias
return CGList([
getSymbolJSID,
# XXX If we ever create non-enumerate properties that can be
# aliased, we should consider making the aliases match
# the enumerability of the property being aliased.
# XXX If we ever create non-enumerable properties that can
# be aliased, we should consider making the aliases
# match the enumerability of the property being aliased.
CGGeneric(fill(
"""
if (!${defineFn}(aCx, proto, ${prop}, aliasedVal, JSPROP_ENUMERATE)) {
return;
$*{failureCode}
}
""",
defineFn=defineFn,
prop=prop))
prop=prop,
failureCode=failureCode))
], "\n")
def defineAliasesFor(m):
@ -2857,21 +2871,23 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
CGGeneric(fill(
"""
if (!JS_GetProperty(aCx, proto, \"${prop}\", &aliasedVal)) {
return;
$*{failureCode}
}
""",
failureCode=failureCode,
prop=m.identifier.name))
] + [defineAlias(alias) for alias in sorted(m.aliases)])
defineAliases = CGList([
CGGeneric(dedent("""
CGGeneric(fill("""
// Set up aliases on the interface prototype object we just created.
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, aGlobal);
if (!proto) {
return;
$*{failureCode}
}
""")),
""",
failureCode=failureCode)),
CGGeneric("JS::Rooted<JS::Value> aliasedVal(aCx);\n\n")
] + [defineAliasesFor(m) for m in sorted(aliasedMembers)])
else:
@ -2897,14 +2913,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
else:
holderClass = "Class.ToJSClass()"
holderProto = "*protoCache"
failureCode = dedent(
"""
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
""")
createUnforgeableHolder = CGGeneric(fill(
"""
JS::Rooted<JSObject*> unforgeableHolder(aCx);