Bug 1499335 - Support module specifiers containing inline data in the shell r=evilpie
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/inline-data.js
@@ -0,0 +1,17 @@
+// |jit-test| module
+
+import { a } from "javascript: export let a = 42;";
+assertEq(a, 42);
+
+let result = null;
+let error = null;
+let promise = import("javascript: export let b = 100;");
+promise.then((ns) => {
+ result = ns;
+}).catch((e) => {
+ error = e;
+});
+
+drainJobQueue();
+assertEq(error, null);
+assertEq(result.b, 100);
--- a/js/src/shell/ModuleLoader.js
+++ b/js/src/shell/ModuleLoader.js
@@ -3,39 +3,49 @@
* 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/. */
/* global getModuleLoadPath setModuleLoadHook setModuleResolveHook setModuleMetadataHook */
/* global getModulePrivate setModulePrivate parseModule os */
/* global setModuleDynamicImportHook finishDynamicModuleImport abortDynamicModuleImport */
// A basic synchronous module loader for testing the shell.
+//
+// Supports loading files and 'javascript:' URLs that embed JS source text.
+
{
// Save standard built-ins before scripts can modify them.
const ArrayPrototypeJoin = Array.prototype.join;
const MapPrototypeGet = Map.prototype.get;
const MapPrototypeHas = Map.prototype.has;
const MapPrototypeSet = Map.prototype.set;
const ObjectDefineProperty = Object.defineProperty;
const ReflectApply = Reflect.apply;
const StringPrototypeIndexOf = String.prototype.indexOf;
const StringPrototypeLastIndexOf = String.prototype.lastIndexOf;
const StringPrototypeStartsWith = String.prototype.startsWith;
const StringPrototypeSubstring = String.prototype.substring;
const ErrorClass = Error;
+const JAVASCRIPT_SCHEME = "javascript:";
+
const ReflectLoader = new class {
constructor() {
this.registry = new Map();
this.loadPath = getModuleLoadPath();
}
+ isJavascriptURL(name) {
+ return ReflectApply(StringPrototypeStartsWith, name, [JAVASCRIPT_SCHEME]);
+ }
+
resolve(name, referencingInfo) {
- if (os.path.isAbsolute(name))
+ if (this.isJavascriptURL(name) || os.path.isAbsolute(name)) {
return name;
+ }
let loadPath = this.loadPath;
// Treat |name| as a relative path if it starts with either "./"
// or "../".
let isRelative = ReflectApply(StringPrototypeStartsWith, name, ["./"])
|| ReflectApply(StringPrototypeStartsWith, name, ["../"])
#ifdef XP_WIN
@@ -62,16 +72,20 @@ const ReflectLoader = new class {
if (sepIndex >= 0)
loadPath = ReflectApply(StringPrototypeSubstring, path, [0, sepIndex]);
}
return os.path.join(loadPath, name);
}
normalize(path) {
+ if (this.isJavascriptURL(path)) {
+ return path;
+ }
+
#ifdef XP_WIN
// Replace all forward slashes with backward slashes.
// NB: It may be tempting to replace this loop with a call to
// String.prototype.replace, but user scripts may have modified
// String.prototype or RegExp.prototype built-in functions, which makes
// it unsafe to call String.prototype.replace.
let newPath = "";
let lastSlash = 0;
@@ -145,16 +159,20 @@ const ReflectLoader = new class {
let normalized = ReflectApply(ArrayPrototypeJoin, components, [pathsep]);
#ifdef XP_WIN
normalized = drive + normalized;
#endif
return normalized;
}
fetch(path) {
+ if (this.isJavascriptURL(path)) {
+ return ReflectApply(StringPrototypeSubstring, path, [JAVASCRIPT_SCHEME.length]);
+ }
+
return os.file.readFile(path);
}
loadAndParse(path) {
let normalized = this.normalize(path);
if (ReflectApply(MapPrototypeHas, this.registry, [normalized]))
return ReflectApply(MapPrototypeGet, this.registry, [normalized]);