mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1154391 - Update import declarations to current ES6 spec r=shu
This commit is contained in:
parent
9c9ab9548c
commit
4d97bbfd94
@ -332,6 +332,8 @@ enum ParseNodeKind
|
||||
* in original source, not introduced via
|
||||
* constant folding or other tree rewriting
|
||||
* PNK_LABEL name pn_atom: label, pn_expr: labeled statement
|
||||
* PNK_IMPORT binary pn_left: PNK_IMPORT_SPEC_LIST import specifiers
|
||||
* pn_right: PNK_STRING module specifier
|
||||
*
|
||||
* <Expressions>
|
||||
* All left-associated binary trees of the same type are optimized into lists
|
||||
|
@ -4177,6 +4177,105 @@ Parser<SyntaxParseHandler>::letDeclarationOrBlock(YieldHandling yieldHandling)
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
|
||||
{
|
||||
if (tt == TOK_LC) {
|
||||
while (true) {
|
||||
// Handle the forms |import {} from 'a'| and
|
||||
// |import { ..., } from 'a'| (where ... is non empty), by
|
||||
// escaping the loop early if the next token is }.
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::KeywordIsName))
|
||||
return false;
|
||||
|
||||
if (tt == TOK_RC)
|
||||
break;
|
||||
|
||||
// If the next token is a keyword, the previous call to
|
||||
// peekToken matched it as a TOK_NAME, and put it in the
|
||||
// lookahead buffer, so this call will match keywords as well.
|
||||
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
|
||||
Node importName = newName(tokenStream.currentName());
|
||||
if (!importName)
|
||||
return false;
|
||||
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return false;
|
||||
|
||||
if (tt == TOK_NAME && tokenStream.currentName() == context->names().as) {
|
||||
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_BINDING_NAME);
|
||||
} else {
|
||||
// Keywords cannot be bound to themselves, so an import name
|
||||
// that is a keyword is a syntax error if it is not followed
|
||||
// by the keyword 'as'.
|
||||
// See the ImportSpecifier production in ES6 section 15.2.2.
|
||||
if (IsKeyword(importName->name())) {
|
||||
JSAutoByteString bytes;
|
||||
if (!AtomToPrintableString(context, importName->name(), &bytes))
|
||||
return false;
|
||||
report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
|
||||
return false;
|
||||
}
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
Node bindingName = newName(tokenStream.currentName());
|
||||
if (!bindingName)
|
||||
return false;
|
||||
|
||||
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
|
||||
if (!importSpec)
|
||||
return false;
|
||||
|
||||
handler.addList(importSpecSet, importSpec);
|
||||
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_COMMA))
|
||||
return false;
|
||||
|
||||
if (!matched)
|
||||
break;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
|
||||
} else {
|
||||
MOZ_ASSERT(tt == TOK_MUL);
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return false;
|
||||
|
||||
if (tt != TOK_NAME || tokenStream.currentName() != context->names().as) {
|
||||
report(ParseError, false, null(), JSMSG_AS_AFTER_IMPORT_STAR);
|
||||
return false;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_BINDING_NAME);
|
||||
|
||||
Node importName = newName(context->names().star);
|
||||
if (!importName)
|
||||
return null();
|
||||
|
||||
Node bindingName = newName(tokenStream.currentName());
|
||||
if (!bindingName)
|
||||
return false;
|
||||
|
||||
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
|
||||
if (!importSpec)
|
||||
return false;
|
||||
|
||||
handler.addList(importSpecSet, importSpec);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::importDeclaration()
|
||||
@ -4197,7 +4296,7 @@ Parser<ParseHandler>::importDeclaration()
|
||||
if (!importSpecSet)
|
||||
return null();
|
||||
|
||||
if (tt == TOK_NAME || tt == TOK_LC) {
|
||||
if (tt == TOK_NAME || tt == TOK_LC || tt == TOK_MUL) {
|
||||
if (tt == TOK_NAME) {
|
||||
// Handle the form |import a from 'b'|, by adding a single import
|
||||
// specifier to the list, with 'default' as the import name and
|
||||
@ -4216,83 +4315,43 @@ Parser<ParseHandler>::importDeclaration()
|
||||
return null();
|
||||
|
||||
handler.addList(importSpecSet, importSpec);
|
||||
} else {
|
||||
while (true) {
|
||||
// Handle the forms |import {} from 'a'| and
|
||||
// |import { ..., } from 'a'| (where ... is non empty), by
|
||||
// escaping the loop early if the next token is }.
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::KeywordIsName))
|
||||
return null();
|
||||
if (tt == TOK_RC)
|
||||
break;
|
||||
|
||||
// If the next token is a keyword, the previous call to
|
||||
// peekToken matched it as a TOK_NAME, and put it in the
|
||||
// lookahead buffer, so this call will match keywords as well.
|
||||
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
|
||||
Node importName = newName(tokenStream.currentName());
|
||||
if (!importName)
|
||||
if (!tokenStream.peekToken(&tt))
|
||||
return null();
|
||||
|
||||
if (tt == TOK_COMMA) {
|
||||
if (!tokenStream.getToken(&tt) || !tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
||||
if (!tokenStream.getToken(&tt))
|
||||
if (tt != TOK_LC && tt != TOK_MUL) {
|
||||
report(ParseError, false, null(), JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT);
|
||||
return null();
|
||||
if (tt == TOK_NAME && tokenStream.currentName() == context->names().as) {
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
if (tt != TOK_NAME) {
|
||||
report(ParseError, false, null(), JSMSG_NO_BINDING_NAME);
|
||||
return null();
|
||||
}
|
||||
} else {
|
||||
// Keywords cannot be bound to themselves, so an import name
|
||||
// that is a keyword is a syntax error if it is not followed
|
||||
// by the keyword 'as'.
|
||||
if (IsKeyword(importName->name())) {
|
||||
JSAutoByteString bytes;
|
||||
if (!AtomToPrintableString(context, importName->name(), &bytes))
|
||||
return null();
|
||||
report(ParseError, false, null(), JSMSG_AS_AFTER_RESERVED_WORD, bytes.ptr());
|
||||
return null();
|
||||
}
|
||||
tokenStream.ungetToken();
|
||||
}
|
||||
Node bindingName = newName(tokenStream.currentName());
|
||||
if (!bindingName)
|
||||
return null();
|
||||
|
||||
Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName);
|
||||
if (!importSpec)
|
||||
if (!namedImportsOrNamespaceImport(tt, importSpecSet))
|
||||
return null();
|
||||
|
||||
handler.addList(importSpecSet, importSpec);
|
||||
|
||||
bool matched;
|
||||
if (!tokenStream.matchToken(&matched, TOK_COMMA))
|
||||
return null();
|
||||
if (!matched)
|
||||
break;
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
|
||||
} else {
|
||||
if (!namedImportsOrNamespaceImport(tt, importSpecSet))
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!tokenStream.getToken(&tt))
|
||||
return null();
|
||||
|
||||
if (tt != TOK_NAME || tokenStream.currentName() != context->names().from) {
|
||||
report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_SPEC_SET);
|
||||
report(ParseError, false, null(), JSMSG_FROM_AFTER_IMPORT_CLAUSE);
|
||||
return null();
|
||||
}
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_STRING, JSMSG_MODULE_SPEC_AFTER_FROM);
|
||||
} else {
|
||||
if (tt != TOK_STRING) {
|
||||
report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
|
||||
return null();
|
||||
}
|
||||
|
||||
} else if (tt == TOK_STRING) {
|
||||
// Handle the form |import 'a'| by leaving the list empty. This is
|
||||
// equivalent to |import {} from 'a'|.
|
||||
importSpecSet->pn_pos.end = importSpecSet->pn_pos.begin;
|
||||
} else {
|
||||
report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT);
|
||||
return null();
|
||||
}
|
||||
|
||||
Node moduleSpec = stringLiteral();
|
||||
@ -4302,8 +4361,7 @@ Parser<ParseHandler>::importDeclaration()
|
||||
if (!MatchOrInsertSemicolon(tokenStream))
|
||||
return null();
|
||||
|
||||
return handler.newImportDeclaration(importSpecSet, moduleSpec,
|
||||
TokenPos(begin, pos().end));
|
||||
return handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end));
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -635,6 +635,8 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
Node destructuringExprWithoutYield(YieldHandling yieldHandling, BindData<ParseHandler>* data,
|
||||
TokenKind tt, unsigned msg);
|
||||
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
|
||||
|
||||
enum ClassContext { ClassStatement, ClassExpression };
|
||||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext);
|
||||
|
||||
|
@ -38,6 +38,18 @@ program([
|
||||
)
|
||||
]).assert(Reflect.parse("import a from 'b'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("*"),
|
||||
ident("a")
|
||||
)
|
||||
],
|
||||
lit("b")
|
||||
)
|
||||
]).assert(Reflect.parse("import * as a from 'b'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[],
|
||||
@ -93,6 +105,106 @@ program([
|
||||
)
|
||||
]).assert(Reflect.parse("import { as as as } from 'a'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("a")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("*"),
|
||||
ident("b")
|
||||
)
|
||||
],
|
||||
lit("c")
|
||||
)
|
||||
]).assert(Reflect.parse("import a, * as b from 'c'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("d")
|
||||
)
|
||||
],
|
||||
lit("a")
|
||||
)
|
||||
]).assert(Reflect.parse("import d, {} from 'a'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("d")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("a"),
|
||||
ident("a")
|
||||
)
|
||||
],
|
||||
lit("b")
|
||||
)
|
||||
]).assert(Reflect.parse("import d, { a } from 'b'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("d")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("a"),
|
||||
ident("b")
|
||||
)
|
||||
],
|
||||
lit("c")
|
||||
)
|
||||
]).assert(Reflect.parse("import d, { a as b } from 'c'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("d")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("a"),
|
||||
ident("a")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("b"),
|
||||
ident("b")
|
||||
),
|
||||
],
|
||||
lit("c")
|
||||
)
|
||||
]).assert(Reflect.parse("import d, { a, b } from 'c'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
importSpecifier(
|
||||
ident("default"),
|
||||
ident("d")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("a"),
|
||||
ident("b")
|
||||
),
|
||||
importSpecifier(
|
||||
ident("c"),
|
||||
ident("d")
|
||||
),
|
||||
],
|
||||
lit("e")
|
||||
)
|
||||
]).assert(Reflect.parse("import d, { a as b, c as d } from 'e'"));
|
||||
|
||||
program([
|
||||
importDeclaration(
|
||||
[
|
||||
@ -184,3 +296,43 @@ assertThrowsInstanceOf(function() {
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import { true } from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import a,");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import a, b from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import * as a,");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import * as a, {} from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import as a from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import * a from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import * as from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import , {} from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import d, from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
Reflect.parse("import * as true from 'b'");
|
||||
}, SyntaxError);
|
||||
|
@ -182,6 +182,7 @@ MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 3, JSEXN_SYNTAXERR, "{0} functions must h
|
||||
MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
|
||||
MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
|
||||
MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 0, JSEXN_INTERNALERR, "array initialiser too large")
|
||||
MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
|
||||
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
||||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||
@ -249,7 +250,7 @@ MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 0, JSEXN_SYNTAXERR, "mistyped ; after con
|
||||
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?")
|
||||
MSG_DEF(JSMSG_EXPORT_DECL_AT_TOP_LEVEL,0, JSEXN_SYNTAXERR, "export declarations may only appear at top level")
|
||||
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 0, JSEXN_SYNTAXERR, "finally without try")
|
||||
MSG_DEF(JSMSG_FROM_AFTER_IMPORT_SPEC_SET, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import specifier set")
|
||||
MSG_DEF(JSMSG_FROM_AFTER_IMPORT_CLAUSE, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import clause")
|
||||
MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}")
|
||||
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
@ -271,6 +272,8 @@ MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 0, JSEXN_SYNTAXERR, "missing octal digits
|
||||
MSG_DEF(JSMSG_MODULES_NOT_IMPLEMENTED, 0, JSEXN_SYNTAXERR, "modules are not implemented yet")
|
||||
MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM, 0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_DOT, 0, JSEXN_SYNTAXERR, "missing name after . operator")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_IMPORT_STAR_AS, 0, JSEXN_SYNTAXERR, "missing name after import * as")
|
||||
MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected named imports or namespace import after comma")
|
||||
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
|
||||
MSG_DEF(JSMSG_NO_BINDING_NAME, 0, JSEXN_SYNTAXERR, "missing binding name")
|
||||
MSG_DEF(JSMSG_NO_CLASS_CONSTRUCTOR, 0, JSEXN_TYPEERR, "class default constructors not yet implemented")
|
||||
|
@ -2156,6 +2156,7 @@ bool
|
||||
ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst)
|
||||
{
|
||||
MOZ_ASSERT(pn->isKind(PNK_IMPORT));
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
|
||||
|
||||
|
@ -187,6 +187,7 @@
|
||||
macro(signMask, signMask, "signMask") \
|
||||
macro(source, source, "source") \
|
||||
macro(stack, stack, "stack") \
|
||||
macro(star, star, "*") \
|
||||
macro(startTimestamp, startTimestamp, "startTimestamp") \
|
||||
macro(static, static_, "static") \
|
||||
macro(sticky, sticky, "sticky") \
|
||||
|
@ -29,11 +29,11 @@ namespace js {
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 285;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 286;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
static_assert(JSErr_Limit == 394,
|
||||
static_assert(JSErr_Limit == 397,
|
||||
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
|
||||
"removed MSG_DEFs from js.msg, you should increment "
|
||||
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
|
||||
|
Loading…
Reference in New Issue
Block a user