mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
Issue #2173 - Fix exporting array and object binding patterns
Examples:
export const [name1, name2] = [1, 2];
export var {...name} = get;
Based-on: m-c 1446811, m-c 1462286
This commit is contained in:
parent
74032644f5
commit
0b2e8c4818
4 changed files with 204 additions and 13 deletions
|
|
@ -1238,14 +1238,25 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
|||
case PNK_CONST:
|
||||
case PNK_LET: {
|
||||
MOZ_ASSERT(kid->isArity(PN_LIST));
|
||||
for (ParseNode* var = kid->pn_head; var; var = var->pn_next) {
|
||||
if (var->isKind(PNK_ASSIGN))
|
||||
var = var->pn_left;
|
||||
MOZ_ASSERT(var->isKind(PNK_NAME));
|
||||
RootedAtom localName(cx_, var->pn_atom);
|
||||
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
for (ParseNode* binding = kid->pn_head; binding; binding = binding->pn_next) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
else
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
|
||||
if (binding->isKind(PNK_NAME)) {
|
||||
RootedAtom localName(cx_, binding->pn_atom);
|
||||
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
} else if (binding->isKind(PNK_ARRAY)) {
|
||||
if (!processExportArrayBinding(binding))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
|
||||
if (!processExportObjectBinding(binding))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1268,6 +1279,75 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportBinding(frontend::ParseNode* binding)
|
||||
{
|
||||
if (binding->isKind(PNK_NAME)) {
|
||||
RootedAtom name(cx_, binding->pn_atom);
|
||||
return appendExportEntry(name, name);
|
||||
}
|
||||
|
||||
if (binding->isKind(PNK_ARRAY))
|
||||
return processExportArrayBinding(binding);
|
||||
|
||||
MOZ_ASSERT(binding->isKind(PNK_OBJECT));
|
||||
return processExportObjectBinding(binding);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportArrayBinding(frontend::ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
if (node->isKind(PNK_ELISION))
|
||||
continue;
|
||||
|
||||
if (node->isKind(PNK_SPREAD))
|
||||
node = node->pn_kid;
|
||||
else if (node->isKind(PNK_ASSIGN))
|
||||
node = node->pn_left;
|
||||
|
||||
if (!processExportBinding(node))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportObjectBinding(frontend::ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
|
||||
node->isKind(PNK_COLON) ||
|
||||
node->isKind(PNK_SHORTHAND) ||
|
||||
node->isKind(PNK_SPREAD));
|
||||
|
||||
ParseNode* target;
|
||||
if (node->isKind(PNK_SPREAD)) {
|
||||
target = node->pn_kid;
|
||||
} else {
|
||||
if (node->isKind(PNK_MUTATEPROTO))
|
||||
target = node->pn_kid;
|
||||
else
|
||||
target = node->pn_right;
|
||||
|
||||
if (target->isKind(PNK_ASSIGN))
|
||||
target = target->pn_left;
|
||||
}
|
||||
|
||||
if (!processExportBinding(target))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -352,6 +352,10 @@ class MOZ_STACK_CLASS ModuleBuilder
|
|||
|
||||
ImportEntryObject* importEntryFor(JSAtom* localName) const;
|
||||
|
||||
bool processExportBinding(frontend::ParseNode* pn);
|
||||
bool processExportArrayBinding(frontend::ParseNode* pn);
|
||||
bool processExportObjectBinding(frontend::ParseNode* pn);
|
||||
|
||||
bool appendExportEntry(HandleAtom exportName, HandleAtom localName,
|
||||
frontend::ParseNode* node = nullptr);
|
||||
bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
|
||||
|
|
|
|||
|
|
@ -5189,16 +5189,94 @@ Parser<SyntaxParseHandler>::checkExportedName(JSAtom* exportName)
|
|||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForArrayBinding(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_ARRAY));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
if (node->isKind(PNK_ELISION))
|
||||
continue;
|
||||
|
||||
ParseNode* binding;
|
||||
if (node->isKind(PNK_SPREAD))
|
||||
binding = node->pn_kid;
|
||||
else if (node->isKind(PNK_ASSIGN))
|
||||
binding = node->pn_left;
|
||||
else
|
||||
binding = node;
|
||||
|
||||
if (!checkExportedNamesForDeclaration(binding))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForArrayBinding(Node node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForObjectBinding(ParseNode* pn)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pn->isArity(PN_LIST));
|
||||
|
||||
for (ParseNode* node = pn->pn_head; node; node = node->pn_next) {
|
||||
MOZ_ASSERT(node->isKind(PNK_MUTATEPROTO) ||
|
||||
node->isKind(PNK_COLON) ||
|
||||
node->isKind(PNK_SHORTHAND) ||
|
||||
node->isKind(PNK_SPREAD));
|
||||
|
||||
ParseNode* target;
|
||||
if (node->isKind(PNK_SPREAD)) {
|
||||
target = node->pn_kid;
|
||||
} else {
|
||||
if (node->isKind(PNK_MUTATEPROTO))
|
||||
target = node->pn_kid;
|
||||
else
|
||||
target = node->pn_right;
|
||||
|
||||
if (target->isKind(PNK_ASSIGN))
|
||||
target = target->pn_left;
|
||||
}
|
||||
|
||||
if (!checkExportedNamesForDeclaration(target))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForObjectBinding(Node node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForDeclaration(ParseNode* node)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
if (!checkExportedName(binding->pn_atom))
|
||||
if (node->isKind(PNK_NAME)) {
|
||||
if (!checkExportedName(node->pn_atom))
|
||||
return false;
|
||||
} else if (node->isKind(PNK_ARRAY)) {
|
||||
if (!checkExportedNamesForArrayBinding(node))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(node->isKind(PNK_OBJECT));
|
||||
if (!checkExportedNamesForObjectBinding(node))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -5213,6 +5291,32 @@ Parser<SyntaxParseHandler>::checkExportedNamesForDeclaration(Node node)
|
|||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNamesForDeclarationList(ParseNode* node)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
else
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
|
||||
if (!checkExportedNamesForDeclaration(binding))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::checkExportedNamesForDeclarationList(Node node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::checkExportedNameForClause(ParseNode* node)
|
||||
|
|
@ -5486,7 +5590,7 @@ Parser<ParseHandler>::exportVariableStatement(uint32_t begin)
|
|||
return null();
|
||||
if (!matchOrInsertSemicolonAfterExpression())
|
||||
return null();
|
||||
if (!checkExportedNamesForDeclaration(kid))
|
||||
if (!checkExportedNamesForDeclarationList(kid))
|
||||
return null();
|
||||
|
||||
Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
|
||||
|
|
@ -5565,7 +5669,7 @@ Parser<ParseHandler>::exportLexicalDeclaration(uint32_t begin, DeclarationKind k
|
|||
Node kid = lexicalDeclaration(YieldIsName, kind);
|
||||
if (!kid)
|
||||
return null();
|
||||
if (!checkExportedNamesForDeclaration(kid))
|
||||
if (!checkExportedNamesForDeclarationList(kid))
|
||||
return null();
|
||||
|
||||
Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end));
|
||||
|
|
|
|||
|
|
@ -1383,7 +1383,10 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
|
||||
bool checkExportedName(JSAtom* exportName);
|
||||
bool checkExportedNamesForArrayBinding(Node node);
|
||||
bool checkExportedNamesForObjectBinding(Node node);
|
||||
bool checkExportedNamesForDeclaration(Node node);
|
||||
bool checkExportedNamesForDeclarationList(Node node);
|
||||
|
||||
bool checkExportedNameForClause(Node node);
|
||||
bool checkExportedNameForFunction(Node node);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue