Bug 319968 - "Some DOM functions don't work in XPCShell (classinfo broken)" [p=Mossop r+sr=jst a1.9=schrep]
authorreed@reedloden.com
Tue, 13 Nov 2007 02:35:49 -0800
changeset 7941 48436c3a98a004b3487783efb51b1d613bba97e5
parent 7940 2232a13f2c45f313f066949e9c3bd673fe84c1f5
child 7942 2a1a18835c28d8b1d2801c8566cdfc5442b3e51c
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
bugs319968
milestone1.9b2pre
Bug 319968 - "Some DOM functions don't work in XPCShell (classinfo broken)" [p=Mossop r+sr=jst a1.9=schrep]
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsDOMScriptObjectFactory.cpp
dom/src/base/nsJSEnvironment.cpp
dom/src/base/nsJSEnvironment.h
dom/tests/Makefile.in
dom/tests/unit/test_bug319968.js
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -88,16 +88,17 @@
 #include "nsIDocShellTreeNode.h"
 #include "nsIScriptExternalNameSet.h"
 #include "nsJSUtils.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsIScriptObjectOwner.h"
 #include "nsIJSNativeInitializer.h"
+#include "nsJSEnvironment.h"
 
 // DOM base includes
 #include "nsIDOMPluginArray.h"
 #include "nsIDOMPlugin.h"
 #include "nsIDOMMimeTypeArray.h"
 #include "nsIDOMMimeType.h"
 #include "nsIDOMNSLocation.h"
 #include "nsIDOMLocation.h"
@@ -1660,31 +1661,31 @@ CutPrefix(const char *aName) {
 
   return aName;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
 {
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
-
-  gNameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
-                                       aClassInfoID);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+
+  nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
+                                      aClassInfoID);
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
 {
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   PRBool found_old;
 
   const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface;
 
   if (!primary_iid || primary_iid == &NS_GET_IID(nsISupports)) {
     return NS_OK;
   }
 
@@ -1707,17 +1708,17 @@ nsDOMClassInfo::RegisterClassProtos(PRIn
       nsMemory::Free(iid);
 
       break;
     }
 
     nsXPIDLCString name;
     if_info->GetName(getter_Copies(name));
 
-    gNameSpaceManager->RegisterClassProto(CutPrefix(name), iid, &found_old);
+    nameSpaceManager->RegisterClassProto(CutPrefix(name), iid, &found_old);
 
     nsMemory::Free(iid);
 
     if (first) {
       first = PR_FALSE;
     } else if (found_old) {
       break;
     }
@@ -1728,22 +1729,21 @@ nsDOMClassInfo::RegisterClassProtos(PRIn
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterExternalClasses()
 {
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
-
-  nsresult rv;
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+
   nsCOMPtr<nsIComponentRegistrar> registrar;
-  rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
+  nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICategoryManager> cm =
     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISimpleEnumerator> e;
   rv = cm->EnumerateCategory(JAVASCRIPT_DOM_CLASS, getter_AddRefs(e));
@@ -1769,22 +1769,22 @@ nsDOMClassInfo::RegisterExternalClasses(
 
     nsCID *cid;
     rv = registrar->ContractIDToCID(contractId, &cid);
     if (NS_FAILED(rv)) {
       NS_WARNING("Bad contract id registered with the script namespace manager");
       continue;
     }
 
-    rv = gNameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid);
+    rv = nameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid);
     nsMemory::Free(cid);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  return gNameSpaceManager->RegisterExternalInterfaces(PR_TRUE);
+  return nameSpaceManager->RegisterExternalInterfaces(PR_TRUE);
 }
 
 #define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if)               \
   {                                                                           \
     nsDOMClassInfoData &d = sClassInfoData[eDOMClassInfo_##_class##_id];      \
     d.mProtoChainInterface = _ifptr;                                          \
     d.mHasClassInterface = _has_class_if;                                     \
     static const nsIID *interface_list[] = {
@@ -1841,18 +1841,18 @@ nsDOMClassInfo::Init()
   /* Errors that can trigger early returns are done first,
      otherwise nsDOMClassInfo is left in a half inited state. */
   NS_ASSERTION(sizeof(PtrBits) == sizeof(void*),
                "BAD! You'll need to adjust the size of PtrBits to the size "
                "of a pointer on your platform.");
 
   NS_ENSURE_TRUE(!sIsInitialized, NS_ERROR_ALREADY_INITIALIZED);
 
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsresult rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIXPCFunctionThisTranslator> old;
 
   nsCOMPtr<nsIXPCFunctionThisTranslator> elt = new nsEventListenerThisTranslator();
   NS_ENSURE_TRUE(elt, NS_ERROR_OUT_OF_MEMORY);
@@ -4897,23 +4897,23 @@ private:
     return nameStruct;
   }
 
   static nsresult GetNameStruct(const nsAString& aName,
                                 const nsGlobalNameStruct **aNameStruct)
   {
     *aNameStruct = nsnull;
 
-    extern nsScriptNameSpaceManager *gNameSpaceManager;
-    if (!gNameSpaceManager) {
+    nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+    if (!nameSpaceManager) {
       NS_ERROR("Can't get namespace manager.");
       return NS_ERROR_UNEXPECTED;
     }
 
-    gNameSpaceManager->LookupName(aName, aNameStruct);
+    nameSpaceManager->LookupName(aName, aNameStruct);
 
     // Return NS_OK here, aName just isn't a DOM class but nothing failed.
     return NS_OK;
   }
 
   static PRBool IsConstructable(const nsGlobalNameStruct *aNameStruct)
   {
     return
@@ -5024,31 +5024,31 @@ nsDOMConstructor::HasInstance(nsIXPConne
   NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE);
 
   if (name_struct == class_name_struct) {
     *bp = JS_TRUE;
 
     return NS_OK;
   }
 
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-  NS_ASSERTION(gNameSpaceManager, "Can't get namespace manager?");
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
 
   const nsIID *class_iid;
   if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
       class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
     class_iid = &class_name_struct->mIID;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     class_iid =
       sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     class_iid = class_name_struct->mData->mProtoChainInterface;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     const nsGlobalNameStruct* alias_struct =
-      gNameSpaceManager->GetConstructorProto(class_name_struct);
+      nameSpaceManager->GetConstructorProto(class_name_struct);
     if (!alias_struct) {
       NS_ERROR("Couldn't get constructor prototype.");
       return NS_ERROR_UNEXPECTED;
     }
 
     if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
       class_iid =
         sClassInfoData[alias_struct->mDOMClassInfoID].mProtoChainInterface;
@@ -5060,17 +5060,17 @@ nsDOMConstructor::HasInstance(nsIXPConne
     }
   } else {
     *bp = JS_FALSE;
 
     return NS_OK;
   }
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
-    name_struct = gNameSpaceManager->GetConstructorProto(name_struct);
+    name_struct = nameSpaceManager->GetConstructorProto(name_struct);
     if (!name_struct) {
       NS_ERROR("Couldn't get constructor prototype.");
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
                name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
@@ -5130,26 +5130,25 @@ nsDOMConstructor::ToString(nsAString &aR
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JSObject *obj, JSString *str, PRUint32 flags,
                           PRBool *did_resolve)
 {
   *did_resolve = PR_FALSE;
 
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsDependentJSString name(str);
 
   const nsGlobalNameStruct *name_struct = nsnull;
   const PRUnichar *class_name = nsnull;
 
-  gNameSpaceManager->LookupName(name, &name_struct, &class_name);
+  nameSpaceManager->LookupName(name, &name_struct, &class_name);
 
   if (!name_struct) {
     return NS_OK;
   }
 
   NS_ENSURE_TRUE(class_name, NS_ERROR_UNEXPECTED);
 
   nsresult rv = NS_OK;
@@ -5159,17 +5158,17 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
     NS_ENSURE_TRUE(sof, NS_ERROR_FAILURE);
 
     rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(name).get(), sof);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = gNameSpaceManager->LookupName(name, &name_struct);
+    rv = nameSpaceManager->LookupName(name, &name_struct);
     if (NS_FAILED(rv) || !name_struct ||
         name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo) {
       NS_ERROR("Couldn't get the DOM ClassInfo data.");
 
       return NS_OK;
     }
   }
 
@@ -5224,17 +5223,17 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     const nsGlobalNameStruct* alias_struct = nsnull;
 
     if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
         name_struct->mDOMClassInfoID >= 0) {
       ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
     } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
       ci_data = name_struct->mData;
     } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
-      alias_struct = gNameSpaceManager->GetConstructorProto(name_struct);
+      alias_struct = nameSpaceManager->GetConstructorProto(name_struct);
       NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED);
 
       if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
         ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID];
       } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
         ci_data = alias_struct->mData;
       }
     }
--- a/dom/src/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/src/base/nsDOMScriptObjectFactory.cpp
@@ -222,32 +222,31 @@ NS_IMETHODIMP_(nsISupports *)
 nsDOMScriptObjectFactory::GetClassInfoInstance(nsDOMClassInfoID aID)
 {
   return NS_GetDOMClassInfoInstance(aID);
 }
 
 NS_IMETHODIMP_(nsISupports *)
 nsDOMScriptObjectFactory::GetExternalClassInfoInstance(const nsAString& aName)
 {
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-
-  NS_ENSURE_TRUE(gNameSpaceManager, nsnull);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, nsnull);
 
   const nsGlobalNameStruct *globalStruct;
-  gNameSpaceManager->LookupName(aName, &globalStruct);
+  nameSpaceManager->LookupName(aName, &globalStruct);
   if (globalStruct) {
     if (globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
       nsresult rv;
       nsCOMPtr<nsIDOMCIExtension> creator(do_CreateInstance(globalStruct->mCID, &rv));
       NS_ENSURE_SUCCESS(rv, nsnull);
 
       rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName).get(), this);
       NS_ENSURE_SUCCESS(rv, nsnull);
 
-      rv = gNameSpaceManager->LookupName(aName, &globalStruct);
+      rv = nameSpaceManager->LookupName(aName, &globalStruct);
       NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && globalStruct, nsnull);
 
       NS_ASSERTION(globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
                    "The classinfo data for this class didn't get registered.");
     }
     if (globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
       return nsDOMClassInfo::GetClassInfoInstance(globalStruct->mData);
     }
@@ -362,27 +361,26 @@ NS_IMETHODIMP
 nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
 					       nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
 					       const nsIID *aProtoChainInterface,
 					       const nsIID **aInterfaces,
 					       PRUint32 aScriptableFlags,
 					       PRBool aHasClassInterface,
 					       const nsCID *aConstructorCID)
 {
-  extern nsScriptNameSpaceManager *gNameSpaceManager;
-
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
-  return gNameSpaceManager->RegisterDOMCIData(aName,
-                                              aConstructorFptr,
-                                              aProtoChainInterface,
-                                              aInterfaces,
-                                              aScriptableFlags,
-                                              aHasClassInterface,
-                                              aConstructorCID);
+  return nameSpaceManager->RegisterDOMCIData(aName,
+                                             aConstructorFptr,
+                                             aProtoChainInterface,
+                                             aInterfaces,
+                                             aScriptableFlags,
+                                             aHasClassInterface,
+                                             aConstructorCID);
 }
 
 /* static */ nsresult
 nsDOMScriptObjectFactory::Startup()
 {
   nsJSRuntime::Startup();
   // nsDOMScriptObjectFactory is a service - assuming that reinitialzing
   // xpcom also recreates all services, then everything else should
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -67,17 +67,16 @@
 #include "nsPresContext.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPrompt.h"
 #include "nsIObserverService.h"
 #include "nsGUIEvent.h"
-#include "nsScriptNameSpaceManager.h"
 #include "nsThreadUtils.h"
 #include "nsITimer.h"
 #include "nsIAtom.h"
 #include "nsContentUtils.h"
 #include "jscntxt.h"
 #include "nsEventDispatcher.h"
 #include "nsIContent.h"
 #include "nsCycleCollector.h"
@@ -2310,26 +2309,16 @@ nsJSContext::InitContext(nsIScriptGlobal
 {
   // Make sure callers of this use
   // WillInitializeContext/DidInitializeContext around this call.
   NS_ENSURE_TRUE(!mIsInitialized, NS_ERROR_ALREADY_INITIALIZED);
 
   if (!mContext)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  nsresult rv;
-
-  if (!gNameSpaceManager) {
-    gNameSpaceManager = new nsScriptNameSpaceManager;
-    NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
-
-    rv = gNameSpaceManager->Init();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
   ::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);
 
   if (!aGlobalObject) {
     // If we don't get a global object then there's nothing more to do here.
 
     return NS_OK;
   }
 
@@ -2337,16 +2326,18 @@ nsJSContext::InitContext(nsIScriptGlobal
 
   JSObject *global = ::JS_GetGlobalObject(mContext);
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
   // If there's already a global object in mContext we won't tell
   // XPConnect to wrap aGlobalObject since it's already wrapped.
 
+  nsresult rv;
+
   if (!global) {
     nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aGlobalObject));
     PRUint32 flags = 0;
     
     if (chromeWindow) {
       // Flag this object and scripts compiled against it as "system", for
       // optional automated XPCNativeWrapper construction when chrome views
       // a content DOM.
@@ -2408,19 +2399,20 @@ nsJSContext::InitContext(nsIScriptGlobal
   NS_ENSURE_SUCCESS(rv, rv);
 
   return rv;
 }
 
 nsresult
 nsJSContext::InitializeExternalClasses()
 {
-  NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_NOT_INITIALIZED);
-
-  return gNameSpaceManager->InitForContext(this);
+  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+
+  return nameSpaceManager->InitForContext(this);
 }
 
 nsresult
 nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs)
 {
   PRUint32  argc;
   jsval    *argv = nsnull;
   void *mark;
@@ -3657,16 +3649,34 @@ nsJSRuntime::Init()
 
   rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &sSecurityManager);
 
   sIsInitialized = NS_SUCCEEDED(rv);
 
   return rv;
 }
 
+//static
+nsScriptNameSpaceManager*
+nsJSRuntime::GetNameSpaceManager()
+{
+  if (sDidShutdown)
+    return nsnull;
+
+  if (!gNameSpaceManager) {
+    gNameSpaceManager = new nsScriptNameSpaceManager;
+    NS_ENSURE_TRUE(gNameSpaceManager, nsnull);
+
+    nsresult rv = gNameSpaceManager->Init();
+    NS_ENSURE_SUCCESS(rv, nsnull);
+  }
+
+  return gNameSpaceManager;
+}
+
 void nsJSRuntime::ShutDown()
 {
   if (sGCTimer) {
     // We're being shut down, if we have a GC timer scheduled, cancel
     // it. The DOM factory will do one final GC once it's shut down.
 
     sGCTimer->Cancel();
 
--- a/dom/src/base/nsJSEnvironment.h
+++ b/dom/src/base/nsJSEnvironment.h
@@ -41,16 +41,17 @@
 #include "nsIScriptRuntime.h"
 #include "nsCOMPtr.h"
 #include "jsapi.h"
 #include "nsIObserver.h"
 #include "nsIXPCScriptNotify.h"
 #include "nsITimer.h"
 #include "prtime.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsScriptNameSpaceManager.h"
 
 class nsIXPConnectJSObjectHolder;
 
 class nsJSContext : public nsIScriptContext,
                     public nsIXPCScriptNotify,
                     public nsITimerCallback
 {
 public:
@@ -321,16 +322,18 @@ public:
   virtual nsresult DropScriptObject(void *object);
   virtual nsresult HoldScriptObject(void *object);
   
   // Private stuff.
   // called by the nsDOMScriptObjectFactory to initialize statics
   static void Startup();
   // Setup all the statics etc - safe to call multiple times after Startup()
   static nsresult Init();
+  // Get the NameSpaceManager, creating if necessary
+  static nsScriptNameSpaceManager* GetNameSpaceManager();
 };
 
 // An interface for fast and native conversion to/from nsIArray. If an object
 // supports this interface, JS can reach directly in for the argv, and avoid
 // nsISupports conversion. If this interface is not supported, the object will
 // be queried for nsIArray, and everything converted via xpcom objects.
 #define NS_IJSARGARRAY_IID \
  { /*{E96FB2AE-CB4F-44a0-81F8-D91C80AFE9A3} */ \
--- a/dom/tests/Makefile.in
+++ b/dom/tests/Makefile.in
@@ -37,14 +37,20 @@
 
 DEPTH		= ../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+MODULE = test_dom
+
 ifdef MOZ_MOCHITEST
 DIRS		+= mochitest
 endif
 
+ifdef ENABLE_TESTS
+XPCSHELL_TESTS = unit
+endif
+
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/dom/tests/unit/test_bug319968.js
@@ -0,0 +1,52 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *      Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+function run_test()
+{
+  var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
+                            .createInstance(Components.interfaces.nsIDOMParser);
+  var aDom = domParser.parseFromString("<root><feed><entry/><entry/></feed></root>",
+                                       "application/xml");
+  var feedList = aDom.getElementsByTagName("feed");
+  do_check_neq(feedList, null);
+  do_check_eq(feedList.length, 1);
+  do_check_neq(feedList[0], null);
+  do_check_eq(feedList[0].tagName, "feed");
+  var entry = feedList[0].getElementsByTagName("entry");
+  do_check_neq(entry, null);
+}