Bug 932322 - Make Window's WebIDL properties be own properties of window. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 08 Oct 2013 18:18:40 +0200
changeset 168185 834b35ebbce7c9b5cbc4aeb1f3907e8de0f73fe2
parent 168184 ba666d2dbb97a144cb1177d21392cd8babef6b46
child 168186 c9eb4218558d85fbd61be24d26a11a146a5c8303
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs932322
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 932322 - Make Window's WebIDL properties be own properties of window. r=bz.
browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/html/content/test/forms/test_restore_form_elements.html
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/imptests/failures/html/html/browsers/the-window-object/test_window-properties.html.json
dom/imptests/html/html/browsers/the-window-object/test_window-properties.html
dom/tests/mochitest/bugs/test_bug684544.html
dom/tests/mochitest/general/file_interfaces.xml
dom/tests/mochitest/general/test_interfaces.html
js/src/tests/js1_5/LexicalConventions/lexical-001.js
js/src/tests/js1_5/extensions/regress-406572.js
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/tests/mochitest/test_bug691059.html
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
@@ -1,16 +1,18 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-632347-iterators-generators.html";
 
 function test() {
+  requestLongerTimeout(2);
+
   addTab(TEST_URI);
   browser.addEventListener("load", function onLoad() {
     browser.removeEventListener("load", onLoad, true);
     openConsole(null, consoleOpened);
   }, true);
 }
 
 function consoleOpened(HUD) {
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -2166,19 +2166,16 @@ public:
   void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
 
   // ParentNode
   nsIHTMLCollection* Children();
   uint32_t ChildElementCount();
 
   virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
 
-  virtual JSObject* WrapObject(JSContext *aCx,
-                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
-
 private:
   uint64_t mWarnedAbout;
   SelectorCache mSelectorCache;
 
 protected:
   ~nsIDocument();
   nsPropertyTable* GetExtraPropertyTable(uint16_t aCategory);
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -11324,67 +11324,16 @@ NS_IMETHODIMP
 nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
                      nsIDOMXPathNSResolver* aResolver, uint16_t aType,
                      nsISupports* aInResult, nsISupports** aResult)
 {
   return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType,
                                     aInResult, aResult);
 } 
 
-// This is just a hack around the fact that window.document is not
-// [Unforgeable] yet.
-JSObject*
-nsIDocument::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
-{
-  MOZ_ASSERT(IsDOMBinding());
-
-  JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, aScope));
-  if (!obj) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetInnerWindow());
-  if (!win) {
-    // No window, nothing else to do here
-    return obj;
-  }
-
-  if (this != win->GetExtantDoc()) {
-    // We're not the current document; we're also done here
-    return obj;
-  }
-
-  JSAutoCompartment ac(aCx, obj);
-
-  JS::Rooted<JS::Value> winVal(aCx);
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
-                                           &NS_GET_IID(nsIDOMWindow),
-                                           &winVal,
-                                           getter_AddRefs(holder),
-                                           false);
-  if (NS_FAILED(rv)) {
-    Throw(aCx, rv);
-    return nullptr;
-  }
-
-  NS_NAMED_LITERAL_STRING(doc_str, "document");
-
-  if (!JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(winVal),
-                           reinterpret_cast<const jschar *>
-                                           (doc_str.get()),
-                           doc_str.Length(), JS::ObjectValue(*obj),
-                           JS_PropertyStub, JS_StrictPropertyStub,
-                           JSPROP_READONLY | JSPROP_ENUMERATE)) {
-    return nullptr;
-  }
-
-  return obj;
-}
-
 XPathEvaluator*
 nsIDocument::XPathEvaluator()
 {
   if (!mXPathEvaluator) {
     mXPathEvaluator = new dom::XPathEvaluator(this);
   }
   return mXPathEvaluator;
 }
--- a/content/html/content/test/forms/test_restore_form_elements.html
+++ b/content/html/content/test/forms/test_restore_form_elements.html
@@ -57,28 +57,28 @@ https://bugzilla.mozilla.org/show_bug.cg
   '></iframe>
 
 </div>
 
 
 <pre id="test">
 <script type="text/javascript">
 
-var frameElement = document.getElementById("frame");
-var frame = frameElement.contentWindow;
+var frameElem = document.getElementById("frame");
+var frame = frameElem.contentWindow;
 
 
 /* -- Main test run -- */
 
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function() {
   shuffle();
   fill();
-  frameElement.addEventListener("load", function() {
+  frameElem.addEventListener("load", function() {
     shuffle();
     checkAllFields();
     SimpleTest.finish();
   });
   frame.location.reload();
 })
 
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -182,32 +182,35 @@
 #include "nsIDOMGlobalObjectConstructor.h"
 #include "nsIDOMLockedFile.h"
 #include "nsDebug.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Likely.h"
 #include "WindowNamedPropertiesHandler.h"
 #include "nsIInterfaceInfoManager.h"
+#include "mozilla/dom/EventTargetBinding.h"
+#include "mozilla/dom/WindowBinding.h"
 
 #ifdef MOZ_TIME_MANAGER
 #include "TimeManager.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::dom::workers::ResolveWorkerClasses;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
 //       are defined in nsIDOMClassInfo.h.
 
 #define WINDOW_SCRIPTABLE_FLAGS                                               \
  (nsIXPCScriptable::WANT_PRECREATE |                                          \
+  nsIXPCScriptable::WANT_POSTCREATE |                                         \
   nsIXPCScriptable::WANT_FINALIZE |                                           \
   nsIXPCScriptable::WANT_ENUMERATE |                                          \
   nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |                               \
   nsIXPCScriptable::IS_GLOBAL_OBJECT |                                        \
   nsIXPCScriptable::WANT_OUTER_OBJECT)
 
 #define ARRAY_SCRIPTABLE_FLAGS                                                \
   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
@@ -580,40 +583,25 @@ static const nsConstructorFuncMapData kC
 };
 #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr;
 bool nsDOMClassInfo::sIsInitialized = false;
 
 
-jsid nsDOMClassInfo::sParent_id          = JSID_VOID;
-jsid nsDOMClassInfo::sScrollbars_id      = JSID_VOID;
 jsid nsDOMClassInfo::sLocation_id        = JSID_VOID;
 jsid nsDOMClassInfo::sConstructor_id     = JSID_VOID;
 jsid nsDOMClassInfo::s_content_id        = JSID_VOID;
-jsid nsDOMClassInfo::sContent_id         = JSID_VOID;
-jsid nsDOMClassInfo::sMenubar_id         = JSID_VOID;
-jsid nsDOMClassInfo::sToolbar_id         = JSID_VOID;
-jsid nsDOMClassInfo::sLocationbar_id     = JSID_VOID;
-jsid nsDOMClassInfo::sPersonalbar_id     = JSID_VOID;
-jsid nsDOMClassInfo::sStatusbar_id       = JSID_VOID;
-jsid nsDOMClassInfo::sControllers_id     = JSID_VOID;
 jsid nsDOMClassInfo::sLength_id          = JSID_VOID;
-jsid nsDOMClassInfo::sScrollX_id         = JSID_VOID;
-jsid nsDOMClassInfo::sScrollY_id         = JSID_VOID;
-jsid nsDOMClassInfo::sScrollMaxX_id      = JSID_VOID;
-jsid nsDOMClassInfo::sScrollMaxY_id      = JSID_VOID;
 jsid nsDOMClassInfo::sItem_id            = JSID_VOID;
 jsid nsDOMClassInfo::sNamedItem_id       = JSID_VOID;
 jsid nsDOMClassInfo::sEnumerate_id       = JSID_VOID;
 jsid nsDOMClassInfo::sTop_id             = JSID_VOID;
 jsid nsDOMClassInfo::sDocument_id        = JSID_VOID;
-jsid nsDOMClassInfo::sFrames_id          = JSID_VOID;
-jsid nsDOMClassInfo::sSelf_id            = JSID_VOID;
 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
 
 static const JSClass *sObjectClass = nullptr;
 
 /**
  * Set our JSClass pointer for the Object class
  */
 static void
@@ -728,40 +716,25 @@ nsresult
 nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
 {
 #define SET_JSID_TO_STRING(_id, _cx, _str)                                    \
   if (JSString *str = ::JS_InternString(_cx, _str))                           \
       _id = INTERNED_STRING_TO_JSID(_cx, str);                                \
   else                                                                        \
       return NS_ERROR_OUT_OF_MEMORY;
 
-  SET_JSID_TO_STRING(sParent_id,          cx, "parent");
-  SET_JSID_TO_STRING(sScrollbars_id,      cx, "scrollbars");
   SET_JSID_TO_STRING(sLocation_id,        cx, "location");
   SET_JSID_TO_STRING(sConstructor_id,     cx, "constructor");
   SET_JSID_TO_STRING(s_content_id,        cx, "_content");
-  SET_JSID_TO_STRING(sContent_id,         cx, "content");
-  SET_JSID_TO_STRING(sMenubar_id,         cx, "menubar");
-  SET_JSID_TO_STRING(sToolbar_id,         cx, "toolbar");
-  SET_JSID_TO_STRING(sLocationbar_id,     cx, "locationbar");
-  SET_JSID_TO_STRING(sPersonalbar_id,     cx, "personalbar");
-  SET_JSID_TO_STRING(sStatusbar_id,       cx, "statusbar");
-  SET_JSID_TO_STRING(sControllers_id,     cx, "controllers");
   SET_JSID_TO_STRING(sLength_id,          cx, "length");
-  SET_JSID_TO_STRING(sScrollX_id,         cx, "scrollX");
-  SET_JSID_TO_STRING(sScrollY_id,         cx, "scrollY");
-  SET_JSID_TO_STRING(sScrollMaxX_id,      cx, "scrollMaxX");
-  SET_JSID_TO_STRING(sScrollMaxY_id,      cx, "scrollMaxY");
   SET_JSID_TO_STRING(sItem_id,            cx, "item");
   SET_JSID_TO_STRING(sNamedItem_id,       cx, "namedItem");
   SET_JSID_TO_STRING(sEnumerate_id,       cx, "enumerateProperties");
   SET_JSID_TO_STRING(sTop_id,             cx, "top");
   SET_JSID_TO_STRING(sDocument_id,        cx, "document");
-  SET_JSID_TO_STRING(sFrames_id,          cx, "frames");
-  SET_JSID_TO_STRING(sSelf_id,            cx, "self");
   SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
 
   return NS_OK;
 }
 
 // static
 bool
 nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
@@ -1996,39 +1969,24 @@ nsDOMClassInfo::ShutDown()
   if (sClassInfoData[0].u.mConstructorFptr) {
     uint32_t i;
 
     for (i = 0; i < eDOMClassInfoIDCount; i++) {
       NS_IF_RELEASE(sClassInfoData[i].mCachedClassInfo);
     }
   }
 
-  sParent_id          = JSID_VOID;
-  sScrollbars_id      = JSID_VOID;
   sLocation_id        = JSID_VOID;
   sConstructor_id     = JSID_VOID;
   s_content_id        = JSID_VOID;
-  sContent_id         = JSID_VOID;
-  sMenubar_id         = JSID_VOID;
-  sToolbar_id         = JSID_VOID;
-  sLocationbar_id     = JSID_VOID;
-  sPersonalbar_id     = JSID_VOID;
-  sStatusbar_id       = JSID_VOID;
-  sControllers_id     = JSID_VOID;
   sLength_id          = JSID_VOID;
-  sScrollX_id         = JSID_VOID;
-  sScrollY_id         = JSID_VOID;
-  sScrollMaxX_id      = JSID_VOID;
-  sScrollMaxY_id      = JSID_VOID;
   sItem_id            = JSID_VOID;
   sEnumerate_id       = JSID_VOID;
   sTop_id             = JSID_VOID;
   sDocument_id        = JSID_VOID;
-  sFrames_id          = JSID_VOID;
-  sSelf_id            = JSID_VOID;
   sWrappedJSObject_id = JSID_VOID;
 
   NS_IF_RELEASE(sXPConnect);
   NS_IF_RELEASE(sSecMan);
   sIsInitialized = false;
 }
 
 // Window helper
@@ -2075,16 +2033,38 @@ nsWindowSH::PostCreatePrototype(JSContex
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We should probably move this into the CreateInterfaceObjects for Window
   // once it is on WebIDL bindings.
   WindowNamedPropertiesHandler::Install(aCx, proto);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
+                       JSContext *cx, JSObject *obj)
+{
+#ifdef DEBUG
+  nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
+
+  NS_ASSERTION(sgo && sgo->GetGlobalJSObject() == nullptr,
+               "Multiple wrappers created for global object!");
+#endif
+
+  const NativeProperties* windowProperties =
+    WindowBinding::sNativePropertyHooks->mNativeProperties.regular;
+  const NativeProperties* eventTargetProperties =
+    EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular;
+
+  JS::Rooted<JSObject*> window(cx, obj);
+  return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) &&
+         DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ?
+         NS_OK : NS_ERROR_FAILURE;
+}
+
 static nsHTMLDocument*
 GetDocument(JSObject *obj)
 {
   MOZ_ASSERT(js::GetObjectJSClass(obj) == &sHTMLDocumentAllClass);
   return static_cast<nsHTMLDocument*>(
     static_cast<nsINode*>(JS_GetPrivate(obj)));
 }
 
@@ -3610,21 +3590,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
   if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
     return NS_ERROR_FAILURE;
   }
   if (tmp) {
     *objp = tmp;
     return NS_OK;
   }
 
-  // Check for names managed by the script namespace manager.  Call
-  // GlobalResolve() after we call FindChildWithName() so that named child
-  // frames will override external properties which have been registered with
-  // the script namespace manager -- pages must be able to depend on frame
-  // names working no matter how Gecko's been configured.
   bool did_resolve = false;
   nsresult rv = GlobalResolve(win, cx, obj, id, &did_resolve);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (did_resolve) {
     *objp = obj;
     return NS_OK;
   }
@@ -3653,61 +3628,38 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       return NS_ERROR_FAILURE;
     }
 
     *objp = obj;
 
     return NS_OK;
   }
 
-  if (flags & JSRESOLVE_ASSIGNING) {
-    if (IsReadonlyReplaceable(id)) {
-      // A readonly "replaceable" property is being set.  Define the property
-      // on obj with the value undefined to override the predefined property.
-      // This isn't quite what WebIDL requires for [Replaceable] properties,
-      // but it'll do until we move Window over to the new DOM bindings.
-
-      if (!::JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, JS_PropertyStub,
-                                   JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
-        return NS_ERROR_FAILURE;
-      }
-      *objp = obj;
-
-      return NS_OK;
-    }
-  } else {
-    if (sDocument_id == id) {
+  if (!(flags & JSRESOLVE_ASSIGNING) && sDocument_id == id) {
+    if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
       nsCOMPtr<nsIDocument> document = win->GetDoc();
       JS::Rooted<JS::Value> v(cx);
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, JS::CurrentGlobalOrNull(cx), document, document,
                       &NS_GET_IID(nsIDOMDocument), &v, getter_AddRefs(holder),
                       false);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      // The PostCreate hook for the document will handle defining the
-      // property
       *objp = obj;
 
-      // NB: We need to do this for any Xray wrapper.
-      if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
-        // Unless our object is a native wrapper, in which case we have to
-        // define it ourselves.
-
-        *_retval = JS_WrapValue(cx, &v) &&
-                   JS_DefineProperty(cx, obj, "document", v,
-                                     JS_PropertyStub, JS_StrictPropertyStub,
-                                     JSPROP_READONLY | JSPROP_ENUMERATE);
-        if (!*_retval) {
-          return NS_ERROR_UNEXPECTED;
-        }
+      *_retval = JS_WrapValue(cx, &v) &&
+                 JS_DefineProperty(cx, obj, "document", v,
+                                   JS_PropertyStub, JS_StrictPropertyStub,
+                                   JSPROP_READONLY | JSPROP_ENUMERATE);
+      if (!*_retval) {
+        return NS_ERROR_UNEXPECTED;
       }
-
-      return NS_OK;
     }
+
+    return NS_OK;
   }
 
   return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, flags, objp,
                                     _retval);
 }
 
 NS_IMETHODIMP
 nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -149,70 +149,34 @@ protected:
                               JSObject **objp);
 
   // Checks if id is a number and returns the number, if aIsNumber is
   // non-null it's set to true if the id is a number and false if it's
   // not a number. If id is not a number this method returns -1
   static int32_t GetArrayIndexFromId(JSContext *cx, JS::Handle<jsid> id,
                                      bool *aIsNumber = nullptr);
 
-  static inline bool IsReadonlyReplaceable(jsid id)
-  {
-    return (id == sParent_id       ||
-            id == sScrollbars_id   ||
-            id == sContent_id      ||
-            id == sMenubar_id      ||
-            id == sToolbar_id      ||
-            id == sLocationbar_id  ||
-            id == sPersonalbar_id  ||
-            id == sStatusbar_id    ||
-            id == sControllers_id  ||
-            id == sScrollX_id      ||
-            id == sScrollY_id      ||
-            id == sScrollMaxX_id   ||
-            id == sScrollMaxY_id   ||
-            id == sLength_id       ||
-            id == sFrames_id       ||
-            id == sSelf_id);
-  }
-
   static nsIXPConnect *sXPConnect;
   static nsIScriptSecurityManager *sSecMan;
 
   // nsIXPCScriptable code
   static nsresult DefineStaticJSVals(JSContext *cx);
 
   static bool sIsInitialized;
 
 public:
-  static jsid sParent_id;
-  static jsid sScrollbars_id;
   static jsid sLocation_id;
   static jsid sConstructor_id;
   static jsid s_content_id;
-  static jsid sContent_id;
-  static jsid sMenubar_id;
-  static jsid sToolbar_id;
-  static jsid sLocationbar_id;
-  static jsid sPersonalbar_id;
-  static jsid sStatusbar_id;
-  static jsid sControllers_id;
   static jsid sLength_id;
-  static jsid sScrollX_id;
-  static jsid sScrollY_id;
-  static jsid sScrollMaxX_id;
-  static jsid sScrollMaxY_id;
   static jsid sItem_id;
   static jsid sNamedItem_id;
   static jsid sEnumerate_id;
   static jsid sTop_id;
   static jsid sDocument_id;
-  static jsid sFrames_id;
-  static jsid sSelf_id;
-  static jsid sJava_id;
   static jsid sWrappedJSObject_id;
 };
 
 // THIS ONE ISN'T SAFE!! It assumes that the private of the JSObject is
 // an nsISupports.
 inline
 const nsQueryInterface
 do_QueryWrappedNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
@@ -294,33 +258,18 @@ protected:
   static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                                 JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                                 bool *did_resolve);
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
                        JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
   NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) MOZ_OVERRIDE;
-#ifdef DEBUG
   NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj) MOZ_OVERRIDE
-  {
-    nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
-
-    NS_ASSERTION(!sgo || sgo->GetGlobalJSObject() == nullptr,
-                 "Multiple wrappers created for global object!");
-
-    return NS_OK;
-  }
-  virtual uint32_t GetScriptableFlags() MOZ_OVERRIDE
-  {
-    return nsDOMGenericSH::GetScriptableFlags() |
-           nsIXPCScriptable::WANT_POSTCREATE;
-  }
-#endif
+                        JSObject *obj) MOZ_OVERRIDE;
   NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
                         JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                       JSObject *obj) MOZ_OVERRIDE;
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -527,27 +527,33 @@ CreateInterfaceObject(JSContext* cx, JS:
       ++namedConstructors;
     }
   }
 
   return constructor;
 }
 
 bool
-DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx,
-                                        JS::Handle<JSObject*> proto,
-                                        const NativeProperties* properties)
+DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
+                                         JS::Handle<JSObject*> obj,
+                                         const NativeProperties* properties,
+                                         bool defineUnforgeableAttributes)
 {
   if (properties->methods &&
-      !DefinePrefable(cx, proto, properties->methods)) {
+      !DefinePrefable(cx, obj, properties->methods)) {
     return false;
   }
 
   if (properties->attributes &&
-      !DefinePrefable(cx, proto, properties->attributes)) {
+      !DefinePrefable(cx, obj, properties->attributes)) {
+    return false;
+  }
+
+  if (defineUnforgeableAttributes && properties->unforgeableAttributes &&
+      !DefinePrefable(cx, obj, properties->unforgeableAttributes)) {
     return false;
   }
 
   return true;
 }
 
 static JSObject*
 CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -396,19 +396,20 @@ CreateInterfaceObjects(JSContext* cx, JS
 /*
  * Define the unforgeable attributes on an object.
  */
 bool
 DefineUnforgeableAttributes(JSContext* cx, JS::Handle<JSObject*> obj,
                             const Prefable<const JSPropertySpec>* props);
 
 bool
-DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx,
-                                        JS::Handle<JSObject*> proto,
-                                        const NativeProperties* properties);
+DefineWebIDLBindingPropertiesOnXPCObject(JSContext* cx,
+                                         JS::Handle<JSObject*> obj,
+                                         const NativeProperties* properties,
+                                         bool defineUnforgeableAttributes);
 
 #ifdef _MSC_VER
 #define HAS_MEMBER_CHECK(_name)                                           \
   template<typename V> static yes& Check(char (*)[(&V::_name == 0) + 1])
 #else
 #define HAS_MEMBER_CHECK(_name)                                           \
   template<typename V> static yes& Check(char (*)[sizeof(&V::_name) + 1])
 #endif
--- a/dom/imptests/failures/html/html/browsers/the-window-object/test_window-properties.html.json
+++ b/dom/imptests/failures/html/html/browsers/the-window-object/test_window-properties.html.json
@@ -1,12 +1,35 @@
 {
   "EventTarget method: addEventListener": true,
   "EventTarget method: removeEventListener": true,
   "EventTarget method: dispatchEvent": true,
+  "Window method: close": true,
+  "Window method: stop": true,
+  "Window method: focus": true,
+  "Window method: blur": true,
+  "Window method: open": true,
+  "Window method: alert": true,
+  "Window method: confirm": true,
+  "Window method: prompt": true,
+  "Window method: print": true,
+  "Window method: showModalDialog": true,
+  "Window method: postMessage": true,
+  "Window method: btoa": true,
+  "Window method: atob": true,
+  "Window method: setTimeout": true,
+  "Window method: clearTimeout": true,
+  "Window method: setInterval": true,
+  "Window method: clearInterval": true,
+  "Window method: getSelection": true,
+  "Window method: getComputedStyle": true,
+  "Window method: matchMedia": true,
+  "Window method: scroll": true,
+  "Window method: scrollTo": true,
+  "Window method: scrollBy": true,
   "Window readonly attribute: history": true,
   "Window readonly attribute: parent": true,
   "Window readonly attribute: frameElement": true,
   "Window readonly attribute: navigator": true,
   "Window readonly attribute: external": true,
   "Window readonly attribute: applicationCache": true,
   "Window readonly attribute: sessionStorage": true,
   "Window readonly attribute: localStorage": true,
@@ -16,19 +39,98 @@
   "Window readonly attribute: scrollX": true,
   "Window readonly attribute: pageXOffset": true,
   "Window readonly attribute: scrollY": true,
   "Window readonly attribute: pageYOffset": true,
   "Window readonly attribute: screenX": true,
   "Window readonly attribute: screenY": true,
   "Window readonly attribute: outerWidth": true,
   "Window readonly attribute: outerHeight": true,
+  "Window attribute: name": true,
+  "Window attribute: status": true,
+  "Window attribute: opener": true,
+  "Window attribute: onabort": true,
+  "Window attribute: onafterprint": true,
+  "Window attribute: onbeforeprint": true,
+  "Window attribute: onbeforeunload": true,
+  "Window attribute: onblur": true,
+  "Window attribute: oncancel": true,
+  "Window attribute: oncanplay": true,
+  "Window attribute: oncanplaythrough": true,
+  "Window attribute: onchange": true,
+  "Window attribute: onclick": true,
+  "Window attribute: onclose": true,
+  "Window attribute: oncontextmenu": true,
+  "Window attribute: oncuechange": true,
+  "Window attribute: ondblclick": true,
+  "Window attribute: ondrag": true,
+  "Window attribute: ondragend": true,
+  "Window attribute: ondragenter": true,
+  "Window attribute: ondragleave": true,
+  "Window attribute: ondragover": true,
+  "Window attribute: ondragstart": true,
+  "Window attribute: ondrop": true,
+  "Window attribute: ondurationchange": true,
+  "Window attribute: onemptied": true,
+  "Window attribute: onended": true,
+  "Window attribute: onerror": true,
+  "Window attribute: onfocus": true,
+  "Window attribute: onhashchange": true,
+  "Window attribute: oninput": true,
+  "Window attribute: oninvalid": true,
+  "Window attribute: onkeydown": true,
+  "Window attribute: onkeypress": true,
+  "Window attribute: onkeyup": true,
   "Window attribute: oncancel": true,
   "Window attribute: onclose": true,
   "Window attribute: oncuechange": true,
   "Window attribute: onmousewheel": true,
+  "Window attribute: onload": true,
+  "Window attribute: onloadeddata": true,
+  "Window attribute: onloadedmetadata": true,
+  "Window attribute: onloadstart": true,
+  "Window attribute: onmessage": true,
+  "Window attribute: onmousedown": true,
+  "Window attribute: onmousemove": true,
+  "Window attribute: onmouseout": true,
+  "Window attribute: onmouseover": true,
+  "Window attribute: onmouseup": true,
+  "Window attribute: onmousewheel": true,
+  "Window attribute: onoffline": true,
+  "Window attribute: ononline": true,
+  "Window attribute: onpause": true,
+  "Window attribute: onplay": true,
+  "Window attribute: onplaying": true,
+  "Window attribute: onpagehide": true,
+  "Window attribute: onpageshow": true,
+  "Window attribute: onpopstate": true,
+  "Window attribute: onprogress": true,
+  "Window attribute: onratechange": true,
+  "Window attribute: onreset": true,
+  "Window attribute: onresize": true,
+  "Window attribute: onscroll": true,
+  "Window attribute: onseeked": true,
+  "Window attribute: onseeking": true,
+  "Window attribute: onselect": true,
+  "Window attribute: onshow": true,
+  "Window attribute: onstalled": true,
   "Window attribute: onstorage": true,
+  "Window attribute: onsubmit": true,
+  "Window attribute: onsuspend": true,
+  "Window attribute: ontimeupdate": true,
+  "Window attribute: onunload": true,
+  "Window attribute: onvolumechange": true,
+  "Window attribute: onwaiting": true,
   "Window unforgeable attribute: window": true,
   "Window unforgeable attribute: document": true,
   "Window unforgeable attribute: location": true,
   "Window unforgeable attribute: top": true,
+  "Window replaceable attribute: self": true,
+  "Window replaceable attribute: locationbar": true,
+  "Window replaceable attribute: menubar": true,
+  "Window replaceable attribute: personalbar": true,
+  "Window replaceable attribute: scrollbars": true,
+  "Window replaceable attribute: statusbar": true,
+  "Window replaceable attribute: toolbar": true,
+  "Window replaceable attribute: frames": true,
+  "Window replaceable attribute: length": true,
   "constructor": true
 }
--- a/dom/imptests/html/html/browsers/the-window-object/test_window-properties.html
+++ b/dom/imptests/html/html/browsers/the-window-object/test_window-properties.html
@@ -246,67 +246,66 @@ test(function() {
 }, "Other Properties of the Global Object");
 test(function() {
   // EventTarget interface
   ["addEventListener", "removeEventListener", "dispatchEvent"].forEach(function(id) {
     test(function() {
       var EventTargetProto = EventTarget.prototype;
       assert_true(id in window, id + " in window");
       assert_equals(window[id], EventTargetProto[id]);
-      assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id),
+      assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
                            true, true, true);
     }, "EventTarget method: " + id);
   });
 }, "EventTarget interface");
 test(function() {
   // Window interface
   methods.forEach(function(id) {
     test(function() {
       var WindowProto = Window.prototype;
       assert_true(id in window, id + " in window");
-      assert_true(id in WindowProto, id + " in Window.prototype");
-      assert_equals(window[id], WindowProto[id]);
-      assert_data_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
+      assert_false(id in WindowProto, id + " in Window.prototype");
+      assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
                            true, true, true);
     }, "Window method: " + id);
   });
   readonlyAttributes.forEach(function(id) {
     test(function() {
       var WindowProto = Window.prototype;
       assert_true(id in window, id + " in window");
-      assert_true(id in WindowProto, id + " in Window.prototype");
-      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
+      assert_false(id in WindowProto, id + " in Window.prototype");
+      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
                                false, true, true);
     }, "Window readonly attribute: " + id);
   });
   writableAttributes.forEach(function(id) {
     test(function() {
       var WindowProto = Window.prototype;
       assert_true(id in window, id + " in window");
-      assert_true(id in WindowProto, id + " in Window.prototype");
-      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
+      assert_false(id in WindowProto, id + " in Window.prototype");
+      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
                                true, true, true);
     }, "Window attribute: " + id);
   });
   unforgeableAttributes.forEach(function(id) {
     test(function() {
       var WindowProto = Window.prototype;
       assert_true(id in window, id + " in window");
+      assert_false(id in WindowProto, id + " in Window.prototype");
       // location has a [PutForwards] extended attribute.
       assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
                                id === "location", true, false);
-      assert_false(id in WindowProto, id + " in Window.prototype");
     }, "Window unforgeable attribute: " + id);
   });
   replacableAttributes.forEach(function(id) {
     test(function() {
       var WindowProto = Window.prototype;
       assert_true(id in window, id + " in window");
-      assert_true(id in WindowProto, id + " in Window.prototype");
-      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(WindowProto, id),
+      assert_false(id in WindowProto, id + " in Window.prototype");
+      assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
                                true, true, true);
     }, "Window replaceable attribute: " + id);
   });
 }, "Window interface");
 test(function() {
   assert_equals(window.constructor, Window);
   assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
   assert_data_propdesc(Object.getOwnPropertyDescriptor(Window.prototype, "constructor"),
--- a/dom/tests/mochitest/bugs/test_bug684544.html
+++ b/dom/tests/mochitest/bugs/test_bug684544.html
@@ -27,20 +27,28 @@ var win = f.contentWindow;
 win.location = "data:text/html,1";
 
 // Now try to make the location object go away.
 f.parentNode.removeChild(f);
 
 // Check that location is now null.  If it's not, the test needs changing
 // (e.g. to use window.close() so that it's null).
 is("location" in win, true, "Should still have a location property");
-todo_is(win.location, null, "There should be no location object now");
+is(win.location, null, "There should be no location object now");
 
-// Just set the location.  This should not crash.
-win.location = "data:text/html,2";
+// Just set the location.  This should not crash but throw an exception.
+var noException;
+try {
+  win.location = "data:text/html,2";
+  noException = true;
+}
+catch(e) {
+  noException = false;
+}
+todo(noException, "Shouldn't throw when setting location.");
 
 // And check that we didn't override the slot in the process.
 is(typeof(win.location), "object", "Location should not have become a string");
 is(win.location, null,
    "There should be no location object for real after the set");
 
 </script>
 </pre>
--- a/dom/tests/mochitest/general/file_interfaces.xml
+++ b/dom/tests/mochitest/general/file_interfaces.xml
@@ -4,17 +4,17 @@
     <content>PASS</content>
     <implementation>
       <constructor>
         var win = XPCNativeWrapper.unwrap(window);
         var SpecialPowers = win.SpecialPowers;
         var is = win.is;
         var todo_is = win.todo_is;
         var ok = win.ok;
-        var excludedNames = win.excludedNames;
+        var legacyMozPrefixedInterfaces = win.legacyMozPrefixedInterfaces;
         var createInterfaceMap = win.createInterfaceMap;
         eval(win.runTest.toString());
         runTest(true);
         win.SimpleTest.finish();
       </constructor>
     </implementation>
   </binding>
 </bindings>
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -64,16 +64,33 @@ var ecmaGlobals =
     "Uint32Array",
     "Uint8Array",
     "Uint8ClampedArray",
     "URIError",
     "WeakMap",
   ];
 // IMPORTANT: Do not change this list without review from a JavaScript Engine peer!
 
+// IMPORTANT: Do not change this list without review from a DOM peer, except to
+//            remove items from it!
+//
+// This is a list of interfaces that were prefixed with 'moz' instead of 'Moz'.
+// We should never to that again, interfaces in the DOM start with an uppercase
+// letter. If you think you need to add an interface here, DON'T. Rename your
+// interface.
+var legacyMozPrefixedInterfaces =
+  [
+    "mozContact",
+    "mozRTCIceCandidate",
+    "mozRTCPeerConnection",
+    "mozRTCSessionDescription",
+  ];
+// IMPORTANT: Do not change this list without review from a DOM peer, except to
+//            remove items from it!
+
 // IMPORTANT: Do not change this list without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
     "AnalyserNode",
     "AnimationEvent",
     "ArchiveRequest",
     "Attr",
     "Audio",
@@ -637,17 +654,19 @@ function createInterfaceMap(isXBLScope) 
 
   return interfaceMap;
 }
 
 function runTest(isXBLScope) {
   var interfaceMap = createInterfaceMap(isXBLScope);
   for (var name of Object.getOwnPropertyNames(window)) {
     // An interface name should start with an upper case character.
-    if (!/^(moz)?[A-Z]/.test(name)) {
+    // However, we have a couple of legacy interfaces that start with 'moz', so
+    // we want to allow those until we can remove them.
+    if (!/^[A-Z]/.test(name) && legacyMozPrefixedInterfaces.indexOf(name) < 0) {
       continue;
     }
     ok(interfaceMap[name],
        "If this is failing: DANGER, are you sure you want to expose the new interface " + name +
        " to all webpages as a property on the window? Do not make a change to this file without a " +
        " review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)");
     delete interfaceMap[name];
   }
--- a/js/src/tests/js1_5/LexicalConventions/lexical-001.js
+++ b/js/src/tests/js1_5/LexicalConventions/lexical-001.js
@@ -22,106 +22,106 @@
  *JavaScript "strict" option is set though, we will give a warning.
  */
 
 //-------------------------------------------------------------------------------------------------
 var BUGNUMBER = '49233';
 var summary = 'Testing numeric literals that begin with 0';
 var statprefix = 'Testing ';
 var quote = "'";
-var status = new Array();
+var asString = new Array();
 var actual = new Array();
 var expect = new Array();
 
 
-status[0]=showStatus('01')
+  asString[0]='01'
   actual[0]=01
   expect[0]=1
 
-  status[1]=showStatus('07')
+  asString[1]='07'
   actual[1]=07
   expect[1]=7
 
-  status[2]=showStatus('08')
+  asString[2]='08'
   actual[2]=08
   expect[2]=8
 
-  status[3]=showStatus('09')
+  asString[3]='09'
   actual[3]=09
   expect[3]=9
 
-  status[4]=showStatus('010')
+  asString[4]='010'
   actual[4]=010
   expect[4]=8
 
-  status[5]=showStatus('017')
+  asString[5]='017'
   actual[5]=017
   expect[5]=15
 
-  status[6]=showStatus('018')
+  asString[6]='018'
   actual[6]=018
   expect[6]=18
 
-  status[7]=showStatus('019')
+  asString[7]='019'
   actual[7]=019
   expect[7]=19
 
-  status[8]=showStatus('079')
+  asString[8]='079'
   actual[8]=079
   expect[8]=79
 
-  status[9]=showStatus('0079')
+  asString[9]='0079'
   actual[9]=0079
   expect[9]=79
 
-  status[10]=showStatus('099')
+  asString[10]='099'
   actual[10]=099
   expect[10]=99
 
-  status[11]=showStatus('0099')
+  asString[11]='0099'
   actual[11]=0099
   expect[11]=99
 
-  status[12]=showStatus('000000000077')
+  asString[12]='000000000077'
   actual[12]=000000000077
   expect[12]=63
 
-  status[13]=showStatus('000000000078')
+  asString[13]='000000000078'
   actual[13]=000000000078
   expect[13]=78
 
-  status[14]=showStatus('0000000000770000')
+  asString[14]='0000000000770000'
   actual[14]=0000000000770000
   expect[14]=258048
 
-  status[15]=showStatus('0000000000780000')
+  asString[15]='0000000000780000'
   actual[15]=0000000000780000
   expect[15]=780000
 
-  status[16]=showStatus('0765432198')
+  asString[16]='0765432198'
   actual[16]=0765432198
   expect[16]=765432198
 
-  status[17]=showStatus('00076543219800')
+  asString[17]='00076543219800'
   actual[17]=00076543219800
   expect[17]=76543219800
 
-  status[18]=showStatus('0000001001007')
+  asString[18]='0000001001007'
   actual[18]=0000001001007
   expect[18]=262663
 
-  status[19]=showStatus('0000001001009')
+  asString[19]='0000001001009'
   actual[19]=0000001001009
   expect[19]=1001009
 
-  status[20]=showStatus('070')
+  asString[20]='070'
   actual[20]=070
   expect[20]=56
 
-  status[21]=showStatus('080')
+  asString[21]='080'
   actual[21]=080
   expect[21]=80
 
 
 
 //-------------------------------------------------------------------------------------------------
   test();
 //-------------------------------------------------------------------------------------------------
@@ -135,15 +135,15 @@ function showStatus(msg)
 
 function test()
 {
   enterFunc ('test');
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
 
-  for (i=0; i !=status.length; i++)
+  for (i=0; i !=asString.length; i++)
   {
-    reportCompare (expect[i], actual[i], status[i]);
+    reportCompare (expect[i], actual[i], showStatus(asString[i]));
   }
 
   exitFunc ('test');
 }
--- a/js/src/tests/js1_5/extensions/regress-406572.js
+++ b/js/src/tests/js1_5/extensions/regress-406572.js
@@ -9,29 +9,29 @@ var summary = 'JSOP_CLOSURE unconditiona
 var actual = '';
 var expect = '';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 
 if (typeof window != 'undefined')
 {
-  var d = document;
+  var s = self;
 
-  d.writeln(uneval(document));
-  document = 1;
-  d.writeln(uneval(document));
+  document.writeln(uneval(self));
+  self = 1;
+  document.writeln(uneval(self));
 
   if (1)
-    function document() { return 1; }
+    function self() { return 1; }
 
-  d.writeln(uneval(document));
+  document.writeln(uneval(self));
 
-  // The test harness relies on document having its original value: restore it.
-  document = d;
+  // The test harness might rely on self having its original value: restore it.
+  self = s;
 }
 else
 {
   expect = actual = 'Test can only run in a Gecko 1.9 browser or later.';
   print(actual);
 }
 reportCompare(expect, actual, summary);
 
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -135,17 +135,17 @@ xpc_qsDefineQuickStubs(JSContext *cx, JS
                     if (!JS_DefineFunction(cx, proto,
                                            stringTable + fs->name_index,
                                            reinterpret_cast<JSNative>(fs->native),
                                            fs->arity, flags))
                         return false;
                 }
 
                 if (entry->newBindingProperties) {
-                    mozilla::dom::DefineWebIDLBindingPropertiesOnXPCProto(cx, proto, entry->newBindingProperties);
+                    mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx, proto, entry->newBindingProperties, false);
                 }
                 // Next.
                 size_t j = entry->parentInterface;
                 if (j == XPC_QS_NULL_INDEX)
                     break;
                 entry = table + j;
             }
         }
--- a/js/xpconnect/tests/mochitest/test_bug691059.html
+++ b/js/xpconnect/tests/mochitest/test_bug691059.html
@@ -43,16 +43,15 @@ function testInterface(obj) {
     ok(false, ex);
   }
 }
 
 testEventTarget(window);
 testEventTarget(document);
 testEventTarget(document.documentElement);
 
-testInterface(Window);
 testInterface(Document);
 testInterface(HTMLElement);
 
 </script>
 </pre>
 </body>
 </html>