mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-23 07:37:29 +09:00
Issue #2173 - Add TryNode
This is adjusted from upstream to follow our data structure with PNK_CATCHLIST Based-on: m-c 1479659/8
This commit is contained in:
parent
3bd300e263
commit
d4103253dd
7 changed files with 64 additions and 37 deletions
|
|
@ -1825,7 +1825,7 @@ class ASTSerializer
|
||||||
bool blockStatement(ListNode* node, MutableHandleValue dst);
|
bool blockStatement(ListNode* node, MutableHandleValue dst);
|
||||||
bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst);
|
bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst);
|
||||||
bool switchCase(CaseClause* caseClause, MutableHandleValue dst);
|
bool switchCase(CaseClause* caseClause, MutableHandleValue dst);
|
||||||
bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst);
|
bool tryStatement(TryNode* tryNode, MutableHandleValue dst);
|
||||||
bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst);
|
bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst);
|
||||||
|
|
||||||
bool optExpression(ParseNode* pn, MutableHandleValue dst) {
|
bool optExpression(ParseNode* pn, MutableHandleValue dst) {
|
||||||
|
|
@ -2358,15 +2358,15 @@ ASTSerializer::catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHand
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
|
ASTSerializer::tryStatement(TryNode* tryNode, MutableHandleValue dst)
|
||||||
{
|
{
|
||||||
ParseNode* bodyNode = tryNode->kid1();
|
ParseNode* bodyNode = tryNode->body();
|
||||||
MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos));
|
MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos));
|
||||||
|
|
||||||
ParseNode* catchNode = tryNode->kid2();
|
ListNode* catchList = tryNode->catchList();
|
||||||
MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos));
|
MOZ_ASSERT_IF(catchList, tryNode->pn_pos.encloses(catchList->pn_pos));
|
||||||
|
|
||||||
ParseNode* finallyNode = tryNode->kid3();
|
ParseNode* finallyNode = tryNode->finallyBlock();
|
||||||
MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos));
|
MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos));
|
||||||
|
|
||||||
RootedValue body(cx);
|
RootedValue body(cx);
|
||||||
|
|
@ -2376,7 +2376,7 @@ ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
|
||||||
NodeVector guarded(cx);
|
NodeVector guarded(cx);
|
||||||
RootedValue unguarded(cx, NullValue());
|
RootedValue unguarded(cx, NullValue());
|
||||||
|
|
||||||
if (ListNode* catchList = &catchNode->as<ListNode>()) {
|
if (catchList) {
|
||||||
if (!guarded.reserve(catchList->count()))
|
if (!guarded.reserve(catchList->count()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -2513,7 +2513,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
||||||
return switchStatement(&pn->as<SwitchStatement>(), dst);
|
return switchStatement(&pn->as<SwitchStatement>(), dst);
|
||||||
|
|
||||||
case PNK_TRY:
|
case PNK_TRY:
|
||||||
return tryStatement(&pn->as<TernaryNode>(), dst);
|
return tryStatement(&pn->as<TryNode>(), dst);
|
||||||
|
|
||||||
case PNK_WITH:
|
case PNK_WITH:
|
||||||
case PNK_WHILE:
|
case PNK_WHILE:
|
||||||
|
|
|
||||||
|
|
@ -1438,19 +1438,18 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||||
|
|
||||||
case PNK_TRY:
|
case PNK_TRY:
|
||||||
{
|
{
|
||||||
TernaryNode* tryNode = &pn->as<TernaryNode>();
|
TryNode* tryNode = &pn->as<TryNode>();
|
||||||
if (!checkSideEffects(tryNode->kid1(), answer))
|
if (!checkSideEffects(tryNode->body(), answer))
|
||||||
return false;
|
return false;
|
||||||
if (*answer)
|
if (*answer)
|
||||||
return true;
|
return true;
|
||||||
if (ParseNode* catchList = tryNode->kid2()) {
|
if (ListNode* catchList = tryNode->catchList()) {
|
||||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
|
||||||
if (!checkSideEffects(catchList, answer))
|
if (!checkSideEffects(catchList, answer))
|
||||||
return false;
|
return false;
|
||||||
if (*answer)
|
if (*answer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
|
||||||
if (!checkSideEffects(finallyBlock, answer))
|
if (!checkSideEffects(finallyBlock, answer))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -4220,10 +4219,10 @@ BytecodeEmitter::emitCatch(TernaryNode* catchNode)
|
||||||
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
|
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
|
||||||
// comment on EmitSwitch.
|
// comment on EmitSwitch.
|
||||||
MOZ_NEVER_INLINE bool
|
MOZ_NEVER_INLINE bool
|
||||||
BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
BytecodeEmitter::emitTry(TryNode* tryNode)
|
||||||
{
|
{
|
||||||
ParseNode* catchList = tryNode->kid2();
|
ListNode* catchList = tryNode->catchList();
|
||||||
ParseNode* finallyNode = tryNode->kid3();
|
ParseNode* finallyNode = tryNode->finallyBlock();
|
||||||
|
|
||||||
TryEmitter::Kind kind;
|
TryEmitter::Kind kind;
|
||||||
if (catchList) {
|
if (catchList) {
|
||||||
|
|
@ -4240,13 +4239,11 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
||||||
if (!tryCatch.emitTry())
|
if (!tryCatch.emitTry())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!emitTree(tryNode->kid1()))
|
if (!emitTree(tryNode->body()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If this try has a catch block, emit it.
|
// If this try has a catch block, emit it.
|
||||||
if (catchList) {
|
if (catchList) {
|
||||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
|
||||||
|
|
||||||
// The emitted code for a catch block looks like:
|
// The emitted code for a catch block looks like:
|
||||||
//
|
//
|
||||||
// [pushlexicalenv] only if any local aliased
|
// [pushlexicalenv] only if any local aliased
|
||||||
|
|
@ -4272,7 +4269,7 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
||||||
// code if appropriate, and is also used for the catch-all trynote for
|
// code if appropriate, and is also used for the catch-all trynote for
|
||||||
// capturing exceptions thrown from catch{} blocks.
|
// capturing exceptions thrown from catch{} blocks.
|
||||||
//
|
//
|
||||||
for (ParseNode* scopeNode : catchList->as<ListNode>().contents()) {
|
for (ParseNode* scopeNode : catchList->contents()) {
|
||||||
LexicalScopeNode* catchScope = &scopeNode->as<LexicalScopeNode>();
|
LexicalScopeNode* catchScope = &scopeNode->as<LexicalScopeNode>();
|
||||||
if (!tryCatch.emitCatch())
|
if (!tryCatch.emitCatch())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -8703,7 +8700,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNK_TRY:
|
case PNK_TRY:
|
||||||
if (!emitTry(&pn->as<TernaryNode>()))
|
if (!emitTry(&pn->as<TryNode>()))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -592,7 +592,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
||||||
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
|
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
|
||||||
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
|
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
|
||||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode);
|
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TryNode* tryNode);
|
||||||
|
|
||||||
enum DestructuringFlavor {
|
enum DestructuringFlavor {
|
||||||
// Destructuring into a declaration.
|
// Destructuring into a declaration.
|
||||||
|
|
|
||||||
|
|
@ -1230,10 +1230,9 @@ FoldReturn(ExclusiveContext* cx, UnaryNode* node, Parser<FullParseHandler>& pars
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
FoldTry(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
FoldTry(ExclusiveContext* cx, TryNode* node, Parser<FullParseHandler>& parser,
|
||||||
bool inGenexpLambda)
|
bool inGenexpLambda)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(node->isKind(PNK_TRY));
|
|
||||||
ParseNode** statements = node->unsafeKid1Reference();
|
ParseNode** statements = node->unsafeKid1Reference();
|
||||||
if (!Fold(cx, statements, parser, inGenexpLambda))
|
if (!Fold(cx, statements, parser, inGenexpLambda))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1845,7 +1844,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||||
return FoldReturn(cx, &pn->as<UnaryNode>(), parser, inGenexpLambda);
|
return FoldReturn(cx, &pn->as<UnaryNode>(), parser, inGenexpLambda);
|
||||||
|
|
||||||
case PNK_TRY:
|
case PNK_TRY:
|
||||||
return FoldTry(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
return FoldTry(cx, &pn->as<TryNode>(), parser, inGenexpLambda);
|
||||||
|
|
||||||
case PNK_CATCH:
|
case PNK_CATCH:
|
||||||
return FoldCatch(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
return FoldCatch(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||||
|
|
|
||||||
|
|
@ -686,8 +686,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
||||||
|
|
||||||
TernaryNodeType newTryStatement(uint32_t begin, Node body, ListNodeType catchList,
|
TernaryNodeType newTryStatement(uint32_t begin, Node body, ListNodeType catchList,
|
||||||
Node finallyBlock) {
|
Node finallyBlock) {
|
||||||
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
|
return new_<TryNode>(begin, body, catchList, finallyBlock);
|
||||||
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
|
DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
|
||||||
|
|
|
||||||
|
|
@ -668,16 +668,15 @@ class NameResolver
|
||||||
// and finally block are optional (but at least one or the other must
|
// and finally block are optional (but at least one or the other must
|
||||||
// be present).
|
// be present).
|
||||||
case PNK_TRY: {
|
case PNK_TRY: {
|
||||||
TernaryNode* tryNode = &cur->as<TernaryNode>();
|
TryNode* tryNode = &cur->as<TryNode>();
|
||||||
if (!resolve(tryNode->kid1(), prefix))
|
if (!resolve(tryNode->body(), prefix))
|
||||||
return false;
|
return false;
|
||||||
MOZ_ASSERT(tryNode->kid2() || tryNode->kid3());
|
MOZ_ASSERT(tryNode->catchList() || tryNode->finallyBlock());
|
||||||
if (ParseNode* catchList = tryNode->kid2()) {
|
if (ListNode* catchList = tryNode->catchList()) {
|
||||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
|
||||||
if (!resolve(catchList, prefix))
|
if (!resolve(catchList, prefix))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
|
||||||
if (!resolve(finallyBlock, prefix))
|
if (!resolve(finallyBlock, prefix))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -308,10 +308,10 @@ IsTypeofKind(ParseNodeKind kind)
|
||||||
* kid3: update expr after second ';' or nullptr
|
* kid3: update expr after second ';' or nullptr
|
||||||
* PNK_THROW (UnaryNode)
|
* PNK_THROW (UnaryNode)
|
||||||
* kid: thrown exception
|
* kid: thrown exception
|
||||||
* PNK_TRY (TernaryNode)
|
* PNK_TRY (TryNode)
|
||||||
* kid1: try block
|
* body: try block
|
||||||
* kid2: null or PNK_CATCHLIST list
|
* catchList: null or PNK_CATCHLIST list
|
||||||
* kid3: null or finally block
|
* finallyBlock: null or finally block
|
||||||
* PNK_CATCHLIST (ListNode)
|
* PNK_CATCHLIST (ListNode)
|
||||||
* head: list of PNK_LEXICALSCOPE nodes, one per catch-block,
|
* head: list of PNK_LEXICALSCOPE nodes, one per catch-block,
|
||||||
* each with scopeBody pointing to a PNK_CATCH node
|
* each with scopeBody pointing to a PNK_CATCH node
|
||||||
|
|
@ -593,6 +593,8 @@ enum ParseNodeArity
|
||||||
macro(TernaryNode, TernaryNodeType, asTernary) \
|
macro(TernaryNode, TernaryNodeType, asTernary) \
|
||||||
macro(ClassNode, ClassNodeType, asClass) \
|
macro(ClassNode, ClassNodeType, asClass) \
|
||||||
macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) \
|
macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) \
|
||||||
|
macro(TryNode, TryNodeType, asTry) \
|
||||||
|
\
|
||||||
macro(UnaryNode, UnaryNodeType, asUnary) \
|
macro(UnaryNode, UnaryNodeType, asUnary) \
|
||||||
macro(ThisLiteral, ThisLiteralType, asThisLiteral)
|
macro(ThisLiteral, ThisLiteralType, asThisLiteral)
|
||||||
|
|
||||||
|
|
@ -1711,6 +1713,37 @@ class ConditionalExpression : public TernaryNode
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TryNode : public TernaryNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TryNode(uint32_t begin, ParseNode* body, ListNode* catchList, ParseNode* finallyBlock)
|
||||||
|
: TernaryNode(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock,
|
||||||
|
TokenPos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end))
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(body);
|
||||||
|
MOZ_ASSERT(catchList || finallyBlock);
|
||||||
|
MOZ_ASSERT_IF(catchList, catchList->isKind(PNK_CATCHLIST));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool test(const ParseNode& node) {
|
||||||
|
bool match = node.isKind(PNK_TRY);
|
||||||
|
MOZ_ASSERT_IF(match, node.is<TernaryNode>());
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode* body() const {
|
||||||
|
return kid1();
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode* catchList() const {
|
||||||
|
return kid2() ? &kid2()->as<ListNode>() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode* finallyBlock() const {
|
||||||
|
return kid3();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ThisLiteral : public UnaryNode
|
class ThisLiteral : public UnaryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue