summaryrefslogtreecommitdiffstats
path: root/js/src/jsscript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsscript.cpp')
-rw-r--r--js/src/jsscript.cpp93
1 files changed, 59 insertions, 34 deletions
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index 2e02aa63d..9f914943e 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -75,24 +75,19 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
{
JSContext* cx = xdr->cx();
- /*
- * A script constant can be an arbitrary primitive value as they are used
- * to implement JSOP_LOOKUPSWITCH. But they cannot be objects, see
- * bug 407186.
- */
enum ConstTag {
- SCRIPT_INT = 0,
- SCRIPT_DOUBLE = 1,
- SCRIPT_ATOM = 2,
- SCRIPT_TRUE = 3,
- SCRIPT_FALSE = 4,
- SCRIPT_NULL = 5,
- SCRIPT_OBJECT = 6,
- SCRIPT_VOID = 7,
- SCRIPT_HOLE = 8
+ SCRIPT_INT,
+ SCRIPT_DOUBLE,
+ SCRIPT_ATOM,
+ SCRIPT_TRUE,
+ SCRIPT_FALSE,
+ SCRIPT_NULL,
+ SCRIPT_OBJECT,
+ SCRIPT_VOID,
+ SCRIPT_HOLE
};
- uint32_t tag;
+ ConstTag tag;
if (mode == XDR_ENCODE) {
if (vp.isInt32()) {
tag = SCRIPT_INT;
@@ -116,7 +111,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
}
}
- if (!xdr->codeUint32(&tag))
+ if (!xdr->codeEnum32(&tag))
return false;
switch (tag) {
@@ -182,6 +177,10 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp)
if (mode == XDR_DECODE)
vp.setMagic(JS_ELEMENTS_HOLE);
break;
+ default:
+ // Fail in debug, but only soft-fail in release
+ MOZ_ASSERT(false, "Bad XDR value kind");
+ return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
}
return true;
}
@@ -317,6 +316,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
IsLegacyGenerator,
IsStarGenerator,
IsAsync,
+ HasRest,
OwnSource,
ExplicitUseStrict,
SelfHosted,
@@ -432,6 +432,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
scriptBits |= (1 << IsStarGenerator);
if (script->asyncKind() == AsyncFunction)
scriptBits |= (1 << IsAsync);
+ if (script->hasRest())
+ scriptBits |= (1 << HasRest);
if (script->hasSingletons())
scriptBits |= (1 << HasSingleton);
if (script->treatAsRunOnce())
@@ -583,6 +585,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
if (scriptBits & (1 << IsAsync))
script->setAsyncKind(AsyncFunction);
+ if (scriptBits & (1 << HasRest))
+ script->setHasRest();
}
JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
@@ -742,11 +746,20 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
case ScopeKind::Module:
MOZ_CRASH("NYI");
break;
+ default:
+ // Fail in debug, but only soft-fail in release
+ MOZ_ASSERT(false, "Bad XDR scope kind");
+ return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
}
if (mode == XDR_DECODE)
vector[i].init(scope);
}
+
+ // Verify marker to detect data corruption after decoding scope data. A
+ // mismatch here indicates we will almost certainly crash in release.
+ if (!xdr->codeMarker(0xF81F7F5A))
+ return false;
}
/*
@@ -832,12 +845,18 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
}
default: {
- MOZ_ASSERT(false, "Unknown class kind.");
- return xdr->fail(JS::TranscodeResult_Failure_UnknownClassKind);
+ // Fail in debug, but only soft-fail in release
+ MOZ_ASSERT(false, "Bad XDR class kind");
+ return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
}
}
}
+ // Verify marker to detect data corruption after decoding object data. A
+ // mismatch here indicates we will almost certainly crash in release.
+ if (!xdr->codeMarker(0x223DB179))
+ return false;
+
if (ntrynotes != 0) {
JSTryNote* tnfirst = script->trynotes()->vector;
MOZ_ASSERT(script->trynotes()->length == ntrynotes);
@@ -1675,6 +1694,16 @@ ScriptSource::substringDontDeflate(JSContext* cx, size_t start, size_t stop)
return NewStringCopyNDontDeflate<CanGC>(cx, chars, len);
}
+JSFlatString*
+ScriptSource::functionBodyString(JSContext* cx)
+{
+ MOZ_ASSERT(isFunctionBody());
+
+ size_t start = parameterListEnd_ + (sizeof(FunctionConstructorMedialSigils) - 1);
+ size_t stop = length() - (sizeof(FunctionConstructorFinalBrace) - 1);
+ return substring(cx, start, stop);
+}
+
MOZ_MUST_USE bool
ScriptSource::setSource(ExclusiveContext* cx,
mozilla::UniquePtr<char16_t[], JS::FreePolicy>&& source,
@@ -1726,10 +1755,9 @@ ScriptSource::setCompressedSource(SharedImmutableString&& raw, size_t uncompress
bool
ScriptSource::setSourceCopy(ExclusiveContext* cx, SourceBufferHolder& srcBuf,
- bool argumentsNotIncluded, SourceCompressionTask* task)
+ SourceCompressionTask* task)
{
MOZ_ASSERT(!hasSourceData());
- argumentsNotIncluded_ = argumentsNotIncluded;
auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings();
auto deduped = cache.getOrCreate(srcBuf.get(), srcBuf.length(), [&]() {
@@ -1926,16 +1954,6 @@ ScriptSource::performXDR(XDRState<mode>* xdr)
if (!xdr->codeUint32(&compressedLength))
return false;
- {
- uint8_t argumentsNotIncluded;
- if (mode == XDR_ENCODE)
- argumentsNotIncluded = argumentsNotIncluded_;
- if (!xdr->codeUint8(&argumentsNotIncluded))
- return false;
- if (mode == XDR_DECODE)
- argumentsNotIncluded_ = argumentsNotIncluded;
- }
-
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));
@@ -2060,7 +2078,8 @@ FormatIntroducedFilename(ExclusiveContext* cx, const char* filename, unsigned li
}
bool
-ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options)
+ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options,
+ Maybe<uint32_t> parameterListEnd)
{
MOZ_ASSERT(!filename_);
MOZ_ASSERT(!introducerFilename_);
@@ -2069,6 +2088,7 @@ ScriptSource::initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions
introductionType_ = options.introductionType;
setIntroductionOffset(options.introductionOffset);
+ parameterListEnd_ = parameterListEnd.isSome() ? parameterListEnd.value() : 0;
if (options.hasIntroductionInfo) {
MOZ_ASSERT(options.introductionType != nullptr);
@@ -2622,6 +2642,8 @@ JSScript::initFromFunctionBox(ExclusiveContext* cx, HandleScript script,
script->isGeneratorExp_ = funbox->isGenexpLambda;
script->setGeneratorKind(funbox->generatorKind());
script->setAsyncKind(funbox->asyncKind());
+ if (funbox->hasRest())
+ script->setHasRest();
PositionalFormalParameterIter fi(script);
while (fi && !fi.closedOver())
@@ -2782,9 +2804,10 @@ JSScript::assertValidJumpTargets() const
for (; tn < tnlimit; tn++) {
jsbytecode* tryStart = mainEntry + tn->start;
jsbytecode* tryPc = tryStart - 1;
- if (JSOp(*tryPc) != JSOP_TRY)
+ if (tn->kind != JSTRY_CATCH && tn->kind != JSTRY_FINALLY)
continue;
+ MOZ_ASSERT(JSOp(*tryPc) == JSOP_TRY);
jsbytecode* tryTarget = tryStart + tn->length;
MOZ_ASSERT(mainEntry <= tryTarget && tryTarget < end);
MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*tryTarget)));
@@ -3280,12 +3303,13 @@ js::detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
dst->needsHomeObject_ = src->needsHomeObject();
dst->isDefaultClassConstructor_ = src->isDefaultClassConstructor();
dst->isAsync_ = src->asyncKind() == AsyncFunction;
+ dst->hasRest_ = src->hasRest_;
if (nconsts != 0) {
GCPtrValue* vector = Rebase<GCPtrValue>(dst, src, src->consts()->vector);
dst->consts()->vector = vector;
for (unsigned i = 0; i < nconsts; ++i)
- MOZ_ASSERT_IF(vector[i].isMarkable(), vector[i].toString()->isAtom());
+ MOZ_ASSERT_IF(vector[i].isGCThing(), vector[i].toString()->isAtom());
}
if (nobjects != 0) {
GCPtrObject* vector = Rebase<GCPtrObject>(dst, src, src->objects()->vector);
@@ -4013,6 +4037,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
p.shouldDeclareArguments = false;
p.hasThisBinding = false;
p.isAsync = false;
+ p.hasRest = false;
p.numClosedOverBindings = closedOverBindings.length();
p.numInnerFunctions = innerFunctions.length();
p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
@@ -4154,7 +4179,7 @@ JSScript::hasLoops()
bool
JSScript::mayReadFrameArgsDirectly()
{
- return argumentsHasVarBinding() || (function() && function()->hasRest());
+ return argumentsHasVarBinding() || hasRest();
}
static inline void