diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4906,16 +4906,26 @@ JS_EvaluateScriptForPrincipals(JSContext return JS_FALSE; JSBool ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno, rval); cx->free(chars); return ok; } JS_PUBLIC_API(JSBool) +JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals, + const char *bytes, uintN nbytes, + const char *filename, uintN lineno, jsval *rval, JSVersion version) +{ + AutoVersionAPI avi(cx, version); + return JS_EvaluateScriptForPrincipals(cx, obj, principals, bytes, nbytes, filename, lineno, + rval); +} + +JS_PUBLIC_API(JSBool) JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, uintN nbytes, const char *filename, uintN lineno, jsval *rval) { JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->defaultCompartment); return JS_EvaluateScriptForPrincipals(cx, obj, NULL, bytes, nbytes, filename, lineno, rval); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsapi.h b/js/src/jsapi.h --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2558,16 +2558,23 @@ JS_EvaluateScript(JSContext *cx, JSObjec extern JS_PUBLIC_API(JSBool) JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals, const char *bytes, uintN length, const char *filename, uintN lineno, jsval *rval); extern JS_PUBLIC_API(JSBool) +JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, + JSPrincipals *principals, + const char *bytes, uintN length, + const char *filename, uintN lineno, + jsval *rval, JSVersion version); + +extern JS_PUBLIC_API(JSBool) JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, uintN length, const char *filename, uintN lineno, jsval *rval); extern JS_PUBLIC_API(JSBool) JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals, diff --git a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp --- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -57,16 +57,18 @@ #include "nsNetUtil.h" #include "nsIProtocolHandler.h" #include "nsIFileURL.h" #include "nsScriptLoader.h" #include "jsapi.h" #include "jsdbgapi.h" #include "jsobj.h" +#include "jsscript.h" +#include "jscntxt.h" #include "mozilla/FunctionTimer.h" /* load() error msgs, XXX localize? */ #define LOAD_ERROR_NOSERVICE "Error creating IO Service." #define LOAD_ERROR_NOURI "Error creating URI (invalid URL scheme?)" #define LOAD_ERROR_NOSCHEME "Failed to get URI scheme. This is bad." #define LOAD_ERROR_URI_NOT_LOCAL "Trying to load a non-local URI." @@ -360,37 +362,45 @@ mozJSSubScriptLoader::LoadSubScript (con errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOPRINCIPALS); goto return_exception; } /* set our own error reporter so we can report any bad things as catchable * exceptions, including the source/line number */ er = JS_SetErrorReporter (cx, mozJSLoaderErrorReporter); - if (charset) { - nsString script; - rv = nsScriptLoader::ConvertToUTF16 (nsnull, - reinterpret_cast(buf.get()), len, - nsDependentString( - reinterpret_cast(charset)), - nsnull, script); - if (NS_FAILED(rv)) + JSVersion version = cx->findVersion(); + /* The API doesn't like getting anything other than the XML flag. */ + JSVersion mungedVersion = js::VersionNumber(version); + js::VersionSetXML(&mungedVersion, js::VersionHasXML(version)); + + if (charset) { - errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_BADCHARSET); - goto return_exception; + nsString script; + rv = nsScriptLoader::ConvertToUTF16( + nsnull, reinterpret_cast(buf.get()), len, + nsDependentString(reinterpret_cast(charset)), nsnull, script); + + if (NS_FAILED(rv)) + { + errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_BADCHARSET); + goto return_exception; + } + ok = JS_EvaluateUCScriptForPrincipalsVersion(cx, target_obj, jsPrincipals, + reinterpret_cast(script.get()), + script.Length(), uriStr.get(), 1, rval, + mungedVersion); } - ok = JS_EvaluateUCScriptForPrincipals (cx, target_obj, jsPrincipals, - reinterpret_cast(script.get()), - script.Length(), uriStr.get(), 1, rval); - } - else - { - ok = JS_EvaluateScriptForPrincipals (cx, target_obj, jsPrincipals, - buf, len, uriStr.get(), 1, rval); + else + { + ok = JS_EvaluateScriptForPrincipalsVersion(cx, target_obj, jsPrincipals, + buf, len, uriStr.get(), 1, rval, + mungedVersion); + } } { JSAutoEnterCompartment rac; if (!rac.enter(cx, result_obj) || !JS_WrapValue(cx, rval)) return NS_ERROR_UNEXPECTED; } diff --git a/js/src/xpconnect/tests/unit/bug596580_versioned.js b/js/src/xpconnect/tests/unit/bug596580_versioned.js new file mode 100644 --- /dev/null +++ b/js/src/xpconnect/tests/unit/bug596580_versioned.js @@ -0,0 +1,4 @@ +/* Some constructs that require a high default version number. */ +let x = 12; +function simpleGen() { yield 12; } +var e4xy = Huzzah! diff --git a/js/src/xpconnect/tests/unit/test_bug596580.js b/js/src/xpconnect/tests/unit/test_bug596580.js new file mode 100644 --- /dev/null +++ b/js/src/xpconnect/tests/unit/test_bug596580.js @@ -0,0 +1,19 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +function run_test() { + var file = do_get_file("bug596580_versioned.js"); + var ios = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + var uri = ios.newFileURI(file); + var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader); + scriptLoader.loadSubScript(uri.spec); + version(150) + try { + scriptLoader.loadSubScript(uri.spec); + throw new Error("Subscript should fail to load."); + } catch (e if e instanceof SyntaxError) { + // Okay. + } +} diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -173,17 +173,21 @@ function _do_quit() { function _dump_exception_stack(stack) { stack.split("\n").forEach(function(frame) { if (!frame) return; // frame is of the form "fname(args)@file:line" let frame_regexp = new RegExp("(.*)\\(.*\\)@(.*):(\\d*)", "g"); let parts = frame_regexp.exec(frame); - dump("JS frame :: " + parts[2] + " :: " + (parts[1] ? parts[1] : "anonymous") + " :: line " + parts[3] + "\n"); + if (parts) + dump("JS frame :: " + parts[2] + " :: " + (parts[1] ? parts[1] : "anonymous") + + " :: line " + parts[3] + "\n"); + else /* Could be a -e (command line string) style location. */ + dump("JS frame :: " + frame + "\n"); }); } function _execute_test() { // Map resource://test/ to the current working directory. let (ios = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService)) { let protocolHandler =