Bug 1400275. Ensure we create reflectors for JS-implemented webidl interfaces with the right prototype when those interfaces are subclassed. r=qdot

MozReview-Commit-ID: 5yYD92NVVFQ
This commit is contained in:
Boris Zbarsky 2017-09-15 23:45:06 -04:00
parent 8e81160ff3
commit 15194f2f07
3 changed files with 47 additions and 5 deletions

View File

@ -7734,6 +7734,10 @@ class CGPerSignatureCall(CGThing):
needsUnwrap = True
needsUnwrappedVar = False
unwrappedVar = "obj"
if descriptor.interface.isJSImplemented():
# We need the desired proto in our constructor, because the
# constructor will actually construct our reflector.
argsPost.append("desiredProto")
elif descriptor.interface.isJSImplemented():
if not idlNode.isStatic():
needsUnwrap = True
@ -15335,8 +15339,10 @@ class CGJSImplMethod(CGJSImplMember):
def getArgs(self, returnType, argList):
if self.isConstructor:
# Skip the JSCompartment bits for constructors; it's handled
# manually in getImpl.
return CGNativeMember.getArgs(self, returnType, argList)
# manually in getImpl. But we do need our aGivenProto argument. We
# allow it to be omitted if the default proto is desired.
return (CGNativeMember.getArgs(self, returnType, argList) +
[Argument("JS::Handle<JSObject*>", "aGivenProto", "nullptr")])
return CGJSImplMember.getArgs(self, returnType, argList)
def getImpl(self):
@ -15349,10 +15355,14 @@ class CGJSImplMethod(CGJSImplMember):
raise TypeError("Named constructors are not supported for JS implemented WebIDL. See bug 851287.")
if len(self.signature[1]) != 0:
# The first two arguments to the constructor implementation are not
# arguments to the WebIDL constructor, so don't pass them to __Init()
# arguments to the WebIDL constructor, so don't pass them to
# __Init(). The last argument is the prototype we're supposed to
# use, and shouldn't get passed to __Init() either.
assert args[0].argType == 'const GlobalObject&'
assert args[1].argType == 'JSContext*'
constructorArgs = [arg.name for arg in args[2:]]
assert args[-1].argType == 'JS::Handle<JSObject*>'
assert args[-1].name == 'aGivenProto'
constructorArgs = [arg.name for arg in args[2:-1]]
constructorArgs.append("js::GetObjectCompartment(scopeObj)")
initCall = fill(
"""
@ -15360,7 +15370,7 @@ class CGJSImplMethod(CGJSImplMember):
JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx));
JS::Rooted<JS::Value> wrappedVal(cx);
if (!GetOrCreateDOMReflector(cx, impl, &wrappedVal)) {
if (!GetOrCreateDOMReflector(cx, impl, &wrappedVal, aGivenProto)) {
//XXX Assertion disabled for now, see bug 991271.
MOZ_ASSERT(true || JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);

View File

@ -81,3 +81,4 @@ skip-if = debug == false
skip-if = os == "android"
[test_stringBindings.html]
skip-if = debug == false
[test_jsimplemented_subclassing.html]

View File

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1400275
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1400275</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1400275 **/
class Foo extends RTCPeerConnection {
}
var obj = new Foo();
is(Object.getPrototypeOf(obj), Foo.prototype,
"Should have the right prototype");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1400275">Mozilla Bug 1400275</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>