Bug 753517 part 4. Set up auto-generation of CSS2Properties.webidl from nsCSSPropList.h and enable Paris bindings for CSSStyleDeclaration and CSS2Properties. r=khuey,peterv,dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 23 Aug 2012 21:08:09 -0700
changeset 105395 c526d9dfb684d8d7c053157861b9c147e8c5b0cb
parent 105394 75f3cd90e74364a16d8d3f5674a81974274e946e
child 105396 dc3f29a730b10ace9129d2605c7a40822ee8121f
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewerskhuey, peterv, dbaron
bugs753517
milestone17.0a1
Bug 753517 part 4. Set up auto-generation of CSS2Properties.webidl from nsCSSPropList.h and enable Paris bindings for CSSStyleDeclaration and CSS2Properties. r=khuey,peterv,dbaron
dom/bindings/Bindings.conf
dom/bindings/GenerateCSS2PropertiesWebIDL.py
dom/bindings/Makefile.in
dom/tests/mochitest/bugs/test_bug529328.html
dom/webidl/CSS2Properties.webidl.in
dom/webidl/CSS2PropertiesProps.h
dom/webidl/CSSStyleDeclaration.webidl
dom/webidl/WebIDL.mk
js/xpconnect/tests/chrome/test_weakmaps.xul
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
layout/style/nsDOMCSSDeclaration.h
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -77,16 +77,26 @@ DOMInterfaces = {
     ],
     'resultNotAddRefed': [ 'canvas' ],
     'binaryNames': {
         'mozImageSmoothingEnabled': 'imageSmoothingEnabled',
         'mozFillRule': 'fillRule'
     }
 }],
 
+'CSS2Properties': {
+  'nativeType': 'nsDOMCSSDeclaration',
+  'prefable': True,
+},
+
+'CSSStyleDeclaration': {
+  'nativeType': 'nsICSSDeclaration',
+  'prefable': True
+},
+
 'Document': [
 {
     'nativeType': 'nsIDocument',
 },
 {
     'workers': True,
     'nativeType': 'JSObject',
     'headerFile': 'jsapi.h',
@@ -368,16 +378,18 @@ def addExternalHTMLElement(element):
    addExternalIface(element, nativeType=nativeElement,
                     headerFile=nativeElement + '.h')
 
 addExternalHTMLElement('HTMLCanvasElement')
 addExternalHTMLElement('HTMLImageElement')
 addExternalHTMLElement('HTMLVideoElement')
 addExternalIface('CanvasGradient', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('CanvasPattern', headerFile='nsIDOMCanvasRenderingContext2D.h')
+addExternalIface('CSSRule')
+addExternalIface('CSSValue')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
 addExternalIface('TextMetrics', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('WebGLActiveInfo', nativeType='mozilla::WebGLActiveInfo',
                  headerFile='WebGLContext.h')
 addExternalIface('WebGLBuffer', nativeType='mozilla::WebGLBuffer',
                  headerFile='WebGLContext.h')
 addExternalIface('WebGLContextAttributes', nativeType='JSObject',
new file mode 100644
--- /dev/null
+++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
@@ -0,0 +1,22 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import sys
+import string
+
+propList = eval(sys.stdin.read())
+props = ""
+for [prop, pref] in propList:
+    pref = '[Pref=%s] ' % pref if pref is not "" else ""
+    if not prop.startswith("Moz"):
+        prop = prop[0].lower() + prop[1:]
+    # Unfortunately, even some of the getters here are fallible
+    # (e.g. on nsComputedDOMStyle).
+    props += "  %sattribute DOMString %s;\n" % (pref, prop)
+
+idlFile = open(sys.argv[1], "r");
+idlTemplate = idlFile.read();
+idlFile.close();
+
+print string.Template(idlTemplate).substitute({ "props": props })
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -17,17 +17,17 @@ EXPORT_LIBRARY   = 1
 include $(topsrcdir)/config/config.mk
 
 # Need this to find all our DOM source files.
 include $(topsrcdir)/dom/dom-config.mk
 
 include $(topsrcdir)/dom/webidl/WebIDL.mk
 
 binding_include_path := mozilla/dom
-all_webidl_files = $(webidl_files)
+all_webidl_files = $(webidl_files) $(generated_webidl_files)
 # Set exported_binding_headers before adding the test IDL to the mix
 exported_binding_headers := $(subst .webidl,Binding.h,$(all_webidl_files))
 # Set linked_binding_cpp_files before adding the test IDL to the mix
 linked_binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files))
 
 all_webidl_files += $(test_webidl_files)
 
 binding_header_files := $(subst .webidl,Binding.h,$(all_webidl_files))
@@ -83,16 +83,26 @@ bindinggen_dependencies := \
   Bindings.conf \
   Configuration.py \
   Codegen.py \
   parser/WebIDL.py \
   ParserResults.pkl \
   $(GLOBAL_DEPS) \
   $(NULL)
 
+CSS2Properties.webidl: $(topsrcdir)/layout/style/nsCSSPropList.h \
+                       $(topsrcdir)/layout/style/nsCSSPropAliasList.h \
+                       $(webidl_base)/CSS2Properties.webidl.in \
+                       $(webidl_base)/CSS2PropertiesProps.h \
+                       $(srcdir)/GenerateCSS2PropertiesWebIDL.py \
+                       $(GLOBAL_DEPS)
+	$(CPP) -I$(topsrcdir)/layout/style $(webidl_base)/CSS2PropertiesProps.h | \
+	  PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \
+	  $(srcdir)/GenerateCSS2PropertiesWebIDL.py $(webidl_base)/CSS2Properties.webidl.in > CSS2Properties.webidl
+
 $(webidl_files): %: $(webidl_base)/%
 	$(INSTALL) $(IFLAGS1) $(webidl_base)/$* .
 
 $(test_webidl_files): %: $(srcdir)/test/%
 	$(INSTALL) $(IFLAGS1) $(srcdir)/test/$* .
 
 $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
                                      %.webidl \
--- a/dom/tests/mochitest/bugs/test_bug529328.html
+++ b/dom/tests/mochitest/bugs/test_bug529328.html
@@ -96,41 +96,31 @@ function testMediaList() {
   is(s.sheet.media.item(0), "a", "Wrong value for in bounds access (MediaList)");
   is(s.sheet.media.item(1), "b", "Wrong value for in bounds access (MediaList)");
   is(s.sheet.media.item(2), null, "Wrong value for out of bounds access (MediaList) (MediaList)");
 }
 
 function testCSSStyleDeclaration() {
   var s = document.createElement("span");
 
-  try {
-    is(s.style[-1], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
-    todo(true, "Didn't throw");
-  } catch (e) {
-    todo(false, "Shouldn't throw");
-  }
-  is(s.style[0], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
-  is(s.style[1], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
-  is(s.style[2], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
+  is(s.style[-1], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
+  is(s.style[0], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
+  is(s.style[1], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
+  is(s.style[2], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(-1), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(0), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(1), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(2), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
 
   s.setAttribute("style", "color: blue; z-index: 42;");
 
-  try {
-    is(s.style[-1], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
-    todo(true, "Didn't throw");
-  } catch (e) {
-    todo(false, "Shouldn't throw");
-  }
+  is(s.style[-1], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style[0], "color", "Wrong value for in bounds access (CSSStyleDeclaration)");
   is(s.style[1], "z-index", "Wrong value for in bounds access (CSSStyleDeclaration)");
-  is(s.style[2], "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
+  is(s.style[2], undefined, "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(-1), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
   is(s.style.item(0), "color", "Wrong value for in bounds access (CSSStyleDeclaration)");
   is(s.style.item(1), "z-index", "Wrong value for in bounds access (CSSStyleDeclaration)");
   is(s.style.item(2), "", "Wrong value for out of bounds access (CSSStyleDeclaration)");
 }
 
 testDOMTokenList();
 testDOMStringList();
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSS2Properties.webidl.in
@@ -0,0 +1,3 @@
+interface CSS2Properties : CSSStyleDeclaration {
+${props}
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSS2PropertiesProps.h
@@ -0,0 +1,34 @@
+/* A file meant as input to the preprocessor only */
+
+/* DO_PROP serves as an extra level of indirection to allow expansion
+   of CSS_PROP_DOMPROP_PREFIXED */
+
+[
+
+#define DO_PROP(method, pref) \
+  [ #method, pref ],
+#define CSS_PROP(name, id, method, flags, pref, parsevariant, kwtable, \
+		 stylestruct, stylestructofset, animtype) \
+  DO_PROP(method, pref)
+#define CSS_PROP_SHORTHAND(name, id, method, flags, pref) \
+  DO_PROP(method, pref)
+#define CSS_PROP_DOMPROP_PREFIXED(val) Moz##val
+#define CSS_PROP_LIST_EXCLUDE_INTERNAL
+
+#include "nsCSSPropList.h"
+
+#undef CSS_PROP_LIST_EXCLUDE_INTERNAL
+#undef CSS_PROP_DOMPROP_PREFIXED
+#undef CSS_PROP_SHORTHAND
+#undef CSS_PROP
+
+#define CSS_PROP_ALIAS(name, id, method, pref) \
+  DO_PROP(method, pref)
+
+#include "nsCSSPropAliasList.h"
+
+#undef CSS_PROP_ALIAS
+
+#undef DO_PROP
+
+]
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSStyleDeclaration.webidl
@@ -0,0 +1,34 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/csswg/cssom/
+ */
+
+interface CSSRule;
+interface CSSValue;
+
+interface CSSStyleDeclaration {
+  [GetterInfallible]
+  attribute DOMString cssText;
+
+  [Infallible]
+  readonly attribute unsigned long length;
+  [Infallible]
+  getter DOMString item(unsigned long index);
+
+  DOMString getPropertyValue(DOMString property);
+  // Mozilla extension, sort of
+  CSSValue getPropertyCSSValue(DOMString property);
+  [Infallible]
+  DOMString getPropertyPriority(DOMString property);
+  // This would be nicer if it used a string default value of "".
+  // See bug 759622.
+  void setProperty(DOMString property, DOMString value, [TreatNullAs=EmptyString] optional DOMString priority);
+  DOMString removeProperty(DOMString property);
+
+  [Infallible]
+  readonly attribute CSSRule parentRule;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -1,16 +1,21 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 webidl_base = $(topsrcdir)/dom/webidl
 
+generated_webidl_files = \
+  CSS2Properties.webidl \
+  $(NULL)
+
 webidl_files = \
   CanvasRenderingContext2D.webidl \
+  CSSStyleDeclaration.webidl \
   Function.webidl \
   EventListener.webidl \
   EventTarget.webidl \
   Performance.webidl \
   PerformanceNavigation.webidl \
   PerformanceTiming.webidl \
   XMLHttpRequest.webidl \
   XMLHttpRequestEventTarget.webidl \
--- a/js/xpconnect/tests/chrome/test_weakmaps.xul
+++ b/js/xpconnect/tests/chrome/test_weakmaps.xul
@@ -215,24 +215,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   let unpreservable_native_key = function () {
     // We only allow natives that support wrapper preservation to be used as weak
     // map keys.  We should be able to try to add unpreservable natives as keys without
     // crashing (bug 711616), but we should throw an error (bug 761620).
 
     let dummy_test_map = new WeakMap;
 
-    let div_fail = false;
-    try {
-      dummy_test_map.set(document.createElement("div").style, 1);
-    } catch (e) {
-      div_fail = true;
-    }
-    ok(div_fail, "Using elem.style as a weak map key should produce an exception because it can't be wrapper preserved.");
-
     let navi_fail = false;
     try {
       dummy_test_map.set(window.navigator, 1);
     } catch (e) {
       navi_fail = true;
     }
     ok(navi_fail, "Using window.navigator as a weak map key should produce an exception because it can't be wrapper preserved.");
 
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -30,16 +30,17 @@
 #include "nsContentUtils.h"
 #include "nsStyleConsts.h"
 #include "nsError.h"
 #include "nsStyleUtil.h"
 #include "mozilla/css/Declaration.h"
 #include "nsCSSParser.h"
 #include "nsPrintfCString.h"
 #include "nsDOMClassInfoID.h"
+#include "mozilla/dom/CSSStyleDeclarationBinding.h"
 
 namespace css = mozilla::css;
 
 #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
 /* virtual */ nsIDOMCSSRule* class_::GetDOMRule() \
   { return this; }
 #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \
 /* virtual */ void class_::MapRuleInfoInto(nsRuleData* aRuleData) \
@@ -1614,16 +1615,24 @@ nsCSSFontFaceStyleDecl::SetPropertyValue
 }
 
 nsINode*
 nsCSSFontFaceStyleDecl::GetParentObject()
 {
   return ContainingRule()->GetDocument();
 }
 
+JSObject*
+nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx, JSObject *scope,
+                                   bool *triedToWrap)
+{
+  return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, scope, this,
+                                                        triedToWrap);
+}
+
 // -------------------------------------------
 // nsCSSFontFaceRule
 // 
 
 /* virtual */ already_AddRefed<css::Rule>
 nsCSSFontFaceRule::Clone() const
 {
   nsRefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -159,22 +159,30 @@ protected:
 class nsCSSFontFaceRule;
 class nsCSSFontFaceStyleDecl : public nsICSSDeclaration
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMCSSSTYLEDECLARATION
   NS_DECL_NSICSSDECLARATION
 
+  nsCSSFontFaceStyleDecl()
+  {
+    SetIsDOMBinding();
+  }
+
   virtual nsINode *GetParentObject();
   virtual void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aPropName);
 
   nsresult GetPropertyValue(nsCSSFontDesc aFontDescID,
                             nsAString & aResult) const;
 
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap);
+
 protected:
   friend class nsCSSFontFaceRule;
 #define CSS_FONT_DESC(name_, method_) nsCSSValue m##method_;
 #include "nsCSSFontDescList.h"
 #undef CSS_FONT_DESC
 
   static nsCSSValue nsCSSFontFaceStyleDecl::* const Fields[];  
   inline nsCSSFontFaceRule* ContainingRule();
--- a/layout/style/nsDOMCSSDeclaration.h
+++ b/layout/style/nsDOMCSSDeclaration.h
@@ -6,16 +6,17 @@
 /* base class for DOM objects for element.style and cssStyleRule.style */
 
 #ifndef nsDOMCSSDeclaration_h___
 #define nsDOMCSSDeclaration_h___
 
 #include "nsICSSDeclaration.h"
 #include "nsIDOMCSS2Properties.h"
 #include "nsCOMPtr.h"
+#include "mozilla/dom/CSS2PropertiesBinding.h"
 
 class nsCSSParser;
 class nsIURI;
 class nsIPrincipal;
 class nsIDocument;
 
 namespace mozilla {
 namespace css {
@@ -91,16 +92,23 @@ public:
 
 #undef CSS_PROP_SHORTHAND
 #undef CSS_PROP_LIST_EXCLUDE_INTERNAL
 #undef CSS_PROP
 #undef CSS_PROP_DOMPROP_PREFIXED
 
   virtual void IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aPropName);
 
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap)
+  {
+    return mozilla::dom::CSS2PropertiesBinding::Wrap(cx, scope, this,
+                                                     triedToWrap);
+  }
+
 protected:
   // This method can return null regardless of the value of aAllocate;
   // however, a null return should only be considered a failure
   // if aAllocate is true.
   virtual mozilla::css::Declaration* GetCSSDeclaration(bool aAllocate) = 0;
   virtual nsresult SetCSSDeclaration(mozilla::css::Declaration* aDecl) = 0;
   // Document that we must call BeginUpdate/EndUpdate on around the
   // calls to SetCSSDeclaration and the style rule mutation that leads
@@ -136,11 +144,15 @@ protected:
                               bool aIsImportant);
 
   // Prop-id based version of RemoveProperty.  Note that this does not
   // return the old value; it just does a straight removal.
   nsresult RemoveProperty(const nsCSSProperty aPropID);
 
 protected:
   virtual ~nsDOMCSSDeclaration();
+  nsDOMCSSDeclaration()
+  {
+    SetIsDOMBinding();
+  }
 };
 
 #endif // nsDOMCSSDeclaration_h___