зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1419094 - Result-ify XDR functions. r=tcampbell
This commit is contained in:
Родитель
51b99ad845
Коммит
e2b13d6466
|
@ -7617,10 +7617,13 @@ JS::EncodeScript(JSContext* cx, TranscodeBuffer& buffer, HandleScript scriptArg)
|
|||
{
|
||||
XDREncoder encoder(cx, buffer, buffer.length());
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (!encoder.codeScript(&script))
|
||||
XDRResult res = encoder.codeScript(&script);
|
||||
if (res.isErr()) {
|
||||
buffer.clearAndFree();
|
||||
MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
|
||||
return encoder.resultCode();
|
||||
return res.unwrapErr();
|
||||
}
|
||||
MOZ_ASSERT(!buffer.empty());
|
||||
return JS::TranscodeResult_Ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::TranscodeResult)
|
||||
|
@ -7628,10 +7631,13 @@ JS::EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, HandleObje
|
|||
{
|
||||
XDREncoder encoder(cx, buffer, buffer.length());
|
||||
RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
|
||||
if (!encoder.codeFunction(&funobj))
|
||||
XDRResult res = encoder.codeFunction(&funobj);
|
||||
if (res.isErr()) {
|
||||
buffer.clearAndFree();
|
||||
MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
|
||||
return encoder.resultCode();
|
||||
return res.unwrapErr();
|
||||
}
|
||||
MOZ_ASSERT(!buffer.empty());
|
||||
return JS::TranscodeResult_Ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::TranscodeResult)
|
||||
|
@ -7639,18 +7645,22 @@ JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript
|
|||
size_t cursorIndex)
|
||||
{
|
||||
XDRDecoder decoder(cx, buffer, cursorIndex);
|
||||
decoder.codeScript(scriptp);
|
||||
MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
|
||||
return decoder.resultCode();
|
||||
XDRResult res = decoder.codeScript(scriptp);
|
||||
MOZ_ASSERT(bool(scriptp) == res.isOk());
|
||||
if (res.isErr())
|
||||
return res.unwrapErr();
|
||||
return JS::TranscodeResult_Ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::TranscodeResult)
|
||||
JS::DecodeScript(JSContext* cx, const TranscodeRange& range, JS::MutableHandleScript scriptp)
|
||||
{
|
||||
XDRDecoder decoder(cx, range);
|
||||
decoder.codeScript(scriptp);
|
||||
MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
|
||||
return decoder.resultCode();
|
||||
XDRResult res = decoder.codeScript(scriptp);
|
||||
MOZ_ASSERT(bool(scriptp) == res.isOk());
|
||||
if (res.isErr())
|
||||
return res.unwrapErr();
|
||||
return JS::TranscodeResult_Ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::TranscodeResult)
|
||||
|
@ -7659,9 +7669,11 @@ JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer,
|
|||
size_t cursorIndex)
|
||||
{
|
||||
XDRDecoder decoder(cx, buffer, cursorIndex);
|
||||
decoder.codeFunction(funp);
|
||||
MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok));
|
||||
return decoder.resultCode();
|
||||
XDRResult res = decoder.codeFunction(funp);
|
||||
MOZ_ASSERT(bool(funp) == res.isOk());
|
||||
if (res.isErr())
|
||||
return res.unwrapErr();
|
||||
return JS::TranscodeResult_Ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
@ -6049,13 +6049,13 @@ struct TranscodeSource
|
|||
|
||||
typedef mozilla::Vector<JS::TranscodeSource> TranscodeSources;
|
||||
|
||||
enum TranscodeResult
|
||||
enum TranscodeResult: uint8_t
|
||||
{
|
||||
// Successful encoding / decoding.
|
||||
TranscodeResult_Ok = 0,
|
||||
|
||||
// A warning message, is set to the message out-param.
|
||||
TranscodeResult_Failure = 0x100,
|
||||
TranscodeResult_Failure = 0x10,
|
||||
TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
|
||||
TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
|
||||
TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
|
||||
|
@ -6064,7 +6064,7 @@ enum TranscodeResult
|
|||
TranscodeResult_Failure_NotInterpretedFun = TranscodeResult_Failure | 0x6,
|
||||
|
||||
// There is a pending exception on the context.
|
||||
TranscodeResult_Throw = 0x200
|
||||
TranscodeResult_Throw = 0x20
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(TranscodeResult)
|
||||
|
|
|
@ -515,9 +515,9 @@ ScriptDecodeTask::parse(JSContext* cx)
|
|||
|
||||
XDROffThreadDecoder decoder(cx, alloc, &options, /* sourceObjectOut = */ &sourceObject.get(),
|
||||
range);
|
||||
decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == (decoder.resultCode() == JS::TranscodeResult_Ok));
|
||||
if (decoder.resultCode() == JS::TranscodeResult_Ok) {
|
||||
XDRResult res = decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == res.isOk());
|
||||
if (res.isOk()) {
|
||||
scripts.infallibleAppend(resultScript);
|
||||
if (sourceObject)
|
||||
sourceObjects.infallibleAppend(sourceObject);
|
||||
|
@ -548,10 +548,10 @@ MultiScriptsDecodeTask::parse(JSContext* cx)
|
|||
Rooted<ScriptSourceObject*> sourceObject(cx);
|
||||
|
||||
XDROffThreadDecoder decoder(cx, alloc, &opts, &sourceObject.get(), source.range);
|
||||
decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == (decoder.resultCode() == JS::TranscodeResult_Ok));
|
||||
XDRResult res = decoder.codeScript(&resultScript);
|
||||
MOZ_ASSERT(bool(resultScript) == res.isOk());
|
||||
|
||||
if (decoder.resultCode() != JS::TranscodeResult_Ok)
|
||||
if (res.isErr())
|
||||
break;
|
||||
MOZ_ASSERT(resultScript);
|
||||
scripts.infallibleAppend(resultScript);
|
||||
|
|
|
@ -709,7 +709,7 @@ template JSAtom*
|
|||
js::ToAtom<NoGC>(JSContext* cx, const Value& v);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
||||
{
|
||||
bool latin1 = false;
|
||||
|
@ -722,8 +722,7 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
lengthAndEncoding = (length << 1) | uint32_t(latin1);
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&lengthAndEncoding))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&lengthAndEncoding));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
length = lengthAndEncoding >> 1;
|
||||
|
@ -732,8 +731,8 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
|
||||
// We need to align the string in the XDR buffer such that we can avoid
|
||||
// non-align loads of 16bits characters.
|
||||
if (!latin1 && !xdr->codeAlign(sizeof(char16_t)))
|
||||
return false;
|
||||
if (!latin1)
|
||||
MOZ_TRY(xdr->codeAlign(sizeof(char16_t)));
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
@ -751,8 +750,7 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
if (length) {
|
||||
const uint8_t *ptr;
|
||||
size_t nbyte = length * sizeof(Latin1Char);
|
||||
if (!xdr->peekData(&ptr, nbyte))
|
||||
return false;
|
||||
MOZ_TRY(xdr->peekData(&ptr, nbyte));
|
||||
chars = reinterpret_cast<const Latin1Char*>(ptr);
|
||||
}
|
||||
atom = AtomizeChars(cx, chars, length);
|
||||
|
@ -763,8 +761,7 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
if (length) {
|
||||
const uint8_t *ptr;
|
||||
size_t nbyte = length * sizeof(char16_t);
|
||||
if (!xdr->peekData(&ptr, nbyte))
|
||||
return false;
|
||||
MOZ_TRY(xdr->peekData(&ptr, nbyte));
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(char16_t) == 0,
|
||||
"non-aligned buffer during JSAtom decoding");
|
||||
chars = reinterpret_cast<const char16_t*>(ptr);
|
||||
|
@ -787,7 +784,7 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
*/
|
||||
chars = cx->pod_malloc<char16_t>(length);
|
||||
if (!chars)
|
||||
return false;
|
||||
return fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
JS_ALWAYS_TRUE(xdr->codeChars(chars, length));
|
||||
|
@ -798,15 +795,15 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp)
|
|||
}
|
||||
|
||||
if (!atom)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
atomp.set(atom);
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRAtom(XDRState<XDR_ENCODE>* xdr, MutableHandleAtom atomp);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRAtom(XDRState<XDR_DECODE>* xdr, MutableHandleAtom atomp);
|
||||
|
||||
Handle<PropertyName*>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "gc/Rooting.h"
|
||||
#include "js/Result.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "vm/CommonPropertyNames.h"
|
||||
|
||||
|
@ -53,6 +54,10 @@ extern const char js_getter_str[];
|
|||
extern const char js_send_str[];
|
||||
extern const char js_setter_str[];
|
||||
|
||||
namespace JS {
|
||||
enum TranscodeResult : uint8_t;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoLockForExclusiveAccess;
|
||||
|
@ -104,8 +109,10 @@ enum XDRMode {
|
|||
template <XDRMode mode>
|
||||
class XDRState;
|
||||
|
||||
using XDRResult = mozilla::Result<mozilla::Ok, JS::TranscodeResult>;
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRAtom(XDRState<mode>* xdr, js::MutableHandleAtom atomp);
|
||||
|
||||
extern JS::Handle<PropertyName*>
|
||||
|
|
|
@ -564,7 +564,7 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
|
||||
HandleScriptSource sourceObject, MutableHandleFunction objp)
|
||||
{
|
||||
|
@ -622,24 +622,21 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
|
||||
// Everything added below can substituted by the non-lazy-script version of
|
||||
// this function later.
|
||||
if (!xdr->codeAlign(sizeof(js::XDRAlignment)))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeAlign(sizeof(js::XDRAlignment)));
|
||||
js::AutoXDRTree funTree(xdr, xdr->getTreeKey(fun));
|
||||
|
||||
if (!xdr->codeUint32(&firstword))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&firstword));
|
||||
|
||||
if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&flagsword))
|
||||
return false;
|
||||
if (firstword & HasAtom)
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
MOZ_TRY(xdr->codeUint32(&flagsword));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
RootedObject proto(cx);
|
||||
if (firstword & HasGeneratorProto) {
|
||||
proto = GlobalObject::getOrCreateGeneratorFunctionPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
|
||||
|
@ -649,17 +646,14 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
/* enclosingDynamicScope = */ nullptr, nullptr, proto,
|
||||
allocKind, TenuredObject);
|
||||
if (!fun)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
script = nullptr;
|
||||
}
|
||||
|
||||
if (firstword & IsLazy) {
|
||||
if (!XDRLazyScript(xdr, enclosingScope, sourceObject, fun, &lazy))
|
||||
return false;
|
||||
} else {
|
||||
if (!XDRScript(xdr, enclosingScope, sourceObject, fun, &script))
|
||||
return false;
|
||||
}
|
||||
if (firstword & IsLazy)
|
||||
MOZ_TRY(XDRLazyScript(xdr, enclosingScope, sourceObject, fun, &lazy));
|
||||
else
|
||||
MOZ_TRY(XDRScript(xdr, enclosingScope, sourceObject, fun, &script));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
fun->setArgCount(flagsword >> 16);
|
||||
|
@ -674,27 +668,25 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
|
||||
bool singleton = firstword & HasSingletonType;
|
||||
if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
objp.set(fun);
|
||||
}
|
||||
|
||||
// Verify marker at end of function to detect buffer trunction.
|
||||
if (!xdr->codeMarker(0x9E35CA1F))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeMarker(0x9E35CA1F));
|
||||
|
||||
// Required by AutoXDRTree to copy & paste snipet of sub-trees while keeping
|
||||
// the alignment.
|
||||
if (!xdr->codeAlign(sizeof(js::XDRAlignment)))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeAlign(sizeof(js::XDRAlignment)));
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRInterpretedFunction(XDRState<XDR_ENCODE>*, HandleScope, HandleScriptSource,
|
||||
MutableHandleFunction);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRInterpretedFunction(XDRState<XDR_DECODE>*, HandleScope, HandleScriptSource,
|
||||
MutableHandleFunction);
|
||||
|
||||
|
|
|
@ -950,7 +950,7 @@ namespace js {
|
|||
JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
|
||||
HandleScriptSource sourceObject, MutableHandleFunction objp);
|
||||
|
||||
|
|
|
@ -1397,7 +1397,7 @@ JS_InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
||||
{
|
||||
/* NB: Keep this in sync with DeepCloneObjectLiteral. */
|
||||
|
@ -1415,8 +1415,7 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
isArray = obj->is<ArrayObject>() ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&isArray))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&isArray));
|
||||
}
|
||||
|
||||
RootedValue tmpValue(cx), tmpIdValue(cx);
|
||||
|
@ -1427,29 +1426,26 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
if (mode == XDR_ENCODE) {
|
||||
RootedArrayObject arr(cx, &obj->as<ArrayObject>());
|
||||
if (!GetScriptArrayObjectElements(arr, &values))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
uint32_t initialized;
|
||||
if (mode == XDR_ENCODE)
|
||||
initialized = values.length();
|
||||
if (!xdr->codeUint32(&initialized))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&initialized));
|
||||
if (mode == XDR_DECODE && !values.appendN(MagicValue(JS_ELEMENTS_HOLE), initialized))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
// Recursively copy dense elements.
|
||||
for (unsigned i = 0; i < initialized; i++) {
|
||||
if (!xdr->codeConstValue(values[i]))
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; i < initialized; i++)
|
||||
MOZ_TRY(xdr->codeConstValue(values[i]));
|
||||
|
||||
uint32_t copyOnWrite;
|
||||
if (mode == XDR_ENCODE)
|
||||
if (mode == XDR_ENCODE) {
|
||||
copyOnWrite = obj->is<ArrayObject>() &&
|
||||
obj->as<ArrayObject>().denseElementsAreCopyOnWrite();
|
||||
if (!xdr->codeUint32(©OnWrite))
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(xdr->codeUint32(©OnWrite));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
ObjectGroup::NewArrayKind arrayKind = copyOnWrite
|
||||
|
@ -1458,23 +1454,22 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
obj.set(ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
|
||||
TenuredObject, arrayKind));
|
||||
if (!obj)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// Code the properties in the object.
|
||||
Rooted<IdValueVector> properties(cx, IdValueVector(cx));
|
||||
if (mode == XDR_ENCODE && !GetScriptPlainObjectProperties(obj, &properties))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
uint32_t nproperties = properties.length();
|
||||
if (!xdr->codeUint32(&nproperties))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&nproperties));
|
||||
|
||||
if (mode == XDR_DECODE && !properties.appendN(IdValuePair(), nproperties))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
for (size_t i = 0; i < nproperties; i++) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
|
@ -1482,12 +1477,12 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
tmpValue = properties[i].get().value;
|
||||
}
|
||||
|
||||
if (!xdr->codeConstValue(&tmpIdValue) || !xdr->codeConstValue(&tmpValue))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeConstValue(&tmpIdValue));
|
||||
MOZ_TRY(xdr->codeConstValue(&tmpValue));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!ValueToId<CanGC>(cx, tmpIdValue, &tmpId))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
properties[i].get().id = tmpId;
|
||||
properties[i].get().value = tmpValue;
|
||||
}
|
||||
|
@ -1497,23 +1492,22 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
uint32_t isSingleton;
|
||||
if (mode == XDR_ENCODE)
|
||||
isSingleton = obj->isSingleton() ? 1 : 0;
|
||||
if (!xdr->codeUint32(&isSingleton))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&isSingleton));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
NewObjectKind newKind = isSingleton ? SingletonObject : TenuredObject;
|
||||
obj.set(ObjectGroup::newPlainObject(cx, properties.begin(), properties.length(), newKind));
|
||||
if (!obj)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRObjectLiteral(XDRState<XDR_ENCODE>* xdr, MutableHandleObject obj);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRObjectLiteral(XDRState<XDR_DECODE>* xdr, MutableHandleObject obj);
|
||||
|
||||
/* static */ bool
|
||||
|
|
|
@ -1253,7 +1253,7 @@ ToObjectFromStack(JSContext* cx, HandleValue vp)
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
|
||||
|
||||
/*
|
||||
|
|
|
@ -85,7 +85,7 @@ CheckScriptDataIntegrity(JSScript* script)
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
|
@ -126,16 +126,14 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
}
|
||||
}
|
||||
|
||||
if (!xdr->codeEnum32(&tag))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeEnum32(&tag));
|
||||
|
||||
switch (tag) {
|
||||
case SCRIPT_INT: {
|
||||
uint32_t i;
|
||||
if (mode == XDR_ENCODE)
|
||||
i = uint32_t(vp.toInt32());
|
||||
if (!xdr->codeUint32(&i))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&i));
|
||||
if (mode == XDR_DECODE)
|
||||
vp.set(Int32Value(int32_t(i)));
|
||||
break;
|
||||
|
@ -144,8 +142,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
double d;
|
||||
if (mode == XDR_ENCODE)
|
||||
d = vp.toDouble();
|
||||
if (!xdr->codeDouble(&d))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeDouble(&d));
|
||||
if (mode == XDR_DECODE)
|
||||
vp.set(DoubleValue(d));
|
||||
break;
|
||||
|
@ -154,8 +151,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
RootedAtom atom(cx);
|
||||
if (mode == XDR_ENCODE)
|
||||
atom = &vp.toString()->asAtom();
|
||||
if (!XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
if (mode == XDR_DECODE)
|
||||
vp.set(StringValue(atom));
|
||||
break;
|
||||
|
@ -177,8 +173,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
if (mode == XDR_ENCODE)
|
||||
obj = &vp.toObject();
|
||||
|
||||
if (!XDRObjectLiteral(xdr, &obj))
|
||||
return false;
|
||||
MOZ_TRY(XDRObjectLiteral(xdr, &obj));
|
||||
|
||||
if (mode == XDR_DECODE)
|
||||
vp.setObject(*obj);
|
||||
|
@ -197,18 +192,18 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
|
|||
MOZ_ASSERT(false, "Bad XDR value kind");
|
||||
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScriptConst(XDRState<XDR_ENCODE>*, MutableHandleValue);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScriptConst(XDRState<XDR_DECODE>*, MutableHandleValue);
|
||||
|
||||
// Code LazyScript's closed over bindings.
|
||||
template<XDRMode mode>
|
||||
static bool
|
||||
static XDRResult
|
||||
XDRLazyClosedOverBindings(XDRState<mode>* xdr, MutableHandle<LazyScript*> lazy)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
|
@ -220,24 +215,23 @@ XDRLazyClosedOverBindings(XDRState<mode>* xdr, MutableHandle<LazyScript*> lazy)
|
|||
endOfScopeSentinel = !atom;
|
||||
}
|
||||
|
||||
if (!xdr->codeUint8(&endOfScopeSentinel))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&endOfScopeSentinel));
|
||||
|
||||
if (endOfScopeSentinel)
|
||||
atom = nullptr;
|
||||
else if (!XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
else
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
|
||||
if (mode == XDR_DECODE)
|
||||
lazy->closedOverBindings()[i] = atom;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// Code the missing part needed to re-create a LazyScript from a JSScript.
|
||||
template<XDRMode mode>
|
||||
static bool
|
||||
static XDRResult
|
||||
XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript script,
|
||||
HandleScope enclosingScope, MutableHandle<LazyScript*> lazy)
|
||||
{
|
||||
|
@ -269,15 +263,14 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
|||
MOZ_ASSERT(lazy->numInnerFunctions() == 0);
|
||||
}
|
||||
|
||||
if (!xdr->codeUint64(&packedFields))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint64(&packedFields));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
RootedScriptSource sourceObject(cx, &script->scriptSourceUnwrap());
|
||||
lazy.set(LazyScript::Create(cx, fun, script, enclosingScope, sourceObject,
|
||||
packedFields, begin, end, toStringStart, lineno, column));
|
||||
if (!lazy)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
lazy->setToStringEnd(toStringEnd);
|
||||
|
||||
|
@ -289,13 +282,12 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
|||
}
|
||||
|
||||
// Code binding names.
|
||||
if (!XDRLazyClosedOverBindings(xdr, lazy))
|
||||
return false;
|
||||
MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
|
||||
|
||||
// No need to do anything with inner functions, since we asserted we don't
|
||||
// have any.
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
|
@ -319,7 +311,7 @@ enum XDRClassKind {
|
|||
};
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
||||
HandleScriptSource sourceObjectArg, HandleFunction fun,
|
||||
MutableHandleScript scriptp)
|
||||
|
@ -391,8 +383,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
|
||||
if (mode == XDR_ENCODE)
|
||||
length = script->length();
|
||||
if (!xdr->codeUint32(&length))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&length));
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
prologueLength = script->mainOffset();
|
||||
|
@ -474,32 +465,20 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
scriptBits |= (1 << IsDefaultClassConstructor);
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&prologueLength))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&prologueLength));
|
||||
|
||||
// To fuse allocations, we need lengths of all embedded arrays early.
|
||||
if (!xdr->codeUint32(&natoms))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nsrcnotes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nconsts))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nobjects))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nscopes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&ntrynotes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nscopenotes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nyieldoffsets))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nTypeSets))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&funLength))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&scriptBits))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&natoms));
|
||||
MOZ_TRY(xdr->codeUint32(&nsrcnotes));
|
||||
MOZ_TRY(xdr->codeUint32(&nconsts));
|
||||
MOZ_TRY(xdr->codeUint32(&nobjects));
|
||||
MOZ_TRY(xdr->codeUint32(&nscopes));
|
||||
MOZ_TRY(xdr->codeUint32(&ntrynotes));
|
||||
MOZ_TRY(xdr->codeUint32(&nscopenotes));
|
||||
MOZ_TRY(xdr->codeUint32(&nyieldoffsets));
|
||||
MOZ_TRY(xdr->codeUint32(&nTypeSets));
|
||||
MOZ_TRY(xdr->codeUint32(&funLength));
|
||||
MOZ_TRY(xdr->codeUint32(&scriptBits));
|
||||
|
||||
MOZ_ASSERT(!!(scriptBits & (1 << OwnSource)) == !sourceObjectArg);
|
||||
RootedScriptSource sourceObject(cx, sourceObjectArg);
|
||||
|
@ -526,7 +505,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
if (scriptBits & (1 << OwnSource)) {
|
||||
ScriptSource* ss = cx->new_<ScriptSource>();
|
||||
if (!ss)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
ScriptSourceHolder ssHolder(ss);
|
||||
|
||||
/*
|
||||
|
@ -536,24 +515,24 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
* aren't preserved by XDR. So this can be simple.
|
||||
*/
|
||||
if (!ss->initFromOptions(cx, *options))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
sourceObject = ScriptSourceObject::create(cx, ss);
|
||||
if (!sourceObject)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
if (xdr->hasScriptSourceObjectOut()) {
|
||||
// When the ScriptSourceObjectOut is provided by ParseTask, it
|
||||
// is stored in a location which is traced by the GC.
|
||||
*xdr->scriptSourceObjectOut() = sourceObject;
|
||||
} else if (!ScriptSourceObject::initFromOptions(cx, sourceObject, *options)) {
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
}
|
||||
|
||||
script = JSScript::Create(cx, *options, sourceObject, 0, 0, 0, 0);
|
||||
if (!script)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
// Set the script in its function now so that inner scripts to be
|
||||
// decoded may iterate the static scope chain.
|
||||
|
@ -569,7 +548,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
if (!JSScript::partiallyInit(cx, script, nscopes, nconsts, nobjects, ntrynotes,
|
||||
nscopenotes, nyieldoffsets, nTypeSets))
|
||||
{
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!script->mainOffset());
|
||||
|
@ -625,29 +604,17 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
|
||||
JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
|
||||
|
||||
if (scriptBits & (1 << OwnSource)) {
|
||||
if (!sourceObject->source()->performXDR<mode>(xdr))
|
||||
return false;
|
||||
}
|
||||
if (!xdr->codeUint32(&script->sourceStart_))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&script->sourceEnd_))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&script->toStringStart_))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&script->toStringEnd_))
|
||||
return false;
|
||||
|
||||
if (!xdr->codeUint32(&lineno) ||
|
||||
!xdr->codeUint32(&column) ||
|
||||
!xdr->codeUint32(&nfixed) ||
|
||||
!xdr->codeUint32(&nslots))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&bodyScopeIndex))
|
||||
return false;
|
||||
if (scriptBits & (1 << OwnSource))
|
||||
MOZ_TRY(sourceObject->source()->performXDR<mode>(xdr));
|
||||
MOZ_TRY(xdr->codeUint32(&script->sourceStart_));
|
||||
MOZ_TRY(xdr->codeUint32(&script->sourceEnd_));
|
||||
MOZ_TRY(xdr->codeUint32(&script->toStringStart_));
|
||||
MOZ_TRY(xdr->codeUint32(&script->toStringEnd_));
|
||||
MOZ_TRY(xdr->codeUint32(&lineno));
|
||||
MOZ_TRY(xdr->codeUint32(&column));
|
||||
MOZ_TRY(xdr->codeUint32(&nfixed));
|
||||
MOZ_TRY(xdr->codeUint32(&nslots));
|
||||
MOZ_TRY(xdr->codeUint32(&bodyScopeIndex));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
script->lineno_ = lineno;
|
||||
|
@ -658,9 +625,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
}
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!script->createScriptData(cx, length, nsrcnotes, natoms)) {
|
||||
return false;
|
||||
}
|
||||
if (!script->createScriptData(cx, length, nsrcnotes, natoms))
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
auto scriptDataGuard = mozilla::MakeScopeExit([&] {
|
||||
|
@ -669,27 +635,24 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
});
|
||||
|
||||
jsbytecode* code = script->code();
|
||||
if (!xdr->codeBytes(code, length) || !xdr->codeBytes(code + length, nsrcnotes)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(xdr->codeBytes(code, length));
|
||||
MOZ_TRY(xdr->codeBytes(code + length, nsrcnotes));
|
||||
|
||||
for (i = 0; i != natoms; ++i) {
|
||||
if (mode == XDR_DECODE) {
|
||||
RootedAtom tmp(cx);
|
||||
if (!XDRAtom(xdr, &tmp))
|
||||
return false;
|
||||
MOZ_TRY(XDRAtom(xdr, &tmp));
|
||||
script->atoms()[i].init(tmp);
|
||||
} else {
|
||||
RootedAtom tmp(cx, script->atoms()[i]);
|
||||
if (!XDRAtom(xdr, &tmp))
|
||||
return false;
|
||||
MOZ_TRY(XDRAtom(xdr, &tmp));
|
||||
}
|
||||
}
|
||||
|
||||
scriptDataGuard.release();
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!script->shareScriptData(cx))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
if (nconsts) {
|
||||
|
@ -698,8 +661,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
for (i = 0; i != nconsts; ++i) {
|
||||
if (mode == XDR_ENCODE)
|
||||
val = vector[i];
|
||||
if (!XDRScriptConst(xdr, &val))
|
||||
return false;
|
||||
MOZ_TRY(XDRScriptConst(xdr, &val));
|
||||
if (mode == XDR_DECODE)
|
||||
vector[i].init(val);
|
||||
}
|
||||
|
@ -720,8 +682,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
scope = nullptr;
|
||||
}
|
||||
|
||||
if (!xdr->codeEnum32(&scopeKind))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeEnum32(&scopeKind));
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
if (i == 0) {
|
||||
|
@ -732,8 +693,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
}
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&enclosingScopeIndex))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&enclosingScopeIndex));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (i == 0) {
|
||||
|
@ -748,38 +708,33 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
switch (scopeKind) {
|
||||
case ScopeKind::Function:
|
||||
MOZ_ASSERT(i == script->bodyScopeIndex());
|
||||
if (!FunctionScope::XDR(xdr, fun, enclosing, &scope))
|
||||
return false;
|
||||
MOZ_TRY(FunctionScope::XDR(xdr, fun, enclosing, &scope));
|
||||
break;
|
||||
case ScopeKind::FunctionBodyVar:
|
||||
case ScopeKind::ParameterExpressionVar:
|
||||
if (!VarScope::XDR(xdr, scopeKind, enclosing, &scope))
|
||||
return false;
|
||||
MOZ_TRY(VarScope::XDR(xdr, scopeKind, enclosing, &scope));
|
||||
break;
|
||||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
if (!LexicalScope::XDR(xdr, scopeKind, enclosing, &scope))
|
||||
return false;
|
||||
MOZ_TRY(LexicalScope::XDR(xdr, scopeKind, enclosing, &scope));
|
||||
break;
|
||||
case ScopeKind::With:
|
||||
if (mode == XDR_DECODE) {
|
||||
scope = WithScope::create(cx, enclosing);
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
break;
|
||||
case ScopeKind::Eval:
|
||||
case ScopeKind::StrictEval:
|
||||
if (!EvalScope::XDR(xdr, scopeKind, enclosing, &scope))
|
||||
return false;
|
||||
MOZ_TRY(EvalScope::XDR(xdr, scopeKind, enclosing, &scope));
|
||||
break;
|
||||
case ScopeKind::Global:
|
||||
case ScopeKind::NonSyntactic:
|
||||
if (!GlobalScope::XDR(xdr, scopeKind, &scope))
|
||||
return false;
|
||||
MOZ_TRY(GlobalScope::XDR(xdr, scopeKind, &scope));
|
||||
break;
|
||||
case ScopeKind::Module:
|
||||
case ScopeKind::WasmInstance:
|
||||
|
@ -800,8 +755,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
|
||||
// Verify marker to detect data corruption after decoding scope data. A
|
||||
// mismatch here indicates we will almost certainly crash in release.
|
||||
if (!xdr->codeMarker(0x48922BAB))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeMarker(0x48922BAB));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -825,16 +779,14 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
MOZ_CRASH("Cannot encode this class of object.");
|
||||
}
|
||||
|
||||
if (!xdr->codeEnum32(&classk))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeEnum32(&classk));
|
||||
|
||||
switch (classk) {
|
||||
case CK_RegexpObject: {
|
||||
Rooted<RegExpObject*> regexp(cx);
|
||||
if (mode == XDR_ENCODE)
|
||||
regexp = &(*objp)->as<RegExpObject>();
|
||||
if (!XDRScriptRegExpObject(xdr, ®exp))
|
||||
return false;
|
||||
MOZ_TRY(XDRScriptRegExpObject(xdr, ®exp));
|
||||
if (mode == XDR_DECODE)
|
||||
*objp = regexp;
|
||||
break;
|
||||
|
@ -859,8 +811,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
funEnclosingScopeIndex = FindScopeIndex(script, *funEnclosingScope);
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&funEnclosingScopeIndex))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&funEnclosingScopeIndex));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
MOZ_ASSERT(funEnclosingScopeIndex < script->scopes()->length);
|
||||
|
@ -871,8 +822,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
RootedFunction tmp(cx);
|
||||
if (mode == XDR_ENCODE)
|
||||
tmp = &(*objp)->as<JSFunction>();
|
||||
if (!XDRInterpretedFunction(xdr, funEnclosingScope, sourceObject, &tmp))
|
||||
return false;
|
||||
MOZ_TRY(XDRInterpretedFunction(xdr, funEnclosingScope, sourceObject, &tmp));
|
||||
*objp = tmp;
|
||||
break;
|
||||
}
|
||||
|
@ -880,8 +830,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
case CK_JSObject: {
|
||||
/* Code object literal. */
|
||||
RootedObject tmp(cx, *objp);
|
||||
if (!XDRObjectLiteral(xdr, &tmp))
|
||||
return false;
|
||||
MOZ_TRY(XDRObjectLiteral(xdr, &tmp));
|
||||
*objp = tmp;
|
||||
break;
|
||||
}
|
||||
|
@ -896,8 +845,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
|
||||
// Verify marker to detect data corruption after decoding object data. A
|
||||
// mismatch here indicates we will almost certainly crash in release.
|
||||
if (!xdr->codeMarker(0xF83B989A))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeMarker(0xF83B989A));
|
||||
|
||||
if (ntrynotes != 0) {
|
||||
JSTryNote* tnfirst = script->trynotes()->vector;
|
||||
|
@ -905,30 +853,24 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
JSTryNote* tn = tnfirst + ntrynotes;
|
||||
do {
|
||||
--tn;
|
||||
if (!xdr->codeUint8(&tn->kind) ||
|
||||
!xdr->codeUint32(&tn->stackDepth) ||
|
||||
!xdr->codeUint32(&tn->start) ||
|
||||
!xdr->codeUint32(&tn->length)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(xdr->codeUint8(&tn->kind));
|
||||
MOZ_TRY(xdr->codeUint32(&tn->stackDepth));
|
||||
MOZ_TRY(xdr->codeUint32(&tn->start));
|
||||
MOZ_TRY(xdr->codeUint32(&tn->length));
|
||||
} while (tn != tnfirst);
|
||||
}
|
||||
|
||||
for (i = 0; i < nscopenotes; ++i) {
|
||||
ScopeNote* note = &script->scopeNotes()->vector[i];
|
||||
if (!xdr->codeUint32(¬e->index) ||
|
||||
!xdr->codeUint32(¬e->start) ||
|
||||
!xdr->codeUint32(¬e->length) ||
|
||||
!xdr->codeUint32(¬e->parent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(xdr->codeUint32(¬e->index));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->start));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->length));
|
||||
MOZ_TRY(xdr->codeUint32(¬e->parent));
|
||||
}
|
||||
|
||||
for (i = 0; i < nyieldoffsets; ++i) {
|
||||
uint32_t* offset = &script->yieldAndAwaitOffsets()[i];
|
||||
if (!xdr->codeUint32(offset))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(offset));
|
||||
}
|
||||
|
||||
if (scriptBits & (1 << HasLazyScript)) {
|
||||
|
@ -936,8 +878,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
if (mode == XDR_ENCODE)
|
||||
lazy = script->maybeLazyScript();
|
||||
|
||||
if (!XDRRelazificationInfo(xdr, fun, script, scriptEnclosingScope, &lazy))
|
||||
return false;
|
||||
MOZ_TRY(XDRRelazificationInfo(xdr, fun, script, scriptEnclosingScope, &lazy));
|
||||
|
||||
if (mode == XDR_DECODE)
|
||||
script->setLazyScript(lazy);
|
||||
|
@ -953,19 +894,19 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope,
|
|||
Debugger::onNewScript(cx, script);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScript(XDRState<XDR_ENCODE>*, HandleScope, HandleScriptSource, HandleFunction,
|
||||
MutableHandleScript);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScript(XDRState<XDR_DECODE>*, HandleScope, HandleScriptSource, HandleFunction,
|
||||
MutableHandleScript);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
||||
HandleScriptSource sourceObject, HandleFunction fun,
|
||||
MutableHandle<LazyScript*> lazy)
|
||||
|
@ -997,28 +938,26 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
packedFields = lazy->packedFields();
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&begin) || !xdr->codeUint32(&end) ||
|
||||
!xdr->codeUint32(&toStringStart) ||
|
||||
!xdr->codeUint32(&toStringEnd) ||
|
||||
!xdr->codeUint32(&lineno) || !xdr->codeUint32(&column) ||
|
||||
!xdr->codeUint64(&packedFields))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(xdr->codeUint32(&begin));
|
||||
MOZ_TRY(xdr->codeUint32(&end));
|
||||
MOZ_TRY(xdr->codeUint32(&toStringStart));
|
||||
MOZ_TRY(xdr->codeUint32(&toStringEnd));
|
||||
MOZ_TRY(xdr->codeUint32(&lineno));
|
||||
MOZ_TRY(xdr->codeUint32(&column));
|
||||
MOZ_TRY(xdr->codeUint64(&packedFields));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, sourceObject,
|
||||
packedFields, begin, end, toStringStart, lineno, column));
|
||||
if (!lazy)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
lazy->setToStringEnd(toStringEnd);
|
||||
fun->initLazyScript(lazy);
|
||||
}
|
||||
}
|
||||
|
||||
// Code closed-over bindings.
|
||||
if (!XDRLazyClosedOverBindings(xdr, lazy))
|
||||
return false;
|
||||
MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
|
||||
|
||||
// Code inner functions.
|
||||
{
|
||||
|
@ -1029,22 +968,21 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
if (mode == XDR_ENCODE)
|
||||
func = innerFunctions[i];
|
||||
|
||||
if (!XDRInterpretedFunction(xdr, nullptr, nullptr, &func))
|
||||
return false;
|
||||
MOZ_TRY(XDRInterpretedFunction(xdr, nullptr, nullptr, &func));
|
||||
|
||||
if (mode == XDR_DECODE)
|
||||
innerFunctions[i] = func;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRLazyScript(XDRState<XDR_ENCODE>*, HandleScope, HandleScriptSource,
|
||||
HandleFunction, MutableHandle<LazyScript*>);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRLazyScript(XDRState<XDR_DECODE>*, HandleScope, HandleScriptSource,
|
||||
HandleFunction, MutableHandle<LazyScript*>);
|
||||
|
||||
|
@ -2103,10 +2041,11 @@ ScriptSource::xdrEncodeTopLevel(JSContext* cx, HandleScript script)
|
|||
}
|
||||
|
||||
RootedScript s(cx, script);
|
||||
if (!xdrEncoder_->codeScript(&s)) {
|
||||
XDRResult res = xdrEncoder_->codeScript(&s);
|
||||
if (res.isErr()) {
|
||||
// On encoding failure, let failureCase destroy encoder and return true
|
||||
// to avoid failing any currently executing script.
|
||||
if (xdrEncoder_->resultCode() & JS::TranscodeResult_Failure)
|
||||
if (res.unwrapErr() & JS::TranscodeResult_Failure)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -2126,12 +2065,12 @@ ScriptSource::xdrEncodeFunction(JSContext* cx, HandleFunction fun, HandleScriptS
|
|||
});
|
||||
|
||||
RootedFunction f(cx, fun);
|
||||
if (!xdrEncoder_->codeFunction(&f, sourceObject)) {
|
||||
XDRResult res = xdrEncoder_->codeFunction(&f, sourceObject);
|
||||
if (res.isErr()) {
|
||||
// On encoding failure, let failureCase destroy encoder and return true
|
||||
// to avoid failing any currently executing script.
|
||||
if (xdrEncoder_->resultCode() & JS::TranscodeResult_Failure)
|
||||
if (res.unwrapErr() & JS::TranscodeResult_Failure)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2149,13 +2088,12 @@ ScriptSource::xdrFinalizeEncoder(JS::TranscodeBuffer& buffer)
|
|||
xdrEncoder_.reset(nullptr);
|
||||
});
|
||||
|
||||
if (!xdrEncoder_->linearize(buffer))
|
||||
return false;
|
||||
return true;
|
||||
XDRResult res = xdrEncoder_->linearize(buffer);
|
||||
return res.isOk();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
ScriptSource::performXDR(XDRState<mode>* xdr)
|
||||
{
|
||||
struct CompressedLengthMatcher
|
||||
|
@ -2191,116 +2129,105 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
|
|||
};
|
||||
|
||||
uint8_t hasSource = hasSourceData();
|
||||
if (!xdr->codeUint8(&hasSource))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&hasSource));
|
||||
|
||||
uint8_t retrievable = sourceRetrievable_;
|
||||
if (!xdr->codeUint8(&retrievable))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&retrievable));
|
||||
sourceRetrievable_ = retrievable;
|
||||
|
||||
if (hasSource && !sourceRetrievable_) {
|
||||
uint32_t len = 0;
|
||||
if (mode == XDR_ENCODE)
|
||||
len = length();
|
||||
if (!xdr->codeUint32(&len))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&len));
|
||||
|
||||
uint32_t compressedLength;
|
||||
if (mode == XDR_ENCODE) {
|
||||
CompressedLengthMatcher m;
|
||||
compressedLength = data.match(m);
|
||||
}
|
||||
if (!xdr->codeUint32(&compressedLength))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&compressedLength));
|
||||
|
||||
size_t byteLen = compressedLength ? compressedLength : (len * sizeof(char16_t));
|
||||
if (mode == XDR_DECODE) {
|
||||
uint8_t* p = xdr->cx()->template pod_malloc<uint8_t>(Max<size_t>(byteLen, 1));
|
||||
if (!p || !xdr->codeBytes(p, byteLen)) {
|
||||
js_free(p);
|
||||
return false;
|
||||
}
|
||||
mozilla::UniquePtr<char[], JS::FreePolicy> bytes(
|
||||
xdr->cx()->template pod_malloc<char>(Max<size_t>(byteLen, 1)));
|
||||
if (!bytes)
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
MOZ_TRY(xdr->codeBytes(bytes.get(), byteLen));
|
||||
|
||||
if (compressedLength) {
|
||||
mozilla::UniquePtr<char[], JS::FreePolicy> compressedSource(
|
||||
reinterpret_cast<char*>(p));
|
||||
if (!setCompressedSource(xdr->cx(), mozilla::Move(compressedSource), byteLen, len))
|
||||
return false;
|
||||
if (!setCompressedSource(xdr->cx(), mozilla::Move(bytes), byteLen, len))
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
} else {
|
||||
mozilla::UniquePtr<char16_t[], JS::FreePolicy> source(
|
||||
reinterpret_cast<char16_t*>(p));
|
||||
reinterpret_cast<char16_t*>(bytes.release()));
|
||||
if (!setSource(xdr->cx(), mozilla::Move(source), len))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
} else {
|
||||
RawDataMatcher rdm;
|
||||
void* p = data.match(rdm);
|
||||
if (!xdr->codeBytes(p, byteLen))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeBytes(p, byteLen));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t haveSourceMap = hasSourceMapURL();
|
||||
if (!xdr->codeUint8(&haveSourceMap))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&haveSourceMap));
|
||||
|
||||
if (haveSourceMap) {
|
||||
uint32_t sourceMapURLLen = (mode == XDR_DECODE) ? 0 : js_strlen(sourceMapURL_.get());
|
||||
if (!xdr->codeUint32(&sourceMapURLLen))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&sourceMapURLLen));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
sourceMapURL_ = xdr->cx()->template make_pod_array<char16_t>(sourceMapURLLen + 1);
|
||||
if (!sourceMapURL_)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
if (!xdr->codeChars(sourceMapURL_.get(), sourceMapURLLen)) {
|
||||
auto guard = mozilla::MakeScopeExit([&] {
|
||||
if (mode == XDR_DECODE)
|
||||
sourceMapURL_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
MOZ_TRY(xdr->codeChars(sourceMapURL_.get(), sourceMapURLLen));
|
||||
guard.release();
|
||||
sourceMapURL_[sourceMapURLLen] = '\0';
|
||||
}
|
||||
|
||||
uint8_t haveDisplayURL = hasDisplayURL();
|
||||
if (!xdr->codeUint8(&haveDisplayURL))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&haveDisplayURL));
|
||||
|
||||
if (haveDisplayURL) {
|
||||
uint32_t displayURLLen = (mode == XDR_DECODE) ? 0 : js_strlen(displayURL_.get());
|
||||
if (!xdr->codeUint32(&displayURLLen))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&displayURLLen));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
displayURL_ = xdr->cx()->template make_pod_array<char16_t>(displayURLLen + 1);
|
||||
if (!displayURL_)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
if (!xdr->codeChars(displayURL_.get(), displayURLLen)) {
|
||||
auto guard = mozilla::MakeScopeExit([&] {
|
||||
if (mode == XDR_DECODE)
|
||||
displayURL_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
MOZ_TRY(xdr->codeChars(displayURL_.get(), displayURLLen));
|
||||
guard.release();
|
||||
displayURL_[displayURLLen] = '\0';
|
||||
}
|
||||
|
||||
uint8_t haveFilename = !!filename_;
|
||||
if (!xdr->codeUint8(&haveFilename))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&haveFilename));
|
||||
|
||||
if (haveFilename) {
|
||||
const char* fn = filename();
|
||||
if (!xdr->codeCString(&fn))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeCString(&fn));
|
||||
// Note: If the decoder has an option, then the filename is defined by
|
||||
// the CompileOption from the document.
|
||||
MOZ_ASSERT_IF(mode == XDR_DECODE && xdr->hasOptions(), filename());
|
||||
if (mode == XDR_DECODE && !xdr->hasOptions() && !setFilename(xdr->cx(), fn))
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// Format and return a cx->zone()->pod_malloc'ed URL for a generated script like:
|
||||
|
|
|
@ -597,7 +597,7 @@ class ScriptSource
|
|||
|
||||
// XDR handling
|
||||
template <XDRMode mode>
|
||||
MOZ_MUST_USE bool performXDR(XDRState<mode>* xdr);
|
||||
MOZ_MUST_USE XDRResult performXDR(XDRState<mode>* xdr);
|
||||
|
||||
MOZ_MUST_USE bool setFilename(JSContext* cx, const char* filename);
|
||||
const char* introducerFilename() const {
|
||||
|
@ -765,12 +765,12 @@ enum class FunctionAsyncKind : bool { SyncFunction, AsyncFunction };
|
|||
* CallNewScriptHook.
|
||||
*/
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScriptSource sourceObject,
|
||||
HandleFunction fun, MutableHandleScript scriptp);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScriptSource sourceObject,
|
||||
HandleFunction fun, MutableHandle<LazyScript*> lazy);
|
||||
|
||||
|
@ -778,7 +778,7 @@ XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScriptSourc
|
|||
* Code any constant value.
|
||||
*/
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
|
||||
|
||||
/*
|
||||
|
@ -890,7 +890,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
{
|
||||
template <js::XDRMode mode>
|
||||
friend
|
||||
bool
|
||||
js::XDRResult
|
||||
js::XDRScript(js::XDRState<mode>* xdr, js::HandleScope enclosingScope,
|
||||
js::HandleScriptSource sourceObject, js::HandleFunction fun,
|
||||
js::MutableHandleScript scriptp);
|
||||
|
|
|
@ -1432,7 +1432,7 @@ js::ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut)
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp)
|
||||
{
|
||||
/* NB: Keep this in sync with CloneScriptRegExpObject. */
|
||||
|
@ -1446,23 +1446,23 @@ js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp
|
|||
source = reobj.getSource();
|
||||
flagsword = reobj.getFlags();
|
||||
}
|
||||
if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword))
|
||||
return false;
|
||||
MOZ_TRY(XDRAtom(xdr, &source));
|
||||
MOZ_TRY(xdr->codeUint32(&flagsword));
|
||||
if (mode == XDR_DECODE) {
|
||||
RegExpObject* reobj = RegExpObject::create(xdr->cx(), source, RegExpFlag(flagsword),
|
||||
xdr->lifoAlloc(), TenuredObject);
|
||||
if (!reobj)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
objp.set(reobj);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScriptRegExpObject(XDRState<XDR_ENCODE>* xdr, MutableHandle<RegExpObject*> objp);
|
||||
|
||||
template bool
|
||||
template XDRResult
|
||||
js::XDRScriptRegExpObject(XDRState<XDR_DECODE>* xdr, MutableHandle<RegExpObject*> objp);
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -211,7 +211,7 @@ RegExpToShared(JSContext* cx, HandleObject obj)
|
|||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp);
|
||||
|
||||
extern JSObject*
|
||||
|
|
|
@ -213,7 +213,7 @@ NewEmptyScopeData(JSContext* cx, uint32_t length = 0)
|
|||
return UniquePtr<typename ConcreteScope::Data>(data);
|
||||
}
|
||||
|
||||
static bool
|
||||
static XDRResult
|
||||
XDRBindingName(XDRState<XDR_ENCODE>* xdr, BindingName* bindingName)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
|
@ -222,34 +222,32 @@ XDRBindingName(XDRState<XDR_ENCODE>* xdr, BindingName* bindingName)
|
|||
bool hasAtom = !!atom;
|
||||
|
||||
uint8_t u8 = uint8_t(hasAtom << 1) | uint8_t(bindingName->closedOver());
|
||||
if (!xdr->codeUint8(&u8))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&u8));
|
||||
|
||||
if (atom && !XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
if (atom)
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
static bool
|
||||
static XDRResult
|
||||
XDRBindingName(XDRState<XDR_DECODE>* xdr, BindingName* bindingName)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
|
||||
uint8_t u8;
|
||||
if (!xdr->codeUint8(&u8))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&u8));
|
||||
|
||||
bool closedOver = u8 & 1;
|
||||
bool hasAtom = u8 >> 1;
|
||||
|
||||
RootedAtom atom(cx);
|
||||
if (hasAtom && !XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
if (hasAtom)
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
|
||||
*bindingName = BindingName(atom, closedOver);
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template <typename ConcreteScopeData>
|
||||
|
@ -262,7 +260,7 @@ DeleteScopeData(ConcreteScopeData* data)
|
|||
}
|
||||
|
||||
template <typename ConcreteScope, XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
Scope::XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
|
||||
MutableHandle<typename ConcreteScope::Data*> data)
|
||||
{
|
||||
|
@ -273,30 +271,29 @@ Scope::XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
|
|||
uint32_t length;
|
||||
if (mode == XDR_ENCODE)
|
||||
length = scope->data().length;
|
||||
if (!xdr->codeUint32(&length))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&length));
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
data.set(&scope->data());
|
||||
} else {
|
||||
data.set(NewEmptyScopeData<ConcreteScope>(cx, length).release());
|
||||
if (!data)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
data->length = length;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (!XDRBindingName(xdr, &data->names[i])) {
|
||||
auto guard = mozilla::MakeScopeExit([&] {
|
||||
if (mode == XDR_DECODE) {
|
||||
DeleteScopeData(data.get());
|
||||
data.set(nullptr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
MOZ_TRY(XDRBindingName(xdr, &data->names[i]));
|
||||
guard.release();
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/* static */ Scope*
|
||||
|
@ -572,15 +569,14 @@ LexicalScope::getEmptyExtensibleEnvironmentShape(JSContext* cx)
|
|||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
LexicalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
|
||||
Rooted<Data*> data(cx);
|
||||
if (!XDRSizedBindingNames<LexicalScope>(xdr, scope.as<LexicalScope>(), &data))
|
||||
return false;
|
||||
MOZ_TRY(XDRSizedBindingNames<LexicalScope>(xdr, scope.as<LexicalScope>(), &data));
|
||||
|
||||
{
|
||||
Maybe<Rooted<UniquePtr<Data>>> uniqueData;
|
||||
|
@ -594,33 +590,30 @@ LexicalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
|||
nextFrameSlot = data->nextFrameSlot;
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&data->constStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&firstFrameSlot))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nextFrameSlot))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&data->constStart));
|
||||
MOZ_TRY(xdr->codeUint32(&firstFrameSlot));
|
||||
MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
scope.set(createWithData(cx, kind, &uniqueData.ref(), firstFrameSlot, enclosing));
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
// nextFrameSlot is used only for this correctness check.
|
||||
MOZ_ASSERT(nextFrameSlot == scope->as<LexicalScope>().data().nextFrameSlot);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
LexicalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
LexicalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
|
@ -761,14 +754,13 @@ FunctionScope::clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction
|
|||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
|
||||
MutableHandleScope scope)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
Rooted<Data*> data(cx);
|
||||
if (!XDRSizedBindingNames<FunctionScope>(xdr, scope.as<FunctionScope>(), &data))
|
||||
return false;
|
||||
MOZ_TRY(XDRSizedBindingNames<FunctionScope>(xdr, scope.as<FunctionScope>(), &data));
|
||||
|
||||
{
|
||||
Maybe<Rooted<UniquePtr<Data>>> uniqueData;
|
||||
|
@ -783,16 +775,11 @@ FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosin
|
|||
hasParameterExprs = data->hasParameterExprs;
|
||||
nextFrameSlot = data->nextFrameSlot;
|
||||
}
|
||||
if (!xdr->codeUint8(&needsEnvironment))
|
||||
return false;
|
||||
if (!xdr->codeUint8(&hasParameterExprs))
|
||||
return false;
|
||||
if (!xdr->codeUint16(&data->nonPositionalFormalStart))
|
||||
return false;
|
||||
if (!xdr->codeUint16(&data->varStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nextFrameSlot))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&needsEnvironment));
|
||||
MOZ_TRY(xdr->codeUint8(&hasParameterExprs));
|
||||
MOZ_TRY(xdr->codeUint16(&data->nonPositionalFormalStart));
|
||||
MOZ_TRY(xdr->codeUint16(&data->varStart));
|
||||
MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!data->length) {
|
||||
|
@ -804,23 +791,23 @@ FunctionScope::XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosin
|
|||
scope.set(createWithData(cx, &uniqueData.ref(), hasParameterExprs, needsEnvironment, fun,
|
||||
enclosing));
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
// nextFrameSlot is used only for this correctness check.
|
||||
MOZ_ASSERT(nextFrameSlot == scope->as<FunctionScope>().data().nextFrameSlot);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
FunctionScope::XDR(XDRState<XDR_ENCODE>* xdr, HandleFunction fun, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
FunctionScope::XDR(XDRState<XDR_DECODE>* xdr, HandleFunction fun, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
|
@ -897,14 +884,13 @@ VarScope::firstFrameSlot() const
|
|||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
VarScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope)
|
||||
{
|
||||
JSContext* cx = xdr->cx();
|
||||
Rooted<Data*> data(cx);
|
||||
if (!XDRSizedBindingNames<VarScope>(xdr, scope.as<VarScope>(), &data))
|
||||
return false;
|
||||
MOZ_TRY(XDRSizedBindingNames<VarScope>(xdr, scope.as<VarScope>(), &data));
|
||||
|
||||
{
|
||||
Maybe<Rooted<UniquePtr<Data>>> uniqueData;
|
||||
|
@ -919,12 +905,9 @@ VarScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
|||
firstFrameSlot = scope->as<VarScope>().firstFrameSlot();
|
||||
nextFrameSlot = data->nextFrameSlot;
|
||||
}
|
||||
if (!xdr->codeUint8(&needsEnvironment))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&firstFrameSlot))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nextFrameSlot))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint8(&needsEnvironment));
|
||||
MOZ_TRY(xdr->codeUint32(&firstFrameSlot));
|
||||
MOZ_TRY(xdr->codeUint32(&nextFrameSlot));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!data->length) {
|
||||
|
@ -934,23 +917,23 @@ VarScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
|||
scope.set(createWithData(cx, kind, &uniqueData.ref(), firstFrameSlot, needsEnvironment,
|
||||
enclosing));
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
|
||||
// nextFrameSlot is used only for this correctness check.
|
||||
MOZ_ASSERT(nextFrameSlot == scope->as<VarScope>().data().nextFrameSlot);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
VarScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
VarScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
|
@ -997,27 +980,23 @@ GlobalScope::clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind)
|
|||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
GlobalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope)
|
||||
{
|
||||
MOZ_ASSERT((mode == XDR_DECODE) == !scope);
|
||||
|
||||
JSContext* cx = xdr->cx();
|
||||
Rooted<Data*> data(cx);
|
||||
if (!XDRSizedBindingNames<GlobalScope>(xdr, scope.as<GlobalScope>(), &data))
|
||||
return false;
|
||||
MOZ_TRY(XDRSizedBindingNames<GlobalScope>(xdr, scope.as<GlobalScope>(), &data));
|
||||
|
||||
{
|
||||
Maybe<Rooted<UniquePtr<Data>>> uniqueData;
|
||||
if (mode == XDR_DECODE)
|
||||
uniqueData.emplace(cx, data);
|
||||
|
||||
if (!xdr->codeUint32(&data->varStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&data->letStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&data->constStart))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&data->varStart));
|
||||
MOZ_TRY(xdr->codeUint32(&data->letStart));
|
||||
MOZ_TRY(xdr->codeUint32(&data->constStart));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!data->length) {
|
||||
|
@ -1028,19 +1007,19 @@ GlobalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope)
|
|||
|
||||
scope.set(createWithData(cx, kind, &uniqueData.ref()));
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
GlobalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, MutableHandleScope scope);
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
GlobalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, MutableHandleScope scope);
|
||||
|
||||
/* static */ WithScope*
|
||||
|
@ -1123,7 +1102,7 @@ EvalScope::getEmptyEnvironmentShape(JSContext* cx)
|
|||
}
|
||||
|
||||
template <XDRMode mode>
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
EvalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope)
|
||||
{
|
||||
|
@ -1135,8 +1114,7 @@ EvalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
|||
if (mode == XDR_DECODE)
|
||||
uniqueData.emplace(cx, data);
|
||||
|
||||
if (!XDRSizedBindingNames<EvalScope>(xdr, scope.as<EvalScope>(), &data))
|
||||
return false;
|
||||
MOZ_TRY(XDRSizedBindingNames<EvalScope>(xdr, scope.as<EvalScope>(), &data));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!data->length)
|
||||
|
@ -1144,20 +1122,20 @@ EvalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
|||
|
||||
scope.set(createWithData(cx, kind, &uniqueData.ref(), enclosing));
|
||||
if (!scope)
|
||||
return false;
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
EvalScope::XDR(XDRState<XDR_ENCODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
template
|
||||
/* static */ bool
|
||||
/* static */ XDRResult
|
||||
EvalScope::XDR(XDRState<XDR_DECODE>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
|
|
|
@ -259,8 +259,8 @@ class Scope : public js::gc::TenuredCell
|
|||
HandleShape envShape, mozilla::UniquePtr<T, D> data);
|
||||
|
||||
template <typename ConcreteScope, XDRMode mode>
|
||||
static bool XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
|
||||
MutableHandle<typename ConcreteScope::Data*> data);
|
||||
static XDRResult XDRSizedBindingNames(XDRState<mode>* xdr, Handle<ConcreteScope*> scope,
|
||||
MutableHandle<typename ConcreteScope::Data*> data);
|
||||
|
||||
Shape* maybeCloneEnvironmentShape(JSContext* cx);
|
||||
|
||||
|
@ -406,7 +406,7 @@ class LexicalScope : public Scope
|
|||
uint32_t firstFrameSlot, HandleScope enclosing);
|
||||
|
||||
template <XDRMode mode>
|
||||
static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
private:
|
||||
|
@ -533,7 +533,7 @@ class FunctionScope : public Scope
|
|||
HandleScope enclosing);
|
||||
|
||||
template <XDRMode mode>
|
||||
static bool XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
|
||||
static XDRResult XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
private:
|
||||
|
@ -631,7 +631,7 @@ class VarScope : public Scope
|
|||
HandleScope enclosing);
|
||||
|
||||
template <XDRMode mode>
|
||||
static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
private:
|
||||
|
@ -729,7 +729,7 @@ class GlobalScope : public Scope
|
|||
static GlobalScope* clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind);
|
||||
|
||||
template <XDRMode mode>
|
||||
static bool XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope);
|
||||
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope);
|
||||
|
||||
private:
|
||||
static GlobalScope* createWithData(JSContext* cx, ScopeKind kind,
|
||||
|
@ -829,7 +829,7 @@ class EvalScope : public Scope
|
|||
HandleScope enclosing);
|
||||
|
||||
template <XDRMode mode>
|
||||
static bool XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
|
||||
MutableHandleScope scope);
|
||||
|
||||
private:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "vm/Xdr.h"
|
||||
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -28,22 +29,20 @@ XDRState<mode>::lifoAlloc() const {
|
|||
return buf.cx()->tempLifoAlloc();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
void
|
||||
XDRState<mode>::postProcessContextErrors(JSContext* cx)
|
||||
{
|
||||
// NOTE: This should only be called on transcode failure. Not all failure
|
||||
// paths call XDRState::fail(...), so we should update resultCode_ if it
|
||||
// doesn't hold a specific transcode error.
|
||||
|
||||
if (resultCode_ & JS::TranscodeResult_Failure)
|
||||
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
|
||||
else
|
||||
resultCode_ = JS::TranscodeResult_Throw;
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
XDRCoderBase::validateResultCode(JSContext* cx, JS::TranscodeResult code) const
|
||||
{
|
||||
// NOTE: This function is called to verify that we do not have a pending
|
||||
// exception on the JSContext at the same time as a TranscodeResult failure.
|
||||
if (cx->helperThread())
|
||||
return true;
|
||||
return cx->isExceptionPending() == bool(code == JS::TranscodeResult_Throw);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<XDRMode mode>
|
||||
XDRResult
|
||||
XDRState<mode>::codeChars(const Latin1Char* chars, size_t nchars)
|
||||
{
|
||||
static_assert(sizeof(Latin1Char) == sizeof(uint8_t), "Latin1Char must fit in 1 byte");
|
||||
|
@ -51,21 +50,21 @@ XDRState<mode>::codeChars(const Latin1Char* chars, size_t nchars)
|
|||
MOZ_ASSERT(mode == XDR_ENCODE);
|
||||
|
||||
if (nchars == 0)
|
||||
return true;
|
||||
return Ok();
|
||||
uint8_t* ptr = buf.write(nchars);
|
||||
if (!ptr)
|
||||
return fail(JS::TranscodeResult_Throw);
|
||||
|
||||
mozilla::PodCopy(ptr, chars, nchars);
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRState<mode>::codeChars(char16_t* chars, size_t nchars)
|
||||
{
|
||||
if (nchars == 0)
|
||||
return true;
|
||||
return Ok();
|
||||
size_t nbytes = nchars * sizeof(char16_t);
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(nbytes);
|
||||
|
@ -78,11 +77,11 @@ XDRState<mode>::codeChars(char16_t* chars, size_t nchars)
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
mozilla::NativeEndian::copyAndSwapFromLittleEndian(chars, ptr, nchars);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
static bool
|
||||
static XDRResult
|
||||
VersionCheck(XDRState<mode>* xdr)
|
||||
{
|
||||
JS::BuildIdCharVector buildId;
|
||||
|
@ -97,15 +96,13 @@ VersionCheck(XDRState<mode>* xdr)
|
|||
if (mode == XDR_ENCODE)
|
||||
buildIdLength = buildId.length();
|
||||
|
||||
if (!xdr->codeUint32(&buildIdLength))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeUint32(&buildIdLength));
|
||||
|
||||
if (mode == XDR_DECODE && buildIdLength != buildId.length())
|
||||
return xdr->fail(JS::TranscodeResult_Failure_BadBuildId);
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
if (!xdr->codeBytes(buildId.begin(), buildIdLength))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeBytes(buildId.begin(), buildIdLength));
|
||||
} else {
|
||||
JS::BuildIdCharVector decodedBuildId;
|
||||
|
||||
|
@ -116,19 +113,18 @@ VersionCheck(XDRState<mode>* xdr)
|
|||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
||||
if (!xdr->codeBytes(decodedBuildId.begin(), buildIdLength))
|
||||
return false;
|
||||
MOZ_TRY(xdr->codeBytes(decodedBuildId.begin(), buildIdLength));
|
||||
|
||||
// We do not provide binary compatibility with older scripts.
|
||||
if (!PodEqual(decodedBuildId.begin(), buildId.begin(), buildIdLength))
|
||||
return xdr->fail(JS::TranscodeResult_Failure_BadBuildId);
|
||||
}
|
||||
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRState<mode>::codeFunction(MutableHandleFunction funp, HandleScriptSource sourceObject)
|
||||
{
|
||||
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx());
|
||||
|
@ -136,6 +132,12 @@ XDRState<mode>::codeFunction(MutableHandleFunction funp, HandleScriptSource sour
|
|||
mode == XDR_DECODE ? TraceLogger_DecodeFunction : TraceLogger_EncodeFunction;
|
||||
AutoTraceLog tl(logger, event);
|
||||
|
||||
#ifdef DEBUG
|
||||
auto sanityCheck = mozilla::MakeScopeExit([&] {
|
||||
MOZ_ASSERT(validateResultCode(cx(), resultCode()));
|
||||
});
|
||||
#endif
|
||||
auto guard = mozilla::MakeScopeExit([&] { funp.set(nullptr); });
|
||||
RootedScope scope(cx(), &cx()->global()->emptyGlobalScope());
|
||||
if (mode == XDR_DECODE) {
|
||||
MOZ_ASSERT(!sourceObject);
|
||||
|
@ -148,22 +150,15 @@ XDRState<mode>::codeFunction(MutableHandleFunction funp, HandleScriptSource sour
|
|||
MOZ_ASSERT(funp->nonLazyScript()->enclosingScope()->is<GlobalScope>());
|
||||
}
|
||||
|
||||
if (!VersionCheck(this)) {
|
||||
postProcessContextErrors(cx());
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(VersionCheck(this));
|
||||
MOZ_TRY(XDRInterpretedFunction(this, scope, sourceObject, funp));
|
||||
|
||||
if (!XDRInterpretedFunction(this, scope, sourceObject, funp)) {
|
||||
postProcessContextErrors(cx());
|
||||
funp.set(nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
guard.release();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRState<mode>::codeScript(MutableHandleScript scriptp)
|
||||
{
|
||||
TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx());
|
||||
|
@ -171,12 +166,18 @@ XDRState<mode>::codeScript(MutableHandleScript scriptp)
|
|||
mode == XDR_DECODE ? TraceLogger_DecodeScript : TraceLogger_EncodeScript;
|
||||
AutoTraceLog tl(logger, event);
|
||||
|
||||
#ifdef DEBUG
|
||||
auto sanityCheck = mozilla::MakeScopeExit([&] {
|
||||
MOZ_ASSERT(validateResultCode(cx(), resultCode()));
|
||||
});
|
||||
#endif
|
||||
auto guard = mozilla::MakeScopeExit([&] { scriptp.set(nullptr); });
|
||||
|
||||
// This should be a no-op when encoding, but when decoding it would eat any
|
||||
// miss-aligned bytes if when encoding the XDR buffer is appended at the end
|
||||
// of an existing buffer, such as in XDRIncrementalEncoder::linearize
|
||||
// function.
|
||||
if (!codeAlign(sizeof(js::XDRAlignment)))
|
||||
return false;
|
||||
MOZ_TRY(codeAlign(sizeof(js::XDRAlignment)));
|
||||
AutoXDRTree scriptTree(this, getTopLevelTreeKey());
|
||||
|
||||
if (mode == XDR_DECODE)
|
||||
|
@ -184,25 +185,16 @@ XDRState<mode>::codeScript(MutableHandleScript scriptp)
|
|||
else
|
||||
MOZ_ASSERT(!scriptp->enclosingScope());
|
||||
|
||||
if (!VersionCheck(this)) {
|
||||
postProcessContextErrors(cx());
|
||||
return false;
|
||||
}
|
||||
MOZ_TRY(VersionCheck(this));
|
||||
MOZ_TRY(XDRScript(this, nullptr, nullptr, nullptr, scriptp));
|
||||
MOZ_TRY(codeAlign(sizeof(js::XDRAlignment)));
|
||||
|
||||
if (!XDRScript(this, nullptr, nullptr, nullptr, scriptp)) {
|
||||
postProcessContextErrors(cx());
|
||||
scriptp.set(nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!codeAlign(sizeof(js::XDRAlignment)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
guard.release();
|
||||
return Ok();
|
||||
}
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRResult
|
||||
XDRState<mode>::codeConstValue(MutableHandleValue vp)
|
||||
{
|
||||
return XDRScriptConst(this, vp);
|
||||
|
@ -225,7 +217,8 @@ AutoXDRTree::AutoXDRTree(XDRCoderBase* xdr, AutoXDRTree::Key key)
|
|||
AutoXDRTree::~AutoXDRTree()
|
||||
{
|
||||
// Expect sub-tree to end with the maximum alignment required.
|
||||
MOZ_ASSERT(xdr_->isAligned(sizeof(js::XDRAlignment)));
|
||||
MOZ_ASSERT_IF(xdr_->resultCode() == JS::TranscodeResult_Ok,
|
||||
xdr_->isAligned(sizeof(js::XDRAlignment)));
|
||||
if (key_ != AutoXDRTree::noKey)
|
||||
xdr_->endSubTree();
|
||||
}
|
||||
|
@ -343,7 +336,7 @@ XDRIncrementalEncoder::endSubTree()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
XDRResult
|
||||
XDRIncrementalEncoder::linearize(JS::TranscodeBuffer& buffer)
|
||||
{
|
||||
if (oom_) {
|
||||
|
@ -412,5 +405,5 @@ XDRIncrementalEncoder::linearize(JS::TranscodeBuffer& buffer)
|
|||
|
||||
tree_.finish();
|
||||
slices_.clearAndFree();
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
|
120
js/src/vm/Xdr.h
120
js/src/vm/Xdr.h
|
@ -184,8 +184,17 @@ class MOZ_RAII AutoXDRTree
|
|||
|
||||
class XDRCoderBase
|
||||
{
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
JS::TranscodeResult resultCode_;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
XDRCoderBase() {}
|
||||
XDRCoderBase()
|
||||
#ifdef DEBUG
|
||||
: resultCode_(JS::TranscodeResult_Ok)
|
||||
#endif
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual AutoXDRTree::Key getTopLevelTreeKey() const { return AutoXDRTree::noKey; }
|
||||
|
@ -193,6 +202,18 @@ class XDRCoderBase
|
|||
virtual void createOrReplaceSubTree(AutoXDRTree* child) {};
|
||||
virtual void endSubTree() {};
|
||||
virtual bool isAligned(size_t n) = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Record logical failures of XDR.
|
||||
JS::TranscodeResult resultCode() const {
|
||||
return resultCode_;
|
||||
}
|
||||
void setResultCode(JS::TranscodeResult code) {
|
||||
MOZ_ASSERT(resultCode() == JS::TranscodeResult_Ok);
|
||||
resultCode_ = code;
|
||||
}
|
||||
bool validateResultCode(JSContext* cx, JS::TranscodeResult code) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -203,20 +224,16 @@ class XDRState : public XDRCoderBase
|
|||
{
|
||||
protected:
|
||||
XDRBuffer<mode> buf;
|
||||
private:
|
||||
JS::TranscodeResult resultCode_;
|
||||
|
||||
public:
|
||||
XDRState(JSContext* cx, JS::TranscodeBuffer& buffer, size_t cursor = 0)
|
||||
: buf(cx, buffer, cursor),
|
||||
resultCode_(JS::TranscodeResult_Ok)
|
||||
: buf(cx, buffer, cursor)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
XDRState(JSContext* cx, const RangeType& range)
|
||||
: buf(cx, range),
|
||||
resultCode_(JS::TranscodeResult_Ok)
|
||||
: buf(cx, range)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -236,39 +253,34 @@ class XDRState : public XDRCoderBase
|
|||
MOZ_CRASH("does not have scriptSourceObjectOut.");
|
||||
}
|
||||
|
||||
// Record logical failures of XDR.
|
||||
void postProcessContextErrors(JSContext* cx);
|
||||
JS::TranscodeResult resultCode() const {
|
||||
return resultCode_;
|
||||
}
|
||||
bool fail(JS::TranscodeResult code) {
|
||||
MOZ_ASSERT(resultCode_ == JS::TranscodeResult_Ok);
|
||||
resultCode_ = code;
|
||||
return false;
|
||||
XDRResult fail(JS::TranscodeResult code) {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(code != JS::TranscodeResult_Ok);
|
||||
MOZ_ASSERT(validateResultCode(cx(), code));
|
||||
setResultCode(code);
|
||||
#endif
|
||||
return mozilla::Err(code);
|
||||
}
|
||||
|
||||
bool peekData(const uint8_t** pptr, size_t length) {
|
||||
XDRResult peekData(const uint8_t** pptr, size_t length) {
|
||||
const uint8_t* ptr = buf.read(length);
|
||||
if (!ptr)
|
||||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*pptr = ptr;
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
// Alignment is required when doing memcpy of data which contains element
|
||||
// largers than 1 byte.
|
||||
bool isAligned(size_t n) override {
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(n));
|
||||
// If there is a failure, always assume that we are aligned.
|
||||
if (resultCode() != JS::TranscodeResult_Ok)
|
||||
return true;
|
||||
size_t mask = n - 1;
|
||||
size_t offset = buf.uptr() & mask;
|
||||
// In debug build, we not only check if the cursor is aligned, but also
|
||||
// if the last cursor manipulation was made by the codeAlign function.
|
||||
return offset == 0 && buf.isAligned();
|
||||
}
|
||||
bool codeAlign(size_t n) {
|
||||
XDRResult codeAlign(size_t n) {
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(n));
|
||||
size_t mask = n - 1;
|
||||
MOZ_ASSERT_IF(mode == XDR_ENCODE, (buf.uptr() & mask) == (buf.cursor() & mask));
|
||||
|
@ -291,10 +303,10 @@ class XDRState : public XDRCoderBase
|
|||
}
|
||||
buf.setAligned(true);
|
||||
MOZ_ASSERT(isAligned(n));
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeUint8(uint8_t* n) {
|
||||
XDRResult codeUint8(uint8_t* n) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(sizeof(*n));
|
||||
if (!ptr)
|
||||
|
@ -306,10 +318,10 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*n = *ptr;
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeUint16(uint16_t* n) {
|
||||
XDRResult codeUint16(uint16_t* n) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(sizeof(*n));
|
||||
if (!ptr)
|
||||
|
@ -321,10 +333,10 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*n = mozilla::LittleEndian::readUint16(ptr);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeUint32(uint32_t* n) {
|
||||
XDRResult codeUint32(uint32_t* n) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(sizeof(*n));
|
||||
if (!ptr)
|
||||
|
@ -336,10 +348,10 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*n = mozilla::LittleEndian::readUint32(ptr);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeUint64(uint64_t* n) {
|
||||
XDRResult codeUint64(uint64_t* n) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(sizeof(*n));
|
||||
if (!ptr)
|
||||
|
@ -351,7 +363,7 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*n = mozilla::LittleEndian::readUint64(ptr);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -360,7 +372,7 @@ class XDRState : public XDRCoderBase
|
|||
* as C++ will extract the parameterized from the argument list.
|
||||
*/
|
||||
template <typename T>
|
||||
bool codeEnum32(T* val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL)
|
||||
XDRResult codeEnum32(T* val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL)
|
||||
{
|
||||
// Mix the enumeration value with a random magic number, such that a
|
||||
// corruption with a low-ranged value (like 0) is less likely to cause a
|
||||
|
@ -369,42 +381,39 @@ class XDRState : public XDRCoderBase
|
|||
uint32_t tmp;
|
||||
if (mode == XDR_ENCODE)
|
||||
tmp = uint32_t(*val) ^ MAGIC;
|
||||
if (!codeUint32(&tmp))
|
||||
return false;
|
||||
MOZ_TRY(codeUint32(&tmp));
|
||||
if (mode == XDR_DECODE)
|
||||
*val = T(tmp ^ MAGIC);
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeDouble(double* dp) {
|
||||
XDRResult codeDouble(double* dp) {
|
||||
union DoublePun {
|
||||
double d;
|
||||
uint64_t u;
|
||||
} pun;
|
||||
if (mode == XDR_ENCODE)
|
||||
pun.d = *dp;
|
||||
if (!codeUint64(&pun.u))
|
||||
return false;
|
||||
MOZ_TRY(codeUint64(&pun.u));
|
||||
if (mode == XDR_DECODE)
|
||||
*dp = pun.d;
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeMarker(uint32_t magic) {
|
||||
XDRResult codeMarker(uint32_t magic) {
|
||||
uint32_t actual = magic;
|
||||
if (!codeUint32(&actual))
|
||||
return false;
|
||||
MOZ_TRY(codeUint32(&actual));
|
||||
if (actual != magic) {
|
||||
// Fail in debug, but only soft-fail in release
|
||||
MOZ_ASSERT(false, "Bad XDR marker");
|
||||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeBytes(void* bytes, size_t len) {
|
||||
XDRResult codeBytes(void* bytes, size_t len) {
|
||||
if (len == 0)
|
||||
return true;
|
||||
return Ok();
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint8_t* ptr = buf.write(len);
|
||||
if (!ptr)
|
||||
|
@ -416,7 +425,7 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
memcpy(bytes, ptr, len);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -425,12 +434,11 @@ class XDRState : public XDRCoderBase
|
|||
* decoding buffer and the caller must copy the string if it will outlive
|
||||
* the decoding buffer.
|
||||
*/
|
||||
bool codeCString(const char** sp) {
|
||||
XDRResult codeCString(const char** sp) {
|
||||
uint64_t len64;
|
||||
if (mode == XDR_ENCODE)
|
||||
len64 = (uint64_t)(strlen(*sp) + 1);
|
||||
if (!codeUint64(&len64))
|
||||
return false;
|
||||
MOZ_TRY(codeUint64(&len64));
|
||||
size_t len = (size_t) len64;
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
|
@ -444,15 +452,15 @@ class XDRState : public XDRCoderBase
|
|||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
*sp = reinterpret_cast<const char*>(ptr);
|
||||
}
|
||||
return true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool codeChars(const JS::Latin1Char* chars, size_t nchars);
|
||||
bool codeChars(char16_t* chars, size_t nchars);
|
||||
XDRResult codeChars(const JS::Latin1Char* chars, size_t nchars);
|
||||
XDRResult codeChars(char16_t* chars, size_t nchars);
|
||||
|
||||
bool codeFunction(JS::MutableHandleFunction objp, HandleScriptSource sourceObject = nullptr);
|
||||
bool codeScript(MutableHandleScript scriptp);
|
||||
bool codeConstValue(MutableHandleValue vp);
|
||||
XDRResult codeFunction(JS::MutableHandleFunction objp, HandleScriptSource sourceObject = nullptr);
|
||||
XDRResult codeScript(MutableHandleScript scriptp);
|
||||
XDRResult codeConstValue(MutableHandleValue vp);
|
||||
};
|
||||
|
||||
using XDREncoder = XDRState<XDR_ENCODE>;
|
||||
|
@ -587,7 +595,7 @@ class XDRIncrementalEncoder : public XDREncoder
|
|||
|
||||
// Append the content collected during the incremental encoding into the
|
||||
// buffer given as argument.
|
||||
MOZ_MUST_USE bool linearize(JS::TranscodeBuffer& buffer);
|
||||
XDRResult linearize(JS::TranscodeBuffer& buffer);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
|
Загрузка…
Ссылка в новой задаче