Bug 1309147 - Part 3: Implement the support for CEReactions in Codegen. r=bz
authorJohn Dai <jdai@mozilla.com>
Wed, 08 Mar 2017 17:11:48 +0800
changeset 401846 c41ec20ea0d4f0fc8305e36af72eb64cc17e4451
parent 401845 fe0ed97a8238f323bf909d9b1a8a6b4f6958c32e
child 401847 782add02e8633927cd280c429684cb4030a6b18d
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1309147
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1309147 - Part 3: Implement the support for CEReactions in Codegen. r=bz MozReview-Commit-ID: F1mxKzlru9s
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
dom/bindings/test/TestJSImplGen.webidl
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -55,16 +55,17 @@
 #include "mozilla/dom/WebIDLGlobalNameHash.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/XrayExpandoClass.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsDOMClassInfo.h"
 #include "ipc/ErrorIPCUtils.h"
 #include "mozilla/UseCounter.h"
+#include "mozilla/dom/DocGroup.h"
 
 namespace mozilla {
 namespace dom {
 
 using namespace workers;
 
 // Forward declare GetConstructorObject methods.
 #define HTML_TAG(_tag, _classname, _interfacename)                             \
@@ -3392,16 +3393,38 @@ GetDesiredProto(JSContext* aCx, const JS
     aDesiredProto.set(nullptr);
     return true;
   }
 
   aDesiredProto.set(&protoVal.toObject());
   return true;
 }
 
+CustomElementReactionsStack*
+GetCustomElementReactionsStack(JS::Handle<JSObject*> aObj)
+{
+  // This might not be the right object, if there are wrappers. Unwrap if we can.
+  JSObject* obj = js::CheckedUnwrap(aObj);
+  if (!obj) {
+    return nullptr;
+  }
+
+  nsGlobalWindow* window = xpc::WindowGlobalOrNull(obj);
+  if (!window) {
+    return nullptr;
+  }
+
+  DocGroup* docGroup = window->AsInner()->GetDocGroup();
+  if (!docGroup) {
+    return nullptr;
+  }
+
+  return docGroup->CustomElementReactionsStack();
+}
+
 // https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor
 already_AddRefed<nsGenericHTMLElement>
 CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
                   ErrorResult& aRv)
 {
   // Step 1.
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -44,16 +44,17 @@
 class nsGenericHTMLElement;
 class nsIJSID;
 
 namespace mozilla {
 
 enum UseCounter : int16_t;
 
 namespace dom {
+class CustomElementReactionsStack;
 template<typename KeyType, typename ValueType> class Record;
 
 nsresult
 UnwrapArgImpl(JSContext* cx, JS::Handle<JSObject*> src, const nsIID& iid,
               void** ppArg);
 
 nsresult
 UnwrapWindowProxyImpl(JSContext* cx, JS::Handle<JSObject*> src,
@@ -3191,16 +3192,22 @@ bool GetSetlikeBackingObject(JSContext* 
                              bool* aBackingObjCreated);
 
 // Get the desired prototype object for an object construction from the given
 // CallArgs.  Null is returned if the default prototype should be used.
 bool
 GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
                 JS::MutableHandle<JSObject*> aDesiredProto);
 
+// Get the CustomElementReactionsStack for the docgroup of the global
+// of the underlying object of aObj.  This can be null if aObj can't
+// be CheckUnwrapped, or if the global of the result has no docgroup
+// (e.g. because it's not a Window global).
+CustomElementReactionsStack*
+GetCustomElementReactionsStack(JS::Handle<JSObject*> aObj);
 // This function is expected to be called from the constructor function for an
 // HTML element interface; the global/callargs need to be whatever was passed to
 // that constructor function.
 already_AddRefed<nsGenericHTMLElement>
 CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
                   ErrorResult& aRv);
 
 void
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1691,16 +1691,20 @@ DOMInterfaces = {
         'register': False,
         },
 
 'TestHTMLConstructorInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         },
 
+'TestCEReactionsInterface' : {
+        'headerFile': 'TestBindingHeader.h',
+        'register': False,
+        },
 }
 
 # These are temporary, until they've been converted to use new DOM bindings
 def addExternalIface(iface, nativeType=None, headerFile=None,
                      notflattened=False):
     if iface in DOMInterfaces:
         raise Exception('Interface declared both as WebIDL and External interface')
     domInterface = {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7696,16 +7696,27 @@ class CGPerSignatureCall(CGThing):
                 xraySteps.extend(
                     wrapArgIntoCurrentCompartment(arg, argname, isMember=False)
                     for arg, argname in self.getArguments())
 
             cgThings.append(
                 CGIfWrapper(CGList(xraySteps),
                             "objIsXray"))
 
+        if (idlNode.getExtendedAttribute('CEReactions') is not None and
+            not getter):
+            cgThings.append(CGGeneric(fill(
+                """
+                CustomElementReactionsStack* reactionsStack = GetCustomElementReactionsStack(${obj});
+                Maybe<AutoCEReaction> ceReaction;
+                if (reactionsStack) {
+                  ceReaction.emplace(reactionsStack);
+                }
+                """, obj=objectName)))
+
         # If this is a method that was generated by a maplike/setlike
         # interface, use the maplike/setlike generator to fill in the body.
         # Otherwise, use CGCallGenerator to call the native method.
         if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeOrIterableMethod():
             if (idlNode.maplikeOrSetlikeOrIterable.isMaplike() or
                 idlNode.maplikeOrSetlikeOrIterable.isSetlike()):
                 cgThings.append(CGMaplikeOrSetlikeMethodGenerator(descriptor,
                                                                   idlNode.maplikeOrSetlikeOrIterable,
@@ -13992,22 +14003,28 @@ class CGBindingRoot(CGThing):
         def descriptorRequiresPreferences(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface])
 
         def descriptorDeprecated(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Deprecated") for m in iface.members + [iface])
 
+        def descriptorHasCEReactions(desc):
+            iface = desc.interface
+            return any(m.getExtendedAttribute("CEReactions") for m in iface.members + [iface])
+
         bindingHeaders["nsIDocument.h"] = any(
             descriptorDeprecated(d) for d in descriptors)
         bindingHeaders["mozilla/Preferences.h"] = any(
             descriptorRequiresPreferences(d) for d in descriptors)
         bindingHeaders["mozilla/dom/DOMJSProxyHandler.h"] = any(
             d.concrete and d.proxy for d in descriptors)
+        bindingHeaders["mozilla/dom/CustomElementRegistry.h"] = any(
+            descriptorHasCEReactions(d) for d in descriptors)
 
         def descriptorHasChromeOnly(desc):
             ctor = desc.interface.ctor()
 
             return (any(isChromeOnly(a) or needsContainsHack(a) or
                         needsCallerType(a)
                         for a in desc.interface.members) or
                     desc.interface.getExtendedAttribute("ChromeOnly") is not None or
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -959,16 +959,21 @@ public:
   bool CanOOMSetterAttr() const;
   void SetCanOOMSetterAttr(bool arg, OOMReporter& aRv);
   void NeedsSubjectPrincipalMethod(nsIPrincipal&);
   bool NeedsSubjectPrincipalAttr(nsIPrincipal&);
   void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&);
   void NeedsCallerTypeMethod(CallerType);
   bool NeedsCallerTypeAttr(CallerType);
   void SetNeedsCallerTypeAttr(bool, CallerType);
+  void CeReactionsMethod();
+  void CeReactionsMethodOverload();
+  void CeReactionsMethodOverload(const nsAString&);
+  bool CeReactionsAttr() const;
+  void SetCeReactionsAttr(bool);
   int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&);
   void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&,
                             TestInterface*, const Dict&, double,
                             const Optional<float>&);
 
   void SetDashed_attribute(int8_t);
   int8_t Dashed_attribute();
   void Dashed_method();
@@ -1451,12 +1456,31 @@ public:
 };
 
 class TestHTMLConstructorInterface : public nsGenericHTMLElement
 {
 public:
   virtual nsISupports* GetParentObject();
 };
 
+class TestCEReactionsInterface : public nsISupports,
+                                 public nsWrapperCache
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  // We need a GetParentObject to make binding codegen happy
+  virtual nsISupports* GetParentObject();
+
+  int32_t Item(uint32_t);
+  uint32_t Length() const;
+  int32_t IndexedGetter(uint32_t, bool &);
+  void IndexedSetter(uint32_t, int32_t);
+  void NamedDeleter(const nsAString&, bool &);
+  void NamedGetter(const nsAString&, bool &, nsString&);
+  void NamedSetter(const nsAString&, const nsAString&);
+  void GetSupportedNames(nsTArray<nsString>&);
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif /* TestBindingHeader_h */
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -952,16 +952,20 @@ interface TestInterface {
   [CanOOM] void canOOMMethod();
   [CanOOM] attribute boolean canOOMAttr;
   [GetterCanOOM] attribute boolean canOOMGetterAttr;
   [SetterCanOOM] attribute boolean canOOMSetterAttr;
   [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
   [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   [NeedsCallerType] void needsCallerTypeMethod();
   [NeedsCallerType] attribute boolean needsCallerTypeAttr;
+  [CEReactions] void ceReactionsMethod();
+  [CEReactions] void ceReactionsMethodOverload();
+  [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+  [CEReactions] attribute boolean ceReactionsAttr;
   legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
 
   attribute any jsonifierShouldSkipThis;
   attribute TestParentInterface jsonifierShouldSkipThis2;
@@ -1285,8 +1289,17 @@ interface TestWorkerExposedInterface {
   [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   [NeedsCallerType] void needsCallerTypeMethod();
   [NeedsCallerType] attribute boolean needsCallerTypeAttr;
 };
 
 [HTMLConstructor]
 interface TestHTMLConstructorInterface {
 };
+
+interface TestCEReactionsInterface {
+  [CEReactions] setter creator void (unsigned long index, long item);
+  [CEReactions] setter creator void (DOMString name, DOMString item);
+  [CEReactions] deleter void (DOMString name);
+  getter long item(unsigned long index);
+  getter DOMString (DOMString name);
+  readonly attribute unsigned long length;
+};
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -780,16 +780,20 @@ interface TestExampleInterface {
   [CanOOM] void canOOMMethod();
   [CanOOM] attribute boolean canOOMAttr;
   [GetterCanOOM] attribute boolean canOOMGetterAttr;
   [SetterCanOOM] attribute boolean canOOMSetterAttr;
   [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
   [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   [NeedsCallerType] void needsCallerTypeMethod();
   [NeedsCallerType] attribute boolean needsCallerTypeAttr;
+  [CEReactions] void ceReactionsMethod();
+  [CEReactions] void ceReactionsMethodOverload();
+  [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+  [CEReactions] attribute boolean ceReactionsAttr;
   legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
   attribute any jsonifierShouldSkipThis;
   attribute TestParentInterface jsonifierShouldSkipThis2;
   attribute TestCallbackInterface jsonifierShouldSkipThis3;
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -796,16 +796,20 @@ interface TestJSImplInterface {
   [Throws] void throwingMethod();
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
   [CanOOM] void canOOMMethod();
   [CanOOM] attribute boolean canOOMAttr;
   [GetterCanOOM] attribute boolean canOOMGetterAttr;
   [SetterCanOOM] attribute boolean canOOMSetterAttr;
+  [CEReactions] void ceReactionsMethod();
+  [CEReactions] void ceReactionsMethodOverload();
+  [CEReactions] void ceReactionsMethodOverload(DOMString bar);
+  [CEReactions] attribute boolean ceReactionsAttr;
   // NeedsSubjectPrincipal not supported on JS-implemented things for
   // now, because we always pass in the caller principal anyway.
   //  [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
   //  [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   // legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,