Backed out changeset 539b9c11ee64 (bug 1286009) for xpcshell bustage CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Wed, 20 Jul 2016 11:04:05 -0700
changeset 305935 62a913298af663d18fee43be84f755599a92090e
parent 305934 903eba9d0ef1cdb6e19de89cc824738447262ab3
child 305936 7f816e3b56be70793f2d09b008ae575dc4ce936b
push id30747
push usercbook@mozilla.com
push dateThu, 21 Jul 2016 14:28:33 +0000
treeherderautoland@8ad7dc5cba0c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1286009
milestone50.0a1
backs out539b9c11ee64f2770da80a38e679fde91b806694
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
Backed out changeset 539b9c11ee64 (bug 1286009) for xpcshell bustage CLOSED TREE
js/src/jit-test/tests/xdr/asm.js
js/src/js.msg
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsscript.cpp
js/src/shell/js.cpp
js/src/vm/Xdr.cpp
js/src/vm/Xdr.h
js/xpconnect/loader/mozJSLoaderUtils.cpp
js/xpconnect/src/nsXPConnect.cpp
--- a/js/src/jit-test/tests/xdr/asm.js
+++ b/js/src/jit-test/tests/xdr/asm.js
@@ -9,10 +9,11 @@ var test = (function () {
     };
   };
   return f.toSource();
 })();
 
 try {
   evalWithCache(test, {});
 } catch (x) {
-  assertEq(x.message.includes("Asm.js is not supported by XDR"), true);
+  assertEq(x.message.includes("AsmJS"), true);
+  assertEq(x.message.includes("XDR"), true);
 }
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -156,16 +156,17 @@ MSG_DEF(JSMSG_UNWRAP_DENIED,           0
 // JSAPI-only (Not thrown as JS exceptions)
 MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE,  0, JSEXN_TYPEERR, "bad cloned function scope chain")
 MSG_DEF(JSMSG_CANT_CLONE_OBJECT,       0, JSEXN_TYPEERR, "can't clone object")
 MSG_DEF(JSMSG_CANT_OPEN,               2, JSEXN_ERR, "can't open {0}: {1}")
 MSG_DEF(JSMSG_USER_DEFINED_ERROR,      0, JSEXN_ERR, "JS_ReportError was called")
 
 // Internal errors
 MSG_DEF(JSMSG_ALLOC_OVERFLOW,          0, JSEXN_INTERNALERR, "allocation size overflow")
+MSG_DEF(JSMSG_BAD_BUILD_ID,            0, JSEXN_INTERNALERR, "bad build ID for XDR script")
 MSG_DEF(JSMSG_BAD_BYTECODE,            1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
 MSG_DEF(JSMSG_BUFFER_TOO_SMALL,        0, JSEXN_INTERNALERR, "buffer too small")
 MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE,  0, JSEXN_INTERNALERR, "build ID is not available")
 MSG_DEF(JSMSG_BYTECODE_TOO_BIG,        2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
 MSG_DEF(JSMSG_ERR_DURING_THROW,        0, JSEXN_INTERNALERR, "an internal error occurred while throwing an exception")
 MSG_DEF(JSMSG_NEED_DIET,               1, JSEXN_INTERNALERR, "{0} too large")
 MSG_DEF(JSMSG_OUT_OF_MEMORY,           0, JSEXN_INTERNALERR, "out of memory")
 MSG_DEF(JSMSG_OVER_RECURSED,           0, JSEXN_INTERNALERR, "too much recursion")
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -21,27 +21,23 @@ GetBuildId(JS::BuildIdCharVector* buildI
 
 static JSScript*
 FreezeThaw(JSContext* cx, JS::HandleScript script)
 {
     JS::SetBuildIdOp(cx, GetBuildId);
 
     // freeze
     uint32_t nbytes;
-    void* memory = nullptr;
-    TranscodeResult rs = JS_EncodeScript(cx, script, &nbytes, &memory);
-    if (rs != TranscodeResult_Ok)
+    void* memory = JS_EncodeScript(cx, script, &nbytes);
+    if (!memory)
         return nullptr;
 
     // thaw
-    JS::RootedScript script2(cx);
-    rs = JS_DecodeScript(cx, memory, nbytes, &script2);
+    JSScript* script2 = JS_DecodeScript(cx, memory, nbytes);
     js_free(memory);
-    if (rs != TranscodeResult_Ok)
-        return nullptr;
     return script2;
 }
 
 enum TestCase {
     TEST_FIRST,
     TEST_SCRIPT = TEST_FIRST,
     TEST_FUNCTION,
     TEST_SERIALIZED_FUNCTION,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6452,60 +6452,54 @@ JS_PUBLIC_API(void)
 JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
 }
 #endif /* JS_DEBUG */
 
-JS_PUBLIC_API(TranscodeResult)
-JS_EncodeScript(JSContext* cx, HandleScript scriptArg,
-                uint32_t* lengthp, void** buffer)
+JS_PUBLIC_API(void*)
+JS_EncodeScript(JSContext* cx, HandleScript scriptArg, uint32_t* lengthp)
 {
     XDREncoder encoder(cx);
     RootedScript script(cx, scriptArg);
-    *buffer = nullptr;
-    if (encoder.codeScript(&script))
-        *buffer = encoder.forgetData(lengthp);
-    MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
-    return encoder.resultCode();
-}
-
-JS_PUBLIC_API(TranscodeResult)
-JS_EncodeInterpretedFunction(JSContext* cx, HandleObject funobjArg,
-                             uint32_t* lengthp, void** buffer)
+    if (!encoder.codeScript(&script))
+        return nullptr;
+    return encoder.forgetData(lengthp);
+}
+
+JS_PUBLIC_API(void*)
+JS_EncodeInterpretedFunction(JSContext* cx, HandleObject funobjArg, uint32_t* lengthp)
 {
     XDREncoder encoder(cx);
     RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
-    *buffer = nullptr;
-    if (encoder.codeFunction(&funobj))
-        *buffer = encoder.forgetData(lengthp);
-    MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
-    return encoder.resultCode();
-}
-
-JS_PUBLIC_API(TranscodeResult)
-JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
-                JS::MutableHandleScript scriptp)
+    if (!encoder.codeFunction(&funobj))
+        return nullptr;
+    return encoder.forgetData(lengthp);
+}
+
+JS_PUBLIC_API(JSScript*)
+JS_DecodeScript(JSContext* cx, const void* data, uint32_t length)
 {
     XDRDecoder decoder(cx, data, length);
-    decoder.codeScript(scriptp);
-    MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
-    return decoder.resultCode();
-}
-
-JS_PUBLIC_API(TranscodeResult)
-JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length,
-                             JS::MutableHandleFunction funp)
+    RootedScript script(cx);
+    if (!decoder.codeScript(&script))
+        return nullptr;
+    return script;
+}
+
+JS_PUBLIC_API(JSObject*)
+JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length)
 {
     XDRDecoder decoder(cx, data, length);
-    decoder.codeFunction(funp);
-    MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok));
-    return decoder.resultCode();
+    RootedFunction funobj(cx);
+    if (!decoder.codeFunction(&funobj))
+        return nullptr;
+    return funobj;
 }
 
 JS_PUBLIC_API(void)
 JS::SetBuildIdOp(JSContext* cx, JS::BuildIdOp buildIdOp)
 {
     cx->runtime()->buildIdOp = buildIdOp;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5688,48 +5688,27 @@ class MOZ_RAII AutoHideScriptedCaller
 };
 
 } /* namespace JS */
 
 /*
  * Encode/Decode interpreted scripts and functions to/from memory.
  */
 
-enum TranscodeResult
-{
-    // Successful encoding / decoding.
-    TranscodeResult_Ok = 0,
-
-    // A warning message, is set to the message out-param.
-    TranscodeResult_Failure = 0x100,
-    TranscodeResult_Failure_BadBuildId =          TranscodeResult_Failure | 0x1,
-    TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
-    TranscodeResult_Failure_AsmJSNotSupported =   TranscodeResult_Failure | 0x3,
-    TranscodeResult_Failure_UnknownClassKind =    TranscodeResult_Failure | 0x4,
-
-    // A error, the JSContext has a pending exception.
-    TranscodeResult_Throw = 0x200
-};
-
-extern JS_PUBLIC_API(TranscodeResult)
-JS_EncodeScript(JSContext* cx, JS::HandleScript script,
-                uint32_t* lengthp, void** buffer);
-
-extern JS_PUBLIC_API(TranscodeResult)
-JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj,
-                             uint32_t* lengthp, void** buffer);
-
-extern JS_PUBLIC_API(TranscodeResult)
-JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
-                JS::MutableHandleScript scriptp);
-
-extern JS_PUBLIC_API(TranscodeResult)
-JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length,
-                             JS::MutableHandleFunction funp);
-
+extern JS_PUBLIC_API(void*)
+JS_EncodeScript(JSContext* cx, JS::HandleScript script, uint32_t* lengthp);
+
+extern JS_PUBLIC_API(void*)
+JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj, uint32_t* lengthp);
+
+extern JS_PUBLIC_API(JSScript*)
+JS_DecodeScript(JSContext* cx, const void* data, uint32_t length);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length);
 
 namespace JS {
 
 /*
  * This callback represents a request by the JS engine to open for reading the
  * existing cache entry for the given global and char range that may contain a
  * module. If a cache entry exists, the callback shall return 'true' and return
  * the size, base address and an opaque file handle as outparams. If the
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -665,17 +665,20 @@ js::XDRScript(XDRState<mode>* xdr, Handl
             // make sure that we're not XDR-saving an object we emitted for
             // JSOP_OBJECT that then got modified.  So throw if we're not
             // cloning in JSOP_OBJECT or if we ever didn't clone in it in the
             // past.
             JSCompartment* comp = cx->compartment();
             if (!comp->creationOptions().cloneSingletons() ||
                 !comp->behaviors().getSingletonsAsTemplates())
             {
-                return xdr->fail(TranscodeResult_Failure_RunOnceNotSupported);
+                JS_ReportError(cx,
+                               "Can't serialize a run-once non-function script "
+                               "when we're not doing singleton cloning");
+                return false;
             }
         }
 
         nargs = script->bindings.numArgs();
         nblocklocals = script->bindings.numBlockScoped();
         nbodylevellexicals = script->bindings.numBodyLevelLexicals();
         nvars = script->bindings.numVars();
         nunaliasedvars = script->bindings.numUnaliasedVars();
@@ -1095,17 +1098,18 @@ js::XDRScript(XDRState<mode>* xdr, Handl
                 RootedFunction function(cx, &(*objp)->as<JSFunction>());
 
                 if (function->isInterpretedLazy())
                     funEnclosingScope = function->lazyScript()->enclosingScope();
                 else if (function->isInterpreted())
                     funEnclosingScope = function->nonLazyScript()->enclosingStaticScope();
                 else {
                     MOZ_ASSERT(function->isAsmJSNative());
-                    return xdr->fail(TranscodeResult_Failure_AsmJSNotSupported);
+                    JS_ReportError(cx, "AsmJS modules are not yet supported in XDR serialization.");
+                    return false;
                 }
 
                 StaticScopeIter<NoGC> ssi(funEnclosingScope);
 
                 // Starting from a nested function, hitting a non-syntactic
                 // scope on the static scope chain means that its enclosing
                 // function has a non-syntactic scope. Nested functions
                 // themselves never have non-syntactic scope chains.
@@ -1161,17 +1165,17 @@ js::XDRScript(XDRState<mode>* xdr, Handl
             if (!XDRObjectLiteral(xdr, &tmp))
                 return false;
             *objp = tmp;
             break;
           }
 
           default: {
             MOZ_ASSERT(false, "Unknown class kind.");
-            return xdr->fail(TranscodeResult_Failure_UnknownClassKind);
+            return false;
           }
         }
     }
 
     if (ntrynotes != 0) {
         JSTryNote* tnfirst = script->trynotes()->vector;
         MOZ_ASSERT(script->trynotes()->length == ntrynotes);
         JSTryNote* tn = tnfirst + ntrynotes;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1298,52 +1298,16 @@ CacheEntry_setBytecode(JSContext* cx, Ha
     if (!arrayBuffer)
         return false;
 
     SetReservedSlot(cache, CacheEntry_BYTECODE, ObjectValue(*arrayBuffer));
     return true;
 }
 
 static bool
-ConvertTranscodeResultToJSException(JSContext* cx, TranscodeResult rv)
-{
-    switch (rv) {
-      case TranscodeResult_Ok:
-        return true;
-
-      default:
-        MOZ_FALLTHROUGH;
-      case TranscodeResult_Failure:
-        MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportError(cx, "generic warning");
-        return false;
-      case TranscodeResult_Failure_BadBuildId:
-        MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportError(cx, "the build-id does not match");
-        return false;
-      case TranscodeResult_Failure_RunOnceNotSupported:
-        MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportError(cx, "run-once script are not supported by XDR");
-        return false;
-      case TranscodeResult_Failure_AsmJSNotSupported:
-        MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportError(cx, "Asm.js is not supported by XDR");
-        return false;
-      case TranscodeResult_Failure_UnknownClassKind:
-        MOZ_ASSERT(!cx->isExceptionPending());
-        JS_ReportError(cx, "Unknown class kind, go fix it.");
-        return false;
-
-      case TranscodeResult_Throw:
-        MOZ_ASSERT(cx->isExceptionPending());
-        return false;
-    }
-}
-
-static bool
 Evaluate(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1 || args.length() > 2) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
                              args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_TOO_MANY_ARGS,
                              "evaluate");
@@ -1478,19 +1442,17 @@ Evaluate(JSContext* cx, unsigned argc, V
                     return false;
                 }
 
                 // cloneSingletons implies that singletons are used as template objects.
                 MOZ_ASSERT(JS::CompartmentBehaviorsRef(cx).getSingletonsAsTemplates());
             }
 
             if (loadBytecode) {
-                TranscodeResult rv = JS_DecodeScript(cx, loadBuffer, loadLength, &script);
-                if (!ConvertTranscodeResultToJSException(cx, rv))
-                    return false;
+                script = JS_DecodeScript(cx, loadBuffer, loadLength);
             } else {
                 mozilla::Range<const char16_t> chars = codeChars.twoByteRange();
                 (void) JS::Compile(cx, options, chars.start().get(), chars.length(), &script);
             }
 
             if (!script)
                 return false;
         }
@@ -1529,19 +1491,18 @@ Evaluate(JSContext* cx, unsigned argc, V
                     return false;
                 args.rval().setString(str);
                 return true;
             }
             return false;
         }
 
         if (saveBytecode) {
-            TranscodeResult rv = JS_EncodeScript(cx, script, &saveLength,
-                                                 reinterpret_cast<void**>(&saveBuffer.rwget()));
-            if (!ConvertTranscodeResultToJSException(cx, rv))
+            saveBuffer = reinterpret_cast<uint8_t*>(JS_EncodeScript(cx, script, &saveLength));
+            if (!saveBuffer)
                 return false;
         }
     }
 
     if (saveBytecode) {
         // If we are both loading and saving, we assert that we are going to
         // replace the current bytecode by the same stream of bytes.
         if (loadBytecode && assertEqBytecode) {
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -54,26 +54,16 @@ XDRBuffer::grow(size_t n)
     }
     base = static_cast<uint8_t*>(data);
     cursor = base + offset;
     limit = base + newCapacity;
     return true;
 }
 
 template<XDRMode mode>
-void
-XDRState<mode>::postProcessContextErrors(JSContext* cx)
-{
-    if (cx->isExceptionPending()) {
-        MOZ_ASSERT(resultCode_ == TranscodeResult_Ok);
-        resultCode_ = TranscodeResult_Throw;
-    }
-}
-
-template<XDRMode mode>
 bool
 XDRState<mode>::codeChars(const Latin1Char* chars, size_t nchars)
 {
     static_assert(sizeof(Latin1Char) == sizeof(uint8_t), "Latin1Char must fit in 1 byte");
 
     MOZ_ASSERT(mode == XDR_ENCODE);
 
     uint8_t* ptr = buf.write(nchars);
@@ -114,18 +104,20 @@ VersionCheck(XDRState<mode>* xdr)
 
     uint32_t buildIdLength;
     if (mode == XDR_ENCODE)
         buildIdLength = buildId.length();
 
     if (!xdr->codeUint32(&buildIdLength))
         return false;
 
-    if (mode == XDR_DECODE && buildIdLength != buildId.length())
-        return xdr->fail(TranscodeResult_Failure_BadBuildId);
+    if (mode == XDR_DECODE && buildIdLength != buildId.length()) {
+        JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
+        return false;
+    }
 
     if (mode == XDR_ENCODE) {
         if (!xdr->codeBytes(buildId.begin(), buildIdLength))
             return false;
     } else {
         JS::BuildIdCharVector decodedBuildId;
 
         // buildIdLength is already checked against the length of current
@@ -133,58 +125,53 @@ VersionCheck(XDRState<mode>* xdr)
         if (!decodedBuildId.resize(buildIdLength)) {
             ReportOutOfMemory(xdr->cx());
             return false;
         }
 
         if (!xdr->codeBytes(decodedBuildId.begin(), buildIdLength))
             return false;
 
-        // We do not provide binary compatibility with older scripts.
-        if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
-            return xdr->fail(TranscodeResult_Failure_BadBuildId);
+        if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength)) {
+            // We do not provide binary compatibility with older scripts.
+            JS_ReportErrorNumber(xdr->cx(), GetErrorMessage, nullptr, JSMSG_BAD_BUILD_ID);
+            return false;
+        }
     }
 
     return true;
 }
 
 template<XDRMode mode>
 bool
 XDRState<mode>::codeFunction(MutableHandleFunction objp)
 {
     if (mode == XDR_DECODE)
         objp.set(nullptr);
 
     if (!VersionCheck(this))
         return false;
 
     RootedObject staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock());
-    if (!XDRInterpretedFunction(this, staticLexical, nullptr, objp)) {
-        postProcessContextErrors(cx());
-        return false;
-    }
-
-    return true;
+    return XDRInterpretedFunction(this, staticLexical, nullptr, objp);
 }
 
 template<XDRMode mode>
 bool
 XDRState<mode>::codeScript(MutableHandleScript scriptp)
 {
     if (mode == XDR_DECODE)
         scriptp.set(nullptr);
 
     if (!VersionCheck(this))
         return false;
 
     RootedObject staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock());
-    if (!XDRScript(this, staticLexical, nullptr, nullptr, scriptp)) {
-        postProcessContextErrors(cx());
+    if (!XDRScript(this, staticLexical, nullptr, nullptr, scriptp))
         return false;
-    }
 
     return true;
 }
 
 template<XDRMode mode>
 bool
 XDRState<mode>::codeConstValue(MutableHandleValue vp)
 {
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -74,38 +74,26 @@ class XDRBuffer {
 
 /*
  * XDR serialization state.  All data is encoded in little endian.
  */
 template <XDRMode mode>
 class XDRState {
   public:
     XDRBuffer buf;
-    TranscodeResult resultCode_;
 
   protected:
     explicit XDRState(JSContext* cx)
-      : buf(cx), resultCode_(TranscodeResult_Ok) { }
+      : buf(cx) { }
 
   public:
     JSContext* cx() const {
         return buf.cx();
     }
 
-    // Record logical failures of XDR.
-    void postProcessContextErrors(JSContext* cx);
-    TranscodeResult resultCode() const {
-        return resultCode_;
-    }
-    bool fail(TranscodeResult code) {
-        MOZ_ASSERT(resultCode_ == TranscodeResult_Ok);
-        resultCode_ = code;
-        return false;
-    }
-
     bool codeUint8(uint8_t* n) {
         if (mode == XDR_ENCODE) {
             uint8_t* ptr = buf.write(sizeof *n);
             if (!ptr)
                 return false;
             *ptr = *n;
         } else {
             *n = *buf.read(sizeof *n);
--- a/js/xpconnect/loader/mozJSLoaderUtils.cpp
+++ b/js/xpconnect/loader/mozJSLoaderUtils.cpp
@@ -24,58 +24,75 @@ ReadCachedScript(StartupCache* cache, ns
                  nsIPrincipal* systemPrincipal, MutableHandleScript scriptp)
 {
     UniquePtr<char[]> buf;
     uint32_t len;
     nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(), &buf, &len);
     if (NS_FAILED(rv))
         return rv; // don't warn since NOT_AVAILABLE is an ok error
 
-    TranscodeResult code = JS_DecodeScript(cx, buf.get(), len, scriptp);
-    if (code == TranscodeResult_Ok)
-        return NS_OK;
-
-    if ((code & TranscodeResult_Failure) != 0)
-        return NS_ERROR_FAILURE;
-
-    MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
-    JS_ClearPendingException(cx);
-    return NS_ERROR_OUT_OF_MEMORY;
+    scriptp.set(JS_DecodeScript(cx, buf.get(), len));
+    if (!scriptp)
+        return NS_ERROR_OUT_OF_MEMORY;
+    return NS_OK;
 }
 
 nsresult
 ReadCachedFunction(StartupCache* cache, nsACString& uri, JSContext* cx,
                    nsIPrincipal* systemPrincipal, JSFunction** functionp)
 {
-    // This doesn't actually work ...
-    return NS_ERROR_NOT_IMPLEMENTED;
+    return NS_ERROR_FAILURE;
+/*  This doesn't actually work ...
+    nsAutoArrayPtr<char> buf;
+    uint32_t len;
+    nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
+                                   getter_Transfers(buf), &len);
+    if (NS_FAILED(rv))
+        return rv; // don't warn since NOT_AVAILABLE is an ok error
+
+    JSObject* obj = JS_DecodeInterpretedFunction(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nullptr);
+    if (!obj)
+        return NS_ERROR_OUT_OF_MEMORY;
+    JSFunction* function = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
+    *functionp = function;
+    return NS_OK;*/
 }
 
 nsresult
 WriteCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
                   nsIPrincipal* systemPrincipal, HandleScript script)
 {
     MOZ_ASSERT(JS_GetScriptPrincipals(script) == nsJSPrincipals::get(systemPrincipal));
 
     uint32_t size;
-    void* data = nullptr;
-    TranscodeResult code = JS_EncodeScript(cx, script, &size, &data);
-    if (code != TranscodeResult_Ok) {
-        if ((code & TranscodeResult_Failure) != 0)
-            return NS_ERROR_FAILURE;
-        MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
+    void* data = JS_EncodeScript(cx, script, &size);
+    if (!data) {
+        // JS_EncodeScript may have set a pending exception.
         JS_ClearPendingException(cx);
-        return NS_ERROR_OUT_OF_MEMORY;
+        return NS_ERROR_FAILURE;
     }
 
-    MOZ_ASSERT(size && data);
+    MOZ_ASSERT(size);
     nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
     js_free(data);
     return rv;
 }
 
 nsresult
 WriteCachedFunction(StartupCache* cache, nsACString& uri, JSContext* cx,
                     nsIPrincipal* systemPrincipal, JSFunction* function)
 {
-    // This doesn't actually work ...
-    return NS_ERROR_NOT_IMPLEMENTED;
+    return NS_ERROR_FAILURE;
+/* This doesn't actually work ...
+    uint32_t size;
+    void* data =
+      JS_EncodeInterpretedFunction(cx, JS_GetFunctionObject(function), &size);
+    if (!data) {
+        // JS_EncodeInterpretedFunction may have set a pending exception.
+        JS_ClearPendingException(cx);
+        return NS_ERROR_FAILURE;
+    }
+
+    MOZ_ASSERT(size);
+    nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
+    js_free(data);
+    return rv;*/
 }
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1095,34 +1095,27 @@ WriteScriptOrFunction(nsIObjectOutputStr
 
     uint8_t flags = 0; // We don't have flags anymore.
     nsresult rv = stream->Write8(flags);
     if (NS_FAILED(rv))
         return rv;
 
 
     uint32_t size;
-    void* data = nullptr;
-    TranscodeResult code;
+    void* data;
     {
         if (functionObj)
-            code = JS_EncodeInterpretedFunction(cx, functionObj, &size, &data);
+            data = JS_EncodeInterpretedFunction(cx, functionObj, &size);
         else
-            code = JS_EncodeScript(cx, script, &size, &data);
+            data = JS_EncodeScript(cx, script, &size);
     }
 
-    if (code != TranscodeResult_Ok) {
-        if ((code & TranscodeResult_Failure) != 0)
-            return NS_ERROR_FAILURE;
-        MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
-        JS_ClearPendingException(cx);
+    if (!data)
         return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    MOZ_ASSERT(size && data);
+    MOZ_ASSERT(size);
     rv = stream->Write32(size);
     if (NS_SUCCEEDED(rv))
         rv = stream->WriteBytes(static_cast<char*>(data), size);
     js_free(data);
 
     return rv;
 }
 
@@ -1150,35 +1143,28 @@ ReadScriptOrFunction(nsIObjectInputStrea
         return rv;
 
     char* data;
     rv = stream->ReadBytes(size, &data);
     if (NS_FAILED(rv))
         return rv;
 
     {
-        TranscodeResult code;
         if (scriptp) {
-            Rooted<JSScript*> script(cx);
-            code = JS_DecodeScript(cx, data, size, &script);
-            if (code == TranscodeResult_Ok)
-                *scriptp = script.get();
+            JSScript* script = JS_DecodeScript(cx, data, size);
+            if (!script)
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            else
+                *scriptp = script;
         } else {
-            Rooted<JSFunction*> funobj(cx);
-            code = JS_DecodeInterpretedFunction(cx, data, size, &funobj);
-            if (code == TranscodeResult_Ok)
-                *functionObjp = JS_GetFunctionObject(funobj.get());
-        }
-
-        if (code != TranscodeResult_Ok) {
-            if ((code & TranscodeResult_Failure) != 0)
-                return NS_ERROR_FAILURE;
-            MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
-            JS_ClearPendingException(cx);
-            return NS_ERROR_OUT_OF_MEMORY;
+            JSObject* funobj = JS_DecodeInterpretedFunction(cx, data, size);
+            if (!funobj)
+                rv = NS_ERROR_OUT_OF_MEMORY;
+            else
+                *functionObjp = funobj;
         }
     }
 
     free(data);
     return rv;
 }
 
 NS_IMETHODIMP