Bug 985536 - Go back to allowing optional any with no default value in WebIDL, but treat it as having a default value of undefined. r=khuey, a=lsblakk
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 03 Apr 2014 23:32:11 -0400
changeset 192694 81e476d9599c88511528853a2c6597a3da2811d8
parent 192693 197474c0eb2f185533c9ab4915228b1a0931c748
child 192695 1e80ec83f5b320dbdcf5a9400d508effd07281f7
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, lsblakk
bugs985536
milestone30.0a2
Bug 985536 - Go back to allowing optional any with no default value in WebIDL, but treat it as having a default value of undefined. r=khuey, a=lsblakk
dom/bindings/parser/WebIDL.py
dom/bindings/parser/tests/test_method.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
dom/bindings/test/TestJSImplGen.webidl
dom/imptests/html/dom/test_interfaces.html
dom/webidl/Console.webidl
dom/webidl/HTMLCanvasElement.webidl
dom/webidl/IDBCursor.webidl
dom/webidl/IDBIndex.webidl
dom/webidl/IDBObjectStore.webidl
dom/webidl/Promise.webidl
dom/webidl/RTCStatsReport.webidl
dom/webidl/TestInterfaceJS.webidl
dom/webidl/Window.webidl
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2924,26 +2924,18 @@ class IDLArgument(IDLObjectWithIdentifie
              self.type.isUnion() and self.type.unroll().hasDictionaryType) and
             self.optional and not self.defaultValue):
             # Default optional dictionaries to null, for simplicity,
             # so the codegen doesn't have to special-case this.
             self.defaultValue = IDLNullValue(self.location)
         elif self.type.isAny():
             assert (self.defaultValue is None or
                     isinstance(self.defaultValue, IDLNullValue))
-            if (self.optional and not self.variadic and
-                not self.dictionaryMember and not self.defaultValue):
-                raise WebIDLError("Arguments of type 'any' are always optional "
-                                  "and shouldn't have the 'optional' keyword "
-                                  "unless they're being given a default value "
-                                  "of 'null'",
-                                  [self.location])
-            # 'any' values are always optional.
-            self.optional = True
-            if not self.defaultValue and not self.variadic:
+            # optional 'any' values always have a default value
+            if self.optional and not self.defaultValue and not self.variadic:
                 # Set the default value to undefined, for simplicity, so the
                 # codegen doesn't have to special-case this.
                 self.defaultValue = IDLUndefinedValue(self.location)
 
         # Now do the coercing thing; this needs to happen after the
         # above creation of a default value.
         if self.defaultValue:
             self.defaultValue = self.defaultValue.coerceToType(self.type,
@@ -4316,19 +4308,19 @@ class Parser(Tokenizer):
         optional = p[2]
         variadic = p[4]
         defaultValue = p[6]
 
         if not optional and defaultValue:
             raise WebIDLError("Mandatory arguments can't have a default value.",
                               [self.getLocation(p, 6)])
 
-        # We can't test t.isAny() here and force optional to true, since at this
-        # point t is not a fully resolved type yet (e.g. it might be a typedef).
-        # We'll handle the 'any' case in IDLArgument.complete.
+        # We can't test t.isAny() here and give it a default value as needed,
+        # since at this point t is not a fully resolved type yet (e.g. it might
+        # be a typedef).  We'll handle the 'any' case in IDLArgument.complete.
 
         if variadic:
             if optional:
                 raise WebIDLError("Variadic arguments should not be marked optional.",
                                   [self.getLocation(p, 2)])
             optional = variadic
 
         p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
--- a/dom/bindings/parser/tests/test_method.py
+++ b/dom/bindings/parser/tests/test_method.py
@@ -107,17 +107,17 @@ def WebIDLTest(parser, harness):
                 "getObject", [("Object", [])])
     checkMethod(methods[10], "::TestMethods::setObject",
                 "setObject",
        [("Void",
         [("::TestMethods::setObject::arg1", "arg1", "Object", False, False)])])
     checkMethod(methods[11], "::TestMethods::setAny",
                 "setAny",
        [("Void",
-        [("::TestMethods::setAny::arg1", "arg1", "Any", True, False)])])
+        [("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])])
     checkMethod(methods[12], "::TestMethods::doFloats",
                 "doFloats",
        [("Float",
         [("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])])
 
     parser = parser.reset()
     threw = False
     try:
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -461,16 +461,17 @@ public:
   void SetTreatAsNullCallback(TestTreatAsNullCallback&);
   already_AddRefed<TestTreatAsNullCallback> TreatAsNullCallback();
   void SetNullableTreatAsNullCallback(TestTreatAsNullCallback*);
   already_AddRefed<TestTreatAsNullCallback> GetNullableTreatAsNullCallback();
 
   // Any types
   void PassAny(JSContext*, JS::Handle<JS::Value>);
   void PassVariadicAny(JSContext*, const Sequence<JS::Value>&);
+  void PassOptionalAny(JSContext*, JS::Handle<JS::Value>);
   void PassAnyDefaultNull(JSContext*, JS::Handle<JS::Value>);
   void PassSequenceOfAny(JSContext*, const Sequence<JS::Value>&);
   void PassNullableSequenceOfAny(JSContext*, const Nullable<Sequence<JS::Value> >&);
   void PassOptionalSequenceOfAny(JSContext*, const Optional<Sequence<JS::Value> >&);
   void PassOptionalNullableSequenceOfAny(JSContext*, const Optional<Nullable<Sequence<JS::Value> > >&);
   void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, const Nullable<Sequence<JS::Value> >&);
   void PassSequenceOfSequenceOfAny(JSContext*, const Sequence<Sequence<JS::Value> >&);
   void PassSequenceOfNullableSequenceOfAny(JSContext*, const Sequence<Nullable<Sequence<JS::Value> > >&);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -105,18 +105,17 @@ interface OnlyForUseInConstructor {
  Constructor(TestInterface? iface),
  Constructor(long arg1, IndirectlyImplementedInterface iface),
  Constructor(Date arg1),
  // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
  AvailableIn=CertifiedApps,
  NamedConstructor=Test,
  NamedConstructor=Test(DOMString str),
  NamedConstructor=Test2(DictForConstructor dict, any any1, object obj1,
-                        object? obj2, sequence<Dict> seq,
-                        optional any any2 = null,
+                        object? obj2, sequence<Dict> seq, optional any any2,
                         optional object obj3, optional object? obj4)
  ]
 interface TestInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
@@ -424,16 +423,17 @@ interface TestInterface {
   void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
   attribute TestTreatAsNullCallback treatAsNullCallback;
   attribute TestTreatAsNullCallback? nullableTreatAsNullCallback;
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
+  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -7,18 +7,17 @@
  Constructor(DOMString str),
  Constructor(unsigned long num, boolean? boolArg),
  Constructor(TestInterface? iface),
  Constructor(long arg1, IndirectlyImplementedInterface iface),
  // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
  NamedConstructor=Example,
  NamedConstructor=Example(DOMString str),
  NamedConstructor=Example2(DictForConstructor dict, any any1, object obj1,
-                           object? obj2, sequence<Dict> seq,
-                           optional any any2 = null,
+                           object? obj2, sequence<Dict> seq, optional any any2,
                            optional object obj3, optional object? obj4)
  ]
 interface TestExampleInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
@@ -317,16 +316,17 @@ interface TestExampleInterface {
   TestCallback? receiveNullableCallback();
   void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
+  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -18,17 +18,17 @@ enum MyTestEnum {
 };
 
 // We don't support multiple constructors (bug 869268) or named constructors
 // for JS-implemented WebIDL.
 [Constructor(DOMString str, unsigned long num, boolean? boolArg,
              TestInterface? iface, long arg1,
              DictForConstructor dict, any any1,
              object obj1,
-             object? obj2, sequence<Dict> seq, optional any any2 = null,
+             object? obj2, sequence<Dict> seq, optional any any2,
              optional object obj3,
              optional object? obj4),
  JSImplementation="@mozilla.org/test-js-impl-interface;1"]
 interface TestJSImplInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
@@ -339,16 +339,17 @@ interface TestJSImplInterface {
   // Hmm. These two don't work, I think because I need a locally modified version of TestTreatAsNullCallback.
   //void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
   //void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
+  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/imptests/html/dom/test_interfaces.html
+++ b/dom/imptests/html/dom/test_interfaces.html
@@ -74,17 +74,17 @@ dictionary EventInit {
   boolean bubbles = false;
   boolean cancelable = false;
 };
 
 [Constructor(DOMString type, optional CustomEventInit eventInitDict)]
 interface CustomEvent : Event {
   readonly attribute any detail;
 
-  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, optional any details);
+  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any details);
 };
 
 dictionary CustomEventInit : EventInit {
   any detail = null;
 };
 
 interface EventTarget {
   void addEventListener(DOMString type, EventListener? callback, optional boolean capture);
--- a/dom/webidl/Console.webidl
+++ b/dom/webidl/Console.webidl
@@ -12,18 +12,18 @@ interface Console {
   void error(any... data);
   void _exception(any... data);
   void debug(any... data);
   void trace();
   void dir(any... data);
   void group(any... data);
   void groupCollapsed(any... data);
   void groupEnd(any... data);
-  void time(any time);
-  void timeEnd(any time);
+  void time(optional any time);
+  void timeEnd(optional any time);
 
   [Throws]
   void profile(any... data);
 
   [Throws]
   void profileEnd(any... data);
 
   void assert(boolean condition, any... data);
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -21,21 +21,21 @@ interface HTMLCanvasElement : HTMLElemen
   [Pure, SetterThrows]
            attribute unsigned long height;
 
   [Throws]
   nsISupports? getContext(DOMString contextId, optional any contextOptions = null);
 
   [Throws]
   DOMString toDataURL(optional DOMString type = "",
-                      any encoderOptions);
+                      optional any encoderOptions);
   [Throws]
   void toBlob(FileCallback _callback,
               optional DOMString type = "",
-              any encoderOptions);
+              optional any encoderOptions);
 };
 
 // Mozilla specific bits
 partial interface HTMLCanvasElement {
   [Pure, SetterThrows]
            attribute boolean mozOpaque;
   [Throws]
   File mozGetAsFile(DOMString name, optional DOMString? type = null);
--- a/dom/webidl/IDBCursor.webidl
+++ b/dom/webidl/IDBCursor.webidl
@@ -27,17 +27,17 @@ interface IDBCursor {
 
     [Throws]
     IDBRequest update (any value);
 
     [Throws]
     void       advance ([EnforceRange] unsigned long count);
 
     [Throws]
-    void       continue (any key);
+    void       continue (optional any key);
 
     [Throws]
     IDBRequest delete ();
 };
 
 interface IDBCursorWithValue : IDBCursor {
     [Throws]
     readonly    attribute any value;
--- a/dom/webidl/IDBIndex.webidl
+++ b/dom/webidl/IDBIndex.webidl
@@ -18,32 +18,32 @@ interface IDBIndex {
 
     [Throws]
     readonly    attribute any            keyPath;
 
     readonly    attribute boolean        multiEntry;
     readonly    attribute boolean        unique;
 
     [Throws]
-    IDBRequest openCursor (any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
-    IDBRequest openKeyCursor (any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest getKey (any key);
 
     [Throws]
-    IDBRequest count (any key);
+    IDBRequest count (optional any key);
 };
 
 partial interface IDBIndex {
     readonly attribute DOMString storeName;
 
     [Throws]
-    IDBRequest mozGetAll (any key, optional unsigned long limit);
+    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
 
     [Throws]
-    IDBRequest mozGetAllKeys (any key, optional unsigned long limit);
+    IDBRequest mozGetAllKeys (optional any key, optional unsigned long limit);
 };
--- a/dom/webidl/IDBObjectStore.webidl
+++ b/dom/webidl/IDBObjectStore.webidl
@@ -20,32 +20,32 @@ interface IDBObjectStore {
     readonly    attribute any            keyPath;
 
     [Throws]
     readonly    attribute DOMStringList  indexNames;
     readonly    attribute IDBTransaction transaction;
     readonly    attribute boolean        autoIncrement;
 
     [Throws]
-    IDBRequest put (any value, any key);
+    IDBRequest put (any value, optional any key);
 
     [Throws]
-    IDBRequest add (any value, any key);
+    IDBRequest add (any value, optional any key);
 
     [Throws]
     IDBRequest delete (any key);
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest clear ();
 
     [Throws]
-    IDBRequest openCursor (any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
 
     // Bug 899972
     // IDBIndex   createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters);
 
     [Throws]
     IDBIndex   createIndex (DOMString name, DOMString keyPath, optional IDBIndexParameters optionalParameters);
 
     [Throws]
@@ -53,25 +53,25 @@ interface IDBObjectStore {
 
     [Throws]
     IDBIndex   index (DOMString name);
 
     [Throws]
     void       deleteIndex (DOMString indexName);
 
     [Throws]
-    IDBRequest count (any key);
+    IDBRequest count (optional any key);
 };
 
 partial interface IDBObjectStore {
     // Success fires IDBTransactionEvent, result == array of values for given keys
     [Throws]
-    IDBRequest mozGetAll (any key, optional unsigned long limit);
+    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAll (any key, optional unsigned long limit);
+    IDBRequest getAll (optional any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAllKeys (any key, optional unsigned long limit);
+    IDBRequest getAllKeys (optional any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest openKeyCursor (any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
 };
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -21,19 +21,19 @@ interface Promise {
   // TODO bug 875289 - static Promise fulfill(any value);
 
   // Disable the static methods when the interface object is supposed to be
   // disabled, just in case some code decides to walk over to .constructor from
   // the proto of a promise object or someone screws up and manages to create a
   // Promise object in this scope without having resolved the interface object
   // first.
   [NewObject, Throws]
-  static Promise resolve(any value);
+  static Promise resolve(optional any value);
   [NewObject, Throws]
-  static Promise reject(any value);
+  static Promise reject(optional any value);
 
   // The [TreatNonCallableAsNull] annotation is required since then() should do
   // nothing instead of throwing errors when non-callable arguments are passed.
   [NewObject]
   Promise then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
                [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
 
   [NewObject]
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -145,12 +145,12 @@ dictionary RTCStatsReportInternal {
 
 [Pref="media.peerconnection.enabled",
 // TODO: Use MapClass here once it's available (Bug 928114)
 // MapClass(DOMString, object)
  JSImplementation="@mozilla.org/dom/rtcstatsreport;1"]
 interface RTCStatsReport {
   [ChromeOnly]
   readonly attribute DOMString mozPcid;
-  void forEach(RTCStatsReportCallback callbackFn, any thisArg);
+  void forEach(RTCStatsReportCallback callbackFn, optional any thisArg);
   object get(DOMString key);
   boolean has(DOMString key);
 };
--- a/dom/webidl/TestInterfaceJS.webidl
+++ b/dom/webidl/TestInterfaceJS.webidl
@@ -1,17 +1,17 @@
 /* -*- 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/.
  */
 
 [JSImplementation="@mozilla.org/dom/test-interface-js;1",
  Pref="dom.expose_test_interfaces",
- Constructor(any anyArg, optional object objectArg)]
+ Constructor(optional any anyArg, optional object objectArg)]
 interface TestInterfaceJS {
   readonly attribute any anyArg;
   readonly attribute object objectArg;
   attribute any anyAttr;
   attribute object objectAttr;
   any pingPongAny(any arg);
   object pingPongObject(any obj);
 
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -69,17 +69,17 @@ typedef any Transferable;
   [Throws] readonly attribute ApplicationCache applicationCache;
 
   // user prompts
   [Throws] void alert(optional DOMString message = "");
   [Throws] boolean confirm(optional DOMString message = "");
   [Throws] DOMString? prompt(optional DOMString message = "", optional DOMString default = "");
   [Throws] void print();
   //[Throws] any showModalDialog(DOMString url, optional any argument);
-  [Throws] any showModalDialog(DOMString url, any argument, optional DOMString options = "");
+  [Throws] any showModalDialog(DOMString url, optional any argument, optional DOMString options = "");
 
   [Throws, CrossOriginCallable] void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
 
   // also has obsolete members
 };
 Window implements GlobalEventHandlers;
 Window implements WindowEventHandlers;