From 15194f2f0709810e0add44ab6c39ad49ae766647 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 15 Sep 2017 23:45:06 -0400 Subject: [PATCH] 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 --- dom/bindings/Codegen.py | 20 +++++++++--- dom/bindings/test/mochitest.ini | 1 + .../test/test_jsimplemented_subclassing.html | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 dom/bindings/test/test_jsimplemented_subclassing.html diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 90badb235b30..5742c2a24dbd 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -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", "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' + 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 scopeObj(cx, globalHolder->GetGlobalJSObject()); MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx)); JS::Rooted 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); diff --git a/dom/bindings/test/mochitest.ini b/dom/bindings/test/mochitest.ini index 621bac5c70f6..6b082bbef018 100644 --- a/dom/bindings/test/mochitest.ini +++ b/dom/bindings/test/mochitest.ini @@ -81,3 +81,4 @@ skip-if = debug == false skip-if = os == "android" [test_stringBindings.html] skip-if = debug == false +[test_jsimplemented_subclassing.html] diff --git a/dom/bindings/test/test_jsimplemented_subclassing.html b/dom/bindings/test/test_jsimplemented_subclassing.html new file mode 100644 index 000000000000..3a5089c3942b --- /dev/null +++ b/dom/bindings/test/test_jsimplemented_subclassing.html @@ -0,0 +1,31 @@ + + + + + + Test for Bug 1400275 + + + + + +Mozilla Bug 1400275 +

+ +
+
+ +