Bug 628669: Provide support for relative URLs in Components utils import (JSM, JS modules) r=bsmedberg r=mrbkap

This patch allows a JS module to import another one with a relative path. For
instance, if you have a set of modules you want to drop-in in any extension, and
these modules depend on each other, you can import XPCOMUtils and then do
XPCOMUtils.importRelative(this, "otherfile.jsm").
This commit is contained in:
Jonathan Protzenko 2011-04-14 00:10:13 +02:00
parent 7a367d7a36
commit c0260ef7cc
5 changed files with 55 additions and 3 deletions

View File

@ -258,7 +258,20 @@ var XPCOMUtils = {
}
}
return factory;
}
},
/**
* Allows you to fake a relative import. Expects the global object from the
* module that's calling us, and the relative filename that we wish to import.
*/
importRelative: function XPCOMUtils__importRelative(that, path) {
if (!("__URI__" in that))
throw Error("importRelative may only be used from a JSM, and its first argument "+
"must be that JSM's global object (hint: use this)");
let uri = that.__URI__;
let i = uri.lastIndexOf("/");
Components.utils.import(uri.substring(0, i+1) + path, that);
},
};
/**

View File

@ -1030,6 +1030,14 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
NS_ENSURE_SUCCESS(rv, rv);
#endif
// Expose the URI from which the script was imported through a special
// variable that we insert into the JSM.
JSString *exposedUri = JS_NewStringCopyN(cx, nativePath.get(), nativePath.Length());
if (!JS_DefineProperty(cx, global, "__URI__",
STRING_TO_JSVAL(exposedUri), nsnull, nsnull, 0))
return NS_ERROR_FAILURE;
JSObject *scriptObj = nsnull;
#ifdef MOZ_ENABLE_LIBXUL

View File

@ -1,5 +1,24 @@
// Module used by test_import_module.js
const EXPORTED_SYMBOLS = [ "MODULE_IMPORTED" ];
const EXPORTED_SYMBOLS = [ "MODULE_IMPORTED", "MODULE_URI", "SUBMODULE_IMPORTED", "same_scope" ];
const MODULE_IMPORTED = true;
const MODULE_URI = __URI__;
// Will import SUBMODULE_IMPORTED into scope.
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.importRelative(this, "import_sub_module.jsm");
// Prepare two scopes that we can import the submodule into.
var scope1 = { __URI__: __URI__ };
var scope2 = { __URI__: __URI__ };
// First one is the regular path.
XPCOMUtils.importRelative(scope1, "import_sub_module.jsm");
scope1.test_obj.i++;
// Second one is with a different path (leads to the same file).
XPCOMUtils.importRelative(scope2, "duh/../import_sub_module.jsm");
// test_obj belongs to import_sub_module.jsm and has a mutable field name i, if
// the two modules are actually the same, then they'll share the same value.
// We'll leave it up to test_import_module.js to check that this variable is
// true.
var same_scope = (scope1.test_obj.i == scope2.test_obj.i);

View File

@ -0,0 +1,6 @@
// Module used by import_module.jsm
var EXPORTED_SYMBOLS = [ "SUBMODULE_IMPORTED", "test_obj" ];
const SUBMODULE_IMPORTED = true;
var test_obj = { i: 0 };

View File

@ -22,6 +22,7 @@
*
* Contributor(s):
* Marco Bonardo <mak77@bonardo.net>
* Jonathan Protzenko <jonathan.protzenko@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
@ -44,6 +45,11 @@
function run_test() {
do_check_true(typeof(this['MODULE_IMPORTED']) == "undefined");
Components.utils.import("resource://test/import_module.jsm");
do_check_true(typeof(this['MODULE_URI']) == "undefined");
let uri = "resource://test/import_module.jsm";
Components.utils.import(uri);
do_check_true(MODULE_URI == uri);
do_check_true(MODULE_IMPORTED);
do_check_true(SUBMODULE_IMPORTED);
do_check_true(same_scope);
}