michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "js/OldDebugAPI.h" michael@0: #include "jsapi-tests/tests.h" michael@0: michael@0: static JSPrincipals *sOriginPrincipalsInErrorReporter = nullptr; michael@0: static TestJSPrincipals prin1(1); michael@0: static TestJSPrincipals prin2(1); michael@0: michael@0: BEGIN_TEST(testOriginPrincipals) michael@0: { michael@0: /* michael@0: * Currently, the only way to set a non-trivial originPrincipal is to use michael@0: * JS_EvaluateUCScriptForPrincipalsVersionOrigin. This does not expose the michael@0: * compiled script, so we can only test nested scripts. michael@0: */ michael@0: michael@0: CHECK(testOuter("function f() {return 1}; f;")); michael@0: CHECK(testOuter("function outer() { return (function () {return 2}); }; outer();")); michael@0: CHECK(testOuter("eval('(function() {return 3})');")); michael@0: CHECK(testOuter("(function (){ return eval('(function() {return 4})'); })()")); michael@0: CHECK(testOuter("(function (){ return eval('(function() { return eval(\"(function(){return 5})\") })()'); })()")); michael@0: CHECK(testOuter("new Function('return 6')")); michael@0: CHECK(testOuter("function f() { return new Function('return 7') }; f();")); michael@0: CHECK(testOuter("eval('new Function(\"return 8\")')")); michael@0: CHECK(testOuter("(new Function('return eval(\"(function(){return 9})\")'))()")); michael@0: CHECK(testOuter("(function(){return function(){return 10}}).bind()()")); michael@0: CHECK(testOuter("var e = eval; (function() { return e('(function(){return 11})') })()")); michael@0: michael@0: JS_SetErrorReporter(cx, ErrorReporter); michael@0: CHECK(testError("eval(-)")); michael@0: CHECK(testError("-")); michael@0: CHECK(testError("new Function('x', '-')")); michael@0: CHECK(testError("eval('new Function(\"x\", \"-\")')")); michael@0: michael@0: /* michael@0: * NB: uncaught exceptions, when reported, have nothing on the stack so michael@0: * both the filename and originPrincipals are null. E.g., this would fail: michael@0: * michael@0: * CHECK(testError("throw 3")); michael@0: */ michael@0: return true; michael@0: } michael@0: michael@0: static void michael@0: ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) michael@0: { michael@0: sOriginPrincipalsInErrorReporter = report->originPrincipals; michael@0: } michael@0: michael@0: bool michael@0: eval(const char *asciiChars, JSPrincipals *principals, JSPrincipals *originPrincipals, JS::MutableHandleValue rval) michael@0: { michael@0: size_t len = strlen(asciiChars); michael@0: jschar *chars = new jschar[len+1]; michael@0: for (size_t i = 0; i < len; ++i) michael@0: chars[i] = asciiChars[i]; michael@0: chars[len] = 0; michael@0: michael@0: JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook)); michael@0: CHECK(global); michael@0: JSAutoCompartment ac(cx, global); michael@0: CHECK(JS_InitStandardClasses(cx, global)); michael@0: michael@0: michael@0: JS::CompileOptions options(cx); michael@0: options.setOriginPrincipals(originPrincipals) michael@0: .setFileAndLine("", 0); michael@0: michael@0: bool ok = JS::Evaluate(cx, global, options, chars, len, rval); michael@0: michael@0: delete[] chars; michael@0: return ok; michael@0: } michael@0: michael@0: bool michael@0: testOuter(const char *asciiChars) michael@0: { michael@0: CHECK(testInner(asciiChars, &prin1, &prin1)); michael@0: CHECK(testInner(asciiChars, &prin1, &prin2)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: testInner(const char *asciiChars, JSPrincipals *principal, JSPrincipals *originPrincipal) michael@0: { michael@0: JS::RootedValue rval(cx); michael@0: CHECK(eval(asciiChars, principal, originPrincipal, &rval)); michael@0: michael@0: JS::RootedFunction fun(cx, &rval.toObject().as()); michael@0: JSScript *script = JS_GetFunctionScript(cx, fun); michael@0: CHECK(JS_GetScriptPrincipals(script) == principal); michael@0: CHECK(JS_GetScriptOriginPrincipals(script) == originPrincipal); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: testError(const char *asciiChars) michael@0: { michael@0: JS::RootedValue rval(cx); michael@0: CHECK(!eval(asciiChars, &prin1, &prin2 /* = originPrincipals */, &rval)); michael@0: CHECK(JS_ReportPendingException(cx)); michael@0: CHECK(sOriginPrincipalsInErrorReporter == &prin2); michael@0: return true; michael@0: } michael@0: END_TEST(testOriginPrincipals)