summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2023-04-30 19:36:28 +0000
committerMoonchild <moonchild@palemoon.org>2023-04-30 19:36:28 +0000
commit3ff018f32f04147eac27cbba93369dfd60e4d4d5 (patch)
tree730dcec162928c93e2159416c800f5f462a8a379
parent4d4d8cfc9f73d48208afcfde9216fcddf9aecec3 (diff)
parent6ab2fe9a694524afd5bd8383ab50973086866b36 (diff)
downloaduxp-3ff018f32f04147eac27cbba93369dfd60e4d4d5.tar.gz
Merge pull request 'Collected small changes' (#2214) from martok/UXP-contrib:mr/collect-1 into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/2214
-rw-r--r--js/src/builtin/ReflectParse.cpp2
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp53
-rw-r--r--js/src/frontend/BytecodeEmitter.h6
-rw-r--r--js/src/frontend/CallOrNewEmitter.cpp1
-rw-r--r--js/src/frontend/FullParseHandler.h6
-rw-r--r--js/src/frontend/ParseNode.h22
-rw-r--r--js/src/frontend/Parser.cpp45
-rw-r--r--js/src/frontend/Parser.h21
-rw-r--r--js/src/frontend/SyntaxParseHandler.h2
-rw-r--r--js/src/jit/BaselineIC.cpp2
-rw-r--r--js/src/jit/IonBuilder.cpp2
-rw-r--r--js/src/jit/VMFunctions.cpp3
-rw-r--r--js/src/js.msg1
-rw-r--r--js/src/vm/GeneratorObject.cpp2
-rw-r--r--js/src/vm/Interpreter-inl.h11
-rw-r--r--js/src/vm/Interpreter.cpp7
-rw-r--r--js/src/vm/RegExpObject.cpp26
-rw-r--r--js/src/vm/Stack-inl.h5
18 files changed, 128 insertions, 89 deletions
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 91bef98884..4aa7f1640b 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3162,7 +3162,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case PNK_OPTDOT:
case PNK_DOT:
{
- PropertyAccess* prop = &pn->as<PropertyAccess>();
+ PropertyAccessBase* prop = &pn->as<PropertyAccessBase>();
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
RootedValue expr(cx);
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 78b134cf58..51ebd81969 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -245,7 +245,7 @@ BytecodeEmitter::locationOfNameBoundInFunctionScope(JSAtom* name, EmitterScope*
}
bool
-BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
+BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset)
{
size_t oldLength = code().length();
*offset = ptrdiff_t(oldLength);
@@ -260,6 +260,13 @@ BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t* offset)
ReportOutOfMemory(cx);
return false;
}
+
+ // If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
+ // reserve a type set to store its result.
+ if (CodeSpec[op].format & JOF_TYPESET) {
+ if (typesetCount < UINT16_MAX)
+ typesetCount++;
+ }
return true;
}
@@ -297,7 +304,7 @@ BytecodeEmitter::emit1(JSOp op)
MOZ_ASSERT(checkStrictOrSloppy(op));
ptrdiff_t offset;
- if (!emitCheck(1, &offset))
+ if (!emitCheck(op, 1, &offset))
return false;
jsbytecode* code = this->code(offset);
@@ -312,7 +319,7 @@ BytecodeEmitter::emit2(JSOp op, uint8_t op1)
MOZ_ASSERT(checkStrictOrSloppy(op));
ptrdiff_t offset;
- if (!emitCheck(2, &offset))
+ if (!emitCheck(op, 2, &offset))
return false;
jsbytecode* code = this->code(offset);
@@ -332,7 +339,7 @@ BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
MOZ_ASSERT(!IsLocalOp(op));
ptrdiff_t offset;
- if (!emitCheck(3, &offset))
+ if (!emitCheck(op, 3, &offset))
return false;
jsbytecode* code = this->code(offset);
@@ -350,7 +357,7 @@ BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset)
ptrdiff_t length = 1 + ptrdiff_t(extra);
ptrdiff_t off;
- if (!emitCheck(length, &off))
+ if (!emitCheck(op, length, &off))
return false;
jsbytecode* code = this->code(off);
@@ -391,7 +398,7 @@ bool
BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump)
{
ptrdiff_t offset;
- if (!emitCheck(5, &offset))
+ if (!emitCheck(op, 5, &offset))
return false;
jsbytecode* code = this->code(offset);
@@ -634,22 +641,12 @@ BytecodeEmitter::emitLoopEntry(ParseNode* nextpn, JumpList entryJump)
return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
}
-void
-BytecodeEmitter::checkTypeSet(JSOp op)
-{
- if (CodeSpec[op].format & JOF_TYPESET) {
- if (typesetCount < UINT16_MAX)
- typesetCount++;
- }
-}
-
bool
BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand)
{
MOZ_ASSERT(operand <= UINT16_MAX);
if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand)))
return false;
- checkTypeSet(op);
return true;
}
@@ -660,7 +657,6 @@ BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand)
if (!emitN(op, 4, &off))
return false;
SET_UINT32(code(off), operand);
- checkTypeSet(op);
return true;
}
@@ -881,13 +877,12 @@ BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
MOZ_ASSERT(len == size_t(CodeSpec[op].length));
ptrdiff_t offset;
- if (!emitCheck(len, &offset))
+ if (!emitCheck(op, len, &offset))
return false;
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
- checkTypeSet(op);
updateDepth(offset);
return true;
}
@@ -901,13 +896,12 @@ BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
ptrdiff_t offset;
- if (!emitCheck(len, &offset))
+ if (!emitCheck(op, len, &offset))
return false;
jsbytecode* code = this->code(offset);
code[0] = jsbytecode(op);
SET_UINT32_INDEX(code, index);
- checkTypeSet(op);
updateDepth(offset);
return true;
}
@@ -1023,7 +1017,6 @@ BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec)
pc += ENVCOORD_HOPS_LEN;
SET_ENVCOORD_SLOT(pc, ec.slot());
pc += ENVCOORD_SLOT_LEN;
- checkTypeSet(op);
return true;
}
@@ -1713,7 +1706,7 @@ BytecodeEmitter::emitNewInit(JSProtoKey key)
{
const size_t len = 1 + UINT32_INDEX_LEN;
ptrdiff_t offset;
- if (!emitCheck(len, &offset))
+ if (!emitCheck(JSOP_NEWINIT, len, &offset))
return false;
jsbytecode* code = this->code(offset);
@@ -1722,7 +1715,6 @@ BytecodeEmitter::emitNewInit(JSProtoKey key)
code[2] = 0;
code[3] = 0;
code[4] = 0;
- checkTypeSet(JSOP_NEWINIT);
updateDepth(offset);
return true;
}
@@ -1953,7 +1945,6 @@ BytecodeEmitter::emitElemOpBase(JSOp op)
if (!emit1(op))
return false;
- checkTypeSet(op);
return true;
}
@@ -2770,7 +2761,6 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter
if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) // ... RESULT
return false;
- checkTypeSet(JSOP_CALL);
return true;
}
@@ -2860,7 +2850,6 @@ BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope,
if (!emitCall(JSOP_CALL, 0)) // ... ... RESULT
return false;
- checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (completionKind != CompletionKind::Throw) {
@@ -4496,7 +4485,6 @@ BytecodeEmitter::emitRequireObjectCoercible()
return false;
if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
return false;
- checkTypeSet(JSOP_CALL_IGNORES_RV);
if (!emit1(JSOP_POP)) // VAL
return false;
@@ -4543,7 +4531,6 @@ BytecodeEmitter::emitCopyDataProperties(CopyOption option)
}
if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
return false;
- checkTypeSet(JSOP_CALL_IGNORES_RV);
if (!emit1(JSOP_POP)) // -
return false;
@@ -4566,7 +4553,6 @@ BytecodeEmitter::emitIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
- checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
return true;
@@ -4605,7 +4591,6 @@ BytecodeEmitter::emitAsyncIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
- checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
@@ -4619,7 +4604,6 @@ BytecodeEmitter::emitAsyncIterator()
return false;
if (!emitCall(JSOP_CALLITER, 0)) // ITER
return false;
- checkTypeSet(JSOP_CALLITER);
if (!emitCheckIsObj(CheckIsObjectKind::GetIterator)) // ITER
return false;
@@ -6425,7 +6409,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1, iter)) // ITER OLDRESULT RESULT
return false;
- checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwaitInInnermostScope()) // NEXT ITER OLDRESULT RESULT
@@ -6496,7 +6479,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1)) // ITER OLDRESULT FTYPE FVALUE RESULT
return false;
- checkTypeSet(JSOP_CALL);
if (iterKind == IteratorKind::Async) {
if (!emitAwaitInInnermostScope()) // ... FTYPE FVALUE RESULT
@@ -6577,7 +6559,6 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
return false;
if (!emitCall(JSOP_CALL, 1, iter)) // ITER RESULT
return false;
- checkTypeSet(JSOP_CALL);
if (isAsyncGenerator) {
if (!emitAwaitInInnermostScope()) // NEXT ITER RESULT RESULT
@@ -7039,7 +7020,6 @@ BytecodeEmitter::emitSelfHostedCallFunction(BinaryNode* callNode)
if (!emitCall(callOp, argc))
return false;
- checkTypeSet(callOp);
return true;
}
@@ -8329,7 +8309,6 @@ BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody)
} else if (isRest) {
if (!emit1(JSOP_REST))
return false;
- checkTypeSet(JSOP_REST);
}
// Initialize the parameter name.
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index 7a59cf0825..9cbf6ee38b 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -418,17 +418,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter
// Emit function code for the tree rooted at body.
MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode);
- // If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
- // reserve a type set to store its result.
- void checkTypeSet(JSOp op);
-
void updateDepth(ptrdiff_t target);
MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
JSOp strictifySetNameOp(JSOp op);
- MOZ_MUST_USE bool emitCheck(ptrdiff_t delta, ptrdiff_t* offset);
+ MOZ_MUST_USE bool emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset);
// Emit one bytecode.
MOZ_MUST_USE bool emit1(JSOp op);
diff --git a/js/src/frontend/CallOrNewEmitter.cpp b/js/src/frontend/CallOrNewEmitter.cpp
index bd1e32ab02..81e1956c25 100644
--- a/js/src/frontend/CallOrNewEmitter.cpp
+++ b/js/src/frontend/CallOrNewEmitter.cpp
@@ -305,7 +305,6 @@ CallOrNewEmitter::emitEnd(uint32_t argc, const Maybe<uint32_t>& beginPos)
return false;
}
}
- bce_->checkTypeSet(op_);
if (isEval() && beginPos) {
uint32_t lineNum = bce_->parser->tokenStream.srcCoords.lineNum(*beginPos);
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
index 173ffcb8d7..a9f7c6de09 100644
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -345,8 +345,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
return new_<ListNode>(PNK_ARGUMENTS, JSOP_NOP, pos);
}
- BinaryNodeType newSuperCall(Node callee, Node args) {
- return new_<BinaryNode>(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args);
+ BinaryNodeType newSuperCall(Node callee, Node args, bool isSpread) {
+ JSOp op = isSpread ? JSOP_SPREADSUPERCALL : JSOP_SUPERCALL;
+ TokenPos pos(callee->pn_pos.begin, args->pn_pos.end);
+ return new_<BinaryNode>(PNK_SUPERCALL, op, pos, callee, args);
}
BinaryNodeType newTaggedTemplate(Node tag, Node args) {
diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
index 54d2bef108..2f6311eace 100644
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -6,6 +6,8 @@
#ifndef frontend_ParseNode_h
#define frontend_ParseNode_h
+#include <functional>
+
#include "mozilla/Attributes.h"
#include "builtin/ModuleObject.h"
@@ -1420,6 +1422,8 @@ class ListNode : public ParseNode
}
};
+ typedef std::function<bool(ParseNode*)> predicate_fun;
+
#ifdef DEBUG
MOZ_MUST_USE bool contains(ParseNode* target) const {
MOZ_ASSERT(target);
@@ -1460,6 +1464,24 @@ class ListNode : public ParseNode
MOZ_ASSERT_IF(end, contains(end));
return range(head(), end);
}
+
+ // Predicate functions, like their counterparts in C++17
+ size_t count_if(predicate_fun predicate) const {
+ size_t count = 0;
+ for (ParseNode* node = head(); node; node = node->pn_next) {
+ if (predicate(node))
+ count++;
+ }
+ return count;
+ }
+
+ bool any_of(predicate_fun predicate) const {
+ for (ParseNode* node = head(); node; node = node->pn_next) {
+ if (predicate(node))
+ return true;
+ }
+ return false;
+ }
};
inline bool
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 23b479bfbb..7a5cef7d78 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -785,7 +785,7 @@ ParserBase::ParserBase(ExclusiveContext* cx, LifoAlloc& alloc,
#endif
abortedSyntaxParse(false),
isUnexpectedEOF_(false),
- awaitIsKeyword_(false),
+ awaitHandling_(AwaitIsName),
parseGoal_(uint8_t(parseGoal))
{
cx->perThreadData->frontendCollectionPool.addActiveCompilation();
@@ -846,18 +846,18 @@ Parser<ParseHandler>::~Parser()
template <>
void
-Parser<SyntaxParseHandler>::setAwaitIsKeyword(bool isKeyword)
+Parser<SyntaxParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{
- awaitIsKeyword_ = isKeyword;
+ awaitHandling_ = awaitHandling;
}
template <>
void
-Parser<FullParseHandler>::setAwaitIsKeyword(bool isKeyword)
+Parser<FullParseHandler>::setAwaitHandling(AwaitHandling awaitHandling)
{
- awaitIsKeyword_ = isKeyword;
+ awaitHandling_ = awaitHandling;
if (Parser<SyntaxParseHandler>* parser = handler.syntaxParser)
- parser->setAwaitIsKeyword(isKeyword);
+ parser->setAwaitHandling(awaitHandling);
}
template <typename ParseHandler>
@@ -2217,7 +2217,7 @@ Parser<FullParseHandler>::moduleBody(ModuleSharedContext* modulesc)
if (!moduleNode)
return null();
- AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, true);
+ AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, AwaitIsModuleKeyword);
ListNode* stmtList = statementList(YieldIsName);
if (!stmtList) {
return null();
@@ -2490,6 +2490,14 @@ GetYieldHandling(GeneratorKind generatorKind)
return YieldIsKeyword;
}
+static AwaitHandling
+GetAwaitHandling(FunctionAsyncKind asyncKind)
+{
+ if (asyncKind == SyncFunction)
+ return AwaitIsName;
+ return AwaitIsKeyword;
+}
+
template <>
FunctionNode*
Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
@@ -2549,7 +2557,8 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
funpc.setIsStandaloneFunctionBody();
YieldHandling yieldHandling = GetYieldHandling(generatorKind);
- AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
+ AwaitHandling awaitHandling = GetAwaitHandling(asyncKind);
+ AutoAwaitIsKeyword<FullParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionFormalParametersAndBody(InAllowed, yieldHandling, funNode, FunctionSyntaxKind::Statement,
parameterListEnd, /* isStandaloneFunction = */ true))
{
@@ -3641,9 +3650,11 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// See below for an explanation why arrow function parameters and arrow
// function bodies are parsed with different yield/await settings.
{
- bool asyncOrArrowInAsync = funbox->isAsync() ||
- (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword());
- AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncOrArrowInAsync);
+ AwaitHandling awaitHandling = funbox->isAsync() ||
+ (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword())
+ ? AwaitIsKeyword
+ : AwaitIsName;
+ AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, awaitHandling);
if (!functionArguments(yieldHandling, kind, funNode))
return false;
}
@@ -3713,9 +3724,10 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
// Whereas the |yield| in the function body is always parsed as a name.
// The same goes when parsing |await| in arrow functions.
YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind());
+ AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind());
LexicalScopeNodeType body;
{
- AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, funbox->isAsync());
+ AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, bodyAwaitHandling);
body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
if (!body)
return false;
@@ -3873,7 +3885,7 @@ Parser<ParseHandler>::functionExpr(uint32_t toStringStart, InvokedPrediction inv
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
- AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, asyncKind == AsyncFunction);
+ AutoAwaitIsKeyword<ParseHandler> awaitIsKeyword(this, GetAwaitHandling(asyncKind));
GeneratorKind generatorKind = NotGenerator;
TokenKind tt;
if (!tokenStream.getToken(&tt))
@@ -9448,13 +9460,10 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
if (!args)
return null();
- nextMember = handler.newSuperCall(lhs, args);
+ nextMember = handler.newSuperCall(lhs, args, isSpread);
if (!nextMember)
return null();
- if (isSpread)
- handler.setOp(nextMember, JSOP_SPREADSUPERCALL);
-
NameNodeType thisName = newThisName();
if (!thisName)
return null();
@@ -10624,7 +10633,7 @@ Parser<ParseHandler>::importExpr(YieldHandling yieldHandling, bool allowCallSynt
return handler.newCallImport(importHolder, arg);
} else {
- error(JSMSG_UNEXPECTED_TOKEN, TokenKindToDesc(next));
+ error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next));
return null();
}
}
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index fce6ead17d..4dd9f64178 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -591,6 +591,7 @@ enum class PropertyType {
// we're in a function box -- easier and simpler than passing an extra
// parameter everywhere.
enum YieldHandling { YieldIsName, YieldIsKeyword };
+enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword };
enum InHandling { InAllowed, InProhibited };
enum DefaultHandling { NameRequired, AllowDefaultName };
enum TripledotHandling { TripledotAllowed, TripledotProhibited };
@@ -800,13 +801,13 @@ class ParserBase : public StrictModeGetter
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
bool isUnexpectedEOF_:1;
- bool awaitIsKeyword_:1;
+ /* AwaitHandling */ uint8_t awaitHandling_:2;
uint8_t parseGoal_:1;
public:
bool awaitIsKeyword() const {
- return awaitIsKeyword_;
+ return awaitHandling_ != AwaitIsName;
}
ParseGoal parseGoal() const {
@@ -1058,7 +1059,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
~Parser();
friend class AutoAwaitIsKeyword<ParseHandler>;
- void setAwaitIsKeyword(bool isKeyword);
+ void setAwaitHandling(AwaitHandling awaitHandling);
bool checkOptions();
@@ -1643,17 +1644,21 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword
{
private:
Parser<ParseHandler>* parser_;
- bool oldAwaitIsKeyword_;
+ AwaitHandling oldAwaitHandling_;
public:
- AutoAwaitIsKeyword(Parser<ParseHandler>* parser, bool awaitIsKeyword) {
+ AutoAwaitIsKeyword(Parser<ParseHandler>* parser, AwaitHandling awaitHandling) {
parser_ = parser;
- oldAwaitIsKeyword_ = parser_->awaitIsKeyword_;
- parser_->setAwaitIsKeyword(awaitIsKeyword);
+ oldAwaitHandling_ = static_cast<AwaitHandling>(parser_->awaitHandling_);
+
+ // 'await' is always a keyword in module contexts, so we don't modify
+ // the state when the original handling is AwaitIsModuleKeyword.
+ if (oldAwaitHandling_ != AwaitIsModuleKeyword)
+ parser_->setAwaitHandling(awaitHandling);
}
~AutoAwaitIsKeyword() {
- parser_->setAwaitIsKeyword(oldAwaitIsKeyword_);
+ parser_->setAwaitHandling(oldAwaitHandling_);
}
};
diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
index e364f9d680..d8bc3e4959 100644
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -307,7 +307,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
BinaryNodeType newCall(Node callee, Node args) { return NodeFunctionCall; }
BinaryNodeType newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; }
ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
- BinaryNodeType newSuperCall(Node callee, Node args) { return NodeGeneric; }
+ BinaryNodeType newSuperCall(Node callee, Node args, bool isSpread) { return NodeGeneric; }
BinaryNodeType newTaggedTemplate(Node callee, Node args) { return NodeGeneric; }
Node newGenExp(Node callee, Node args) { return NodeGeneric; }
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 7dbe239a7e..61d77adc2e 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4584,7 +4584,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
op == JSOP_INITLOCKEDPROP ||
op == JSOP_INITHIDDENPROP)
{
- if (!InitPropertyOperation(cx, op, obj, id, rhs))
+ if (!InitPropertyOperation(cx, op, obj, name, rhs))
return false;
} else if (op == JSOP_SETNAME ||
op == JSOP_STRICTSETNAME ||
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 7721ed99d5..a6dcdf001a 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -4443,7 +4443,7 @@ IonBuilder::jsop_logical(JSOp op)
MIsNullOrUndefined* isNullOrUndefined =
MIsNullOrUndefined::New(alloc(), lhs);
current->add(isNullOrUndefined);
- test = newTest(isNullOrUndefined, evalLhs, evalRhs);
+ test = newTest(isNullOrUndefined, evalRhs, evalLhs);
break;
}
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 01a22482eb..f191ce7d6d 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -232,8 +232,7 @@ bool
InitProp(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
jsbytecode* pc)
{
- RootedId id(cx, NameToId(name));
- return InitPropertyOperation(cx, JSOp(*pc), obj, id, value);
+ return InitPropertyOperation(cx, JSOp(*pc), obj, name, value);
}
template<bool Equal>
diff --git a/js/src/js.msg b/js/src/js.msg
index b98e6d860b..413469b808 100644
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -339,6 +339,7 @@ MSG_DEF(JSMSG_TOO_MANY_LOCALS, 0, JSEXN_SYNTAXERR, "too many local varia
MSG_DEF(JSMSG_TOO_MANY_YIELDS, 0, JSEXN_SYNTAXERR, "too many yield expressions")
MSG_DEF(JSMSG_TOUGH_BREAK, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch")
MSG_DEF(JSMSG_UNEXPECTED_TOKEN, 2, JSEXN_SYNTAXERR, "expected {0}, got {1}")
+MSG_DEF(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, 1, JSEXN_SYNTAXERR, "unexpected token: {0}")
MSG_DEF(JSMSG_UNEXPECTED_PARAMLIST_END,0, JSEXN_SYNTAXERR, "unexpected end of function parameter list")
MSG_DEF(JSMSG_UNNAMED_CLASS_STMT, 0, JSEXN_SYNTAXERR, "class statement requires a name")
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 0, JSEXN_SYNTAXERR, "function statement requires a name")
diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp
index 082e382663..f0718c0f86 100644
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -179,6 +179,8 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation,
{
Rooted<GeneratorObject*> genObj(cx, &obj->as<GeneratorObject>());
MOZ_ASSERT(genObj->isSuspended());
+ // See comment in InterpreterStack::resumeGeneratorCallFrame
+ MOZ_ASSERT_IF(genObj->isConstructing(), genObj->is<LegacyGeneratorObject>());
RootedFunction callee(cx, &genObj->callee());
RootedValue newTarget(cx, genObj->newTarget());
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 5c2320d3fb..79a4b90200 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -340,12 +340,15 @@ InitGlobalLexicalOperation(JSContext* cx, LexicalEnvironmentObject* lexicalEnvAr
}
inline bool
-InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandleId id, HandleValue rhs)
+InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandlePropertyName name, HandleValue rhs)
{
- if (obj->is<PlainObject>() || obj->is<JSFunction>()) {
+ RootedId id(cx, NameToId(name));
+
+ // {Goanna} DefineProperty works on almost any JSObject, but there's no good way to check what works
+ // So instead, check what we don't handle explicitly.
+ if (!obj->is<UnboxedPlainObject>()) {
unsigned propAttrs = GetInitDataPropAttrs(op);
- return NativeDefineProperty(cx, obj.as<NativeObject>(), id, rhs, nullptr, nullptr,
- propAttrs);
+ return DefineProperty(cx, obj, id, rhs, nullptr, nullptr, propAttrs);
}
MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 5fccc00d54..b17c762eae 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3744,12 +3744,9 @@ CASE(JSOP_INITHIDDENPROP)
/* Load the object being initialized into lval/obj. */
ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
- PropertyName* name = script->getName(REGS.pc);
-
- RootedId& id = rootId0;
- id = NameToId(name);
+ ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
- if (!InitPropertyOperation(cx, JSOp(*REGS.pc), obj, id, rval))
+ if (!InitPropertyOperation(cx, JSOp(*REGS.pc), obj, name, rval))
goto error;
REGS.sp--;
diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
index f46f4b4510..1d88754084 100644
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -994,11 +994,33 @@ RegExpShared::initializeNamedCaptures(JSContext* cx, HandleRegExpShared re,
irregexp::CharacterVectorVector* names,
irregexp::IntegerVector* indices)
{
- MOZ_ASSERT(!re->groupsTemplate_);
MOZ_ASSERT(names);
MOZ_ASSERT(indices);
MOZ_ASSERT(names->length() == indices->length());
+ if (re->getGroupsTemplate()) {
+ // If initializeNamedCaptures was previously called for a different CompilationMode/Latin1Chars combination,
+ // the template object is already created and correct.
+#ifdef DEBUG
+ // In debug builds, verify that.
+ MOZ_ASSERT(re->getGroupsTemplate()->propertyCount() == names->length());
+ RootedId id(cx);
+ RootedNativeObject groupsTemplate(cx, re->getGroupsTemplate());
+ Rooted<PropertyDescriptor> desc(cx);
+ for (uint32_t i = 0; i < names->length(); i++) {
+ irregexp::CharacterVector* cv = (*names)[i];
+ JSAtom* atom = AtomizeChars(cx, cv->begin(), cv->length());
+ MOZ_ASSERT(atom);
+ id = NameToId(atom->asPropertyName());
+ MOZ_ASSERT(NativeGetOwnPropertyDescriptor(cx, groupsTemplate, id, &desc));
+ int32_t idx;
+ MOZ_ASSERT(ToInt32(cx, desc.value(), &idx));
+ MOZ_ASSERT(idx == (*indices)[i]);
+ }
+#endif
+ return true;
+ }
+
// The irregexp parser returns named capture information in the form
// of two arrays. We create a template object with a property for each
// capture name, and store the capture index as Integer in the corresponding value.
@@ -1025,7 +1047,7 @@ RegExpShared::initializeNamedCaptures(JSContext* cx, HandleRegExpShared re,
// Need to explicitly create an Atom (not a String) or it won't get added to the atom table
JSAtom* atom = AtomizeChars(cx, cv->begin(), cv->length());
if (!atom) {
- return false;
+ return false;
}
id = NameToId(atom->asPropertyName());
RootedValue idx(cx, Int32Value((*indices)[i]));
diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h
index 9114a6a79e..5f66159c2c 100644
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -351,7 +351,10 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
constructing = MaybeConstruct(newTarget.isObject());
MOZ_ASSERT_IF(constructing, callee->isConstructor());
} else {
- MOZ_ASSERT(!callee->isConstructor());
+ // We should really be doing MOZ_ASSERT(!callee->isConstructor()) here.
+ // However, the GeneratorObject only stores the callee as-is, which in the case of a lambda generator
+ // (i.e. a |new GeneratorFunction(...)| or derieved generator class) is still flagged as a constructor.
+ // Instead, we check for the correct state in GeneratorObject::resume.
}
// Include callee, |this|, and maybe |new.target|