Bug 384168. C.u.import doesn't prevent recursion in the presence of circular dependencies. r=brendan, sr=bsmedberg

This commit is contained in:
sayrer@gmail.com 2007-06-19 23:29:49 -07:00
parent 629db88a38
commit 9a3ee4c1ac
5 changed files with 172 additions and 9 deletions

View File

@ -530,6 +530,8 @@ mozJSComponentLoader::ReallyInit()
return NS_ERROR_OUT_OF_MEMORY;
if (!mImports.Init(32))
return NS_ERROR_OUT_OF_MEMORY;
if (!mInProgressImports.Init(32))
return NS_ERROR_OUT_OF_MEMORY;
// Set up our fastload file
nsCOMPtr<nsIFastLoadService> flSvc = do_GetFastLoadService(&rv);
@ -1251,11 +1253,16 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
// Restore the old state of the fastload service.
flState.pop();
// Assign aGlobal here so that it's available to recursive imports.
// See bug 384168.
*aGlobal = global;
jsval retval;
if (!JS_ExecuteScript(cx, global, script, &retval)) {
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: failed to execute %s\n", nativePath.get());
#endif
*aGlobal = nsnull;
return NS_ERROR_FAILURE;
}
@ -1263,10 +1270,11 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
nsCAutoString path;
aComponent->GetNativePath(path);
*aLocation = ToNewCString(path);
if (!*aLocation)
if (!*aLocation) {
*aGlobal = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
*aGlobal = global;
JS_AddNamedRoot(cx, aGlobal, *aLocation);
return NS_OK;
}
@ -1276,15 +1284,15 @@ mozJSComponentLoader::UnloadModules()
{
mInitialized = PR_FALSE;
mModules.Clear();
mInProgressImports.Clear();
mImports.Clear();
mModules.Clear();
// Destroying our context will force a GC.
JS_DestroyContext(mContext);
mContext = nsnull;
mRuntimeService = nsnull;
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: UnloadAll(%d)\n", aWhen);
#endif
@ -1422,18 +1430,21 @@ mozJSComponentLoader::ImportInto(const nsACString & aLocation,
ModuleEntry* mod;
nsAutoPtr<ModuleEntry> newEntry;
if (!mImports.Get(lfhash, &mod)) {
if (!mImports.Get(lfhash, &mod) && !mInProgressImports.Get(lfhash, &mod)) {
newEntry = new ModuleEntry;
if (!newEntry)
if (!newEntry || !mInProgressImports.Put(lfhash, newEntry))
return NS_ERROR_OUT_OF_MEMORY;
rv = GlobalForLocation(componentFile, &newEntry->global,
&newEntry->location);
mInProgressImports.Remove(lfhash);
if (NS_FAILED(rv)) {
*_retval = nsnull;
return NS_ERROR_FILE_NOT_FOUND;
}
mod = newEntry;
}

View File

@ -54,6 +54,7 @@
#include "nsIObserver.h"
#include "xpcIJSModuleLoader.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#ifndef XPCONNECT_STANDALONE
#include "nsIPrincipal.h"
#endif
@ -122,7 +123,6 @@ class mozJSComponentLoader : public nsIModuleLoader,
void CloseFastLoad();
nsresult ReportOnCaller(nsIXPCNativeCallContext *cc,
const char *format, ...);
nsCOMPtr<nsIComponentManager> mCompMgr;
nsCOMPtr<nsIJSRuntimeService> mRuntimeService;
@ -167,6 +167,7 @@ class mozJSComponentLoader : public nsIModuleLoader,
nsClassHashtable<nsHashableHashKey, ModuleEntry> mModules;
nsClassHashtable<nsHashableHashKey, ModuleEntry> mImports;
nsDataHashtable<nsHashableHashKey, ModuleEntry*> mInProgressImports;
PRBool mInitialized;
};

View File

@ -0,0 +1,44 @@
/* ***** 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 module loader tests.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* 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 ***** */
EXPORTED_SYMBOLS = ["foo", "bar"]
function foo() {
return "foo";
}
var bar = {}
Components.utils.import("resource://test/recursive_importB.jsm", bar);

View File

@ -0,0 +1,45 @@
/* ***** 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 module loader tests.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* 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 ***** */
EXPORTED_SYMBOLS = ["baz", "qux"]
function baz() {
return "baz";
}
var qux = {}
Components.utils.import("resource://test/recursive_importA.jsm", qux);

View File

@ -0,0 +1,62 @@
/*
* ***** 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 code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Sayre <sayrer@gmail.com> (original author)
* Alexander J. Vincent <ajvincent@gmail.com>
*
* 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() {
const Ci = Components.interfaces;
const ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
const resProt = ioService.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
var curdir = do_get_file("js/src/xpconnect/tests/unit");
var curURI = ioService.newFileURI(curdir);
resProt.setSubstitution("test", curURI);
var scope = {};
Components.utils.import("resource://test/recursive_importA.jsm", scope);
// A imported correctly
do_check_true(scope.foo() == "foo");
// Symbols from B are visible through A
do_check_true(scope.bar.baz() == "baz");
// Symbols from A are visible through A, B, A.
do_check_true(scope.bar.qux.foo() == "foo");
}