Commit e791ded4 authored by gsathya's avatar gsathya Committed by Commit bot

[ESnext] Parse dynamic import expression

Rewrites import expression into a runtime call. Uses peekahead to
determine if parsing an import declaration or import expression.

The runtime call doesn't actually do the import yet, will be added in
follow on patch.

Adds a new --harmony-dynamic-import flag.

Adds a ignore_error_msg parameter to the test runner to ignore the
discrepancy in the error messages while parsing import expression with
parser and pre parser. This discrepancy will actually never happen in
real code.

BUG=v8:5785

Review-Url: https://codereview.chromium.org/2661933003
Cr-Commit-Position: refs/heads/master@{#42820}
parent c41f5f2d
......@@ -3516,6 +3516,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_generators)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_trailing_commas)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_class_fields)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object_rest_spread)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_dynamic_import)
void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
const char* name, Handle<Symbol> value) {
......@@ -4085,6 +4086,7 @@ bool Genesis::InstallExperimentalNatives() {
static const char* harmony_class_fields_natives[] = {nullptr};
static const char* harmony_object_rest_spread_natives[] = {nullptr};
static const char* harmony_async_iteration_natives[] = {nullptr};
static const char* harmony_dynamic_import_natives[] = {nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......
......@@ -194,16 +194,17 @@ DEFINE_IMPLICATION(es_staging, harmony_regexp_lookbehind)
DEFINE_IMPLICATION(es_staging, move_object_start)
// Features that are still work in progress (behind individual flags).
#define HARMONY_INPROGRESS(V) \
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_named_captures, "harmony regexp named captures") \
V(harmony_regexp_property, "harmony unicode regexp property classes") \
V(harmony_class_fields, "harmony public fields in class literals") \
V(harmony_async_iteration, "harmony async iteration")
#define HARMONY_INPROGRESS(V) \
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_named_captures, "harmony regexp named captures") \
V(harmony_regexp_property, "harmony unicode regexp property classes") \
V(harmony_class_fields, "harmony public fields in class literals") \
V(harmony_async_iteration, "harmony async iteration") \
V(harmony_dynamic_import, "harmony dynamic import")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \
......
......@@ -224,7 +224,8 @@ class ParserBase {
allow_harmony_restrictive_generators_(false),
allow_harmony_trailing_commas_(false),
allow_harmony_class_fields_(false),
allow_harmony_object_rest_spread_(false) {}
allow_harmony_object_rest_spread_(false),
allow_harmony_dynamic_import_(false) {}
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
......@@ -238,6 +239,7 @@ class ParserBase {
ALLOW_ACCESSORS(harmony_trailing_commas);
ALLOW_ACCESSORS(harmony_class_fields);
ALLOW_ACCESSORS(harmony_object_rest_spread);
ALLOW_ACCESSORS(harmony_dynamic_import);
#undef ALLOW_ACCESSORS
......@@ -1206,6 +1208,7 @@ class ParserBase {
int class_token_pos, bool* ok);
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
ExpressionT ParseSuperExpression(bool is_new, bool* ok);
ExpressionT ParseDynamicImportExpression(bool* ok);
ExpressionT ParseNewTargetExpression(bool* ok);
void ParseFormalParameter(FormalParametersT* parameters, bool* ok);
......@@ -1484,6 +1487,7 @@ class ParserBase {
bool allow_harmony_trailing_commas_;
bool allow_harmony_class_fields_;
bool allow_harmony_object_rest_spread_;
bool allow_harmony_dynamic_import_;
friend class DiscardableZoneScope;
};
......@@ -3350,7 +3354,11 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
// MemberExpression ::
// (PrimaryExpression | FunctionLiteral | ClassLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
//
// CallExpression ::
// (SuperCall | ImportCall)
// ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
//
// The '[' Expression ']' and '.' Identifier parts are parsed by
// ParseMemberExpressionContinuation, and the Arguments part is parsed by the
// caller.
......@@ -3403,6 +3411,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
} else if (peek() == Token::SUPER) {
const bool is_new = false;
result = ParseSuperExpression(is_new, CHECK_OK);
} else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT) {
result = ParseDynamicImportExpression(CHECK_OK);
} else {
result = ParsePrimaryExpression(is_async, CHECK_OK);
}
......@@ -3411,6 +3421,20 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
return result;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseDynamicImportExpression(bool* ok) {
DCHECK(allow_harmony_dynamic_import());
Consume(Token::IMPORT);
int pos = position();
Expect(Token::LPAREN, CHECK_OK);
ExpressionT arg = ParseAssignmentExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
ZoneList<ExpressionT>* args = new (zone()) ZoneList<ExpressionT>(1, zone());
args->Add(arg, zone());
return factory()->NewCallRuntime(Runtime::kDynamicImportCall, args, pos);
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
bool is_new, bool* ok) {
......
......@@ -553,6 +553,7 @@ Parser::Parser(ParseInfo* info)
set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
set_allow_harmony_class_fields(FLAG_harmony_class_fields);
set_allow_harmony_object_rest_spread(FLAG_harmony_object_rest_spread);
set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
......@@ -962,15 +963,21 @@ Statement* Parser::ParseModuleItem(bool* ok) {
// ExportDeclaration
// StatementListItem
switch (peek()) {
case Token::IMPORT:
ParseImportDeclaration(CHECK_OK);
return factory()->NewEmptyStatement(kNoSourcePosition);
case Token::EXPORT:
return ParseExportDeclaration(ok);
default:
return ParseStatementListItem(ok);
Token::Value next = peek();
if (next == Token::EXPORT) {
return ParseExportDeclaration(ok);
}
// We must be careful not to parse a dynamic import expression as an import
// declaration.
if (next == Token::IMPORT &&
(!allow_harmony_dynamic_import() || PeekAhead() != Token::LPAREN)) {
ParseImportDeclaration(CHECK_OK);
return factory()->NewEmptyStatement(kNoSourcePosition);
}
return ParseStatementListItem(ok);
}
......@@ -2795,6 +2802,7 @@ Parser::LazyParsingResult Parser::SkipFunction(
SET_ALLOW(harmony_trailing_commas);
SET_ALLOW(harmony_class_fields);
SET_ALLOW(harmony_object_rest_spread);
SET_ALLOW(harmony_dynamic_import);
#undef SET_ALLOW
}
// Aborting inner function preparsing would leave scopes in an inconsistent
......
......@@ -759,6 +759,12 @@ class PreParserFactory {
return PreParserStatement::Default();
}
PreParserExpression NewCallRuntime(Runtime::FunctionId id,
ZoneList<PreParserExpression>* arguments,
int pos) {
return PreParserExpression::Default();
}
// Return the object itself as AstVisitor and implement the needed
// dummy method right in this class.
PreParserFactory* visitor() { return this; }
......
......@@ -9,6 +9,13 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_DynamicImportCall) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
// TODO(gsathya): Implement ImportCall.
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_GetModuleNamespace) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -350,6 +350,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1)
#define FOR_EACH_INTRINSIC_MODULE(F) \
F(DynamicImportCall, 1, 1) \
F(GetModuleNamespace, 1, 1) \
F(LoadModuleVariable, 1, 1) \
F(StoreModuleVariable, 2, 1)
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment