Back out 8 changesets (bug 990353) for gaia-integration bustage
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 19 Apr 2014 08:37:32 -0700
changeset 179748 7e51adede3b6b78c19c755fe08a1b177745e979c
parent 179747 6022ca67befb0d749024085dd2678728565b38fb
child 179749 cc10a90487bb8ed0948db260b7b6c3da796d0210
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
bugs990353
milestone31.0a1
backs outf6b3c03454a4354ad2f2a214f36c8eafdda45e2e
6e1f9b821ae0a7b66e1a222ab85c2e4130012ccb
2926ad6c594fd1ef27907b8d79823dfbbd46fe3f
74b75c1552050dd846ed1508fc0498cb1e35e952
394e09fe2da2ecc2d8a57fedacaa8563ad6f90b7
0fdd36b19a51571706502d848457da8e38f22bae
0792729890cc035ad9794e7592c8e599183cd430
487e6f72fcf74e590b6b475958abc88315bd05b0
Back out 8 changesets (bug 990353) for gaia-integration bustage CLOSED TREE Backed out changeset f6b3c03454a4 (bug 990353) Backed out changeset 6e1f9b821ae0 (bug 990353) Backed out changeset 2926ad6c594f (bug 990353) Backed out changeset 74b75c155205 (bug 990353) Backed out changeset 394e09fe2da2 (bug 990353) Backed out changeset 0fdd36b19a51 (bug 990353) Backed out changeset 0792729890cc (bug 990353) Backed out changeset 487e6f72fcf7 (bug 990353)
b2g/app/b2g.js
content/xul/content/src/nsXULElement.cpp
content/xul/document/src/nsXULPrototypeDocument.cpp
dom/workers/ScriptLoader.cpp
dom/xbl/nsXBLDocumentInfo.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/jit-test/tests/basic/withSourceHook.js
js/src/jit-test/tests/debug/Source-text-lazy.js
js/src/jsapi-tests/testSourcePolicy.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsfriendapi.h
js/src/shell/js.cpp
js/src/vm/SelfHosting.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcpublic.h
js/xpconnect/tests/chrome/chrome.ini
js/xpconnect/tests/chrome/file_discardSystemSource.html
js/xpconnect/tests/chrome/mochitest.ini
js/xpconnect/tests/chrome/moz.build
js/xpconnect/tests/chrome/test_discardSystemSource.xul
js/xpconnect/tests/chrome/worker_discardSystemSource.js
js/xpconnect/tests/moz.build
modules/libpref/src/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -594,22 +594,16 @@ pref("dom.forms.number", true);
 
 // Don't enable <input type=color> yet as we don't have a color picker
 // implemented for b2g (bug 875751)
 pref("dom.forms.color", false);
 
 // Turns on gralloc-based direct texturing for Gonk
 pref("gfx.gralloc.enabled", false);
 
-// This preference instructs the JS engine to discard the
-// source of any privileged JS after compilation. This saves
-// memory, but makes things like Function.prototype.toSource()
-// fail.
-pref("javascript.options.discardSystemSource", true);
-
 // XXXX REMOVE FOR PRODUCTION. Turns on GC and CC logging
 pref("javascript.options.mem.log", false);
 
 // Increase mark slice time from 10ms to 30ms
 pref("javascript.options.mem.gc_incremental_slice_ms", 30);
 
 // Increase time to get more high frequency GC on benchmarks from 1000ms to 1500ms
 pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1500);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2651,17 +2651,18 @@ nsXULPrototypeScript::Compile(const char
     NS_ENSURE_TRUE(JSVersion(mLangVersion) != JSVERSION_UNKNOWN, NS_OK);
     JS::CompileOptions options(cx);
     options.setIntroductionType("scriptElement")
            .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.setSourceIsLazy(mOutOfLine);
+    options.setSourcePolicy(mOutOfLine ? JS::CompileOptions::LAZY_SOURCE
+                                       : JS::CompileOptions::SAVE_SOURCE);
     JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
     if (scope) {
       JS::ExposeObjectToActiveJS(scope);
     }
 
     if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
         if (!JS::CompileOffThread(cx, options,
                                   static_cast<const jschar*>(aText), aTextLength,
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -743,18 +743,17 @@ nsXULPDGlobalObject::GetCompilationGloba
 
   if (mDestroyed) {
     return nullptr;
   }
 
   AutoSafeJSContext cx;
   JS::CompartmentOptions options;
   options.setZone(JS::SystemZone)
-         .setInvisibleToDebugger(true)
-         .setDiscardSource(xpc::ShouldDiscardSystemSource());
+         .setInvisibleToDebugger(true);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
                                  JS::DontFireOnNewGlobalHook, options);
   NS_ENSURE_TRUE(mJSObject, nullptr);
 
   mozilla::HoldJSObjects(this);
 
   // Add an owning reference from JS back to us. This'll be
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -694,30 +694,16 @@ 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!");
 
-  // Determine whether we want to be discarding source on this global to save
-  // memory. It would make more sense to do this when we create the global, but
-  // the information behind UsesSystemPrincipal() et al isn't finalized until
-  // the call to SetPrincipal during the first script load. After that, however,
-  // it never changes. So we can just idempotently set the bits here.
-  //
-  // Note that we read a pref that is cached on the main thread. This is benignly
-  // racey.
-  if (xpc::ShouldDiscardSystemSource()) {
-    bool discard = aWorkerPrivate->UsesSystemPrincipal() ||
-                   aWorkerPrivate->IsInPrivilegedApp();
-    JS::CompartmentOptionsRef(global).setDiscardSource(discard);
-  }
-
   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)) {
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -163,18 +163,17 @@ nsXBLDocGlobalObject::GetCompilationGlob
   if (mJSObject || mDestroyed) {
     // We've been initialized before - what we have is what you get.
     return mJSObject;
   }
 
   AutoSafeJSContext cx;
   JS::CompartmentOptions options;
   options.setZone(JS::SystemZone)
-         .setInvisibleToDebugger(true)
-         .setDiscardSource(xpc::ShouldDiscardSystemSource());
+         .setInvisibleToDebugger(true);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
                                  JS::DontFireOnNewGlobalHook,
                                  options);
   if (!mJSObject)
       return nullptr;
 
   mozilla::HoldJSObjects(this);
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -141,18 +141,17 @@ MaybeCheckEvalFreeVariables(ExclusiveCon
     return true;
 }
 
 static inline bool
 CanLazilyParse(ExclusiveContext *cx, const ReadOnlyCompileOptions &options)
 {
     return options.canLazilyParse &&
         options.compileAndGo &&
-        !cx->compartment()->options().discardSource() &&
-        !options.sourceIsLazy &&
+        options.sourcePolicy == CompileOptions::SAVE_SOURCE &&
         !(cx->compartment()->debugMode() &&
           cx->compartment()->runtimeFromAnyThread()->debugHooks.newScriptHook);
 }
 
 void
 frontend::MaybeCallSourceHandler(JSContext *cx, const ReadOnlyCompileOptions &options,
                                  const jschar *chars, size_t length)
 {
@@ -208,32 +207,37 @@ frontend::CompileScript(ExclusiveContext
      * and non-zero static level requires callerFrame.
      */
     JS_ASSERT_IF(evalCaller, options.compileAndGo);
     JS_ASSERT_IF(evalCaller, options.forEval);
     JS_ASSERT_IF(staticLevel != 0, evalCaller);
 
     if (!CheckLength(cx, length))
         return nullptr;
-    JS_ASSERT_IF(staticLevel != 0, !options.sourceIsLazy);
+    JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE);
 
     RootedScriptSource sourceObject(cx, CreateScriptSourceObject(cx, options));
     if (!sourceObject)
         return nullptr;
 
     ScriptSource *ss = sourceObject->source();
 
     SourceCompressionTask mysct(cx);
     SourceCompressionTask *sct = extraSct ? extraSct : &mysct;
 
-    if (!cx->compartment()->options().discardSource()) {
-        if (options.sourceIsLazy)
-            ss->setSourceRetrievable();
-        else if (!ss->setSourceCopy(cx, chars, length, false, sct))
+    switch (options.sourcePolicy) {
+      case CompileOptions::SAVE_SOURCE:
+        if (!ss->setSourceCopy(cx, chars, length, false, sct))
             return nullptr;
+        break;
+      case CompileOptions::LAZY_SOURCE:
+        ss->setSourceRetrievable();
+        break;
+      case CompileOptions::NO_SOURCE:
+        break;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
         syntaxParser.construct(cx, alloc, options, chars, length, /* foldConstants = */ false,
                                (Parser<SyntaxParseHandler> *) nullptr,
@@ -508,18 +512,18 @@ CompileFunctionBody(JSContext *cx, Mutab
         return false;
 
     RootedScriptSource sourceObject(cx, CreateScriptSourceObject(cx, options));
     if (!sourceObject)
         return nullptr;
     ScriptSource *ss = sourceObject->source();
 
     SourceCompressionTask sct(cx);
-    JS_ASSERT(!options.sourceIsLazy);
-    if (!cx->compartment()->options().discardSource()) {
+    JS_ASSERT(options.sourcePolicy != CompileOptions::LAZY_SOURCE);
+    if (options.sourcePolicy == CompileOptions::SAVE_SOURCE) {
         if (!ss->setSourceCopy(cx, chars, length, true, &sct))
             return false;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
--- a/js/src/jit-test/tests/basic/withSourceHook.js
+++ b/js/src/jit-test/tests/basic/withSourceHook.js
@@ -30,27 +30,27 @@ withSourceHook(function (url) {
       // and verify that it is in force.
       assertEq(withSourceHook(function (url) {
                                 log += 'i';
                                 assertEq(url, 'inner');
                                 return '(function inner() { 1; })';
                               }, function () {
                                 log += 'I';
                                 return evaluate('(function inner() { 2; })',
-                                                { fileName: 'inner', sourceIsLazy: true })
+                                                { fileName: 'inner', sourcePolicy: 'LAZY_SOURCE' })
                                        .toSource();
                               }),
                '(function inner() { 1; })');
       // Verify that the source hook that throws has been reinstated.
       evaluate('(function middle() { })',
-               { fileName: 'middle', sourceIsLazy: true })
+               { fileName: 'middle', sourcePolicy: 'LAZY_SOURCE' })
       .toSource();
     });
   }, 'borborygmus');
 
   // Verify that the outermost source hook has been restored.
   assertEq(evaluate('(function outer() { 4; })',
-                    { fileName: 'outer', sourceIsLazy: true })
+                    { fileName: 'outer', sourcePolicy: 'LAZY_SOURCE' })
            .toSource(),
            '(function outer() { 3; })');
 });
 
 assertEq(log, 'OMIimo');
--- a/js/src/jit-test/tests/debug/Source-text-lazy.js
+++ b/js/src/jit-test/tests/debug/Source-text-lazy.js
@@ -23,17 +23,17 @@ function test(source) {
     return frobbed;
   }, () => {
     dbg.onDebuggerStatement = function (frame) {
       log += 'd';
       assertEq(frame.script.source.text, frobbed);
     }
 
     g.evaluate(source, { fileName: "BanalBivalve.jsm",
-                         sourceIsLazy: true });
+                         sourcePolicy: "LAZY_SOURCE"});
   });
 
   assertEq(log, 'ds');
 }
 
 test("debugger; // Ignominious Iguana");
 test("(function () { debugger; /* Meretricious Marmoset */})();");
 test("(() => { debugger; })(); // Gaunt Gibbon");
--- a/js/src/jsapi-tests/testSourcePolicy.cpp
+++ b/js/src/jsapi-tests/testSourcePolicy.cpp
@@ -4,17 +4,17 @@
 
 #include "jsscript.h"
 
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testBug795104)
 {
     JS::CompileOptions opts(cx);
-    JS::CompartmentOptionsRef(cx->compartment()).setDiscardSource(true);
+    opts.setSourcePolicy(JS::CompileOptions::NO_SOURCE);
     const size_t strLen = 60002;
     char *s = static_cast<char *>(JS_malloc(cx, strLen));
     CHECK(s);
     s[0] = '"';
     memset(s + 1, 'x', strLen - 2);
     s[strLen - 1] = '"';
     CHECK(JS::Evaluate(cx, global, opts, s, strLen));
     CHECK(JS::CompileFunction(cx, global, opts, "f", 0, nullptr, s, strLen));
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2475,22 +2475,16 @@ JS::CompartmentOptions::setSameZoneAs(JS
 
 JS::CompartmentOptions &
 JS::CompartmentOptionsRef(JSCompartment *compartment)
 {
     return compartment->options();
 }
 
 JS::CompartmentOptions &
-JS::CompartmentOptionsRef(JSObject *obj)
-{
-    return obj->compartment()->options();
-}
-
-JS::CompartmentOptions &
 JS::CompartmentOptionsRef(JSContext *cx)
 {
     return cx->compartment()->options();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewGlobalObject(JSContext *cx, const JSClass *clasp, JSPrincipals *principals,
                    JS::OnNewGlobalHookOption hookOption,
@@ -4349,17 +4343,17 @@ JS::ReadOnlyCompileOptions::copyPODOptio
     selfHostingMode = rhs.selfHostingMode;
     canLazilyParse = rhs.canLazilyParse;
     strictOption = rhs.strictOption;
     extraWarningsOption = rhs.extraWarningsOption;
     werrorOption = rhs.werrorOption;
     asmJSOption = rhs.asmJSOption;
     forceAsync = rhs.forceAsync;
     installedFile = rhs.installedFile;
-    sourceIsLazy = rhs.sourceIsLazy;
+    sourcePolicy = rhs.sourcePolicy;
     introductionType = rhs.introductionType;
     introductionLineno = rhs.introductionLineno;
     introductionOffset = rhs.introductionOffset;
     hasIntroductionInfo = rhs.hasIntroductionInfo;
 }
 
 JSPrincipals *
 JS::ReadOnlyCompileOptions::originPrincipals(ExclusiveContext *cx) const
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2544,17 +2544,16 @@ class JS_PUBLIC_API(CompartmentOptions)
 
         Mode mode_;
     };
 
     explicit CompartmentOptions()
       : version_(JSVERSION_UNKNOWN)
       , invisibleToDebugger_(false)
       , mergeable_(false)
-      , discardSource_(false)
       , traceGlobal_(nullptr)
       , singletonsAsTemplates_(true)
     {
         zone_.spec = JS::FreshZone;
     }
 
     JSVersion version() const { return version_; }
     CompartmentOptions &setVersion(JSVersion aVersion) {
@@ -2578,25 +2577,16 @@ class JS_PUBLIC_API(CompartmentOptions)
     // allowed if this flag is set.  The invisibleToDebugger flag must also be
     // set for such compartments.
     bool mergeable() const { return mergeable_; }
     CompartmentOptions &setMergeable(bool flag) {
         mergeable_ = flag;
         return *this;
     }
 
-    // For certain globals, we know enough about the code that will run in them
-    // that we can discard script source entirely.
-    bool discardSource() const { return discardSource_; }
-    CompartmentOptions &setDiscardSource(bool flag) {
-        discardSource_ = flag;
-        return *this;
-    }
-
-
     bool cloneSingletons(JSContext *cx) const;
     Override &cloneSingletonsOverride() { return cloneSingletonsOverride_; }
 
     void *zonePointer() const {
         JS_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
         return zone_.pointer;
     }
     ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
@@ -2617,17 +2607,16 @@ class JS_PUBLIC_API(CompartmentOptions)
     JSTraceOp getTrace() const {
         return traceGlobal_;
     }
 
   private:
     JSVersion version_;
     bool invisibleToDebugger_;
     bool mergeable_;
-    bool discardSource_;
     Override cloneSingletonsOverride_;
     union {
         ZoneSpecifier spec;
         void *pointer; // js::Zone* is not exposed in the API.
     } zone_;
     JSTraceOp traceGlobal_;
 
     // To XDR singletons, we need to ensure that all singletons are all used as
@@ -2635,19 +2624,16 @@ class JS_PUBLIC_API(CompartmentOptions)
     // singleton, instead of returning the value which is baked in the JSScript.
     bool singletonsAsTemplates_;
 };
 
 JS_PUBLIC_API(CompartmentOptions &)
 CompartmentOptionsRef(JSCompartment *compartment);
 
 JS_PUBLIC_API(CompartmentOptions &)
-CompartmentOptionsRef(JSObject *obj);
-
-JS_PUBLIC_API(CompartmentOptions &)
 CompartmentOptionsRef(JSContext *cx);
 
 // During global creation, we fire notifications to callbacks registered
 // via the Debugger API. These callbacks are arbitrary script, and can touch
 // the global in arbitrary ways. When that happens, the global should not be
 // in a half-baked state. But this creates a problem for consumers that need
 // to set slots on the global to put it in a consistent state.
 //
@@ -3411,17 +3397,17 @@ class JS_FRIEND_API(ReadOnlyCompileOptio
         selfHostingMode(false),
         canLazilyParse(true),
         strictOption(false),
         extraWarningsOption(false),
         werrorOption(false),
         asmJSOption(false),
         forceAsync(false),
         installedFile(false),
-        sourceIsLazy(false),
+        sourcePolicy(SAVE_SOURCE),
         introductionType(nullptr),
         introductionLineno(0),
         introductionOffset(0),
         hasIntroductionInfo(false)
     { }
 
     // Set all POD options (those not requiring reference counts, copies,
     // rooting, or other hand-holding) to their values in |rhs|.
@@ -3451,17 +3437,21 @@ class JS_FRIEND_API(ReadOnlyCompileOptio
     bool selfHostingMode;
     bool canLazilyParse;
     bool strictOption;
     bool extraWarningsOption;
     bool werrorOption;
     bool asmJSOption;
     bool forceAsync;
     bool installedFile;  // 'true' iff pre-compiling js file in packaged app
-    bool sourceIsLazy;
+    enum SourcePolicy {
+        NO_SOURCE,
+        LAZY_SOURCE,
+        SAVE_SOURCE
+    } sourcePolicy;
 
     // |introductionType| is a statically allocated C string:
     // one of "eval", "Function", or "GeneratorFunction".
     const char *introductionType;
     unsigned introductionLineno;
     uint32_t introductionOffset;
     bool hasIntroductionInfo;
 
@@ -3543,17 +3533,17 @@ class JS_FRIEND_API(OwningCompileOptions
     OwningCompileOptions &setUTF8(bool u) { utf8 = u; return *this; }
     OwningCompileOptions &setColumn(unsigned c) { column = c; return *this; }
     OwningCompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
     OwningCompileOptions &setForEval(bool eval) { forEval = eval; return *this; }
     OwningCompileOptions &setDefineOnScope(bool define) { defineOnScope = define; return *this; }
     OwningCompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
     OwningCompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
     OwningCompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
-    OwningCompileOptions &setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
+    OwningCompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; }
     OwningCompileOptions &setIntroductionType(const char *t) { introductionType = t; return *this; }
     bool setIntroductionInfo(JSContext *cx, const char *introducerFn, const char *intro,
                              unsigned line, JSScript *script, uint32_t offset)
     {
         if (!setIntroducerFilename(cx, introducerFn))
             return false;
         introductionType = intro;
         introductionLineno = line;
@@ -3629,17 +3619,17 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
     CompileOptions &setUTF8(bool u) { utf8 = u; return *this; }
     CompileOptions &setColumn(unsigned c) { column = c; return *this; }
     CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
     CompileOptions &setForEval(bool eval) { forEval = eval; return *this; }
     CompileOptions &setDefineOnScope(bool define) { defineOnScope = define; return *this; }
     CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
     CompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
     CompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
-    CompileOptions &setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
+    CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; }
     CompileOptions &setIntroductionType(const char *t) { introductionType = t; return *this; }
     CompileOptions &setIntroductionInfo(const char *introducerFn, const char *intro,
                                         unsigned line, JSScript *script, uint32_t offset)
     {
         introducerFilename_ = introducerFn;
         introductionType = intro;
         introductionLineno = line;
         introductionScriptRoot = script;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -378,38 +378,38 @@ extern JS_FRIEND_API(bool)
 proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
 extern JS_FRIEND_API(bool)
 proxy_Slice(JSContext *cx, JS::HandleObject proxy, uint32_t begin, uint32_t end,
             JS::HandleObject result);
 
 /*
  * A class of objects that return source code on demand.
  *
- * When code is compiled with setSourceIsLazy(true), SpiderMonkey doesn't
- * retain the source code (and doesn't do lazy bytecode generation). If we ever
- * need the source code, say, in response to a call to Function.prototype.
- * toSource or Debugger.Source.prototype.text, then we call the 'load' member
- * function of the instance of this class that has hopefully been registered
- * with the runtime, passing the code's URL, and hope that it will be able to
- * find the source.
+ * When code is compiled with CompileOptions::LAZY_SOURCE, SpiderMonkey
+ * doesn't retain the source code (and doesn't do lazy bytecode
+ * generation). If we ever need the source code, say, in response to a call
+ * to Function.prototype.toSource or Debugger.Source.prototype.text, then
+ * we call the 'load' member function of the instance of this class that
+ * has hopefully been registered with the runtime, passing the code's URL,
+ * and hope that it will be able to find the source.
  */
 class SourceHook {
   public:
     virtual ~SourceHook() { }
 
     /*
      * Set |*src| and |*length| to refer to the source code for |filename|.
      * On success, the caller owns the buffer to which |*src| points, and
      * should use JS_free to free it.
      */
     virtual bool load(JSContext *cx, const char *filename, jschar **src, size_t *length) = 0;
 };
 
 /*
- * Have |rt| use |hook| to retrieve lazily-retrieved source code. See the
+ * Have |rt| use |hook| to retrieve LAZY_SOURCE source code. See the
  * comments for SourceHook. The runtime takes ownership of the hook, and
  * will delete it when the runtime itself is deleted, or when a new hook is
  * set.
  */
 extern JS_FRIEND_API(void)
 SetSourceHook(JSRuntime *rt, SourceHook *hook);
 
 /* Remove |rt|'s source hook, and return it. The caller now owns the hook. */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -861,20 +861,38 @@ ParseCompileOptions(JSContext *cx, Compi
         return false;
     if (!v.isUndefined()) {
         uint32_t u;
         if (!ToUint32(cx, v, &u))
             return false;
         options.setLine(u);
     }
 
-    if (!JS_GetProperty(cx, opts, "sourceIsLazy", &v))
-        return false;
-    if (v.isBoolean())
-        options.setSourceIsLazy(v.toBoolean());
+    if (!JS_GetProperty(cx, opts, "sourcePolicy", &v))
+        return false;
+    if (!v.isUndefined()) {
+        RootedString s(cx, ToString(cx, v));
+        if (!s)
+            return false;
+
+        JSAutoByteString bytes;
+        char *policy = bytes.encodeUtf8(cx, s);
+        if (!policy)
+            return false;
+        if (strcmp(policy, "NO_SOURCE") == 0) {
+            options.setSourcePolicy(CompileOptions::NO_SOURCE);
+        } else if (strcmp(policy, "LAZY_SOURCE") == 0) {
+            options.setSourcePolicy(CompileOptions::LAZY_SOURCE);
+        } else if (strcmp(policy, "SAVE_SOURCE") == 0) {
+            options.setSourcePolicy(CompileOptions::SAVE_SOURCE);
+        } else {
+            JS_ReportError(cx, "bad 'sourcePolicy' option: '%s'", policy);
+            return false;
+        }
+    }
 
     return true;
 }
 
 class AutoNewContext
 {
   private:
     JSContext *oldcx;
@@ -3614,17 +3632,17 @@ OffThreadCompileScript(JSContext *cx, un
 
         RootedObject opts(cx, &args[1].toObject());
         if (!ParseCompileOptions(cx, options, opts, fileNameBytes))
             return false;
     }
 
     // These option settings must override whatever the caller requested.
     options.setCompileAndGo(true)
-           .setSourceIsLazy(false);
+           .setSourcePolicy(CompileOptions::SAVE_SOURCE);
 
     // We assume the caller wants caching if at all possible, ignoring
     // heuristics that make sense for a real browser.
     options.forceAsync = true;
 
     JSString *scriptContents = args[0].toString();
     const jschar *chars = JS_GetStringCharsZ(cx, scriptContents);
     if (!chars)
@@ -4367,19 +4385,19 @@ static const JSFunctionSpecWithHelp shel
 "         any DOM element.\n"
 "      elementAttributeName: if present and not undefined, the name of\n"
 "         property of 'element' that holds this code. This is what\n"
 "         Debugger.Source.prototype.elementAttributeName returns.\n"
 "      sourceMapURL: if present with value |v|, convert |v| to a string, and\n"
 "         provide that as the code's source map URL. If omitted, attach no\n"
 "         source map URL to the code (although the code may provide one itself,\n"
 "         via a //#sourceMappingURL comment).\n"
-"      sourceIsLazy: if present and true, indicates that, after compilation, \n"
-          "script source should not be cached by the JS engine and should be \n"
-          "lazily loaded from the embedding as-needed.\n"
+"      sourcePolicy: if present, the value converted to a string must be either\n"
+"         'NO_SOURCE', 'LAZY_SOURCE', or 'SAVE_SOURCE'; use the given source\n"
+"         retention policy for this compilation.\n"
 "      loadBytecode: if true, and if the source is a CacheEntryObject,\n"
 "         the bytecode would be loaded and decoded from the cache entry instead\n"
 "         of being parsed, then it would be executed as usual.\n"
 "      saveBytecode: if true, and if the source is a CacheEntryObject,\n"
 "         the bytecode would be encoded and saved into the cache entry after\n"
 "         the script execution.\n"
 "      assertEqBytecode: if true, and if both loadBytecode and saveBytecode are \n"
 "         true, then the loaded bytecode and the encoded bytecode are compared.\n"
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -899,16 +899,17 @@ js::FillSelfHostingCompileOptions(Compil
      * Additionally, the special syntax callFunction(fun, receiver, ...args)
      * is supported, for which bytecode is emitted that invokes |fun| with
      * |receiver| as the this-object and ...args as the arguments.
      */
     options.setIntroductionType("self-hosted");
     options.setFileAndLine("self-hosted", 1);
     options.setSelfHostingMode(true);
     options.setCanLazilyParse(false);
+    options.setSourcePolicy(CompileOptions::NO_SOURCE);
     options.setVersion(JSVERSION_LATEST);
     options.werrorOption = true;
     options.strictOption = true;
 
 #ifdef DEBUG
     options.extraWarningsOption = true;
 #endif
 }
@@ -928,21 +929,18 @@ JSRuntime::initSelfHosting(JSContext *cx
      * parented to this one, so cannot include state in the nursery.
      */
     JS::AutoDisableGenerationalGC disable(cx->runtime());
 
     bool receivesDefaultObject = !cx->options().noDefaultCompartmentObject();
     RootedObject savedGlobal(cx, receivesDefaultObject
                                  ? js::DefaultObjectForContextOrNull(cx)
                                  : nullptr);
-    JS::CompartmentOptions compartmentOptions;
-    compartmentOptions.setDiscardSource(true);
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class,
-                                                  nullptr, JS::DontFireOnNewGlobalHook,
-                                                  compartmentOptions)))
+                                                  nullptr, JS::DontFireOnNewGlobalHook)))
         return false;
     JSAutoCompartment ac(cx, selfHostingGlobal_);
     if (receivesDefaultObject)
         js::SetDefaultObjectForContext(cx, selfHostingGlobal_);
     Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
     selfHostingGlobal_->compartment()->isSelfHosting = true;
     selfHostingGlobal_->compartment()->isSystem = true;
     /*
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -809,26 +809,23 @@ 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);
 
-        // Note - if mReuseLoaderGlobal is true, then we can't do lazy source,
-        // because we compile things as functions (rather than script), and lazy
-        // source isn't supported in that configuration. That's ok though,
-        // because we only do mReuseLoaderGlobal on b2g, where we invoke
-        // setDiscardSource(true) on the entire global.
         CompileOptions options(cx);
         options.setNoScriptRval(mReuseLoaderGlobal ? false : true)
                .setVersion(JSVERSION_LATEST)
                .setFileAndLine(nativePath.get(), 1)
-               .setSourceIsLazy(!mReuseLoaderGlobal);
+               .setSourcePolicy(mReuseLoaderGlobal ?
+                                CompileOptions::NO_SOURCE :
+                                CompileOptions::LAZY_SOURCE);
 
         if (realFile) {
 #ifdef HAVE_PR_MEMMAP
             int64_t fileSize;
             rv = aComponentFile->GetFileSize(&fileSize);
             if (NS_FAILED(rv)) {
                 return rv;
             }
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -159,20 +159,20 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
                                    script.Length());
         } else {
             *functionp = JS::CompileFunction(cx, target_obj, options,
                                              nullptr, 0, nullptr,
                                              script.get(),
                                              script.Length());
         }
     } else {
-        // We only use lazy source when no special encoding is specified because
+        // We only use LAZY_SOURCE when no special encoding is specified because
         // the lazy source loader doesn't know the encoding.
         if (!reuseGlobal) {
-            options.setSourceIsLazy(true);
+            options.setSourcePolicy(JS::CompileOptions::LAZY_SOURCE);
             *scriptp = JS::Compile(cx, target_obj, options, buf.get(), len);
         } else {
             *functionp = JS::CompileFunction(cx, target_obj, options,
                                              nullptr, 0, nullptr, buf.get(),
                                              len);
         }
     }
 
@@ -493,16 +493,17 @@ ScriptPrecompiler::OnStreamComplete(nsIS
     sandboxOptions.sandboxName.AssignASCII("asm.js precompilation");
     sandboxOptions.invisibleToDebugger = true;
     rv = CreateSandboxObject(cx, &v, mPrincipal, sandboxOptions);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
     JSAutoCompartment ac(cx, js::UncheckedUnwrap(&v.toObject()));
 
     JS::CompileOptions options(cx, JSVERSION_DEFAULT);
+    options.setSourcePolicy(CompileOptions::NO_SOURCE);
     options.forceAsync = true;
     options.compileAndGo = true;
     options.installedFile = true;
 
     nsCOMPtr<nsIURI> uri;
     mChannel->GetURI(getter_AddRefs(uri));
     nsAutoCString spec;
     uri->GetSpec(spec);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -35,17 +35,16 @@
 #include "jsfriendapi.h"
 #include "jsprf.h"
 #include "js/MemoryMetrics.h"
 #include "js/OldDebugAPI.h"
 #include "mozilla/dom/GeneratedAtomList.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/WindowBinding.h"
-#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "AccessCheck.h"
 #include "nsGlobalWindow.h"
 #include "nsAboutProtocolUtils.h"
 
 #include "GeckoProfiler.h"
 #include "nsIXULRuntime.h"
 #include "nsJSPrincipals.h"
@@ -80,20 +79,21 @@ const char* const XPCJSRuntime::mStrings
     "__iterator__",         // IDX_ITERATOR
     "__exposedProps__",     // IDX_EXPOSEDPROPS
     "eval",                 // IDX_EVAL
     "controllers",           // IDX_CONTROLLERS
 };
 
 /***************************************************************************/
 
-static mozilla::Atomic<bool> sDiscardSystemSource(false);
-
-bool
-xpc::ShouldDiscardSystemSource() { return sDiscardSystemSource; }
+struct CX_AND_XPCRT_Data
+{
+    JSContext* cx;
+    XPCJSRuntime* rt;
+};
 
 static void * const UNMARK_ONLY = nullptr;
 static void * const UNMARK_AND_SWEEP = (void *)1;
 
 static PLDHashOperator
 NativeInterfaceSweeper(PLDHashTable *table, PLDHashEntryHdr *hdr,
                        uint32_t number, void *arg)
 {
@@ -1547,18 +1547,16 @@ ReloadPrefsCallback(const char *pref, vo
 
     bool parallelParsing = Preferences::GetBool(JS_OPTIONS_DOT_STR "parallel_parsing");
     bool parallelIonCompilation = Preferences::GetBool(JS_OPTIONS_DOT_STR
                                                        "ion.parallel_compilation");
     bool useBaselineEager = Preferences::GetBool(JS_OPTIONS_DOT_STR
                                                  "baselinejit.unsafe_eager_compilation");
     bool useIonEager = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion.unsafe_eager_compilation");
 
-    sDiscardSystemSource = Preferences::GetBool(JS_OPTIONS_DOT_STR "discardSystemSource");
-
     JS::RuntimeOptionsRef(rt).setBaseline(useBaseline)
                              .setIon(useIon)
                            .  setAsmJS(useAsmJS);
 
     JS_SetParallelParsingEnabled(rt, parallelParsing);
     JS_SetParallelIonCompilationEnabled(rt, parallelIonCompilation);
     JS_SetGlobalJitCompilerOption(rt, JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER,
                                   useBaselineEager ? 0 : -1);
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -1545,21 +1545,16 @@ XRE_XPCShellMain(int argc, char **argv, 
             return 1;
 
         {
             JS::Rooted<JSObject*> glob(cx, holder->GetJSObject());
             if (!glob) {
                 return 1;
             }
 
-            // Even if we're building in a configuration where source is
-            // discarded, there's no reason to do that on XPCShell, and doing so
-            // might break various automation scripts.
-            JS::CompartmentOptionsRef(glob).setDiscardSource(false);
-
             backstagePass->SetGlobalObject(glob);
 
             JSAutoCompartment ac(cx, glob);
 
             if (!JS_InitReflect(cx, glob)) {
                 JS_EndRequest(cx);
                 return 1;
             }
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -409,27 +409,16 @@ InitGlobalObject(JSContext* aJSContext, 
     if (!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
         // XPCCallContext gives us an active request needed to save/restore.
         if (!GetCompartmentPrivate(aGlobal)->scope->AttachComponentsObject(aJSContext) ||
             !XPCNativeWrapper::AttachNewConstructorObject(aJSContext, aGlobal)) {
             return UnexpectedFailure(false);
         }
     }
 
-    if (ShouldDiscardSystemSource()) {
-        nsIPrincipal *prin = GetObjectPrincipal(aGlobal);
-        bool isSystem = nsContentUtils::IsSystemPrincipal(prin);
-        if (!isSystem) {
-            short status = prin->GetAppStatus();
-            isSystem = status == nsIPrincipal::APP_STATUS_PRIVILEGED ||
-                       status == nsIPrincipal::APP_STATUS_CERTIFIED;
-        }
-        JS::CompartmentOptionsRef(aGlobal).setDiscardSource(isSystem);
-    }
-
     // Stuff coming through this path always ends up as a DOM global.
     MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL);
 
     // Init WebIDL binding constructors wanted on all XPConnect globals.
     //
     // XXX Please do not add any additional classes here without the approval of
     //     the XPConnect module owner.
     if (!PromiseBinding::GetConstructorObject(aJSContext, aGlobal) ||
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -465,21 +465,16 @@ void
 SimulateActivityCallback(bool aActive);
 
 void
 RecordAdoptedNode(JSCompartment *c);
 
 void
 RecordDonatedNode(JSCompartment *c);
 
-// This function may be used off-main-thread, in which case it is benignly
-// racey.
-bool
-ShouldDiscardSystemSource();
-
 } // namespace xpc
 
 namespace mozilla {
 namespace dom {
 
 typedef JSObject*
 (*DefineInterface)(JSContext *cx, JS::Handle<JSObject*> global,
                    JS::Handle<jsid> id, bool defineOnGlobal);
--- a/js/xpconnect/tests/chrome/chrome.ini
+++ b/js/xpconnect/tests/chrome/chrome.ini
@@ -1,15 +1,13 @@
 [DEFAULT]
 support-files =
   bug503926.xul
   file_bug618176.xul
   file_bug996069.html
-  file_discardSystemSource.html
-  worker_discardSystemSource.js
   file_evalInSandbox.html
   file_expandosharing.jsm
   outoflinexulscript.js
   subscript.js
   utf8_subscript.js
 
 [test_APIExposer.xul]
 [test_bug361111.xul]
@@ -54,17 +52,16 @@ support-files =
 [test_bug866823.xul]
 [test_bug895340.xul]
 [test_bug932906.xul]
 [test_bug996069.xul]
 [test_xrayToJS.xul]
 [test_chrometoSource.xul]
 [test_cloneInto.xul]
 [test_cows.xul]
-[test_discardSystemSource.xul]
 [test_documentdomain.xul]
 [test_doublewrappedcompartments.xul]
 [test_evalInSandbox.xul]
 [test_evalInWindow.xul]
 [test_exnstack.xul]
 [test_expandosharing.xul]
 [test_exposeInDerived.xul]
 [test_getweakmapkeys.xul]
deleted file mode 100644
--- a/js/xpconnect/tests/chrome/file_discardSystemSource.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-  function canary() {
-    var someBitOfSource = 42;
-  }
-  function inner() {
-    throw new Error("some error");
-  }
-  function throwSomething() {
-    inner();
-  }
-</script>
-</head>
-<body onload="someBitOfSource = 42">
-</body>
-</html>
deleted file mode 100644
--- a/js/xpconnect/tests/chrome/mochitest.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[DEFAULT]
-support-files =
-  file_discardSystemSource.html
-  worker_discardSystemSource.js
deleted file mode 100644
--- a/js/xpconnect/tests/chrome/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
-MOCHITEST_MANIFESTS += ['mochitest.ini']
-
deleted file mode 100644
--- a/js/xpconnect/tests/chrome/test_discardSystemSource.xul
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=990353
--->
-<window title="Mozilla Bug 990353"
-        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-
-  <!-- test results are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml">
-  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=990353"
-     target="_blank">Mozilla Bug 990353</a>
-  </body>
-
-  <!-- test code goes here -->
-  <script type="application/javascript">
-  <![CDATA[
-  /** Test for Bug 990353 **/
-  SimpleTest.waitForExplicitFinish();
-  const Cu = Components.utils;
-
-  function canary() {
-    var someBitOfSource = 42;
-  }
-
-  var gLoadCount = 0;
-  function frameLoaded() {
-    switch (++gLoadCount) {
-      case 1:
-        ok(/sourceless/.test(window[0].canary.toSource()), "System function should be sourceless: " + window[0].canary.toSource());
-        ok(/sourceless/.test(window[0].onload.toSource()), "System event handler should be sourceless: " + window[0].onload.toSource());
-        try {
-          window[0].throwSomething();
-          ok(false, "should have thrown");
-        } catch (e) {
-          ok(/some error/.test(e), "Threw exception as expected: " + e);
-          ok(/throwSomething/.test(e.stack), "Exception stack trace works: " + e.stack);
-        }
-        window[0].location = "http://example.org/tests/js/xpconnect/tests/chrome/file_discardSystemSource.html";
-        break;
-      case 2:
-        ok(/someBitOfSource/.test(Cu.waiveXrays(window[0]).canary.toSource()), "Content function should have source");
-        ok(/someBitOfSource/.test(Cu.waiveXrays(window[0]).onload.toSource()), "Content event handler should have source");
-        testWorker();
-        break;
-    }
-  }
-
-  function testWorker() {
-    var worker = new window[0].wrappedJSObject.Worker('worker_discardSystemSource.js');
-    worker.onmessage = function(evt) {
-      ok(/someBitOfSource/.test(evt.data), "Non-chrome worker should have source: " + evt.data);
-      var chromeWorker = new Worker('worker_discardSystemSource.js');
-      chromeWorker.onmessage = function(evt) {
-        ok(/sourceless/.test(evt.data), "Chrome worker should not have source: " + evt.data);
-        SimpleTest.finish();
-      }
-    }
-  }
-
-  function go() {
-    // We should have our own source, because the pref wasn't enabled when we
-    // were loaded.
-    ok(/someBitOfSource/.test(canary.toSource()), "Should have own source");
-
-    window[0].frameElement.onload = frameLoaded;
-    window[0].location = "file_discardSystemSource.html";
-  }
-  addLoadEvent(function() {
-    SpecialPowers.pushPrefEnv({set: [['javascript.options.discardSystemSource', true]]}, go);
-  });
-
-  ]]>
-  </script>
-  <iframe></iframe>
-</window>
deleted file mode 100644
--- a/js/xpconnect/tests/chrome/worker_discardSystemSource.js
+++ /dev/null
@@ -1,5 +0,0 @@
-function canary() {
-  var someBitOfSource = 42;
-}
-
-postMessage(canary.toSource());
--- a/js/xpconnect/tests/moz.build
+++ b/js/xpconnect/tests/moz.build
@@ -2,16 +2,16 @@
 # vim: set filetype=python:
 # 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/.
 
 TEST_TOOL_DIRS += [
     'idl',
     'mochitest',
-    'chrome',
     'browser',
     'components/native',
     'components/js',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
+MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -776,21 +776,16 @@ pref("javascript.options.strict",       
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     true);
 #endif
 pref("javascript.options.baselinejit",      true);
 pref("javascript.options.ion",              true);
 pref("javascript.options.asmjs",            true);
 pref("javascript.options.parallel_parsing", true);
 pref("javascript.options.ion.parallel_compilation", true);
-// This preference instructs the JS engine to discard the
-// source of any privileged JS after compilation. This saves
-// memory, but makes things like Function.prototype.toSource()
-// fail.
-pref("javascript.options.discardSystemSource", false);
 // This preference limits the memory usage of javascript.
 // If you want to change these values for your device,
 // please find Bug 417052 comment 17 and Bug 456721
 // Comment 32 and Bug 613551.
 pref("javascript.options.mem.high_water_mark", 128);
 pref("javascript.options.mem.max", -1);
 pref("javascript.options.mem.gc_per_compartment", true);
 pref("javascript.options.mem.gc_incremental", true);