summaryrefslogtreecommitdiff
path: root/js/src/frontend/ParseNode.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend/ParseNode.h')
-rw-r--r--js/src/frontend/ParseNode.h108
1 files changed, 101 insertions, 7 deletions
diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
index 8e5e74d3b7..0ad0fe0885 100644
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -34,6 +34,10 @@ class ObjectBox;
F(POSTDECREMENT) \
F(DOT) \
F(ELEM) \
+ F(OPTDOT) \
+ F(OPTCHAIN) \
+ F(OPTELEM) \
+ F(OPTCALL) \
F(ARRAY) \
F(ELISION) \
F(STATEMENTLIST) \
@@ -76,6 +80,7 @@ class ObjectBox;
F(DELETEPROP) \
F(DELETEELEM) \
F(DELETEEXPR) \
+ F(DELETEOPTCHAIN) \
F(TRY) \
F(CATCH) \
F(CATCHLIST) \
@@ -371,6 +376,29 @@ IsTypeofKind(ParseNodeKind kind)
* for a more-specific PNK_DELETE* unless constant
* folding (or a similar parse tree manipulation) has
* occurred
+ * PNK_DELETEOPTCHAIN unary pn_kid: MEMBER expr that's evaluated, then the
+ * overall delete evaluates to true; If constant
+ * folding occurs, PNK_ELEM may become PNK_DOT.
+ * PNK_OPTELEM does not get folded into PNK_OPTDOT.
+ * PNK_OPTCHAIN unary pn_kid: expression that is evaluated as a chain.
+ * Contains one or more optional nodes. Its first node
+ * is always an optional node, such as PNK_OPTELEM,
+ * PNK_OPTDOT, or PNK_OPTCALL. This will shortcircuit
+ * and return 'undefined' without evaluating the rest
+ * of the expression if any of the optional nodes it
+ * contains are nullish. An optional chain can also
+ * contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME,
+ * PNK_CALL, etc. These are evaluated normally.
+ * PNK_OPTDOT name pn_expr: MEMBER expr to left of .
+ * short circuits back to PNK_OPTCHAIN if nullish.
+ * pn_atom: name to right of .
+ * PNK_OPTELEM binary pn_left: MEMBER expr to left of [
+ * short circuits back to PNK_OPTCHAIN if nullish.
+ * pn_right: expr between [ and ]
+ * PNK_OPTCALL list pn_head: list of call, arg1, arg2, ... argN
+ * pn_count: 1 + N (where N is number of args)
+ * call is a MEMBER expr naming a callable object,
+ * short circuits back to PNK_OPTCHAIN if nullish.
* PNK_DOT name pn_expr: MEMBER expr to left of .
* pn_atom: name to right of .
* PNK_ELEM binary pn_left: MEMBER expr to left of [
@@ -1182,11 +1210,12 @@ class RegExpLiteral : public NullaryNode
}
};
-class PropertyAccess : public ParseNode
+class PropertyAccessBase : public ParseNode
{
public:
- PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin, uint32_t end)
- : ParseNode(PNK_DOT, JSOP_NOP, PN_NAME, TokenPos(begin, end))
+ PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, PropertyName* name,
+ uint32_t begin, uint32_t end)
+ : ParseNode(kind, JSOP_NOP, PN_NAME, TokenPos(begin, end))
{
MOZ_ASSERT(lhs != nullptr);
MOZ_ASSERT(name != nullptr);
@@ -1195,7 +1224,8 @@ class PropertyAccess : public ParseNode
}
static bool test(const ParseNode& node) {
- bool match = node.isKind(PNK_DOT);
+ bool match = node.isKind(PNK_DOT) ||
+ node.isKind(PNK_OPTDOT);
MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
return match;
}
@@ -1207,6 +1237,24 @@ class PropertyAccess : public ParseNode
PropertyName& name() const {
return *pn_u.name.atom->asPropertyName();
}
+};
+
+class PropertyAccess : public PropertyAccessBase
+{
+ public:
+ PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin,
+ uint32_t end)
+ : PropertyAccessBase(PNK_DOT, lhs, name, begin, end)
+ {
+ MOZ_ASSERT(lhs != nullptr);
+ MOZ_ASSERT(name != nullptr);
+ }
+
+ static bool test(const ParseNode& node) {
+ bool match = node.isKind(PNK_DOT);
+ MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
+ return match;
+ }
bool isSuper() const {
// PNK_SUPERBASE cannot result from any expression syntax.
@@ -1214,17 +1262,50 @@ class PropertyAccess : public ParseNode
}
};
-class PropertyByValue : public ParseNode
+class OptionalPropertyAccess : public PropertyAccessBase
+{
+ public:
+ OptionalPropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin,
+ uint32_t end)
+ : PropertyAccessBase(PNK_OPTDOT, lhs, name, begin, end)
+ {
+ MOZ_ASSERT(lhs != nullptr);
+ MOZ_ASSERT(name != nullptr);
+ }
+
+ static bool test(const ParseNode& node) {
+ bool match = node.isKind(PNK_OPTDOT);
+ MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
+ return match;
+ }
+};
+
+class PropertyByValueBase : public ParseNode
{
public:
- PropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin, uint32_t end)
- : ParseNode(PNK_ELEM, JSOP_NOP, PN_BINARY, TokenPos(begin, end))
+ PropertyByValueBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* propExpr,
+ uint32_t begin, uint32_t end)
+ : ParseNode(kind, JSOP_NOP, PN_BINARY, TokenPos(begin, end))
{
pn_u.binary.left = lhs;
pn_u.binary.right = propExpr;
}
static bool test(const ParseNode& node) {
+ bool match = node.isKind(PNK_ELEM) ||
+ node.isKind(PNK_OPTELEM);
+ MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
+ return match;
+ }
+};
+
+class PropertyByValue : public PropertyByValueBase {
+ public:
+ PropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin,
+ uint32_t end)
+ : PropertyByValueBase(PNK_ELEM, lhs, propExpr, begin, end) {}
+
+ static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_ELEM);
MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
return match;
@@ -1235,6 +1316,19 @@ class PropertyByValue : public ParseNode
}
};
+class OptionalPropertyByValue : public PropertyByValueBase {
+ public:
+ OptionalPropertyByValue(ParseNode* lhs, ParseNode* propExpr,
+ uint32_t begin, uint32_t end)
+ : PropertyByValueBase(PNK_OPTELEM, lhs, propExpr, begin, end) {}
+
+ static bool test(const ParseNode& node) {
+ bool match = node.isKind(PNK_OPTELEM);
+ MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
+ return match;
+ }
+};
+
/*
* A CallSiteNode represents the implicit call site object argument in a TaggedTemplate.
*/