Bug 970764. Remove support for non-optional "any" arguments values, since "any" needs to be able to include undefined anyway. Have "any" arguments and dictionary entries default to undefined unless the IDL explicitly says "= null". r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 19 Feb 2014 10:13:38 -0500
changeset 169864 fed727c1231575a3df990f18cff61799c69ac245
parent 169863 9291178fcfd15013e0f16e58813ebf8c291e4d93
child 169865 b54f72ef2d3554e83962e1c4866bd4f4db031001
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerskhuey
bugs970764
milestone30.0a1
Bug 970764. Remove support for non-optional "any" arguments values, since "any" needs to be able to include undefined anyway. Have "any" arguments and dictionary entries default to undefined unless the IDL explicitly says "= null". r=khuey
content/html/content/public/HTMLCanvasElement.h
content/html/content/src/HTMLCanvasElement.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/bindings/BindingDeclarations.h
dom/bindings/Codegen.py
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/events/nsDOMMessageEvent.cpp
dom/imptests/html/dom/test_interfaces.html
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBIndex.h
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBObjectStore.h
dom/promise/Promise.cpp
dom/promise/Promise.h
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
dom/webidl/WorkerConsole.webidl
dom/workers/Console.cpp
dom/workers/Console.h
--- a/content/html/content/public/HTMLCanvasElement.h
+++ b/content/html/content/public/HTMLCanvasElement.h
@@ -78,28 +78,25 @@ public:
   {
     SetUnsignedIntAttr(nsGkAtoms::width, aWidth, aRv);
   }
   already_AddRefed<nsISupports>
   GetContext(JSContext* aCx, const nsAString& aContextId,
              JS::Handle<JS::Value> aContextOptions,
              ErrorResult& aRv);
   void ToDataURL(JSContext* aCx, const nsAString& aType,
-                 const Optional<JS::Handle<JS::Value> >& aParams,
+                 JS::Handle<JS::Value> aParams,
                  nsAString& aDataURL, ErrorResult& aRv)
   {
-    JS::Handle<JS::Value> params = aParams.WasPassed()
-                                 ? aParams.Value()
-                                 : JS::UndefinedHandleValue;
-    aRv = ToDataURL(aType, params, aCx, aDataURL);
+    aRv = ToDataURL(aType, aParams, aCx, aDataURL);
   }
   void ToBlob(JSContext* aCx,
               FileCallback& aCallback,
               const nsAString& aType,
-              const Optional<JS::Handle<JS::Value> >& aParams,
+              JS::Handle<JS::Value> aParams,
               ErrorResult& aRv);
 
   bool MozOpaque() const
   {
     return GetBoolAttr(nsGkAtoms::moz_opaque);
   }
   void SetMozOpaque(bool aValue, ErrorResult& aRv)
   {
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -482,38 +482,34 @@ HTMLCanvasElement::ToDataURLImpl(JSConte
 
   return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
 }
 
 void
 HTMLCanvasElement::ToBlob(JSContext* aCx,
                           FileCallback& aCallback,
                           const nsAString& aType,
-                          const Optional<JS::Handle<JS::Value> >& aParams,
+                          JS::Handle<JS::Value> aParams,
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly && !nsContentUtils::IsCallerChrome()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsAutoString type;
   aRv = nsContentUtils::ASCIIToLower(aType, type);
   if (aRv.Failed()) {
     return;
   }
 
-  JS::Value encoderOptions = aParams.WasPassed()
-                             ? aParams.Value()
-                             : JS::UndefinedValue();
-
   nsAutoString params;
   bool usingCustomParseOptions;
-  aRv = ParseParams(aCx, type, encoderOptions, params, &usingCustomParseOptions);
+  aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
   if (aRv.Failed()) {
     return;
   }
 
 #ifdef DEBUG
   if (mCurrentContext) {
     // We disallow canvases of width or height zero, and set them to 1, so
     // we will have a discrepancy with the sizes of the canvas and the context.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8802,28 +8802,24 @@ nsGlobalWindow::ShowModalDialog(const ns
   aError = dialog->GetReturnValue(getter_AddRefs(retVal));
   MOZ_ASSERT(!aError.Failed());
 
   return retVal.forget();
 }
 
 JS::Value
 nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
-                                const Optional<JS::Handle<JS::Value> >& aArgument,
+                                JS::Handle<JS::Value> aArgument,
                                 const nsAString& aOptions,
                                 ErrorResult& aError)
 {
   nsCOMPtr<nsIVariant> args;
-  if (aArgument.WasPassed()) {
-    aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
-                                                      aArgument.Value(),
-                                                      getter_AddRefs(args));
-  } else {
-    args = CreateVoidVariant();
-  }
+  aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
+                                                    aArgument,
+                                                    getter_AddRefs(args));
 
   nsCOMPtr<nsIVariant> retVal = ShowModalDialog(aUrl, args, aOptions, aError);
   if (aError.Failed()) {
     return JS::UndefinedValue();
   }
 
   JS::Rooted<JS::Value> result(aCx);
   if (retVal) {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -819,17 +819,17 @@ protected:
                       mozilla::ErrorResult& aError);
 
 public:
   void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
   bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
   void Prompt(const nsAString& aMessage, const nsAString& aInitial,
               nsAString& aReturn, mozilla::ErrorResult& aError);
   void Print(mozilla::ErrorResult& aError);
-  JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, const mozilla::dom::Optional<JS::Handle<JS::Value> >& aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
+  JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, JS::Handle<JS::Value> aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
                       mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
                      int32_t aTimeout,
                      const mozilla::dom::Sequence<JS::Value>& aArguments,
                      mozilla::ErrorResult& aError);
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -236,42 +236,24 @@ public:
 
   template <class T1>
   void Construct(const T1& t1)
   {
     Optional_base<JSObject*, JSObject*>::Construct(t1);
   }
 };
 
-// A specialization of Optional for JS::Value to make sure that when someone
-// calls Construct() on it we will pre-initialized the JS::Value to
-// JS::UndefinedValue() so it can be traced safely.
+// A specialization of Optional for JS::Value to make sure no one ever uses it.
 template<>
-class Optional<JS::Value> : public Optional_base<JS::Value, JS::Value>
+class Optional<JS::Value>
 {
-public:
-  Optional() :
-    Optional_base<JS::Value, JS::Value>()
-  {}
+private:
+  Optional() MOZ_DELETE;
 
-  explicit Optional(JS::Value aValue) :
-    Optional_base<JS::Value, JS::Value>(aValue)
-  {}
-
-  // Don't allow us to have an uninitialized JS::Value
-  void Construct()
-  {
-    Optional_base<JS::Value, JS::Value>::Construct(JS::UndefinedValue());
-  }
-
-  template <class T1>
-  void Construct(const T1& t1)
-  {
-    Optional_base<JS::Value, JS::Value>::Construct(t1);
-  }
+  explicit Optional(JS::Value aValue) MOZ_DELETE;
 };
 
 // A specialization of Optional for NonNull that lets us get a T& from Value()
 template<typename U> class NonNull;
 template<typename T>
 class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
 {
 public:
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6,17 +6,17 @@
 
 import operator
 import os
 import re
 import string
 import math
 import itertools
 
-from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute
+from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue
 from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
@@ -3839,31 +3839,32 @@ for (uint32_t i = 0; i < length; ++i) {
 
         declArgs = None
         if (isMember == "Variadic" or isMember == "Sequence" or
             isMember == "Dictionary"):
             # Rooting is handled by the sequence and dictionary tracers.
             declType = "JS::Value"
         else:
             assert not isMember
-            if isOptional:
-                # We have a specialization of Optional that will use a
-                # Rooted for the storage here.
-                declType = "JS::Handle<JS::Value>"
+            declType = "JS::Rooted<JS::Value>"
+            declArgs = "cx"
+
+        assert not isOptional
+        templateBody = "${declName} = ${val};"
+        # We may not have a default value if we're being converted for
+        # a setter, say.
+        if defaultValue:
+            if isinstance(defaultValue, IDLNullValue):
+                defaultHandling = "${declName} = JS::NullValue()"
             else:
-                declType = "JS::Rooted<JS::Value>"
-            declArgs = "cx"
-
-        templateBody = "${declName} = ${val};"
-        nullHandling = "${declName} = JS::NullValue()"
-
-        templateBody = handleDefaultNull(templateBody, nullHandling)
+                assert isinstance(defaultValue, IDLUndefinedValue)
+                defaultHandling = "${declName} = JS::UndefinedValue()"
+            templateBody = handleDefault(templateBody, defaultHandling)
         return JSToNativeConversionInfo(templateBody,
                                         declType=CGGeneric(declType),
-                                        dealWithOptional=isOptional,
                                         declArgs=declArgs)
 
     if type.isObject():
         assert not isEnforceRange and not isClamp
         return handleJSObjectType(type, isMember, failureCode)
 
     if type.isDictionary():
         # There are no nullable dictionaries
@@ -4137,16 +4138,18 @@ def instantiateJSToNativeConversion(info
     # Add an empty CGGeneric to get an extra newline after the argument
     # conversion.
     result.append(CGGeneric(""))
     return result
 
 def convertConstIDLValueToJSVal(value):
     if isinstance(value, IDLNullValue):
         return "JS::NullValue()"
+    if isinstance(value, IDLUndefinedValue):
+        return "JS::UndefinedValue()"
     tag = value.type.tag()
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
         return "INT_TO_JSVAL(%s)" % (value.value)
     if tag == IDLType.Tags.uint32:
         return "UINT_TO_JSVAL(%sU)" % (value.value)
     if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
         return "DOUBLE_TO_JSVAL(%s)" % numericValue(tag, value.value)
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2526,17 +2526,34 @@ class IDLNullValue(IDLObject):
                 if t.isDictionary():
                     nullValue.type = t
                     return nullValue
         nullValue.type = type
         return nullValue
 
     def _getDependentObjects(self):
         return set()
-  
+
+class IDLUndefinedValue(IDLObject):
+    def __init__(self, location):
+        IDLObject.__init__(self, location)
+        self.type = None
+        self.value = None
+
+    def coerceToType(self, type, location):
+        if not type.isAny():
+            raise WebIDLError("Cannot coerce undefined value to type %s." % type,
+                              [location])
+
+        undefinedValue = IDLUndefinedValue(self.location)
+        undefinedValue.type = type
+        return undefinedValue
+
+    def _getDependentObjects(self):
+        return set()
 
 class IDLInterfaceMember(IDLObjectWithIdentifier):
 
     Tags = enum(
         'Const',
         'Attr',
         'Method'
     )
@@ -2904,16 +2921,32 @@ class IDLArgument(IDLObjectWithIdentifie
             self.type = type
 
         if ((self.type.isDictionary() or
              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:
+                # 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,
                                                                self.location)
             assert self.defaultValue
 
@@ -4283,16 +4316,20 @@ 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.
+
         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)
         p[0].addExtendedAttributes(p[1])
--- 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", False, False)])])
+        [("::TestMethods::setAny::arg1", "arg1", "Any", True, 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
@@ -141,21 +141,21 @@ public:
   static
   already_AddRefed<TestInterface> Test(const GlobalObject&, const nsACString&,
                                        ErrorResult&);
 
   static
   already_AddRefed<TestInterface> Test2(const GlobalObject&,
                                         JSContext*,
                                         const DictForConstructor&,
-                                        JS::Value,
+                                        JS::Handle<JS::Value>,
                                         JS::Handle<JSObject*>,
                                         JS::Handle<JSObject*>,
                                         const Sequence<Dict>&,
-                                        const Optional<JS::Handle<JS::Value> >&,
+                                        JS::Handle<JS::Value>,
                                         const Optional<JS::Handle<JSObject*> >&,
                                         const Optional<JS::Handle<JSObject*> >&,
                                         ErrorResult&);
 
   // Integer types
   int8_t ReadonlyByte();
   int8_t WritableByte();
   void SetWritableByte(int8_t);
@@ -461,17 +461,16 @@ 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*, const Optional<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,17 +105,18 @@ 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,
+                        object? obj2, sequence<Dict> seq,
+                        optional any any2 = null,
                         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);
@@ -423,17 +424,16 @@ 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,17 +7,18 @@
  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,
+                           object? obj2, sequence<Dict> seq,
+                           optional any any2 = null,
                            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);
@@ -316,17 +317,16 @@ 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,
+             object? obj2, sequence<Dict> seq, optional any any2 = null,
              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,17 +339,16 @@ 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/events/nsDOMMessageEvent.cpp
+++ b/dom/events/nsDOMMessageEvent.cpp
@@ -125,19 +125,17 @@ nsDOMMessageEvent::Constructor(const moz
   aRv = event->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   bool trusted = event->Init(t);
   event->SetTrusted(trusted);
 
-  if (aParam.mData.WasPassed()) {
-    event->mData = aParam.mData.Value();
-  }
+  event->mData = aParam.mData;
 
   mozilla::HoldJSObjects(event.get());
 
   if (aParam.mOrigin.WasPassed()) {
     event->mOrigin = aParam.mOrigin.Value();
   }
 
   if (aParam.mLastEventId.WasPassed()) {
--- 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, any details);
+  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, optional any details);
 };
 
 dictionary CustomEventInit : EventInit {
   any detail = null;
 };
 
 interface EventTarget {
   void addEventListener(DOMString type, EventListener? callback, optional boolean capture);
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -692,26 +692,24 @@ IDBCursor::GetValue(JSContext* aCx, Erro
     mHaveCachedValue = true;
   }
 
   return mCachedValue;
 }
 
 void
 IDBCursor::Continue(JSContext* aCx,
-                    const Optional<JS::Handle<JS::Value> >& aKey,
+                    JS::Handle<JS::Value> aKey,
                     ErrorResult &aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   Key key;
-  if (aKey.WasPassed()) {
-    aRv = key.SetFromJSVal(aCx, aKey.Value());
-    ENSURE_SUCCESS_VOID(aRv);
-  }
+  aRv = key.SetFromJSVal(aCx, aKey);
+  ENSURE_SUCCESS_VOID(aRv);
 
   if (!key.IsUnset()) {
     switch (mDirection) {
       case IDBCursor::NEXT:
       case IDBCursor::NEXT_UNIQUE:
         if (key <= mKey) {
           aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
           return;
@@ -804,31 +802,27 @@ IDBCursor::Update(JSContext* aCx, JS::Ha
       return nullptr;
     }
 
     if (key != objectKey) {
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
       return nullptr;
     }
 
-    JS::Rooted<JS::Value> value(aCx, aValue);
-    Optional<JS::Handle<JS::Value> > keyValue(aCx);
-    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    request = mObjectStore->Put(aCx, aValue, JS::UndefinedHandleValue, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
   else {
     JS::Rooted<JS::Value> keyVal(aCx);
     aRv = objectKey.ToJSVal(aCx, &keyVal);
     ENSURE_SUCCESS(aRv, nullptr);
 
-    JS::Rooted<JS::Value> value(aCx, aValue);
-    Optional<JS::Handle<JS::Value> > keyValue(aCx, keyVal);
-    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    request = mObjectStore->Put(aCx, aValue, keyVal, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
 #ifdef IDB_PROFILER_USE_MARKS
   {
     uint64_t requestSerial =
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -192,18 +192,17 @@ public:
 
   already_AddRefed<IDBRequest>
   Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   void
   Advance(uint32_t aCount, ErrorResult& aRv);
 
   void
-  Continue(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
-           ErrorResult& aRv);
+  Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Delete(JSContext* aCx, ErrorResult& aRv);
 
   JS::Value
   GetValue(JSContext* aCx, ErrorResult& aRv);
 
 protected:
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -891,86 +891,80 @@ IDBIndex::GetKey(JSContext* aCx, JS::Han
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     return nullptr;
   }
 
   return GetKeyInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
-IDBIndex::GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+IDBIndex::GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
                  const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() > 0) {
     limit = aLimit.Value();
   }
 
   return GetAllInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::GetAllKeys(JSContext* aCx,
-                     const Optional<JS::Handle<JS::Value> >& aKey,
+                     JS::Handle<JS::Value> aKey,
                      const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() > 0) {
     limit = aLimit.Value();
   }
 
   return GetAllKeysInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::OpenCursor(JSContext* aCx,
-                     const Optional<JS::Handle<JS::Value> >& aRange,
+                     JS::Handle<JS::Value> aRange,
                      IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   if (!request) {
     IDB_WARNING("Failed to generate request!");
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return nullptr;
@@ -986,53 +980,49 @@ IDBIndex::OpenCursor(JSContext* aCx,
     return nullptr;
   }
 
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::OpenKeyCursor(JSContext* aCx,
-                        const Optional<JS::Handle<JS::Value> >& aRange,
+                        JS::Handle<JS::Value> aRange,
                         IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   return OpenKeyCursorInternal(keyRange, direction, aRv);
 }
 
 already_AddRefed<IDBRequest>
-IDBIndex::Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+IDBIndex::Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
                 ErrorResult& aRv)
 {
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   return CountInternal(keyRange, aRv);
 }
 
 void
 IndexHelper::ReleaseMainThreadObjects()
 {
   mIndex = nullptr;
--- a/dom/indexedDB/IDBIndex.h
+++ b/dom/indexedDB/IDBIndex.h
@@ -189,46 +189,46 @@ public:
   bool
   Unique() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mUnique;
   }
 
   already_AddRefed<IDBRequest>
-  OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
              IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenKeyCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
                 IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
          ErrorResult& aRv);
 
   void
   GetStoreName(nsString& aStoreName) const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     mObjectStore->GetName(aStoreName);
   }
 
   already_AddRefed<IDBRequest>
-  GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
          const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAllKeys(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
              const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
 private:
   IDBIndex();
   ~IDBIndex();
 
   nsRefPtr<IDBObjectStore> mObjectStore;
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1902,40 +1902,37 @@ IDBObjectStore::GetAddInfo(JSContext* aC
     rv = GetAddInfoCallback(aCx, &data);
   }
 
   return rv;
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
-                         const Optional<JS::Handle<JS::Value> >& aKey,
+                         JS::Handle<JS::Value> aKey,
                          bool aOverwrite, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
 
-  JS::Rooted<JS::Value> keyval(aCx, aKey.WasPassed() ? aKey.Value()
-                                                     : JSVAL_VOID);
-
   StructuredCloneWriteInfo cloneWriteInfo;
   Key key;
   nsTArray<IndexUpdateInfo> updateInfo;
 
   JS::Rooted<JS::Value> value(aCx, aValue);
-  aRv = GetAddInfo(aCx, value, keyval, cloneWriteInfo, key, updateInfo);
+  aRv = GetAddInfo(aCx, value, aKey, cloneWriteInfo, key, updateInfo);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   if (!request) {
     IDB_WARNING("Failed to generate request!");
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@@ -2695,31 +2692,29 @@ IDBObjectStore::Get(JSContext* aCx, JS::
     return nullptr;
   }
 
   return GetInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::GetAll(JSContext* aCx,
-                       const Optional<JS::Handle<JS::Value> >& aKey,
+                       JS::Handle<JS::Value> aKey,
                        const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() != 0) {
     limit = aLimit.Value();
   }
 
   return GetAllInternal(keyRange, limit, aRv);
 }
@@ -2750,31 +2745,29 @@ IDBObjectStore::Delete(JSContext* aCx, J
     return nullptr;
   }
 
   return DeleteInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::OpenCursor(JSContext* aCx,
-                           const Optional<JS::Handle<JS::Value> >& aRange,
+                           JS::Handle<JS::Value> aRange,
                            IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
   size_t argDirection = static_cast<size_t>(direction);
 
   return OpenCursorInternal(keyRange, argDirection, aRv);
 }
 
 already_AddRefed<IDBIndex>
@@ -2936,76 +2929,70 @@ IDBObjectStore::DeleteIndex(const nsAStr
                     IDB_PROFILER_STRING(Transaction()->Database()),
                     IDB_PROFILER_STRING(Transaction()),
                     IDB_PROFILER_STRING(this),
                     NS_ConvertUTF16toUTF8(aName).get());
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::Count(JSContext* aCx,
-                      const Optional<JS::Handle<JS::Value> >& aKey,
+                      JS::Handle<JS::Value> aKey,
                       ErrorResult& aRv)
 {
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   return CountInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::GetAllKeys(JSContext* aCx,
-                           const Optional<JS::Handle<JS::Value>>& aKey,
+                           JS::Handle<JS::Value> aKey,
                            const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() != 0) {
     limit = aLimit.Value();
   }
 
   return GetAllKeysInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::OpenKeyCursor(JSContext* aCx,
-                              const Optional<JS::Handle<JS::Value>>& aRange,
+                              JS::Handle<JS::Value> aRange,
                               IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   return OpenKeyCursorInternal(keyRange, static_cast<size_t>(direction), aRv);
 }
 
 inline nsresult
 CopyData(nsIInputStream* aInputStream, nsIOutputStream* aOutputStream)
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -299,41 +299,41 @@ public:
   AutoIncrement() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mAutoIncrement;
   }
 
   already_AddRefed<IDBRequest>
   Put(JSContext* aCx, JS::Handle<JS::Value> aValue,
-      const Optional<JS::Handle<JS::Value> >& aKey, ErrorResult& aRv)
+      JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return AddOrPut(aCx, aValue, aKey, true, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Add(JSContext* aCx, JS::Handle<JS::Value> aValue,
-      const Optional<JS::Handle<JS::Value> >& aKey, ErrorResult& aRv)
+      JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return AddOrPut(aCx, aValue, aKey, false, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Delete(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Clear(ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
              IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName,
@@ -342,45 +342,45 @@ public:
 
   already_AddRefed<IDBIndex>
   Index(const nsAString& aName, ErrorResult &aRv);
 
   void
   DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
         ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
          const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAllKeys(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aKey,
+  GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
              const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenKeyCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aRange,
+  OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
                 IDBCursorDirection aDirection, ErrorResult& aRv);
 
 protected:
   IDBObjectStore();
   ~IDBObjectStore();
 
   nsresult GetAddInfo(JSContext* aCx,
                       JS::Handle<JS::Value> aValue,
                       JS::Handle<JS::Value> aKeyVal,
                       StructuredCloneWriteInfo& aCloneWriteInfo,
                       Key& aKey,
                       nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
 
   already_AddRefed<IDBRequest>
   AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
-           const Optional<JS::Handle<JS::Value> >& aKey, bool aOverwrite,
+           JS::Handle<JS::Value> aKey, bool aOverwrite,
            ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
   static void
   ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -495,23 +495,21 @@ Promise::Constructor(const GlobalObject&
     promise->MaybeRejectInternal(cx, value);
   }
 
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
-                 const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
+                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // If a Promise was passed, just return it.
-  JS::Rooted<JS::Value> value(aCx, aValue.WasPassed() ? aValue.Value() :
-                                                        JS::UndefinedValue());
-  if (value.isObject()) {
-    JS::Rooted<JSObject*> valueObj(aCx, &value.toObject());
+  if (aValue.isObject()) {
+    JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
     Promise* nextPromise;
     nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
 
     if (NS_SUCCEEDED(rv)) {
       nsRefPtr<Promise> addRefed = nextPromise;
       return addRefed.forget();
     }
   }
@@ -520,46 +518,44 @@ Promise::Resolve(const GlobalObject& aGl
   if (MOZ_LIKELY(NS_IsMainThread())) {
     window = do_QueryInterface(aGlobal.GetAsSupports());
     if (!window) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
-  return Resolve(window, aCx, value, aRv);
+  return Resolve(window, aCx, aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(nsPIDOMWindow* aWindow, JSContext* aCx,
                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // aWindow may be null.
   nsRefPtr<Promise> promise = new Promise(aWindow);
 
   promise->MaybeResolveInternal(aCx, aValue);
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
-                const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
+                JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window;
   if (MOZ_LIKELY(NS_IsMainThread())) {
     window = do_QueryInterface(aGlobal.GetAsSupports());
     if (!window) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
-  return Reject(window, aCx,
-                aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
-                aRv);
+  return Reject(window, aCx, aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(nsPIDOMWindow* aWindow, JSContext* aCx,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // aWindow may be null.
   nsRefPtr<Promise> promise = new Promise(aWindow);
@@ -731,29 +727,29 @@ Promise::All(const GlobalObject& aGlobal
   }
 
   if (aIterable.Length() == 0) {
     JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0));
     if (!empty) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
-    Optional<JS::Handle<JS::Value>> optValue(aCx, JS::ObjectValue(*empty));
-    return Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*empty));
+    return Promise::Resolve(aGlobal, aCx, value, aRv);
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
   nsRefPtr<CountdownHolder> holder =
     new CountdownHolder(aGlobal, promise, aIterable.Length());
 
   nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
 
   for (uint32_t i = 0; i < aIterable.Length(); ++i) {
-    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
-    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
 
     MOZ_ASSERT(!aRv.Failed());
 
     nsRefPtr<PromiseNativeHandler> resolveHandler =
       new AllResolveHandler(holder, i);
 
     nsRefPtr<PromiseCallback> resolveCb =
       new NativePromiseCallback(resolveHandler, Resolved);
@@ -778,18 +774,18 @@ Promise::Race(const GlobalObject& aGloba
     }
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
   nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(promise);
   nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
 
   for (uint32_t i = 0; i < aIterable.Length(); ++i) {
-    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
-    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
     // According to spec, Resolve can throw, but our implementation never does.
     // Well it does when window isn't passed on the main thread, but that is an
     // implementation detail which should never be reached since we are checking
     // for window above. Remove this when subclassing is supported.
     MOZ_ASSERT(!aRv.Failed());
     nextPromise->AppendCallbacks(resolveCb, rejectCb);
   }
 
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -61,25 +61,25 @@ public:
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   static already_AddRefed<Promise>
   Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
               ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Resolve(const GlobalObject& aGlobal, JSContext* aCx,
-          const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
+          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Resolve(nsPIDOMWindow* aWindow, JSContext* aCx,
           JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Reject(const GlobalObject& aGlobal, JSContext* aCx,
-         const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
+         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Reject(nsPIDOMWindow* aWindow, JSContext* aCx,
          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   already_AddRefed<Promise>
   Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
 
--- 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 = "",
-                      optional any encoderOptions);
+                      any encoderOptions);
   [Throws]
   void toBlob(FileCallback _callback,
               optional DOMString type = "",
-              optional any encoderOptions);
+              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 (optional any key);
+    void       continue (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 (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
-    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest getKey (any key);
 
     [Throws]
-    IDBRequest count (optional any key);
+    IDBRequest count (any key);
 };
 
 partial interface IDBIndex {
     readonly attribute DOMString storeName;
 
     [Throws]
-    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAll (any key, optional unsigned long limit);
 
     [Throws]
-    IDBRequest mozGetAllKeys (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAllKeys (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, optional any key);
+    IDBRequest put (any value, any key);
 
     [Throws]
-    IDBRequest add (any value, optional any key);
+    IDBRequest add (any value, any key);
 
     [Throws]
     IDBRequest delete (any key);
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest clear ();
 
     [Throws]
-    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (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 (optional any key);
+    IDBRequest count (any key);
 };
 
 partial interface IDBObjectStore {
     // Success fires IDBTransactionEvent, result == array of values for given keys
     [Throws]
-    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAll (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAll (optional any key, optional unsigned long limit);
+    IDBRequest getAll (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAllKeys (optional any key, optional unsigned long limit);
+    IDBRequest getAllKeys (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (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(optional any value);
+  static Promise resolve(any value);
   [NewObject, Throws]
-  static Promise reject(optional any value);
+  static Promise reject(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
@@ -141,12 +141,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, optional any thisArg);
+  void forEach(RTCStatsReportCallback callbackFn, 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(optional any anyArg, optional object objectArg)]
+ Constructor(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, optional any argument, optional DOMString options = "");
+  [Throws] any showModalDialog(DOMString url, 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;
 
--- a/dom/webidl/WorkerConsole.webidl
+++ b/dom/webidl/WorkerConsole.webidl
@@ -7,22 +7,22 @@
 interface WorkerConsole {
   void log(any... data);
   void info(any... data);
   void warn(any... data);
   void error(any... data);
   void _exception(any... data);
   void debug(any... data);
   void trace();
-  void dir(optional any data);
+  void dir(any data);
   void group(any... data);
   void groupCollapsed(any... data);
   void groupEnd(any... data);
-  void time(optional any time);
-  void timeEnd(optional any time);
+  void time(any time);
+  void timeEnd(any time);
   void profile(any... data);
   void profileEnd(any... data);
   void assert(boolean condition, any... data);
   void ___noSuchMethod__();
 };
 
 // This dictionary is used internally to send the stack trace from the worker to
 // the main thread Console API implementation.
--- a/dom/workers/Console.cpp
+++ b/dom/workers/Console.cpp
@@ -487,56 +487,54 @@ void
 WorkerConsole::Trace(JSContext* aCx)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
   Method(aCx, "trace", data, DEFAULT_MAX_STACKTRACE_DEPTH);
 }
 
 void
-WorkerConsole::Dir(JSContext* aCx,
-                   const Optional<JS::Handle<JS::Value>>& aValue)
+WorkerConsole::Dir(JSContext* aCx, JS::Handle<JS::Value> aValue)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aValue.WasPassed()) {
-    data.AppendElement(aValue.Value());
+  if (!aValue.isUndefined()) {
+    data.AppendElement(aValue);
   }
 
   Method(aCx, "dir", data, 1);
 }
 
 METHOD(Group, "group")
 METHOD(GroupCollapsed, "groupCollapsed")
 METHOD(GroupEnd, "groupEnd")
 
 void
-WorkerConsole::Time(JSContext* aCx,
-                    const Optional<JS::Handle<JS::Value>>& aTimer)
+WorkerConsole::Time(JSContext* aCx, JS::Handle<JS::Value> aTimer)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aTimer.WasPassed()) {
-    data.AppendElement(aTimer.Value());
+  if (!aTimer.isUndefined()) {
+    data.AppendElement(aTimer);
   }
 
   Method(aCx, "time", data, 1);
 }
 
 void
 WorkerConsole::TimeEnd(JSContext* aCx,
-                       const Optional<JS::Handle<JS::Value>>& aTimer)
+                       JS::Handle<JS::Value> aTimer)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aTimer.WasPassed()) {
-    data.AppendElement(aTimer.Value());
+  if (!aTimer.isUndefined()) {
+    data.AppendElement(aTimer);
   }
 
   Method(aCx, "timeEnd", data, 1);
 }
 
 METHOD(Profile, "profile")
 METHOD(ProfileEnd, "profileEnd")
 
--- a/dom/workers/Console.h
+++ b/dom/workers/Console.h
@@ -65,32 +65,32 @@ public:
 
   void
   Debug(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   Trace(JSContext* aCx);
 
   void
-  Dir(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aValue);
+  Dir(JSContext* aCx, JS::Handle<JS::Value> aValue);
 
   void
   Group(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   GroupEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
-  Time(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
+  Time(JSContext* aCx, JS::Handle<JS::Value> aTimer);
 
   void
-  TimeEnd(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
+  TimeEnd(JSContext* aCx, JS::Handle<JS::Value> aTimer);
 
   void
   Profile(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void