Bug 1419094 - Result-ify XDR functions. r=tcampbell

This commit is contained in:
Nicolas B. Pierron 2018-03-13 16:22:13 +00:00
Родитель 51b99ad845
Коммит e2b13d6466
17 изменённых файлов: 439 добавлений и 531 удалений

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

@ -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(&copyOnWrite))
return false;
}
MOZ_TRY(xdr->codeUint32(&copyOnWrite));
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, &regexp))
return false;
MOZ_TRY(XDRScriptRegExpObject(xdr, &regexp));
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(&note->index) ||
!xdr->codeUint32(&note->start) ||
!xdr->codeUint32(&note->length) ||
!xdr->codeUint32(&note->parent))
{
return false;
}
MOZ_TRY(xdr->codeUint32(&note->index));
MOZ_TRY(xdr->codeUint32(&note->start));
MOZ_TRY(xdr->codeUint32(&note->length));
MOZ_TRY(xdr->codeUint32(&note->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();
}

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

@ -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 */