mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 15:17:29 +09:00
Issue #2298 - Support '#x in obj' ergonomic brand check syntax
This commit is contained in:
parent
b0d9f0e2ed
commit
6ff7b5269e
3 changed files with 40 additions and 4 deletions
|
|
@ -7754,10 +7754,23 @@ bool
|
||||||
BytecodeEmitter::emitLeftAssociative(ListNode* node)
|
BytecodeEmitter::emitLeftAssociative(ListNode* node)
|
||||||
{
|
{
|
||||||
// Left-associative operator chain.
|
// Left-associative operator chain.
|
||||||
if (!emitTree(node->head()))
|
|
||||||
return false;
|
|
||||||
JSOp op = node->getOp();
|
JSOp op = node->getOp();
|
||||||
ParseNode* nextExpr = node->head()->pn_next;
|
ParseNode* headExpr = node->head();
|
||||||
|
if (op == JSOP_IN && headExpr->isKind(PNK_NAME) && headExpr->as<NameNode>().isPrivateName()) {
|
||||||
|
// {Goanna} The only way a "naked" private name can show up as the leftmost side of an in-chain
|
||||||
|
// is from an ergonomic brand check (`this.#x in ...` would be a PNK_DOT child node).
|
||||||
|
// Instead of going through the emitTree machinery, we pretend that this identifier
|
||||||
|
// reference is actually a string, which allows us to use the JSOP_IN interpreter routines.
|
||||||
|
// This erroneously doesn't call updateLineNumberNotes, but this is not a big issue:
|
||||||
|
// the begin pos is correct as we're on the start of the current tree, the end is on the
|
||||||
|
// same line anyway.
|
||||||
|
if (!emitAtomOp(headExpr->as<NameNode>().atom(), JSOP_STRING))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!emitTree(headExpr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ParseNode* nextExpr = headExpr->pn_next;
|
||||||
do {
|
do {
|
||||||
if (!emitTree(nextExpr))
|
if (!emitTree(nextExpr))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -8949,6 +8949,15 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
|
||||||
if (!tokenStream.getToken(&tok))
|
if (!tokenStream.getToken(&tok))
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
|
// Ensure that if we have a private name lhs we are legally constructing a
|
||||||
|
// `#x in obj` expression:
|
||||||
|
if (handler.isPrivateName(pn)) {
|
||||||
|
if (tok != TOK_IN) {
|
||||||
|
error(JSMSG_ILLEGAL_PRIVATE_NAME);
|
||||||
|
return null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ParseNodeKind pnk;
|
ParseNodeKind pnk;
|
||||||
if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) {
|
if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) {
|
||||||
// We're definitely not in a destructuring context, so report any
|
// We're definitely not in a destructuring context, so report any
|
||||||
|
|
@ -8985,7 +8994,20 @@ Parser<ParseHandler>::orExpr1(InHandling inHandling, YieldHandling yieldHandling
|
||||||
// If we have not detected a mixing error at this point, record that
|
// If we have not detected a mixing error at this point, record that
|
||||||
// we have an unparenthesized expression, in case we have one later.
|
// we have an unparenthesized expression, in case we have one later.
|
||||||
unparenthesizedExpression = EnforcedParentheses::CoalesceExpr;
|
unparenthesizedExpression = EnforcedParentheses::CoalesceExpr;
|
||||||
break;
|
break;
|
||||||
|
case TOK_IN:
|
||||||
|
// if the LHS is a private name, and the operator is In,
|
||||||
|
// ensure we're construcing an ergonomic brand check of
|
||||||
|
// '#x in y', rather than having a higher precedence operator
|
||||||
|
// like + cause a different reduction, such as
|
||||||
|
// 1 + #x in y.
|
||||||
|
if (handler.isPrivateName(pn)) {
|
||||||
|
if (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(PNK_IN)) {
|
||||||
|
error(JSMSG_ILLEGAL_PRIVATE_NAME);
|
||||||
|
return null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// Do nothing in other cases.
|
// Do nothing in other cases.
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -364,6 +364,7 @@ MSG_DEF(JSMSG_BAD_NEW_OPTIONAL, 0, JSEXN_SYNTAXERR, "new keyword cannot b
|
||||||
MSG_DEF(JSMSG_BAD_OPTIONAL_TEMPLATE, 0, JSEXN_SYNTAXERR, "tagged template cannot be used with optional chain")
|
MSG_DEF(JSMSG_BAD_OPTIONAL_TEMPLATE, 0, JSEXN_SYNTAXERR, "tagged template cannot be used with optional chain")
|
||||||
MSG_DEF(JSMSG_ESCAPED_KEYWORD, 0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
|
MSG_DEF(JSMSG_ESCAPED_KEYWORD, 0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
|
||||||
MSG_DEF(JSMSG_FIELDS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "fields are not currently supported")
|
MSG_DEF(JSMSG_FIELDS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "fields are not currently supported")
|
||||||
|
MSG_DEF(JSMSG_ILLEGAL_PRIVATE_NAME, 0, JSEXN_SYNTAXERR, "private names aren't valid in this context")
|
||||||
|
|
||||||
// asm.js
|
// asm.js
|
||||||
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}")
|
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue