Bug 980180 - remove principals as an argument to compilation, part 1 (r=terrence)
authorLuke Wagner <luke@mozilla.com>
Thu, 06 Mar 2014 16:28:05 -0600
changeset 172350 3aa4c0b57f214eb690cf8e0e2bff6d2ffd6e8590
parent 172349 797981dc56951f4ad2f58beac956702be2392848
child 172351 7fd4f489f0ab82a63f1caa3959cd313bf74fb9dd
push id40715
push userlwagner@mozilla.com
push dateFri, 07 Mar 2014 00:40:44 +0000
treeherdermozilla-inbound@7fd4f489f0ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs980180
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 980180 - remove principals as an argument to compilation, part 1 (r=terrence)
content/base/src/nsFrameMessageManager.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsJSUtils.cpp
dom/workers/ScriptLoader.cpp
dom/workers/WorkerPrivate.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/src/builtin/Eval.cpp
js/src/builtin/Eval.h
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/TokenStream.cpp
js/src/jit/AsmJSLink.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testCloneScript.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsfun.cpp
js/src/jsscript.cpp
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCShellImpl.cpp
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1489,18 +1489,17 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
   }
 
   if (!dataString.IsEmpty()) {
     AutoSafeJSContext cx;
     JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
     if (global) {
       JSAutoCompartment ac(cx, global);
       JS::CompileOptions options(cx);
-      options.setFileAndLine(url.get(), 1)
-             .setPrincipals(nsJSPrincipals::get(mPrincipal));
+      options.setFileAndLine(url.get(), 1);
       JS::Rooted<JSScript*> script(cx);
       JS::Rooted<JSObject*> funobj(cx);
       if (aRunInGlobalScope) {
         options.setNoScriptRval(true);
         script = JS::Compile(cx, JS::NullPtr(), options, dataString.get(),
                              dataString.Length());
       } else {
         JS::Rooted<JSFunction *> fun(cx);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2638,18 +2638,17 @@ nsXULPrototypeScript::Compile(const char
     JSAutoCompartment ac(cx, aProtoDoc->GetCompilationGlobal());
 
     nsAutoCString urlspec;
     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);
 
     // Ok, compile it to create a prototype script object!
     NS_ENSURE_TRUE(JSVersion(mLangVersion) != JSVERSION_UNKNOWN, NS_OK);
     JS::CompileOptions options(cx);
-    options.setPrincipals(nsJSPrincipals::get(aDocument->NodePrincipal()))
-           .setFileAndLine(urlspec.get(), aLineNo)
+    options.setFileAndLine(urlspec.get(), aLineNo)
            .setVersion(JSVersion(mLangVersion));
     // If the script was inline, tell the JS parser to save source for
     // Function.prototype.toSource(). If it's out of line, we retrieve the
     // source from the files on demand.
     options.setSourcePolicy(mOutOfLine ? JS::CompileOptions::LAZY_SOURCE
                                        : JS::CompileOptions::SAVE_SOURCE);
     JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
     if (scope) {
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -146,22 +146,16 @@ nsJSUtils::CompileFunction(JSContext* aC
                            JSObject** aFunctionObject)
 {
   MOZ_ASSERT(js::GetEnterCompartmentDepth(aCx) > 0);
   MOZ_ASSERT_IF(aTarget, js::IsObjectInContextCompartment(aTarget, aCx));
   MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN);
   mozilla::DebugOnly<nsIScriptContext*> ctx = GetScriptContextFromJSContext(aCx);
   MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized());
 
-  // Since aTarget and aCx are same-compartment, there should be no distinction
-  // between the object principal and the cx principal.
-  // However, aTarget may be null in the wacky aShared case. So use the cx.
-  JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetContextCompartment(aCx));
-  aOptions.setPrincipals(p);
-
   // Do the junk Gecko is supposed to do before calling into JSAPI.
   if (aTarget) {
     JS::ExposeObjectToActiveJS(aTarget);
   }
 
   // Compile.
   JSFunction* fun = JS::CompileFunction(aCx, aTarget, aOptions,
                                         PromiseFlatCString(aName).get(),
@@ -200,19 +194,16 @@ nsJSUtils::EvaluateString(JSContext* aCx
   if (aRetValue) {
     *aRetValue = JSVAL_VOID;
   }
 
   JS::ExposeObjectToActiveJS(aScopeObject);
   nsAutoMicroTask mt;
   nsresult rv = NS_OK;
 
-  JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject));
-  aCompileOptions.setPrincipals(p);
-
   bool ok = false;
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK);
 
   mozilla::Maybe<AutoDontReportUncaught> dontReport;
   if (!aEvaluateOptions.reportUncaught) {
     // We need to prevent AutoLastFrameCheck from reporting and clearing
     // any pending exceptions.
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -694,37 +694,33 @@ ScriptExecutorRunnable::WorkerRun(JSCont
     if (!loadInfo.mExecutionResult) {
       return true;
     }
   }
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   NS_ASSERTION(global, "Must have a global by now!");
 
-  JSPrincipals* principal = GetWorkerPrincipal();
-  NS_ASSERTION(principal, "This should never be null!");
-
   for (uint32_t index = mFirstIndex; index <= mLastIndex; index++) {
     ScriptLoadInfo& loadInfo = loadInfos.ElementAt(index);
 
     NS_ASSERTION(!loadInfo.mChannel, "Should no longer have a channel!");
     NS_ASSERTION(loadInfo.mExecutionScheduled, "Should be scheduled!");
     NS_ASSERTION(!loadInfo.mExecutionResult, "Should not have executed yet!");
 
     if (NS_FAILED(loadInfo.mLoadResult)) {
       scriptloader::ReportLoadError(aCx, loadInfo.mURL, loadInfo.mLoadResult,
                                     false);
       return true;
     }
 
     NS_ConvertUTF16toUTF8 filename(loadInfo.mURL);
 
     JS::CompileOptions options(aCx);
-    options.setPrincipals(principal)
-           .setFileAndLine(filename.get(), 1);
+    options.setFileAndLine(filename.get(), 1);
     if (!JS::Evaluate(aCx, global, options, loadInfo.mScriptText.get(),
                       loadInfo.mScriptText.Length(), nullptr)) {
       return true;
     }
 
     loadInfo.mExecutionResult = true;
   }
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5364,17 +5364,16 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
 
   NS_ASSERTION(mTimer, "Must have a timer!");
   NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!");
 
   bool retval = true;
 
   AutoPtrComparator<TimeoutInfo> comparator = GetAutoPtrComparator(mTimeouts);
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-  JSPrincipals* principal = GetWorkerPrincipal();
 
   // We want to make sure to run *something*, even if the timer fired a little
   // early. Fudge the value of now to at least include the first timeout.
   const TimeStamp now = std::max(TimeStamp::Now(), mTimeouts[0]->mTargetTime);
 
   nsAutoTArray<TimeoutInfo*, 10> expiredTimeouts;
   for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
     nsAutoPtr<TimeoutInfo>& info = mTimeouts[index];
@@ -5410,18 +5409,17 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
         retval = false;
         break;
       }
     }
     else {
       nsString expression = info->mTimeoutString;
 
       JS::CompileOptions options(aCx);
-      options.setPrincipals(principal)
-        .setFileAndLine(info->mFilename.get(), info->mLineNumber);
+      options.setFileAndLine(info->mFilename.get(), info->mLineNumber);
 
       if ((expression.IsEmpty() ||
            !JS::Evaluate(aCx, global, options, expression.get(),
                          expression.Length(), nullptr)) &&
           !JS_ReportPendingException(aCx)) {
         retval = false;
         break;
       }
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -159,18 +159,17 @@ Load(JSContext *cx,
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return false;
         }
         Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
         JS::CompileOptions options(cx);
         options.setUTF8(true)
-               .setFileAndLine(filename.ptr(), 1)
-               .setPrincipals(Environment(global)->GetPrincipal());
+               .setFileAndLine(filename.ptr(), 1);
         JS::RootedObject rootedObj(cx, obj);
         JSScript *script = JS::Compile(cx, rootedObj, options, file);
         fclose(file);
         if (!script)
             return false;
 
         JS::Rooted<JS::Value> result(cx);
         if (!JS_ExecuteScript(cx, obj, script, result.address())) {
@@ -328,18 +327,17 @@ XPCShellEnvironment::ProcessFile(JSConte
         }
         ungetc(ch, file);
 
         JSAutoRequest ar(cx);
         JSAutoCompartment ac(cx, obj);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
-               .setFileAndLine(filename, 1)
-               .setPrincipals(env->GetPrincipal());
+               .setFileAndLine(filename, 1);
         JSScript* script = JS::Compile(cx, obj, options, file);
         if (script)
             (void)JS_ExecuteScript(cx, obj, script, result.address());
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
@@ -366,18 +364,17 @@ XPCShellEnvironment::ProcessFile(JSConte
             }
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
-        options.setFileAndLine("typein", startline)
-               .setPrincipals(env->GetPrincipal());
+        options.setFileAndLine("typein", startline);
         script = JS_CompileScript(cx, obj, buffer, strlen(buffer), options);
         if (script) {
             JSErrorReporter older;
 
             ok = JS_ExecuteScript(cx, obj, script, result.address());
             if (ok && result != JSVAL_VOID) {
                 /* Suppress error reports from JS::ToString(). */
                 older = JS_SetErrorReporter(cx, nullptr);
@@ -575,18 +572,17 @@ bool
 XPCShellEnvironment::EvaluateString(const nsString& aString,
                                     nsString* aResult)
 {
   AutoSafeJSContext cx;
   JS::Rooted<JSObject*> global(cx, GetGlobalObject());
   JSAutoCompartment ac(cx, global);
 
   JS::CompileOptions options(cx);
-  options.setFileAndLine("typein", 0)
-         .setPrincipals(GetPrincipal());
+  options.setFileAndLine("typein", 0);
   JSScript* script = JS_CompileUCScript(cx, global, aString.get(),
                                         aString.Length(), options);
   if (!script) {
      return false;
   }
 
   if (aResult) {
       aResult->Truncate();
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -282,18 +282,16 @@ EvalKernel(JSContext *cx, const CallArgs
 
     Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
     if (!flatStr)
         return false;
 
     size_t length = flatStr->length();
     ConstTwoByteChars chars(flatStr->chars(), length);
 
-    JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
-
     RootedScript callerScript(cx, caller ? caller.script() : nullptr);
     EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, args.rval());
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
     if (evalType == DIRECT_EVAL && caller.isNonEvalFunctionFrame())
@@ -315,17 +313,16 @@ EvalKernel(JSContext *cx, const CallArgs
         if (maybeScript && maybeScript->scriptSource()->introducerFilename())
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         CompileOptions options(cx);
         options.setFileAndLine(filename, 1)
                .setCompileAndGo(true)
                .setForEval(true)
                .setNoScriptRval(false)
-               .setPrincipals(principals)
                .setOriginPrincipals(originPrincipals)
                .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
         JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                      scopeobj, callerScript, options,
                                                      chars.get(), length, flatStr, staticLevel);
         if (!compiled)
             return false;
 
@@ -364,19 +361,16 @@ js::DirectEvalStringFromIon(JSContext *c
     ConstTwoByteChars chars(flatStr->chars(), length);
 
     EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, vp);
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
-    // Ion will not perform cross compartment direct eval calls.
-    JSPrincipals *principals = cx->compartment()->principals;
-
     esg.lookupInEvalCache(flatStr, callerScript, pc);
 
     if (!esg.foundScript()) {
         JSScript *maybeScript;
         const char *filename;
         unsigned lineno;
         JSPrincipals *originPrincipals;
         uint32_t pcOffset;
@@ -387,17 +381,16 @@ js::DirectEvalStringFromIon(JSContext *c
         if (maybeScript && maybeScript->scriptSource()->introducerFilename())
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         CompileOptions options(cx);
         options.setFileAndLine(filename, 1)
                .setCompileAndGo(true)
                .setForEval(true)
                .setNoScriptRval(false)
-               .setPrincipals(principals)
                .setOriginPrincipals(originPrincipals)
                .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
         JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                      scopeobj, callerScript, options,
                                                      chars.get(), length, flatStr, staticLevel);
         if (!compiled)
             return false;
 
@@ -455,32 +448,8 @@ js::DirectEval(JSContext *cx, const Call
     return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain, iter.pc());
 }
 
 bool
 js::IsAnyBuiltinEval(JSFunction *fun)
 {
     return fun->maybeNative() == IndirectEval;
 }
-
-JSPrincipals *
-js::PrincipalsForCompiledCode(const CallReceiver &call, JSContext *cx)
-{
-    JSObject &callee = call.callee();
-    JS_ASSERT(IsAnyBuiltinEval(&callee.as<JSFunction>()) ||
-              callee.as<JSFunction>().isBuiltinFunctionConstructor());
-
-    // To compute the principals of the compiled eval/Function code, we simply
-    // use the callee's principals. To see why the caller's principals are
-    // ignored, consider first that, in the capability-model we assume, the
-    // high-privileged eval/Function should never have escaped to the
-    // low-privileged caller. (For the Mozilla embedding, this is brute-enforced
-    // by explicit filtering by wrappers.) Thus, the caller's privileges should
-    // subsume the callee's.
-    //
-    // In the converse situation, where the callee has lower privileges than the
-    // caller, we might initially guess that the caller would want to retain
-    // their higher privileges in the generated code. However, since the
-    // compiled code will be run with the callee's scope chain, this would make
-    // fp->script()->compartment() != fp->compartment().
-
-    return callee.compartment()->principals;
-}
--- a/js/src/builtin/Eval.h
+++ b/js/src/builtin/Eval.h
@@ -37,15 +37,10 @@ DirectEvalValueFromIon(JSContext *cx,
                        HandleObject scopeObj, HandleScript callerScript,
                        HandleValue thisValue, HandleValue evalArg,
                        jsbytecode * pc, MutableHandleValue vp);
 
 // True iff fun is a built-in eval function.
 extern bool
 IsAnyBuiltinEval(JSFunction *fun);
 
-// Return the principals to assign to code compiled for a call to
-// eval or the Function constructor.
-extern JSPrincipals *
-PrincipalsForCompiledCode(const CallReceiver &call, JSContext *cx);
-
 }  // namespace js
 #endif /* builtin_Eval_h */
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -426,18 +426,17 @@ frontend::CompileScript(ExclusiveContext
 }
 
 bool
 frontend::CompileLazyFunction(JSContext *cx, Handle<LazyScript*> lazy, const jschar *chars, size_t length)
 {
     JS_ASSERT(cx->compartment() == lazy->functionNonDelazifying()->compartment());
 
     CompileOptions options(cx, lazy->version());
-    options.setPrincipals(cx->compartment()->principals)
-           .setOriginPrincipals(lazy->originPrincipals())
+    options.setOriginPrincipals(lazy->originPrincipals())
            .setFileAndLine(lazy->source()->filename(), lazy->lineno())
            .setColumn(lazy->column())
            .setCompileAndGo(true)
            .setNoScriptRval(false)
            .setSelfHostingMode(false);
 
 #if JS_TRACE_LOGGING
         js::AutoTraceLog logger(js::TraceLogging::defaultLogger(),
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4845,18 +4845,17 @@ EmitFunc(ExclusiveContext *cx, BytecodeE
 
             if (outersc->isFunctionBox() && outersc->asFunctionBox()->mightAliasLocals())
                 funbox->setMightAliasLocals();      // inherit mightAliasLocals from parent
             JS_ASSERT_IF(outersc->strict, funbox->strict);
 
             // Inherit most things (principals, version, etc) from the parent.
             Rooted<JSScript*> parent(cx, bce->script);
             CompileOptions options(cx, bce->parser->options());
-            options.setPrincipals(parent->principals())
-                   .setOriginPrincipals(parent->originPrincipals())
+            options.setOriginPrincipals(parent->originPrincipals())
                    .setCompileAndGo(parent->compileAndGo())
                    .setSelfHostingMode(parent->selfHosted())
                    .setNoScriptRval(false)
                    .setForEval(false)
                    .setVersion(parent->getVersion());
 
             Rooted<JSObject*> enclosingScope(cx, EnclosingStaticScope(bce));
             Rooted<JSObject*> sourceObject(cx, bce->script->sourceObject());
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -272,24 +272,22 @@ TokenStream::TokenStream(ExclusiveContex
     linebase(base - options.column),
     prevLinebase(nullptr),
     userbuf(cx, base - options.column, length + options.column), // See comment below
     filename(options.filename()),
     displayURL_(nullptr),
     sourceMapURL_(nullptr),
     tokenbuf(cx),
     cx(cx),
-    originPrincipals(options.originPrincipals()),
+    originPrincipals(options.originPrincipals(cx)),
     strictModeGetter(smg),
     tokenSkip(cx, &tokens),
     linebaseSkip(cx, &linebase),
     prevLinebaseSkip(cx, &prevLinebase)
 {
-    JS_ASSERT_IF(options.principals(), options.originPrincipals());
-
     // The caller must ensure that a reference is held on the supplied principals
     // throughout compilation.
     JS_ASSERT_IF(originPrincipals, originPrincipals->refcount > 0);
 
     // Column numbers are computed as offsets from the current line's base, so the
     // initial line's base must be included in the buffer. linebase and userbuf
     // were adjusted above, and if we are starting tokenization part way through
     // this line then adjust the next character.
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -450,18 +450,17 @@ HandleDynamicLinkFailure(JSContext *cx, 
     if (module.globalArgumentName())
         formals.infallibleAppend(module.globalArgumentName());
     if (module.importArgumentName())
         formals.infallibleAppend(module.importArgumentName());
     if (module.bufferArgumentName())
         formals.infallibleAppend(module.bufferArgumentName());
 
     CompileOptions options(cx);
-    options.setPrincipals(cx->compartment()->principals)
-           .setOriginPrincipals(module.scriptSource()->originPrincipals())
+    options.setOriginPrincipals(module.scriptSource()->originPrincipals())
            .setCompileAndGo(false)
            .setNoScriptRval(false);
 
     if (!frontend::CompileFunctionBody(cx, &fun, options, formals, src->chars(), end - begin))
         return false;
 
     // Call the function we just recompiled.
 
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -60,18 +60,17 @@ BEGIN_TEST(testChromeBuffer)
      */
     {
         {
             JSAutoCompartment ac(cx, trusted_glob);
             const char *paramName = "x";
             const char *bytes = "return x ? 1 + trusted(x-1) : 0";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
             JS::CompileOptions options(cx);
-            options.setFileAndLine("", 0)
-                   .setPrincipals(&system_principals);
+            options.setFileAndLine("", 0);
             CHECK(fun = JS_CompileFunction(cx, global, "trusted", 1, &paramName,
                                            bytes, strlen(bytes), options));
             trusted_fun = JS_GetFunctionObject(fun);
             if (!JS_AddNamedObjectRoot(cx, &trusted_fun, "trusted-function"))
                 return false;
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
@@ -107,18 +106,17 @@ BEGIN_TEST(testChromeBuffer)
             const char *paramName = "untrusted";
             const char *bytes = "try {                                  "
                                 "  untrusted();                         "
                                 "} catch (e) {                          "
                                 "  return 'From trusted: ' + e;         "
                                 "}                                      ";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
             JS::CompileOptions options(cx);
-            options.setFileAndLine("", 0)
-                   .setPrincipals(&system_principals);
+            options.setFileAndLine("", 0);
             CHECK(fun = JS_CompileFunction(cx, global, "trusted", 1, &paramName,
                                            bytes, strlen(bytes), options));
             trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JS::RootedValue v(cx, JS::ObjectValue(*trusted_fun));
         CHECK(JS_WrapValue(cx, &v));
 
@@ -145,18 +143,17 @@ BEGIN_TEST(testChromeBuffer)
      * (say, as done by XPCJSContextSTack::Push) works.
      */
     {
         {
             JSAutoCompartment ac(cx, trusted_glob);
             const char *bytes = "return 42";
             JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
             JS::CompileOptions options(cx);
-            options.setFileAndLine("", 0)
-                   .setPrincipals(&system_principals);
+            options.setFileAndLine("", 0);
             CHECK(fun = JS_CompileFunction(cx, global, "trusted", 0, nullptr,
                                            bytes, strlen(bytes), options));
             trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JS::RootedFunction fun(cx, JS_NewFunction(cx, CallTrusted, 0, 0, global, "callTrusted"));
         JS::RootedObject callTrusted(cx, JS_GetFunctionObject(fun));
 
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -102,18 +102,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
     const char *source = "return function() { return arg; }";
 
     JS::RootedObject obj(cx);
 
     // Compile in A
     {
         JSAutoCompartment a(cx, A);
         JS::CompileOptions options(cx);
-        options.setFileAndLine(__FILE__, 1)
-               .setPrincipals(principalsA);
+        options.setFileAndLine(__FILE__, 1);
         JS::RootedFunction fun(cx, JS_CompileFunction(cx, A, "f",
                 mozilla::ArrayLength(argnames), argnames, source,
                 strlen(source), options));
         CHECK(fun);
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -53,18 +53,17 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, 
     options.setFileAndLine(__FILE__, __LINE__);
     return tryScript(global, JS_CompileScript(cx, global, "", 0, options));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 {
     JS::CompileOptions options(cx);
-    options.setFileAndLine(__FILE__, __LINE__)
-           .setPrincipals(nullptr);
+    options.setFileAndLine(__FILE__, __LINE__);
     return tryScript(global, JS_CompileScript(cx, global, code, code_size,
                                               options));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 {
     JS::CompileOptions options(cx);
@@ -81,18 +80,17 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, 
     return tryScript(global, JS_CompileUCScript(cx, global, uc_code, 0,
                                                 options));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 {
     JS::CompileOptions options(cx);
-    options.setFileAndLine(__FILE__, __LINE__)
-           .setPrincipals(nullptr);
+    options.setFileAndLine(__FILE__, __LINE__);
     return tryScript(global, JS_CompileUCScript(cx, global, uc_code, code_size,
                                                 options));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 {
     TempFile tempScript;
@@ -148,13 +146,12 @@ END_FIXTURE_TEST(ScriptObjectFixture, bu
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandleForPrincipals");
     CHECK(fputs(code, script_stream) != EOF);
     CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
     JS::CompileOptions options(cx);
-    options.setFileAndLine("temporary file", 1)
-           .setPrincipals(nullptr);
+    options.setFileAndLine("temporary file", 1);
     return tryScript(global, JS::Compile(cx, global, options, script_stream));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -9,31 +9,30 @@
 #include "jsstr.h"
 
 #include "jsapi-tests/tests.h"
 
 #include "jsscriptinlines.h"
 
 static JSScript *
 CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
-                                        JSPrincipals *principals, JSPrincipals *originPrincipals,
+                                        JSPrincipals *originPrincipals,
                                         const char *bytes, size_t nbytes,
                                         const char *filename, unsigned lineno,
                                         JSVersion version)
 {
     size_t nchars;
     if (!JS_DecodeBytes(cx, bytes, nbytes, nullptr, &nchars))
         return nullptr;
     jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
     if (!chars)
         return nullptr;
     JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
     JS::CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setOriginPrincipals(originPrincipals)
+    options.setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
     JSScript *script = JS::Compile(cx, obj, options, chars, nchars);
     free(chars);
     return script;
 }
 
 static JSScript *
@@ -82,51 +81,51 @@ static TestJSPrincipals testPrincipal1(1
 BEGIN_TEST(testXDR_principals)
 {
     JSScript *script;
     JSCompartment *compartment = js::GetContextCompartment(cx);
     for (int i = TEST_FIRST; i != TEST_END; ++i) {
         // Appease the new JSAPI assertions. The stuff being tested here is
         // going away anyway.
         JS_SetCompartmentPrincipals(compartment, &testPrincipal0);
-        script = createScriptViaXDR(&testPrincipal0, nullptr, i);
+        script = createScriptViaXDR(nullptr, i);
         CHECK(script);
         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
 
-        script = createScriptViaXDR(&testPrincipal0, &testPrincipal0, i);
+        script = createScriptViaXDR(&testPrincipal0, i);
         CHECK(script);
         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal0);
 
-        script = createScriptViaXDR(&testPrincipal0, &testPrincipal1, i);
+        script = createScriptViaXDR(&testPrincipal1, i);
         CHECK(script);
         CHECK(JS_GetScriptPrincipals(script) == &testPrincipal0);
         CHECK(JS_GetScriptOriginPrincipals(script) == &testPrincipal1);
     }
 
     return true;
 }
 
 enum TestCase {
     TEST_FIRST,
     TEST_SCRIPT = TEST_FIRST,
     TEST_FUNCTION,
     TEST_SERIALIZED_FUNCTION,
     TEST_END
 };
 
-JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
+JSScript *createScriptViaXDR(JSPrincipals *orig, int testCase)
 {
     const char src[] =
         "function f() { return 1; }\n"
         "f;\n";
 
     JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
-    JS::RootedScript script(cx, CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
+    JS::RootedScript script(cx, CompileScriptForPrincipalsVersionOrigin(cx, global, orig,
                                                                         src, strlen(src), "test", 1,
                                                                         JSVERSION_DEFAULT));
     if (!script)
         return nullptr;
 
     if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
         script = FreezeThaw(cx, script);
         if (!script)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4322,50 +4322,47 @@ JS::ReadOnlyCompileOptions::copyPODOptio
     sourcePolicy = rhs.sourcePolicy;
     introductionType = rhs.introductionType;
     introductionLineno = rhs.introductionLineno;
     introductionOffset = rhs.introductionOffset;
     hasIntroductionInfo = rhs.hasIntroductionInfo;
 }
 
 JSPrincipals *
-JS::ReadOnlyCompileOptions::originPrincipals() const
-{
-    return NormalizeOriginPrincipals(principals_, originPrincipals_);
+JS::ReadOnlyCompileOptions::originPrincipals(ExclusiveContext *cx) const
+{
+    return NormalizeOriginPrincipals(cx->compartment()->principals, originPrincipals_);
 }
 
 JS::OwningCompileOptions::OwningCompileOptions(JSContext *cx)
     : ReadOnlyCompileOptions(),
       runtime(GetRuntime(cx)),
       elementRoot(cx),
       elementAttributeNameRoot(cx),
       introductionScriptRoot(cx)
 {
 }
 
 JS::OwningCompileOptions::~OwningCompileOptions()
 {
-    if (principals_)
-        JS_DropPrincipals(runtime, principals_);
     if (originPrincipals_)
         JS_DropPrincipals(runtime, originPrincipals_);
 
     // OwningCompileOptions always owns these, so these casts are okay.
     js_free(const_cast<char *>(filename_));
     js_free(const_cast<jschar *>(sourceMapURL_));
     js_free(const_cast<char *>(introducerFilename_));
 }
 
 bool
 JS::OwningCompileOptions::copy(JSContext *cx, const ReadOnlyCompileOptions &rhs)
 {
     copyPODOptions(rhs);
 
-    setPrincipals(rhs.principals());
-    setOriginPrincipals(rhs.originPrincipals());
+    setOriginPrincipals(rhs.originPrincipals(cx));
     setElement(rhs.element());
     setElementAttributeName(rhs.elementAttributeName());
     setIntroductionScript(rhs.introductionScript());
 
     return (setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
             setSourceMapURL(cx, rhs.sourceMapURL()) &&
             setIntroducerFilename(cx, rhs.introducerFilename()));
 }
@@ -4494,17 +4491,16 @@ JS::CompileOptions::wrap(JSContext *cx, 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
             const jschar *chars, size_t length)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals(), cx->compartment()->principals == options.principals());
     AutoLastFrameCheck lfc(cx);
 
     return frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, chars, length);
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
             const char *bytes, size_t length)
@@ -4659,17 +4655,16 @@ JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
                     const jschar *chars, size_t length)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals(), cx->compartment()->principals == options.principals());
     AutoLastFrameCheck lfc(cx);
 
     RootedAtom funAtom(cx);
     if (name) {
         funAtom = Atomize(cx, name, strlen(name));
         if (!funAtom)
             return nullptr;
     }
@@ -4819,17 +4814,16 @@ extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
              const jschar *chars, size_t length, jsval *rval)
 {
     CompileOptions options(cx, optionsArg);
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals(), cx->compartment()->principals == options.principals());
 
     AutoLastFrameCheck lfc(cx);
 
     options.setCompileAndGo(obj->is<GlobalObject>());
     options.setNoScriptRval(!rval);
     SourceCompressionTask sct(cx);
     RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     obj, NullPtr(), options,
@@ -4892,49 +4886,52 @@ JS::Evaluate(JSContext *cx, HandleObject
 
 JS_PUBLIC_API(bool)
 JS_EvaluateUCScriptForPrincipals(JSContext *cx, HandleObject obj,
                                  JSPrincipals *principals,
                                  const jschar *chars, unsigned length,
                                  const char *filename, unsigned lineno,
                                  MutableHandleValue rval)
 {
+    JS_ASSERT(principals == cx->compartment()->principals);
+
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno);
+    options.setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, chars, length, rval.address());
 }
 
 JS_PUBLIC_API(bool)
 JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, HandleObject obj,
                                         JSPrincipals *principals,
                                         const jschar *chars, unsigned length,
                                         const char *filename, unsigned lineno,
                                         MutableHandleValue rval, JSVersion version)
 {
+    JS_ASSERT(principals == cx->compartment()->principals);
+
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno)
+    options.setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Evaluate(cx, obj, options, chars, length, rval.address());
 }
 
 extern JS_PUBLIC_API(bool)
 JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, HandleObject obj,
                                               JSPrincipals *principals,
                                               JSPrincipals *originPrincipals,
                                               const jschar *chars, unsigned length,
                                               const char *filename, unsigned lineno,
                                               MutableHandleValue rval, JSVersion version)
 {
+    JS_ASSERT(principals == cx->compartment()->principals);
+
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setOriginPrincipals(originPrincipals)
+    options.setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Evaluate(cx, obj, options, chars, length, rval.address());
 }
 
 JS_PUBLIC_API(bool)
 JS_EvaluateUCScript(JSContext *cx, HandleObject obj, const jschar *chars, unsigned length,
@@ -4947,34 +4944,36 @@ JS_EvaluateUCScript(JSContext *cx, Handl
 }
 
 /* Ancient unsigned nbytes is part of API/ABI, so use size_t length local. */
 JS_PUBLIC_API(bool)
 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                const char *bytes, unsigned nbytes,
                                const char *filename, unsigned lineno, jsval *rval)
 {
+    JS_ASSERT(principals == cx->compartment()->principals);
+
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno);
+    options.setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                       const char *bytes, unsigned nbytes,
                                       const char *filename, unsigned lineno, jsval *rval,
                                       JSVersion version)
 {
+    JS_ASSERT(principals == cx->compartment()->principals);
+
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setVersion(version)
+    options.setVersion(version)
            .setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS_EvaluateScript(JSContext *cx, JSObject *objArg, const char *bytes, unsigned nbytes,
                   const char *filename, unsigned lineno, jsval *rval)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3454,30 +3454,30 @@ namespace JS {
  *
  * Use this in code that only needs to access compilation options created
  * elsewhere, like the compiler. Don't instantiate this class (the constructor
  * is protected anyway); instead, create instances only of the derived classes:
  * CompileOptions and OwningCompileOptions.
  */
 class JS_FRIEND_API(ReadOnlyCompileOptions)
 {
+    friend class CompileOptions;
+
   protected:
-    JSPrincipals *principals_;
     JSPrincipals *originPrincipals_;
     const char *filename_;
     const char *introducerFilename_;
     const jschar *sourceMapURL_;
 
     // This constructor leaves 'version' set to JSVERSION_UNKNOWN. The structure
     // is unusable until that's set to something more specific; the derived
     // classes' constructors take care of that, in ways appropriate to their
     // purpose.
     ReadOnlyCompileOptions()
-      : principals_(nullptr),
-        originPrincipals_(nullptr),
+      : originPrincipals_(nullptr),
         filename_(nullptr),
         introducerFilename_(nullptr),
         sourceMapURL_(nullptr),
         version(JSVERSION_UNKNOWN),
         versionSet(false),
         utf8(false),
         lineno(1),
         column(0),
@@ -3501,18 +3501,17 @@ class JS_FRIEND_API(ReadOnlyCompileOptio
 
     // Set all POD options (those not requiring reference counts, copies,
     // rooting, or other hand-holding) to their values in |rhs|.
     void copyPODOptions(const ReadOnlyCompileOptions &rhs);
 
   public:
     // Read-only accessors for non-POD options. The proper way to set these
     // depends on the derived type.
-    JSPrincipals *principals() const { return principals_; }
-    JSPrincipals *originPrincipals() const;
+    JSPrincipals *originPrincipals(js::ExclusiveContext *cx) const;
     const char *filename() const { return filename_; }
     const char *introducerFilename() const { return introducerFilename_; }
     const jschar *sourceMapURL() const { return sourceMapURL_; }
     virtual JSObject *element() const = 0;
     virtual JSString *elementAttributeName() const = 0;
     virtual JSScript *introductionScript() const = 0;
 
     // POD options.
@@ -3604,22 +3603,16 @@ class JS_FRIEND_API(OwningCompileOptions
     OwningCompileOptions &setElementAttributeName(JSString *p) {
         elementAttributeNameRoot = p;
         return *this;
     }
     OwningCompileOptions &setIntroductionScript(JSScript *s) {
         introductionScriptRoot = s;
         return *this;
     }
-    OwningCompileOptions &setPrincipals(JSPrincipals *p) {
-        if (p) JS_HoldPrincipals(p);
-        if (principals_) JS_DropPrincipals(runtime, principals_);
-        principals_ = p;
-        return *this;
-    }
     OwningCompileOptions &setOriginPrincipals(JSPrincipals *p) {
         if (p) JS_HoldPrincipals(p);
         if (originPrincipals_) JS_DropPrincipals(runtime, originPrincipals_);
         originPrincipals_ = p;
         return *this;
     }
     OwningCompileOptions &setVersion(JSVersion v) {
         version = v;
@@ -3644,16 +3637,19 @@ class JS_FRIEND_API(OwningCompileOptions
         introductionLineno = line;
         introductionScriptRoot = script;
         introductionOffset = offset;
         hasIntroductionInfo = true;
         return true;
     }
 
     virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE;
+
+  private:
+    void operator=(const CompileOptions &rhs) MOZ_DELETE;
 };
 
 /*
  * Compilation options stored on the stack. An instance of this type
  * simply holds references to dynamically allocated resources (element;
  * filename; source map URL) that are owned by something else. If you
  * create an instance of this type, it's up to you to guarantee that
  * everything you store in it will outlive it.
@@ -3667,18 +3663,17 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
   public:
     explicit CompileOptions(JSContext *cx, JSVersion version = JSVERSION_UNKNOWN);
     CompileOptions(js::ContextFriendFields *cx, const ReadOnlyCompileOptions &rhs)
       : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
         introductionScriptRoot(cx)
     {
         copyPODOptions(rhs);
 
-        principals_ = rhs.principals();
-        originPrincipals_ = rhs.originPrincipals();
+        originPrincipals_ = rhs.originPrincipals_;
         filename_ = rhs.filename();
         sourceMapURL_ = rhs.sourceMapURL();
         elementRoot = rhs.element();
         elementAttributeNameRoot = rhs.elementAttributeName();
         introductionScriptRoot = rhs.introductionScript();
     }
 
     JSObject *element() const MOZ_OVERRIDE { return elementRoot; }
@@ -3695,20 +3690,16 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
     CompileOptions &setElementAttributeName(JSString *p) {
         elementAttributeNameRoot = p;
         return *this;
     }
     CompileOptions &setIntroductionScript(JSScript *s) {
         introductionScriptRoot = s;
         return *this;
     }
-    CompileOptions &setPrincipals(JSPrincipals *p) {
-        principals_ = p;
-        return *this;
-    }
     CompileOptions &setOriginPrincipals(JSPrincipals *p) {
         originPrincipals_ = p;
         return *this;
     }
     CompileOptions &setVersion(JSVersion v) {
         version = v;
         versionSet = true;
         return *this;
@@ -3730,16 +3721,19 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
         introductionLineno = line;
         introductionScriptRoot = script;
         introductionOffset = offset;
         hasIntroductionInfo = true;
         return *this;
     }
 
     virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE;
+
+  private:
+    void operator=(const CompileOptions &rhs) MOZ_DELETE;
 };
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
         const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1427,29 +1427,26 @@ FunctionConstructor(JSContext *cx, unsig
     JSScript *maybeScript = nullptr;
     const char *filename;
     unsigned lineno;
     JSPrincipals *originPrincipals;
     uint32_t pcOffset;
     DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                          &originPrincipals);
 
-    JSPrincipals *principals = PrincipalsForCompiledCode(args, cx);
-
     const char *introductionType = "Function";
     if (generatorKind != NotGenerator)
         introductionType = "GeneratorFunction";
 
     const char *introducerFilename = filename;
     if (maybeScript && maybeScript->scriptSource()->introducerFilename())
         introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
     CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setOriginPrincipals(originPrincipals)
+    options.setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, 1)
            .setNoScriptRval(false)
            .setCompileAndGo(true)
            .setIntroductionInfo(introducerFilename, introductionType, lineno, maybeScript, pcOffset);
 
     unsigned n = args.length() ? args.length() - 1 : 0;
     if (n > 0) {
         /*
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1819,17 +1819,17 @@ FormatIntroducedFilename(ExclusiveContex
 }
 
 bool
 ScriptSource::initFromOptions(ExclusiveContext *cx, const ReadOnlyCompileOptions &options)
 {
     JS_ASSERT(!filename_);
     JS_ASSERT(!introducerFilename_);
 
-    originPrincipals_ = options.originPrincipals();
+    originPrincipals_ = options.originPrincipals(cx);
     if (originPrincipals_)
         JS_HoldPrincipals(originPrincipals_);
 
     introductionType_ = options.introductionType;
     setIntroductionOffset(options.introductionOffset);
 
     if (options.hasIntroductionInfo) {
         JS_ASSERT(options.introductionType != nullptr);
@@ -2902,18 +2902,17 @@ js::CloneScript(JSContext *cx, HandleObj
         sourceObject = src->sourceObject();
         if (!cx->compartment()->wrap(cx, &sourceObject))
             return nullptr;
     }
 
     /* Now that all fallible allocation is complete, create the GC thing. */
 
     CompileOptions options(cx);
-    options.setPrincipals(cx->compartment()->principals)
-           .setOriginPrincipals(src->originPrincipals())
+    options.setOriginPrincipals(src->originPrincipals())
            .setCompileAndGo(src->compileAndGo())
            .setSelfHostingMode(src->selfHosted())
            .setNoScriptRval(src->noScriptRval())
            .setVersion(src->getVersion());
 
     RootedScript dst(cx, JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
                                           options, src->staticLevel(),
                                           sourceObject, src->sourceStart(), src->sourceEnd()));
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1176,18 +1176,18 @@ Evaluate(JSContext *cx, unsigned argc, j
                     JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
                                          JSSMSG_CACHE_SINGLETON_FAILED);
                     return false;
                 }
                 JS::CompartmentOptionsRef(cx).cloneSingletonsOverride().set(true);
             }
 
             if (loadBytecode) {
-                script = JS_DecodeScript(cx, loadBuffer, loadLength, options.principals(),
-                                         options.originPrincipals());
+                script = JS_DecodeScript(cx, loadBuffer, loadLength, cx->compartment()->principals,
+                                         options.originPrincipals(cx));
             } else {
                 script = JS::Compile(cx, global, options, codeChars, codeLength);
             }
 
             if (!script)
                 return false;
         }
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4463,18 +4463,17 @@ js::EvaluateInEnv(JSContext *cx, Handle<
     JS_ASSERT(!IsPoisonedPtr(chars.get()));
 
     /*
      * NB: This function breaks the assumption that the compiler can see all
      * calls and properly compute a static level. In practice, any non-zero
      * static level will suffice.
      */
     CompileOptions options(cx);
-    options.setPrincipals(env->compartment()->principals)
-           .setCompileAndGo(true)
+    options.setCompileAndGo(true)
            .setForEval(true)
            .setNoScriptRval(false)
            .setFileAndLine(filename, lineno)
            .setCanLazilyParse(false)
            .setIntroductionType("debugger eval");
     RootedScript callerScript(cx, frame ? frame.script() : nullptr);
     RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,
                                                     options, chars.get(), length,
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -802,18 +802,17 @@ mozJSComponentLoader::ObjectForLocation(
         // If aPropagateExceptions is true, then our caller wants us to propagate
         // any exceptions out to our caller. Ensure that the engine doesn't
         // eagerly report the exception.
         AutoSaveContextOptions asco(cx);
         if (aPropagateExceptions)
             ContextOptionsRef(cx).setDontReportUncaught(true);
 
         CompileOptions options(cx);
-        options.setPrincipals(nsJSPrincipals::get(mSystemPrincipal))
-               .setNoScriptRval(mReuseLoaderGlobal ? false : true)
+        options.setNoScriptRval(mReuseLoaderGlobal ? false : true)
                .setVersion(JSVERSION_LATEST)
                .setFileAndLine(nativePath.get(), 1)
                .setSourcePolicy(mReuseLoaderGlobal ?
                                 CompileOptions::NO_SOURCE :
                                 CompileOptions::LAZY_SOURCE);
 
         if (realFile) {
 #ifdef HAVE_PR_MEMMAP
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -134,18 +134,17 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
     if (NS_FAILED(rv))
         return rv;
 
     /* set our own error reporter so we can report any bad things as catchable
      * exceptions, including the source/line number */
     JSErrorReporter er = JS_SetErrorReporter(cx, xpc::SystemErrorReporter);
 
     JS::CompileOptions options(cx);
-    options.setPrincipals(nsJSPrincipals::get(principal))
-           .setFileAndLine(uriStr, 1);
+    options.setFileAndLine(uriStr, 1);
     if (!charset.IsVoid()) {
         nsString script;
         rv = nsScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast<const uint8_t*>(buf.get()), len,
                                             charset, nullptr, script);
 
         if (NS_FAILED(rv)) {
             return ReportError(cx, LOAD_ERROR_BADCHARSET);
         }
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1677,18 +1677,17 @@ xpc::EvalInSandbox(JSContext *cx, Handle
             JS_ReportError(cx, "Can't prepare context for evalInSandbox");
             return NS_ERROR_OUT_OF_MEMORY;
         }
         nsCxPusher pusher;
         pusher.Push(sandcx);
         JSAutoCompartment ac(sandcx, sandbox);
 
         JS::CompileOptions options(sandcx);
-        options.setPrincipals(nsJSPrincipals::get(prin))
-               .setFileAndLine(filenameBuf.get(), lineNo);
+        options.setFileAndLine(filenameBuf.get(), lineNo);
         if (jsVersion != JSVERSION_DEFAULT)
                options.setVersion(jsVersion);
         JS::RootedObject rootedSandbox(sandcx, sandbox);
         ok = JS::Evaluate(sandcx, rootedSandbox, options,
                           PromiseFlatString(source).get(), source.Length(),
                           v.address());
         if (ok && returnStringOnly && !v.isUndefined()) {
             JSString *str = ToString(sandcx, v);
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -333,18 +333,17 @@ Load(JSContext *cx, unsigned argc, jsval
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading",
                            filename.ptr());
             return false;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
-               .setFileAndLine(filename.ptr(), 1)
-               .setPrincipals(gJSPrincipals);
+               .setFileAndLine(filename.ptr(), 1);
         JS::RootedObject rootedObj(cx, obj);
         JSScript *script = JS::Compile(cx, rootedObj, options, file);
         fclose(file);
         if (!script)
             return false;
 
         JS::Rooted<JS::Value> result(cx);
         if (!compileOnly && !JS_ExecuteScript(cx, obj, script, result.address()))
@@ -919,18 +918,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
                     break;
             }
         }
         ungetc(ch, file);
         DoBeginRequest(cx);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
-               .setFileAndLine(filename, 1)
-               .setPrincipals(gJSPrincipals);
+               .setFileAndLine(filename, 1);
         script = JS::Compile(cx, obj, options, file);
         if (script && !compileOnly)
             (void)JS_ExecuteScript(cx, obj, script, result.address());
         DoEndRequest(cx);
 
         return;
     }
 
@@ -956,18 +954,17 @@ ProcessFile(JSContext *cx, JS::Handle<JS
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         DoBeginRequest(cx);
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
-        options.setFileAndLine("typein", startline)
-               .setPrincipals(gJSPrincipals);
+        options.setFileAndLine("typein", startline);
         script = JS_CompileScript(cx, obj, buffer, strlen(buffer), options);
         if (script) {
             JSErrorReporter older;
 
             if (!compileOnly) {
                 ok = JS_ExecuteScript(cx, obj, script, result.address());
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS::ToString(). */