зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1427610 - Implement import.meta in the JS frontent r=jorendorff
This commit is contained in:
Родитель
7dcc1b6880
Коммит
a2f88658e9
|
@ -33,12 +33,6 @@ using JS::AutoValueArray;
|
|||
using mozilla::DebugOnly;
|
||||
using mozilla::Forward;
|
||||
|
||||
enum class ParseTarget
|
||||
{
|
||||
Script,
|
||||
Module
|
||||
};
|
||||
|
||||
enum ASTType {
|
||||
AST_ERROR = -1,
|
||||
#define ASTDEF(ast, str, method) ast,
|
||||
|
@ -2928,21 +2922,30 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
return classDefinition(pn, true, dst);
|
||||
|
||||
case ParseNodeKind::NewTarget:
|
||||
case ParseNodeKind::ImportMeta:
|
||||
{
|
||||
MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
|
||||
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
|
||||
|
||||
RootedValue newIdent(cx);
|
||||
RootedValue targetIdent(cx);
|
||||
RootedValue firstIdent(cx);
|
||||
RootedValue secondIdent(cx);
|
||||
|
||||
RootedAtom newStr(cx, cx->names().new_);
|
||||
RootedAtom targetStr(cx, cx->names().target);
|
||||
RootedAtom firstStr(cx);
|
||||
RootedAtom secondStr(cx);
|
||||
|
||||
return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) &&
|
||||
identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) &&
|
||||
builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst);
|
||||
if (pn->getKind() == ParseNodeKind::NewTarget) {
|
||||
firstStr = cx->names().new_;
|
||||
secondStr = cx->names().target;
|
||||
} else {
|
||||
firstStr = cx->names().import;
|
||||
secondStr = cx->names().meta;
|
||||
}
|
||||
|
||||
return identifier(firstStr, &pn->pn_left->pn_pos, &firstIdent) &&
|
||||
identifier(secondStr, &pn->pn_right->pn_pos, &secondIdent) &&
|
||||
builder.metaProperty(firstIdent, secondIdent, &pn->pn_pos, dst);
|
||||
}
|
||||
|
||||
case ParseNodeKind::SetThis:
|
||||
|
@ -3354,7 +3357,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
|||
uint32_t lineno = 1;
|
||||
bool loc = true;
|
||||
RootedObject builder(cx);
|
||||
ParseTarget target = ParseTarget::Script;
|
||||
ParseGoal target = ParseGoal::Script;
|
||||
|
||||
RootedValue arg(cx, args.get(1));
|
||||
|
||||
|
@ -3442,9 +3445,9 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
|||
return false;
|
||||
|
||||
if (isScript) {
|
||||
target = ParseTarget::Script;
|
||||
target = ParseGoal::Script;
|
||||
} else if (isModule) {
|
||||
target = ParseTarget::Module;
|
||||
target = ParseGoal::Module;
|
||||
} else {
|
||||
JS_ReportErrorASCII(cx, "Bad target value, expected 'script' or 'module'");
|
||||
return false;
|
||||
|
@ -3467,7 +3470,7 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
|||
CompileOptions options(cx);
|
||||
options.setFileAndLine(filename, lineno);
|
||||
options.setCanLazilyParse(false);
|
||||
options.allowHTMLComments = target == ParseTarget::Script;
|
||||
options.allowHTMLComments = target == ParseGoal::Script;
|
||||
mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
|
||||
UsedNameTracker usedNames(cx);
|
||||
if (!usedNames.init())
|
||||
|
@ -3481,14 +3484,14 @@ reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
|||
Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options,
|
||||
chars.begin().get(), chars.length(),
|
||||
/* foldConstants = */ false, usedNames, nullptr,
|
||||
nullptr, sourceObject);
|
||||
nullptr, sourceObject, target);
|
||||
if (!parser.checkOptions())
|
||||
return false;
|
||||
|
||||
serialize.setParser(&parser);
|
||||
|
||||
ParseNode* pn;
|
||||
if (target == ParseTarget::Script) {
|
||||
if (target == ParseGoal::Script) {
|
||||
pn = parser.parse();
|
||||
if (!pn)
|
||||
return false;
|
||||
|
|
|
@ -59,8 +59,9 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
bool checkLength();
|
||||
bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
|
||||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
bool createParser(ParseGoal goal);
|
||||
bool createSourceAndParser(ParseGoal goal,
|
||||
const Maybe<uint32_t>& parameterListEnd = Nothing());
|
||||
|
||||
// If toString{Start,End} are not explicitly passed, assume the script's
|
||||
// offsets in the source used to parse it are the same as what should be
|
||||
|
@ -215,7 +216,7 @@ BytecodeCompiler::canLazilyParse()
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createParser()
|
||||
BytecodeCompiler::createParser(ParseGoal goal)
|
||||
{
|
||||
usedNames.emplace(cx);
|
||||
if (!usedNames->init())
|
||||
|
@ -224,23 +225,24 @@ BytecodeCompiler::createParser()
|
|||
if (canLazilyParse()) {
|
||||
syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ false, *usedNames, nullptr, nullptr,
|
||||
sourceObject);
|
||||
sourceObject, goal);
|
||||
if (!syntaxParser->checkOptions())
|
||||
return false;
|
||||
}
|
||||
|
||||
parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
|
||||
/* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr,
|
||||
sourceObject);
|
||||
sourceObject, goal);
|
||||
parser->ss = scriptSource;
|
||||
return parser->checkOptions();
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createSourceAndParser(const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
BytecodeCompiler::createSourceAndParser(ParseGoal goal,
|
||||
const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
|
||||
{
|
||||
return createScriptSource(parameterListEnd) &&
|
||||
createParser();
|
||||
createParser(goal);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -314,7 +316,7 @@ BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObj
|
|||
JSScript*
|
||||
BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
|
||||
{
|
||||
if (!createSourceAndParser())
|
||||
if (!createSourceAndParser(ParseGoal::Script))
|
||||
return nullptr;
|
||||
|
||||
TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
|
||||
|
@ -390,7 +392,7 @@ BytecodeCompiler::compileEvalScript(HandleObject environment, HandleScope enclos
|
|||
ModuleObject*
|
||||
BytecodeCompiler::compileModule()
|
||||
{
|
||||
if (!createSourceAndParser())
|
||||
if (!createSourceAndParser(ParseGoal::Module))
|
||||
return nullptr;
|
||||
|
||||
Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
|
||||
|
@ -449,7 +451,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
MOZ_ASSERT(fun);
|
||||
MOZ_ASSERT(fun->isTenured());
|
||||
|
||||
if (!createSourceAndParser(parameterListEnd))
|
||||
if (!createSourceAndParser(ParseGoal::Script, parameterListEnd))
|
||||
return false;
|
||||
|
||||
TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
|
||||
|
@ -780,7 +782,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
RootedScriptSourceObject sourceObject(cx, &lazy->sourceObject());
|
||||
Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, chars, length,
|
||||
/* foldConstants = */ true, usedNames, nullptr,
|
||||
lazy, sourceObject);
|
||||
lazy, sourceObject, lazy->parseGoal());
|
||||
if (!parser.checkOptions())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -3303,6 +3303,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
|
||||
// Trivial binary nodes with more token pos holders.
|
||||
case ParseNodeKind::NewTarget:
|
||||
case ParseNodeKind::ImportMeta:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
|
||||
|
@ -11146,6 +11147,10 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
return false;
|
||||
break;
|
||||
|
||||
case ParseNodeKind::ImportMeta:
|
||||
MOZ_CRASH("NYI");
|
||||
break;
|
||||
|
||||
case ParseNodeKind::SetThis:
|
||||
if (!emitSetThis(pn))
|
||||
return false;
|
||||
|
|
|
@ -375,6 +375,7 @@ ContainsHoistedDeclaration(JSContext* cx, ParseNode* node, bool* result)
|
|||
case ParseNodeKind::ClassMethodList:
|
||||
case ParseNodeKind::ClassNames:
|
||||
case ParseNodeKind::NewTarget:
|
||||
case ParseNodeKind::ImportMeta:
|
||||
case ParseNodeKind::PosHolder:
|
||||
case ParseNodeKind::SuperCall:
|
||||
case ParseNodeKind::SuperBase:
|
||||
|
@ -1725,6 +1726,7 @@ Fold(JSContext* cx, ParseNode** pnp, PerHandlerParser<FullParseHandler>& parser)
|
|||
Fold(cx, &pn->pn_right, parser);
|
||||
|
||||
case ParseNodeKind::NewTarget:
|
||||
case ParseNodeKind::ImportMeta:
|
||||
MOZ_ASSERT(pn->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
|
||||
MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
|
||||
|
|
|
@ -560,6 +560,10 @@ class FullParseHandler
|
|||
return new_<NullaryNode>(ParseNodeKind::ExportBatchSpec, JSOP_NOP, pos);
|
||||
}
|
||||
|
||||
ParseNode* newImportMeta(ParseNode* importHolder, ParseNode* metaHolder) {
|
||||
return new_<BinaryNode>(ParseNodeKind::ImportMeta, JSOP_NOP, importHolder, metaHolder);
|
||||
}
|
||||
|
||||
ParseNode* newExprStatement(ParseNode* expr, uint32_t end) {
|
||||
MOZ_ASSERT(expr->pn_pos.end <= end);
|
||||
return new_<UnaryNode>(ParseNodeKind::ExpressionStatement,
|
||||
|
|
|
@ -64,6 +64,12 @@ class EnvironmentCoordinate
|
|||
|
||||
namespace frontend {
|
||||
|
||||
enum class ParseGoal : uint8_t
|
||||
{
|
||||
Script,
|
||||
Module
|
||||
};
|
||||
|
||||
// A detailed kind used for tracking declarations in the Parser. Used for
|
||||
// specific early error semantics and better error messages.
|
||||
enum class DeclarationKind : uint8_t
|
||||
|
|
|
@ -417,6 +417,7 @@ class NameResolver
|
|||
break;
|
||||
|
||||
case ParseNodeKind::NewTarget:
|
||||
case ParseNodeKind::ImportMeta:
|
||||
MOZ_ASSERT(cur->isArity(PN_BINARY));
|
||||
MOZ_ASSERT(cur->pn_left->isKind(ParseNodeKind::PosHolder));
|
||||
MOZ_ASSERT(cur->pn_right->isKind(ParseNodeKind::PosHolder));
|
||||
|
|
|
@ -132,6 +132,7 @@ class ObjectBox;
|
|||
F(SuperBase) \
|
||||
F(SuperCall) \
|
||||
F(SetThis) \
|
||||
F(ImportMeta) \
|
||||
\
|
||||
/* Unary operators. */ \
|
||||
F(TypeOfName) \
|
||||
|
|
|
@ -800,7 +800,8 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
|
|||
const ReadOnlyCompileOptions& options,
|
||||
bool foldConstants,
|
||||
UsedNameTracker& usedNames,
|
||||
ScriptSourceObject* sourceObject)
|
||||
ScriptSourceObject* sourceObject,
|
||||
ParseGoal parseGoal)
|
||||
: AutoGCRooter(cx, AutoGCRooter::Tag::Parser),
|
||||
context(cx),
|
||||
alloc(alloc),
|
||||
|
@ -816,7 +817,8 @@ ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
|
|||
checkOptionsCalled(false),
|
||||
#endif
|
||||
isUnexpectedEOF_(false),
|
||||
awaitHandling_(AwaitIsName)
|
||||
awaitHandling_(AwaitIsName),
|
||||
parseGoal_(uint8_t(parseGoal))
|
||||
{
|
||||
cx->frontendCollectionPool().addActiveCompilation();
|
||||
tempPoolMark = alloc.mark();
|
||||
|
@ -853,8 +855,9 @@ PerHandlerParser<ParseHandler>::PerHandlerParser(JSContext* cx, LifoAlloc& alloc
|
|||
const ReadOnlyCompileOptions& options,
|
||||
bool foldConstants, UsedNameTracker& usedNames,
|
||||
LazyScript* lazyOuterFunction,
|
||||
ScriptSourceObject* sourceObject)
|
||||
: ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject),
|
||||
ScriptSourceObject* sourceObject,
|
||||
ParseGoal parseGoal)
|
||||
: ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject, parseGoal),
|
||||
handler(cx, alloc, lazyOuterFunction)
|
||||
{
|
||||
|
||||
|
@ -868,8 +871,9 @@ GeneralParser<ParseHandler, CharT>::GeneralParser(JSContext* cx, LifoAlloc& allo
|
|||
UsedNameTracker& usedNames,
|
||||
SyntaxParser* syntaxParser,
|
||||
LazyScript* lazyOuterFunction,
|
||||
ScriptSourceObject* sourceObject)
|
||||
: Base(cx, alloc, options, foldConstants, usedNames, lazyOuterFunction, sourceObject),
|
||||
ScriptSourceObject* sourceObject,
|
||||
ParseGoal parseGoal)
|
||||
: Base(cx, alloc, options, foldConstants, usedNames, lazyOuterFunction, sourceObject, parseGoal),
|
||||
tokenStream(cx, options, chars, length)
|
||||
{
|
||||
// The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
|
||||
|
@ -2551,7 +2555,8 @@ PerHandlerParser<SyntaxParseHandler>::finishFunction(bool isStandaloneFunction /
|
|||
pc->innerFunctionsForLazy,
|
||||
funbox->bufStart, funbox->bufEnd,
|
||||
funbox->toStringStart,
|
||||
funbox->startLine, funbox->startColumn);
|
||||
funbox->startLine, funbox->startColumn,
|
||||
parseGoal());
|
||||
if (!lazy)
|
||||
return false;
|
||||
|
||||
|
@ -5351,6 +5356,22 @@ GeneralParser<ParseHandler, CharT>::importDeclaration()
|
|||
return asFinalParser()->importDeclaration();
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
inline typename ParseHandler::Node
|
||||
GeneralParser<ParseHandler, CharT>::importDeclarationOrImportMeta(YieldHandling yieldHandling)
|
||||
{
|
||||
MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
|
||||
|
||||
TokenKind tt;
|
||||
if (!tokenStream.peekToken(&tt))
|
||||
return null();
|
||||
|
||||
if (tt == TokenKind::Dot)
|
||||
return expressionStatement(yieldHandling);
|
||||
|
||||
return importDeclaration();
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
bool
|
||||
Parser<FullParseHandler, CharT>::checkExportedName(JSAtom* exportName)
|
||||
|
@ -7699,7 +7720,7 @@ GeneralParser<ParseHandler, CharT>::statement(YieldHandling yieldHandling)
|
|||
|
||||
// ImportDeclaration (only inside modules)
|
||||
case TokenKind::Import:
|
||||
return importDeclaration();
|
||||
return importDeclarationOrImportMeta(yieldHandling);
|
||||
|
||||
// ExportDeclaration (only inside modules)
|
||||
case TokenKind::Export:
|
||||
|
@ -7892,7 +7913,7 @@ GeneralParser<ParseHandler, CharT>::statementListItem(YieldHandling yieldHandlin
|
|||
|
||||
// ImportDeclaration (only inside modules)
|
||||
case TokenKind::Import:
|
||||
return importDeclaration();
|
||||
return importDeclarationOrImportMeta(yieldHandling);
|
||||
|
||||
// ExportDeclaration (only inside modules)
|
||||
case TokenKind::Export:
|
||||
|
@ -8714,6 +8735,10 @@ GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling,
|
|||
lhs = handler.newSuperBase(thisName, pos());
|
||||
if (!lhs)
|
||||
return null();
|
||||
} else if (tt == TokenKind::Import) {
|
||||
lhs = importMeta();
|
||||
if (!lhs)
|
||||
return null();
|
||||
} else {
|
||||
lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError, invoked);
|
||||
if (!lhs)
|
||||
|
@ -9890,6 +9915,45 @@ GeneralParser<ParseHandler, CharT>::tryNewTarget(Node &newTarget)
|
|||
return !!newTarget;
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
typename ParseHandler::Node
|
||||
GeneralParser<ParseHandler, CharT>::importMeta()
|
||||
{
|
||||
MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
|
||||
|
||||
uint32_t begin = pos().begin;
|
||||
|
||||
if (parseGoal() != ParseGoal::Module) {
|
||||
errorAt(begin, JSMSG_IMPORT_OUTSIDE_MODULE);
|
||||
return null();
|
||||
}
|
||||
|
||||
Node importHolder = handler.newPosHolder(pos());
|
||||
if (!importHolder)
|
||||
return null();
|
||||
|
||||
TokenKind next;
|
||||
if (!tokenStream.getToken(&next))
|
||||
return null();
|
||||
if (next != TokenKind::Dot) {
|
||||
error(JSMSG_UNEXPECTED_TOKEN, "dot", TokenKindToDesc(next));
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!tokenStream.getToken(&next))
|
||||
return null();
|
||||
if (next != TokenKind::Meta) {
|
||||
error(JSMSG_UNEXPECTED_TOKEN, "meta", TokenKindToDesc(next));
|
||||
return null();
|
||||
}
|
||||
|
||||
Node metaHolder = handler.newPosHolder(pos());
|
||||
if (!metaHolder)
|
||||
return null();
|
||||
|
||||
return handler.newImportMeta(importHolder, metaHolder);
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
typename ParseHandler::Node
|
||||
GeneralParser<ParseHandler, CharT>::primaryExpr(YieldHandling yieldHandling,
|
||||
|
|
|
@ -295,16 +295,22 @@ class MOZ_STACK_CLASS ParserBase
|
|||
|
||||
/* AwaitHandling */ uint8_t awaitHandling_:2;
|
||||
|
||||
/* ParseGoal */ uint8_t parseGoal_:1;
|
||||
|
||||
public:
|
||||
bool awaitIsKeyword() const {
|
||||
return awaitHandling_ != AwaitIsName;
|
||||
}
|
||||
|
||||
ParseGoal parseGoal() const {
|
||||
return ParseGoal(parseGoal_);
|
||||
}
|
||||
|
||||
template<class, typename> friend class AutoAwaitIsKeyword;
|
||||
|
||||
ParserBase(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
bool foldConstants, UsedNameTracker& usedNames,
|
||||
ScriptSourceObject* sourceObject);
|
||||
ScriptSourceObject* sourceObject, ParseGoal parseGoal);
|
||||
~ParserBase();
|
||||
|
||||
bool checkOptions();
|
||||
|
@ -469,7 +475,8 @@ class MOZ_STACK_CLASS PerHandlerParser
|
|||
PerHandlerParser(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
bool foldConstants, UsedNameTracker& usedNames,
|
||||
LazyScript* lazyOuterFunction,
|
||||
ScriptSourceObject* sourceObject);
|
||||
ScriptSourceObject* sourceObject,
|
||||
ParseGoal parseGoal);
|
||||
|
||||
static Node null() { return ParseHandler::null(); }
|
||||
|
||||
|
@ -662,6 +669,7 @@ class MOZ_STACK_CLASS GeneralParser
|
|||
|
||||
using Base::alloc;
|
||||
using Base::awaitIsKeyword;
|
||||
using Base::parseGoal;
|
||||
#if DEBUG
|
||||
using Base::checkOptionsCalled;
|
||||
#endif
|
||||
|
@ -872,7 +880,8 @@ class MOZ_STACK_CLASS GeneralParser
|
|||
const CharT* chars, size_t length, bool foldConstants,
|
||||
UsedNameTracker& usedNames, SyntaxParser* syntaxParser,
|
||||
LazyScript* lazyOuterFunction,
|
||||
ScriptSourceObject* sourceObject);
|
||||
ScriptSourceObject* sourceObject,
|
||||
ParseGoal parseGoal);
|
||||
|
||||
inline void setAwaitHandling(AwaitHandling awaitHandling);
|
||||
|
||||
|
@ -1013,6 +1022,7 @@ class MOZ_STACK_CLASS GeneralParser
|
|||
Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
|
||||
|
||||
inline Node importDeclaration();
|
||||
Node importDeclarationOrImportMeta(YieldHandling yieldHandling);
|
||||
|
||||
Node exportFrom(uint32_t begin, Node specList);
|
||||
Node exportBatch(uint32_t begin);
|
||||
|
@ -1112,6 +1122,8 @@ class MOZ_STACK_CLASS GeneralParser
|
|||
|
||||
bool tryNewTarget(Node& newTarget);
|
||||
|
||||
Node importMeta();
|
||||
|
||||
Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName);
|
||||
|
||||
/*
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
macro(from, from, TokenKind::From) \
|
||||
macro(get, get, TokenKind::Get) \
|
||||
macro(let, let, TokenKind::Let) \
|
||||
macro(meta, meta, TokenKind::Meta) \
|
||||
macro(of, of, TokenKind::Of) \
|
||||
macro(set, set, TokenKind::Set) \
|
||||
macro(static, static_, TokenKind::Static) \
|
||||
|
|
|
@ -297,6 +297,9 @@ class SyntaxParseHandler
|
|||
Node newExportBatchSpec(const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newImportMeta(Node importHolder, Node metaHolder) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newSetThis(Node thisName, Node value) { return value; }
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
macro(From, "'from'") \
|
||||
macro(Get, "'get'") \
|
||||
macro(Let, "'let'") \
|
||||
macro(Meta, "'meta'") \
|
||||
macro(Of, "'of'") \
|
||||
macro(Set, "'set'") \
|
||||
macro(Static, "'static'") \
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
load(libdir + "match.js");
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
var { Pattern, MatchError } = Match;
|
||||
|
||||
program = (elts) => Pattern({
|
||||
type: "Program",
|
||||
body: elts
|
||||
});
|
||||
expressionStatement = (expression) => Pattern({
|
||||
type: "ExpressionStatement",
|
||||
expression: expression
|
||||
});
|
||||
assignmentExpression = (left, operator, right) => Pattern({
|
||||
type: "AssignmentExpression",
|
||||
operator: operator,
|
||||
left: left,
|
||||
right: right
|
||||
});
|
||||
ident = (name) => Pattern({
|
||||
type: "Identifier",
|
||||
name: name
|
||||
});
|
||||
metaProperty = (meta, property) => Pattern({
|
||||
type: "MetaProperty",
|
||||
meta: meta,
|
||||
property: property
|
||||
});
|
||||
memberExpression = (object, property) => Pattern({
|
||||
type: "MemberExpression",
|
||||
object: object,
|
||||
property: property
|
||||
});
|
||||
|
||||
function parseAsModule(source)
|
||||
{
|
||||
return Reflect.parse(source, {target: "module"});
|
||||
}
|
||||
|
||||
program([
|
||||
expressionStatement(
|
||||
metaProperty(
|
||||
ident("import"),
|
||||
ident("meta")
|
||||
)
|
||||
)
|
||||
]).assert(parseAsModule("import.meta;"));
|
||||
|
||||
program([
|
||||
expressionStatement(
|
||||
assignmentExpression(
|
||||
ident("x"),
|
||||
"=",
|
||||
metaProperty(
|
||||
ident("import"),
|
||||
ident("meta")
|
||||
)
|
||||
)
|
||||
)
|
||||
]).assert(parseAsModule("x = import.meta;"));
|
||||
|
||||
program([
|
||||
expressionStatement(
|
||||
assignmentExpression(
|
||||
memberExpression(
|
||||
metaProperty(
|
||||
ident("import"),
|
||||
ident("meta")
|
||||
),
|
||||
ident("foo")
|
||||
),
|
||||
"=",
|
||||
ident("x"),
|
||||
)
|
||||
)
|
||||
]).assert(parseAsModule("import.meta.foo = x;"));
|
||||
|
||||
function assertModuleParseThrowsSyntaxError(source)
|
||||
{
|
||||
assertThrowsInstanceOf(() => parseAsModule(source), SyntaxError);
|
||||
}
|
||||
|
||||
function assertModuleParseThrowsReferenceError(source)
|
||||
{
|
||||
assertThrowsInstanceOf(() => parseAsModule(source), ReferenceError);
|
||||
}
|
||||
|
||||
assertModuleParseThrowsSyntaxError("import");
|
||||
assertModuleParseThrowsSyntaxError("import.");
|
||||
assertModuleParseThrowsSyntaxError("import.met");
|
||||
assertModuleParseThrowsSyntaxError("import.metaa");
|
||||
assertModuleParseThrowsSyntaxError("x = import");
|
||||
assertModuleParseThrowsSyntaxError("x = import.");
|
||||
assertModuleParseThrowsSyntaxError("x = import.met");
|
||||
assertModuleParseThrowsSyntaxError("x = import.metaa");
|
||||
|
||||
assertModuleParseThrowsReferenceError("import.meta = x");
|
|
@ -261,6 +261,7 @@ MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage a
|
|||
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
|
||||
MSG_DEF(JSMSG_BAD_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid escape sequence")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
MSG_DEF(JSMSG_IMPORT_OUTSIDE_MODULE, 0, JSEXN_SYNTAXERR, "the import keyword may only appear in a module")
|
||||
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
|
||||
MSG_DEF(JSMSG_OF_AFTER_FOR_LOOP_DECL, 0, JSEXN_SYNTAXERR, "a declaration in the head of a for-of loop can't have an initializer")
|
||||
MSG_DEF(JSMSG_IN_AFTER_LEXICAL_FOR_DECL,0,JSEXN_SYNTAXERR, "a lexical declaration in the head of a for-in loop can't have an initializer")
|
||||
|
|
|
@ -177,7 +177,7 @@ runTestFromPath(JSContext* cx, const char* path)
|
|||
js::frontend::Parser<js::frontend::FullParseHandler, char16_t> txtParser(
|
||||
cx, allocScope.alloc(), txtOptions, txtSource.begin(), txtSource.length(),
|
||||
/* foldConstants = */ false, txtUsedNames, nullptr,
|
||||
nullptr, sourceObject);
|
||||
nullptr, sourceObject, frontend::ParseGoal::Script);
|
||||
if (!txtParser.checkOptions())
|
||||
MOZ_CRASH("Bad options");
|
||||
|
||||
|
|
|
@ -4479,7 +4479,8 @@ JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, siz
|
|||
options, chars, length,
|
||||
/* foldConstants = */ true,
|
||||
usedNames, nullptr, nullptr,
|
||||
sourceObject);
|
||||
sourceObject,
|
||||
frontend::ParseGoal::Script);
|
||||
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
|
||||
if (!parser.checkOptions() || !parser.parse()) {
|
||||
// We ran into an error. If it was because we ran out of source, we
|
||||
|
|
|
@ -4518,7 +4518,7 @@ Parse(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, chars, length,
|
||||
/* foldConstants = */ false, usedNames, nullptr,
|
||||
nullptr, sourceObject);
|
||||
nullptr, sourceObject, ParseGoal::Script);
|
||||
if (!parser.checkOptions())
|
||||
return false;
|
||||
|
||||
|
@ -4576,7 +4576,8 @@ SyntaxParse(JSContext* cx, unsigned argc, Value* vp)
|
|||
Parser<frontend::SyntaxParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
|
||||
options, chars, length, false,
|
||||
usedNames, nullptr, nullptr,
|
||||
sourceObject);
|
||||
sourceObject,
|
||||
frontend::ParseGoal::Script);
|
||||
if (!parser.checkOptions())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -230,6 +230,7 @@
|
|||
macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
|
||||
macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
|
||||
macro(message, message, "message") \
|
||||
macro(meta, meta, "meta") \
|
||||
macro(minDays, minDays, "minDays") \
|
||||
macro(minimumFractionDigits, minimumFractionDigits, "minimumFractionDigits") \
|
||||
macro(minimumIntegerDigits, minimumIntegerDigits, "minimumIntegerDigits") \
|
||||
|
|
|
@ -5061,7 +5061,8 @@ Debugger::isCompilableUnit(JSContext* cx, unsigned argc, Value* vp)
|
|||
length,
|
||||
/* foldConstants = */ true,
|
||||
usedNames, nullptr, nullptr,
|
||||
sourceObject);
|
||||
sourceObject,
|
||||
frontend::ParseGoal::Script);
|
||||
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
|
||||
if (!parser.checkOptions() || !parser.parse()) {
|
||||
// We ran into an error. If it was because we ran out of memory we report
|
||||
|
|
|
@ -4302,7 +4302,8 @@ LazyScript::Create(JSContext* cx, HandleFunction fun,
|
|||
const frontend::AtomVector& closedOverBindings,
|
||||
Handle<GCVector<JSFunction*, 8>> innerFunctions,
|
||||
uint32_t sourceStart, uint32_t sourceEnd,
|
||||
uint32_t toStringStart, uint32_t lineno, uint32_t column)
|
||||
uint32_t toStringStart, uint32_t lineno, uint32_t column,
|
||||
frontend::ParseGoal parseGoal)
|
||||
{
|
||||
union {
|
||||
PackedView p;
|
||||
|
@ -4323,6 +4324,7 @@ LazyScript::Create(JSContext* cx, HandleFunction fun,
|
|||
p.isLikelyConstructorWrapper = false;
|
||||
p.isDerivedClassConstructor = false;
|
||||
p.needsHomeObject = false;
|
||||
p.parseGoal = uint32_t(parseGoal);
|
||||
|
||||
LazyScript* res = LazyScript::CreateRaw(cx, fun, sourceObject, packedFields,
|
||||
sourceStart, sourceEnd,
|
||||
|
|
|
@ -2187,6 +2187,7 @@ class LazyScript : public gc::TenuredCell
|
|||
uint32_t isDerivedClassConstructor : 1;
|
||||
uint32_t needsHomeObject : 1;
|
||||
uint32_t hasRest : 1;
|
||||
uint32_t parseGoal : 1;
|
||||
};
|
||||
|
||||
union {
|
||||
|
@ -2229,7 +2230,8 @@ class LazyScript : public gc::TenuredCell
|
|||
const frontend::AtomVector& closedOverBindings,
|
||||
Handle<GCVector<JSFunction*, 8>> innerFunctions,
|
||||
uint32_t begin, uint32_t end,
|
||||
uint32_t toStringStart, uint32_t lineno, uint32_t column);
|
||||
uint32_t toStringStart, uint32_t lineno, uint32_t column,
|
||||
frontend::ParseGoal parseGoal);
|
||||
|
||||
// Create a LazyScript and initialize the closedOverBindings and the
|
||||
// innerFunctions with dummy values to be replaced in a later initialization
|
||||
|
@ -2326,6 +2328,10 @@ class LazyScript : public gc::TenuredCell
|
|||
p_.hasRest = true;
|
||||
}
|
||||
|
||||
frontend::ParseGoal parseGoal() const {
|
||||
return frontend::ParseGoal(p_.parseGoal);
|
||||
}
|
||||
|
||||
bool strict() const {
|
||||
return p_.strict;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче