mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +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 switchStatement(SwitchStatement* switchStmt, 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 optExpression(ParseNode* pn, MutableHandleValue dst) {
|
||||
|
|
@ -2358,15 +2358,15 @@ ASTSerializer::catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHand
|
|||
}
|
||||
|
||||
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));
|
||||
|
||||
ParseNode* catchNode = tryNode->kid2();
|
||||
MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos));
|
||||
ListNode* catchList = tryNode->catchList();
|
||||
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));
|
||||
|
||||
RootedValue body(cx);
|
||||
|
|
@ -2376,7 +2376,7 @@ ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
|
|||
NodeVector guarded(cx);
|
||||
RootedValue unguarded(cx, NullValue());
|
||||
|
||||
if (ListNode* catchList = &catchNode->as<ListNode>()) {
|
||||
if (catchList) {
|
||||
if (!guarded.reserve(catchList->count()))
|
||||
return false;
|
||||
|
||||
|
|
@ -2513,7 +2513,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
|||
return switchStatement(&pn->as<SwitchStatement>(), dst);
|
||||
|
||||
case PNK_TRY:
|
||||
return tryStatement(&pn->as<TernaryNode>(), dst);
|
||||
return tryStatement(&pn->as<TryNode>(), dst);
|
||||
|
||||
case PNK_WITH:
|
||||
case PNK_WHILE:
|
||||
|
|
|
|||
|
|
@ -1438,19 +1438,18 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
|
||||
case PNK_TRY:
|
||||
{
|
||||
TernaryNode* tryNode = &pn->as<TernaryNode>();
|
||||
if (!checkSideEffects(tryNode->kid1(), answer))
|
||||
TryNode* tryNode = &pn->as<TryNode>();
|
||||
if (!checkSideEffects(tryNode->body(), answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
if (ParseNode* catchList = tryNode->kid2()) {
|
||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
||||
if (ListNode* catchList = tryNode->catchList()) {
|
||||
if (!checkSideEffects(catchList, answer))
|
||||
return false;
|
||||
if (*answer)
|
||||
return true;
|
||||
}
|
||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
||||
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
|
||||
if (!checkSideEffects(finallyBlock, answer))
|
||||
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
|
||||
// comment on EmitSwitch.
|
||||
MOZ_NEVER_INLINE bool
|
||||
BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
||||
BytecodeEmitter::emitTry(TryNode* tryNode)
|
||||
{
|
||||
ParseNode* catchList = tryNode->kid2();
|
||||
ParseNode* finallyNode = tryNode->kid3();
|
||||
ListNode* catchList = tryNode->catchList();
|
||||
ParseNode* finallyNode = tryNode->finallyBlock();
|
||||
|
||||
TryEmitter::Kind kind;
|
||||
if (catchList) {
|
||||
|
|
@ -4240,13 +4239,11 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
|
|||
if (!tryCatch.emitTry())
|
||||
return false;
|
||||
|
||||
if (!emitTree(tryNode->kid1()))
|
||||
if (!emitTree(tryNode->body()))
|
||||
return false;
|
||||
|
||||
// If this try has a catch block, emit it.
|
||||
if (catchList) {
|
||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
||||
|
||||
// The emitted code for a catch block looks like:
|
||||
//
|
||||
// [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
|
||||
// capturing exceptions thrown from catch{} blocks.
|
||||
//
|
||||
for (ParseNode* scopeNode : catchList->as<ListNode>().contents()) {
|
||||
for (ParseNode* scopeNode : catchList->contents()) {
|
||||
LexicalScopeNode* catchScope = &scopeNode->as<LexicalScopeNode>();
|
||||
if (!tryCatch.emitCatch())
|
||||
return false;
|
||||
|
|
@ -8703,7 +8700,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case PNK_TRY:
|
||||
if (!emitTry(&pn->as<TernaryNode>()))
|
||||
if (!emitTry(&pn->as<TryNode>()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
|
||||
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
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 {
|
||||
// Destructuring into a declaration.
|
||||
|
|
|
|||
|
|
@ -1230,10 +1230,9 @@ FoldReturn(ExclusiveContext* cx, UnaryNode* node, Parser<FullParseHandler>& pars
|
|||
}
|
||||
|
||||
static bool
|
||||
FoldTry(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
|
||||
FoldTry(ExclusiveContext* cx, TryNode* node, Parser<FullParseHandler>& parser,
|
||||
bool inGenexpLambda)
|
||||
{
|
||||
MOZ_ASSERT(node->isKind(PNK_TRY));
|
||||
ParseNode** statements = node->unsafeKid1Reference();
|
||||
if (!Fold(cx, statements, parser, inGenexpLambda))
|
||||
return false;
|
||||
|
|
@ -1845,7 +1844,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
return FoldReturn(cx, &pn->as<UnaryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_TRY:
|
||||
return FoldTry(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
|
||||
return FoldTry(cx, &pn->as<TryNode>(), parser, inGenexpLambda);
|
||||
|
||||
case PNK_CATCH:
|
||||
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,
|
||||
Node finallyBlock) {
|
||||
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
|
||||
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
|
||||
return new_<TryNode>(begin, body, catchList, finallyBlock);
|
||||
}
|
||||
|
||||
DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
|
||||
|
|
|
|||
|
|
@ -668,16 +668,15 @@ class NameResolver
|
|||
// and finally block are optional (but at least one or the other must
|
||||
// be present).
|
||||
case PNK_TRY: {
|
||||
TernaryNode* tryNode = &cur->as<TernaryNode>();
|
||||
if (!resolve(tryNode->kid1(), prefix))
|
||||
TryNode* tryNode = &cur->as<TryNode>();
|
||||
if (!resolve(tryNode->body(), prefix))
|
||||
return false;
|
||||
MOZ_ASSERT(tryNode->kid2() || tryNode->kid3());
|
||||
if (ParseNode* catchList = tryNode->kid2()) {
|
||||
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
|
||||
MOZ_ASSERT(tryNode->catchList() || tryNode->finallyBlock());
|
||||
if (ListNode* catchList = tryNode->catchList()) {
|
||||
if (!resolve(catchList, prefix))
|
||||
return false;
|
||||
}
|
||||
if (ParseNode* finallyBlock = tryNode->kid3()) {
|
||||
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
|
||||
if (!resolve(finallyBlock, prefix))
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,10 +308,10 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* kid3: update expr after second ';' or nullptr
|
||||
* PNK_THROW (UnaryNode)
|
||||
* kid: thrown exception
|
||||
* PNK_TRY (TernaryNode)
|
||||
* kid1: try block
|
||||
* kid2: null or PNK_CATCHLIST list
|
||||
* kid3: null or finally block
|
||||
* PNK_TRY (TryNode)
|
||||
* body: try block
|
||||
* catchList: null or PNK_CATCHLIST list
|
||||
* finallyBlock: null or finally block
|
||||
* PNK_CATCHLIST (ListNode)
|
||||
* head: list of PNK_LEXICALSCOPE nodes, one per catch-block,
|
||||
* each with scopeBody pointing to a PNK_CATCH node
|
||||
|
|
@ -593,6 +593,8 @@ enum ParseNodeArity
|
|||
macro(TernaryNode, TernaryNodeType, asTernary) \
|
||||
macro(ClassNode, ClassNodeType, asClass) \
|
||||
macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) \
|
||||
macro(TryNode, TryNodeType, asTry) \
|
||||
\
|
||||
macro(UnaryNode, UnaryNodeType, asUnary) \
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue