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