| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * 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/. */ |
| |
| #include "tests.h" |
| #include "jsdbgapi.h" |
| |
| JSPrincipals *sOriginPrincipalsInErrorReporter = NULL; |
| |
| static void |
| ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) |
| { |
| sOriginPrincipalsInErrorReporter = report->originPrincipals; |
| } |
| |
| JSPrincipals prin1 = { 1 }; |
| JSPrincipals prin2 = { 1 }; |
| |
| BEGIN_TEST(testOriginPrincipals) |
| { |
| /* |
| * Currently, the only way to set a non-trivial originPrincipal is to use |
| * JS_EvaluateUCScriptForPrincipalsVersionOrigin. This does not expose the |
| * compiled script, so we can only test nested scripts. |
| */ |
| |
| CHECK(testOuter("function f() {return 1}; f;")); |
| CHECK(testOuter("function outer() { return (function () {return 2}); }; outer();")); |
| CHECK(testOuter("eval('(function() {return 3})');")); |
| CHECK(testOuter("(function (){ return eval('(function() {return 4})'); })()")); |
| CHECK(testOuter("(function (){ return eval('(function() { return eval(\"(function(){return 5})\") })()'); })()")); |
| CHECK(testOuter("new Function('return 6')")); |
| CHECK(testOuter("function f() { return new Function('return 7') }; f();")); |
| CHECK(testOuter("eval('new Function(\"return 8\")')")); |
| CHECK(testOuter("(new Function('return eval(\"(function(){return 9})\")'))()")); |
| CHECK(testOuter("(function(){return function(){return 10}}).bind()()")); |
| CHECK(testOuter("var e = eval; (function() { return e('(function(){return 11})') })()")); |
| |
| JS_SetErrorReporter(cx, ErrorReporter); |
| CHECK(testError("eval(-)")); |
| CHECK(testError("-")); |
| CHECK(testError("new Function('x', '-')")); |
| CHECK(testError("eval('new Function(\"x\", \"-\")')")); |
| |
| /* |
| * NB: uncaught exceptions, when reported, have nothing on the stack so |
| * both the filename and originPrincipals are null. E.g., this would fail: |
| * |
| * CHECK(testError("throw 3")); |
| */ |
| return true; |
| } |
| |
| bool |
| eval(const char *asciiChars, JSPrincipals *principals, JSPrincipals *originPrincipals, jsval *rval) |
| { |
| size_t len = strlen(asciiChars); |
| jschar *chars = new jschar[len+1]; |
| for (size_t i = 0; i < len; ++i) |
| chars[i] = asciiChars[i]; |
| chars[len] = 0; |
| |
| JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals)); |
| CHECK(global); |
| JSAutoCompartment ac(cx, global); |
| CHECK(JS_InitStandardClasses(cx, global)); |
| bool ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin(cx, global, |
| principals, |
| originPrincipals, |
| chars, len, "", 0, rval, |
| JSVERSION_DEFAULT); |
| delete[] chars; |
| return ok; |
| } |
| |
| bool |
| testOuter(const char *asciiChars) |
| { |
| CHECK(testInner(asciiChars, &prin1, &prin1)); |
| CHECK(testInner(asciiChars, &prin1, &prin2)); |
| return true; |
| } |
| |
| bool |
| testInner(const char *asciiChars, JSPrincipals *principal, JSPrincipals *originPrincipal) |
| { |
| JS::RootedValue rval(cx); |
| CHECK(eval(asciiChars, principal, originPrincipal, rval.address())); |
| |
| JSScript *script = JS_GetFunctionScript(cx, &rval.toObject().as<JSFunction>()); |
| CHECK(JS_GetScriptPrincipals(script) == principal); |
| CHECK(JS_GetScriptOriginPrincipals(script) == originPrincipal); |
| |
| return true; |
| } |
| |
| bool |
| testError(const char *asciiChars) |
| { |
| jsval rval; |
| CHECK(!eval(asciiChars, &prin1, &prin2 /* = originPrincipals */, &rval)); |
| CHECK(JS_ReportPendingException(cx)); |
| CHECK(sOriginPrincipalsInErrorReporter == &prin2); |
| return true; |
| } |
| END_TEST(testOriginPrincipals) |