Bug 1288104 part 1 - Move XDR buffer to the caller. r=luke

Add a typedef on top of mozilla::Vector to define the TranscodeBuffer which owns
the encoded content of a Script / Function.

This modification renames JS_EncodeScript, into JS::EncodeScript, and change its
prototype to have a JSContext, a TranscodeBuffer, and a Handle on a script that
we want to encode.

Similar modifications are made to JS_EncodeInterpretedFunction, and the Decode
variant of these.
This commit is contained in:
Nicolas B. Pierron 2016-10-20 09:44:33 +00:00
Родитель 41f4e7423a
Коммит b3e4b94e1e
10 изменённых файлов: 148 добавлений и 219 удалений

Просмотреть файл

@ -25,17 +25,15 @@ 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)
JS::TranscodeBuffer buffer;
JS::TranscodeResult rs = JS::EncodeScript(cx, buffer, script);
if (rs != JS::TranscodeResult_Ok)
return nullptr;
// thaw
JS::RootedScript script2(cx);
rs = JS_DecodeScript(cx, memory, nbytes, &script2);
js_free(memory);
if (rs != TranscodeResult_Ok)
rs = JS::DecodeScript(cx, buffer, &script2);
if (rs != JS::TranscodeResult_Ok)
return nullptr;
return script2;
}

Просмотреть файл

@ -6592,47 +6592,42 @@ JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
}
#endif /* JS_DEBUG */
JS_PUBLIC_API(TranscodeResult)
JS_EncodeScript(JSContext* cx, HandleScript scriptArg,
uint32_t* lengthp, void** buffer)
JS_PUBLIC_API(JS::TranscodeResult)
JS::EncodeScript(JSContext* cx, TranscodeBuffer& buffer, HandleScript scriptArg)
{
XDREncoder encoder(cx);
XDREncoder encoder(cx, buffer);
RootedScript script(cx, scriptArg);
*buffer = nullptr;
if (encoder.codeScript(&script))
*buffer = encoder.forgetData(lengthp);
MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
if (!encoder.codeScript(&script))
buffer.clearAndFree();
MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
return encoder.resultCode();
}
JS_PUBLIC_API(TranscodeResult)
JS_EncodeInterpretedFunction(JSContext* cx, HandleObject funobjArg,
uint32_t* lengthp, void** buffer)
JS_PUBLIC_API(JS::TranscodeResult)
JS::EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, HandleObject funobjArg)
{
XDREncoder encoder(cx);
XDREncoder encoder(cx, buffer);
RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
*buffer = nullptr;
if (encoder.codeFunction(&funobj))
*buffer = encoder.forgetData(lengthp);
MOZ_ASSERT(bool(*buffer) == (encoder.resultCode() == TranscodeResult_Ok));
if (!encoder.codeFunction(&funobj))
buffer.clearAndFree();
MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
return encoder.resultCode();
}
JS_PUBLIC_API(TranscodeResult)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleScript scriptp)
JS_PUBLIC_API(JS::TranscodeResult)
JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp)
{
XDRDecoder decoder(cx, data, length);
XDRDecoder decoder(cx, buffer);
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)
JS_PUBLIC_API(JS::TranscodeResult)
JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer,
JS::MutableHandleFunction funp)
{
XDRDecoder decoder(cx, data, length);
XDRDecoder decoder(cx, buffer);
decoder.codeFunction(funp);
MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok));
return decoder.resultCode();

Просмотреть файл

@ -5830,12 +5830,12 @@ class MOZ_RAII AutoHideScriptedCaller
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
} /* namespace JS */
/*
* Encode/Decode interpreted scripts and functions to/from memory.
*/
typedef mozilla::Vector<uint8_t> TranscodeBuffer;
enum TranscodeResult
{
// Successful encoding / decoding.
@ -5853,21 +5853,18 @@ enum TranscodeResult
};
extern JS_PUBLIC_API(TranscodeResult)
JS_EncodeScript(JSContext* cx, JS::HandleScript script,
uint32_t* lengthp, void** buffer);
EncodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::HandleScript script);
extern JS_PUBLIC_API(TranscodeResult)
JS_EncodeInterpretedFunction(JSContext* cx, JS::HandleObject funobj,
uint32_t* lengthp, void** buffer);
EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::HandleObject funobj);
extern JS_PUBLIC_API(TranscodeResult)
JS_DecodeScript(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleScript scriptp);
DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp);
extern JS_PUBLIC_API(TranscodeResult)
JS_DecodeInterpretedFunction(JSContext* cx, const void* data, uint32_t length,
JS::MutableHandleFunction funp);
DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleFunction funp);
} /* namespace JS */
namespace js {

Просмотреть файл

@ -565,12 +565,16 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
JSContext* cx = xdr->cx();
JSAtom* atom;
if (latin1) {
const Latin1Char* chars = reinterpret_cast<const Latin1Char*>(xdr->buf.read(length));
const Latin1Char* chars = nullptr;
if (length)
chars = reinterpret_cast<const Latin1Char*>(xdr->buf.read(length));
atom = AtomizeChars(cx, chars, length);
} else {
#if MOZ_LITTLE_ENDIAN
/* Directly access the little endian chars in the XDR buffer. */
const char16_t* chars = reinterpret_cast<const char16_t*>(xdr->buf.read(length * sizeof(char16_t)));
const char16_t* chars = nullptr;
if (length)
chars = reinterpret_cast<const char16_t*>(xdr->buf.read(length * sizeof(char16_t)));
atom = AtomizeChars(cx, chars, length);
#else
/*

Просмотреть файл

@ -358,7 +358,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
if (!comp->creationOptions().cloneSingletons() ||
!comp->behaviors().getSingletonsAsTemplates())
{
return xdr->fail(TranscodeResult_Failure_RunOnceNotSupported);
return xdr->fail(JS::TranscodeResult_Failure_RunOnceNotSupported);
}
}
}
@ -792,7 +792,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
funEnclosingScope = function->nonLazyScript()->enclosingScope();
} else {
MOZ_ASSERT(function->isAsmJSNative());
return xdr->fail(TranscodeResult_Failure_AsmJSNotSupported);
return xdr->fail(JS::TranscodeResult_Failure_AsmJSNotSupported);
}
funEnclosingScopeIndex = FindScopeIndex(script, *funEnclosingScope);
@ -827,7 +827,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
default: {
MOZ_ASSERT(false, "Unknown class kind.");
return xdr->fail(TranscodeResult_Failure_UnknownClassKind);
return xdr->fail(JS::TranscodeResult_Failure_UnknownClassKind);
}
}
}

Просмотреть файл

@ -1511,36 +1511,36 @@ CacheEntry_setBytecode(JSContext* cx, HandleObject cache, uint8_t* buffer, uint3
}
static bool
ConvertTranscodeResultToJSException(JSContext* cx, TranscodeResult rv)
ConvertTranscodeResultToJSException(JSContext* cx, JS::TranscodeResult rv)
{
switch (rv) {
case TranscodeResult_Ok:
case JS::TranscodeResult_Ok:
return true;
default:
MOZ_FALLTHROUGH;
case TranscodeResult_Failure:
case JS::TranscodeResult_Failure:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "generic warning");
return false;
case TranscodeResult_Failure_BadBuildId:
case JS::TranscodeResult_Failure_BadBuildId:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "the build-id does not match");
return false;
case TranscodeResult_Failure_RunOnceNotSupported:
case JS::TranscodeResult_Failure_RunOnceNotSupported:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "run-once script are not supported by XDR");
return false;
case TranscodeResult_Failure_AsmJSNotSupported:
case JS::TranscodeResult_Failure_AsmJSNotSupported:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "Asm.js is not supported by XDR");
return false;
case TranscodeResult_Failure_UnknownClassKind:
case JS::TranscodeResult_Failure_UnknownClassKind:
MOZ_ASSERT(!cx->isExceptionPending());
JS_ReportErrorASCII(cx, "Unknown class kind, go fix it.");
return false;
case TranscodeResult_Throw:
case JS::TranscodeResult_Throw:
MOZ_ASSERT(cx->isExceptionPending());
return false;
}
@ -1663,15 +1663,19 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
if (!codeChars.initTwoByte(cx, code))
return false;
uint32_t loadLength = 0;
uint8_t* loadBuffer = nullptr;
uint32_t saveLength = 0;
ScopedJSFreePtr<uint8_t> saveBuffer;
JS::TranscodeBuffer loadBuffer;
JS::TranscodeBuffer saveBuffer;
if (loadBytecode) {
loadBuffer = CacheEntry_getBytecode(cacheEntry, &loadLength);
if (!loadBuffer)
uint32_t loadLength = 0;
uint8_t* loadData = nullptr;
loadData = CacheEntry_getBytecode(cacheEntry, &loadLength);
if (!loadData)
return false;
if (!loadBuffer.append(loadData, loadLength)) {
JS_ReportOutOfMemory(cx);
return false;
}
}
{
@ -1691,7 +1695,7 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
}
if (loadBytecode) {
TranscodeResult rv = JS_DecodeScript(cx, loadBuffer, loadLength, &script);
JS::TranscodeResult rv = JS::DecodeScript(cx, loadBuffer, &script);
if (!ConvertTranscodeResultToJSException(cx, rv))
return false;
} else {
@ -1742,8 +1746,7 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
}
if (saveBytecode) {
TranscodeResult rv = JS_EncodeScript(cx, script, &saveLength,
reinterpret_cast<void**>(&saveBuffer.rwget()));
JS::TranscodeResult rv = JS::EncodeScript(cx, saveBuffer, script);
if (!ConvertTranscodeResultToJSException(cx, rv))
return false;
}
@ -1753,28 +1756,34 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
// 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) {
if (saveLength != loadLength) {
if (saveBuffer.length() != loadBuffer.length()) {
char loadLengthStr[16];
SprintfLiteral(loadLengthStr, "%" PRIu32, loadLength);
SprintfLiteral(loadLengthStr, "%" PRIuSIZE, loadBuffer.length());
char saveLengthStr[16];
SprintfLiteral(saveLengthStr,"%" PRIu32, saveLength);
SprintfLiteral(saveLengthStr,"%" PRIuSIZE, saveBuffer.length());
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_CACHE_EQ_SIZE_FAILED,
loadLengthStr, saveLengthStr);
return false;
}
if (!PodEqual(loadBuffer, saveBuffer.get(), loadLength)) {
if (!PodEqual(loadBuffer.begin(), saveBuffer.begin(), loadBuffer.length())) {
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr,
JSSMSG_CACHE_EQ_CONTENT_FAILED);
return false;
}
}
if (!CacheEntry_setBytecode(cx, cacheEntry, saveBuffer, saveLength))
size_t saveLength = saveBuffer.length();
if (saveLength >= INT32_MAX) {
JS_ReportErrorASCII(cx, "Cannot save large cache entry content");
return false;
saveBuffer.forget();
}
uint8_t* saveData = saveBuffer.extractOrCopyRawBuffer();
if (!CacheEntry_setBytecode(cx, cacheEntry, saveData, saveLength)) {
js_free(saveData);
return false;
}
}
return JS_WrapValue(cx, args.rval());

Просмотреть файл

@ -19,52 +19,13 @@
using namespace js;
using mozilla::PodEqual;
void
XDRBuffer::freeBuffer()
{
js_free(base);
#ifdef DEBUG
memset(this, 0xe2, sizeof *this);
#endif
}
bool
XDRBuffer::grow(size_t n)
{
MOZ_ASSERT(n > size_t(limit - cursor));
const size_t MIN_CAPACITY = 8192;
const size_t MAX_CAPACITY = size_t(INT32_MAX) + 1;
size_t offset = cursor - base;
MOZ_ASSERT(offset <= MAX_CAPACITY);
if (n > MAX_CAPACITY - offset) {
js::gc::AutoSuppressGC suppressGC(cx());
JS_ReportErrorNumberASCII(cx(), GetErrorMessage, nullptr, JSMSG_TOO_BIG_TO_ENCODE);
return false;
}
size_t newCapacity = mozilla::RoundUpPow2(offset + n);
if (newCapacity < MIN_CAPACITY)
newCapacity = MIN_CAPACITY;
MOZ_ASSERT(newCapacity <= MAX_CAPACITY);
void* data = js_realloc(base, newCapacity);
if (!data) {
ReportOutOfMemory(cx());
return false;
}
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;
MOZ_ASSERT(resultCode_ == JS::TranscodeResult_Ok);
resultCode_ = JS::TranscodeResult_Throw;
}
}
@ -76,6 +37,8 @@ XDRState<mode>::codeChars(const Latin1Char* chars, size_t nchars)
MOZ_ASSERT(mode == XDR_ENCODE);
if (nchars == 0)
return true;
uint8_t* ptr = buf.write(nchars);
if (!ptr)
return false;
@ -88,6 +51,8 @@ template<XDRMode mode>
bool
XDRState<mode>::codeChars(char16_t* chars, size_t nchars)
{
if (nchars == 0)
return true;
size_t nbytes = nchars * sizeof(char16_t);
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(nbytes);
@ -121,7 +86,7 @@ VersionCheck(XDRState<mode>* xdr)
return false;
if (mode == XDR_DECODE && buildIdLength != buildId.length())
return xdr->fail(TranscodeResult_Failure_BadBuildId);
return xdr->fail(JS::TranscodeResult_Failure_BadBuildId);
if (mode == XDR_ENCODE) {
if (!xdr->codeBytes(buildId.begin(), buildIdLength))
@ -141,7 +106,7 @@ VersionCheck(XDRState<mode>* xdr)
// We do not provide binary compatibility with older scripts.
if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
return xdr->fail(TranscodeResult_Failure_BadBuildId);
return xdr->fail(JS::TranscodeResult_Failure_BadBuildId);
}
return true;
@ -201,11 +166,5 @@ XDRState<mode>::codeConstValue(MutableHandleValue vp)
return XDRScriptConst(this, vp);
}
XDRDecoder::XDRDecoder(JSContext* cx, const void* data, uint32_t length)
: XDRState<XDR_DECODE>(cx)
{
buf.setData(data, length);
}
template class js::XDRState<XDR_ENCODE>;
template class js::XDRState<XDR_DECODE>;

Просмотреть файл

@ -17,59 +17,44 @@ namespace js {
class XDRBuffer {
public:
explicit XDRBuffer(JSContext* cx)
: context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
XDRBuffer(JSContext* cx, JS::TranscodeBuffer& buffer)
: context_(cx), buffer_(buffer), cursor_(0) { }
JSContext* cx() const {
return context;
}
void* getData(uint32_t* lengthp) const {
MOZ_ASSERT(size_t(cursor - base) <= size_t(UINT32_MAX));
*lengthp = uint32_t(cursor - base);
return base;
}
void setData(const void* data, uint32_t length) {
base = static_cast<uint8_t*>(const_cast<void*>(data));
cursor = base;
limit = base + length;
return context_;
}
const uint8_t* read(size_t n) {
MOZ_ASSERT(n <= size_t(limit - cursor));
uint8_t* ptr = cursor;
cursor += n;
MOZ_ASSERT(cursor_ < buffer_.length());
uint8_t* ptr = &buffer_[cursor_];
cursor_ += n;
return ptr;
}
const char* readCString() {
char* ptr = reinterpret_cast<char*>(cursor);
cursor = reinterpret_cast<uint8_t*>(strchr(ptr, '\0')) + 1;
MOZ_ASSERT(base < cursor);
MOZ_ASSERT(cursor <= limit);
char* ptr = reinterpret_cast<char*>(&buffer_[cursor_]);
uint8_t* end = reinterpret_cast<uint8_t*>(strchr(ptr, '\0')) + 1;
MOZ_ASSERT(buffer_.begin() < end);
MOZ_ASSERT(end <= buffer_.end());
cursor_ = end - buffer_.begin();
return ptr;
}
uint8_t* write(size_t n) {
if (n > size_t(limit - cursor)) {
if (!grow(n))
return nullptr;
MOZ_ASSERT(n != 0);
if (!buffer_.growByUninitialized(n)) {
JS_ReportOutOfMemory(cx());
return nullptr;
}
uint8_t* ptr = cursor;
cursor += n;
uint8_t* ptr = &buffer_[cursor_];
cursor_ += n;
return ptr;
}
void freeBuffer();
private:
bool grow(size_t n);
JSContext* const context;
uint8_t* base;
uint8_t* cursor;
uint8_t* limit;
JSContext* const context_;
JS::TranscodeBuffer& buffer_;
size_t cursor_;
};
/*
@ -79,48 +64,46 @@ template <XDRMode mode>
class XDRState {
public:
XDRBuffer buf;
TranscodeResult resultCode_;
JS::TranscodeResult resultCode_;
protected:
explicit XDRState(JSContext* cx)
: buf(cx), resultCode_(TranscodeResult_Ok) { }
XDRState(JSContext* cx, JS::TranscodeBuffer& buffer)
: buf(cx, buffer), resultCode_(JS::TranscodeResult_Ok) { }
public:
JSContext* cx() const {
return buf.cx();
}
// Record logical failures of XDR.
void postProcessContextErrors(JSContext* cx);
TranscodeResult resultCode() const {
JS::TranscodeResult resultCode() const {
return resultCode_;
}
bool fail(TranscodeResult code) {
MOZ_ASSERT(resultCode_ == TranscodeResult_Ok);
bool fail(JS::TranscodeResult code) {
MOZ_ASSERT(resultCode_ == JS::TranscodeResult_Ok);
resultCode_ = code;
return false;
}
bool codeUint8(uint8_t* n) {
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(sizeof *n);
uint8_t* ptr = buf.write(sizeof(*n));
if (!ptr)
return false;
*ptr = *n;
} else {
*n = *buf.read(sizeof *n);
*n = *buf.read(sizeof(*n));
}
return true;
}
bool codeUint16(uint16_t* n) {
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(sizeof *n);
uint8_t* ptr = buf.write(sizeof(*n));
if (!ptr)
return false;
mozilla::LittleEndian::writeUint16(ptr, *n);
} else {
const uint8_t* ptr = buf.read(sizeof *n);
const uint8_t* ptr = buf.read(sizeof(*n));
*n = mozilla::LittleEndian::readUint16(ptr);
}
return true;
@ -128,12 +111,12 @@ class XDRState {
bool codeUint32(uint32_t* n) {
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(sizeof *n);
uint8_t* ptr = buf.write(sizeof(*n));
if (!ptr)
return false;
mozilla::LittleEndian::writeUint32(ptr, *n);
} else {
const uint8_t* ptr = buf.read(sizeof *n);
const uint8_t* ptr = buf.read(sizeof(*n));
*n = mozilla::LittleEndian::readUint32(ptr);
}
return true;
@ -185,6 +168,8 @@ class XDRState {
}
bool codeBytes(void* bytes, size_t len) {
if (len == 0)
return true;
if (mode == XDR_ENCODE) {
uint8_t* ptr = buf.write(len);
if (!ptr)
@ -223,32 +208,8 @@ class XDRState {
bool codeConstValue(MutableHandleValue vp);
};
class XDREncoder : public XDRState<XDR_ENCODE> {
public:
explicit XDREncoder(JSContext* cx)
: XDRState<XDR_ENCODE>(cx) {
}
~XDREncoder() {
buf.freeBuffer();
}
const void* getData(uint32_t* lengthp) const {
return buf.getData(lengthp);
}
void* forgetData(uint32_t* lengthp) {
void* data = buf.getData(lengthp);
buf.setData(nullptr, 0);
return data;
}
};
class XDRDecoder : public XDRState<XDR_DECODE> {
public:
XDRDecoder(JSContext* cx, const void* data, uint32_t length);
};
using XDREncoder = XDRState<XDR_ENCODE>;
using XDRDecoder = XDRState<XDR_DECODE>;
} /* namespace js */

Просмотреть файл

@ -5,13 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/scache/StartupCache.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "nsJSPrincipals.h"
#include "mozilla/scache/StartupCache.h"
using namespace JS;
using namespace mozilla::scache;
using mozilla::UniquePtr;
@ -29,14 +29,16 @@ ReadCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
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)
JS::TranscodeBuffer buffer;
buffer.replaceRawBuffer(reinterpret_cast<uint8_t*>(buf.release()), len);
JS::TranscodeResult code = JS::DecodeScript(cx, buffer, scriptp);
if (code == JS::TranscodeResult_Ok)
return NS_OK;
if ((code & TranscodeResult_Failure) != 0)
if ((code & JS::TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
MOZ_ASSERT((code & JS::TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
@ -55,20 +57,22 @@ WriteCachedScript(StartupCache* cache, nsACString& uri, JSContext* cx,
{
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)
JS::TranscodeBuffer buffer;
JS::TranscodeResult code = JS::EncodeScript(cx, buffer, script);
if (code != JS::TranscodeResult_Ok) {
if ((code & JS::TranscodeResult_Failure) != 0)
return NS_ERROR_FAILURE;
MOZ_ASSERT((code & TranscodeResult_Throw) != 0);
MOZ_ASSERT((code & JS::TranscodeResult_Throw) != 0);
JS_ClearPendingException(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
MOZ_ASSERT(size && data);
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(), static_cast<char*>(data), size);
js_free(data);
size_t size = buffer.length();
if (size > UINT32_MAX)
return NS_ERROR_FAILURE;
nsresult rv = cache->PutBuffer(PromiseFlatCString(uri).get(),
reinterpret_cast<char*>(buffer.begin()),
size);
return rv;
}

Просмотреть файл

@ -1090,14 +1090,13 @@ WriteScriptOrFunction(nsIObjectOutputStream* stream, JSContext* cx,
return rv;
uint32_t size;
void* data = nullptr;
TranscodeBuffer buffer;
TranscodeResult code;
{
if (functionObj)
code = JS_EncodeInterpretedFunction(cx, functionObj, &size, &data);
code = EncodeInterpretedFunction(cx, buffer, functionObj);
else
code = JS_EncodeScript(cx, script, &size, &data);
code = EncodeScript(cx, buffer, script);
}
if (code != TranscodeResult_Ok) {
@ -1108,11 +1107,12 @@ WriteScriptOrFunction(nsIObjectOutputStream* stream, JSContext* cx,
return NS_ERROR_OUT_OF_MEMORY;
}
MOZ_ASSERT(size && data);
size_t size = buffer.length();
if (size > UINT32_MAX)
return NS_ERROR_FAILURE;
rv = stream->Write32(size);
if (NS_SUCCEEDED(rv))
rv = stream->WriteBytes(static_cast<char*>(data), size);
js_free(data);
rv = stream->WriteBytes(reinterpret_cast<char*>(buffer.begin()), size);
return rv;
}
@ -1145,16 +1145,19 @@ ReadScriptOrFunction(nsIObjectInputStream* stream, JSContext* cx,
if (NS_FAILED(rv))
return rv;
TranscodeBuffer buffer;
buffer.replaceRawBuffer(reinterpret_cast<uint8_t*>(data), size);
{
TranscodeResult code;
if (scriptp) {
Rooted<JSScript*> script(cx);
code = JS_DecodeScript(cx, data, size, &script);
code = DecodeScript(cx, buffer, &script);
if (code == TranscodeResult_Ok)
*scriptp = script.get();
} else {
Rooted<JSFunction*> funobj(cx);
code = JS_DecodeInterpretedFunction(cx, data, size, &funobj);
code = DecodeInterpretedFunction(cx, buffer, &funobj);
if (code == TranscodeResult_Ok)
*functionObjp = JS_GetFunctionObject(funobj.get());
}
@ -1168,7 +1171,6 @@ ReadScriptOrFunction(nsIObjectInputStream* stream, JSContext* cx,
}
}
free(data);
return rv;
}