Bug 1340110 - Make shell resolve root module relative to current directory as happens for non-module scripts r=anba
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 23 Feb 2017 16:26:14 +0000
changeset 373638 942c217ca90d4af830f5bc1bccb807b9c2d5e05b
parent 373637 f8c367bec5de25a16bd17a29bbd68ceafa3b0935
child 373639 c8b32cb1f15b5ad2588ddde5a3127697537b965a
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1340110
milestone54.0a1
Bug 1340110 - Make shell resolve root module relative to current directory as happens for non-module scripts r=anba
js/src/shell/ModuleLoader.js
js/src/shell/OSObject.cpp
js/src/shell/js.cpp
--- a/js/src/shell/ModuleLoader.js
+++ b/js/src/shell/ModuleLoader.js
@@ -16,28 +16,38 @@ Reflect.Loader = new class {
 
         return os.path.join(this.loadPath, name);
     }
 
     fetch(path) {
         return os.file.readFile(path);
     }
 
-    loadAndParse(name) {
-        let path = this.resolve(name);
-
+    loadAndParse(path) {
         if (this.registry.has(path))
             return this.registry.get(path);
 
         let source = this.fetch(path);
         let module = parseModule(source, path);
         this.registry.set(path, module);
         return module;
     }
 
-    ["import"](name, referrer) {
-        let module = this.loadAndParse(name);
+    loadAndExecute(path) {
+        let module = this.loadAndParse(path);
         module.declarationInstantiation();
         return module.evaluation();
     }
+
+    importRoot(path) {
+        return this.loadAndExecute(path);
+    }
+
+    ["import"](name, referrer) {
+        let path = this.resolve(name);
+        return this.loadAndExecute(path);
+    }
 };
 
-setModuleResolveHook((module, requestName) => Reflect.Loader.loadAndParse(requestName));
+setModuleResolveHook((module, requestName) => {
+    let path = Reflect.Loader.resolve(requestName);
+    return Reflect.Loader.loadAndParse(path)
+});
--- a/js/src/shell/OSObject.cpp
+++ b/js/src/shell/OSObject.cpp
@@ -107,26 +107,28 @@ ResolvePath(JSContext* cx, HandleString 
 
     JSAutoByteString filename(cx, filenameStr);
     if (!filename)
         return nullptr;
 
     if (IsAbsolutePath(filename))
         return filenameStr;
 
-    /* Get the currently executing script's name. */
     JS::AutoFilename scriptFilename;
-    if (!DescribeScriptedCaller(cx, &scriptFilename))
-        return nullptr;
+    if (resolveMode == ScriptRelative) {
+        // Get the currently executing script's name.
+        if (!DescribeScriptedCaller(cx, &scriptFilename))
+            return nullptr;
 
-    if (!scriptFilename.get())
-        return nullptr;
+        if (!scriptFilename.get())
+            return nullptr;
 
-    if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
-        resolveMode = RootRelative;
+        if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
+            resolveMode = RootRelative;
+    }
 
     static char buffer[PATH_MAX+1];
     if (resolveMode == ScriptRelative) {
 #ifdef XP_WIN
         // The docs say it can return EINVAL, but the compiler says it's void
         _splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr);
 #else
         strncpy(buffer, scriptFilename.get(), PATH_MAX+1);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -728,46 +728,60 @@ GetLoaderObject(JSContext* cx, MutableHa
     if (!JS_GetProperty(cx, object, "Loader", &value) || !value.isObject())
         return false;
 
     resultOut.set(&value.toObject());
     return true;
 }
 
 static bool
-GetImportMethod(JSContext* cx, HandleObject loader, MutableHandleFunction resultOut)
-{
-    // Look up the module loader's |import| method.
+GetImportRootMethod(JSContext* cx, HandleObject loader, MutableHandleFunction resultOut)
+{
+    // Look up the module loader's |importRoot| method.
 
     RootedValue value(cx);
-    if (!JS_GetProperty(cx, loader, "import", &value) || !value.isObject())
+    if (!JS_GetProperty(cx, loader, "importRoot", &value) || !value.isObject())
         return false;
 
     RootedObject object(cx, &value.toObject());
     if (!object->is<JSFunction>())
         return false;
 
     resultOut.set(&object->as<JSFunction>());
     return true;
 }
 
 static MOZ_MUST_USE bool
 RunModule(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
 {
-    // Execute a module by calling |Reflect.Loader.import(filename)|.
+    // Execute a module by calling Reflect.Loader.importRoot on the resolved
+    // filename.
 
     RootedObject loaderObj(cx);
-    MOZ_ALWAYS_TRUE(GetLoaderObject(cx, &loaderObj));
+    if (!GetLoaderObject(cx, &loaderObj)) {
+        JS_ReportErrorASCII(cx, "Failed to get Reflect.Loader");
+        return false;
+    }
 
     RootedFunction importFun(cx);
-    MOZ_ALWAYS_TRUE(GetImportMethod(cx, loaderObj, &importFun));
-
-    JS::AutoValueArray<2> args(cx);
-    args[0].setString(JS_NewStringCopyZ(cx, filename));
-    args[1].setUndefined();
+    if (!GetImportRootMethod(cx, loaderObj, &importFun)) {
+        JS_ReportErrorASCII(cx, "Failed to get Reflect.Loader.importRoot method");
+        return false;
+    }
+
+    RootedString path(cx, JS_NewStringCopyZ(cx, filename));
+    if (!path)
+        return false;
+
+    path = ResolvePath(cx, path, RootRelative);
+    if (!path)
+        return false;
+
+    JS::AutoValueArray<1> args(cx);
+    args[0].setString(path);
 
     RootedValue value(cx);
     return JS_CallFunction(cx, loaderObj, importFun, args, &value);
 }
 
 static JSObject*
 ShellGetIncumbentGlobalCallback(JSContext* cx)
 {