Commit aeb3a717 authored by adamk's avatar adamk Committed by Commit bot

Begin modernization of --harmony-modules

The approach taken in this CL is to incrementally move toward the
currently-specced version of modules in ES6. The biggest change in this
patch is separating the parsing of modules from the parsing of scripts,
getting rid of the 'module' keyword and thus disallowing modules-in-scripts
as well as modules-in-modules.

The syntax supported by import/export declarations has not yet been significantly
changed, with the major exception being that import declarations require a string
as the 'from' part.

Most of the existing tests have been disabled, with a first new test added
in cctest/test-parsing.

BUG=v8:1569
LOG=n

Review URL: https://codereview.chromium.org/881623002

Cr-Commit-Position: refs/heads/master@{#26299}
parent 701c6e74
......@@ -253,7 +253,6 @@ class AstValue : public ZoneObject {
F(make_reference_error, "MakeReferenceErrorEmbedded") \
F(make_syntax_error, "MakeSyntaxErrorEmbedded") \
F(make_type_error, "MakeTypeErrorEmbedded") \
F(module, "module") \
F(native, "native") \
F(next, "next") \
F(proto, "__proto__") \
......
......@@ -89,7 +89,8 @@ class CompilationInfo {
kInliningEnabled = 1 << 17,
kTypingEnabled = 1 << 18,
kDisableFutureOptimization = 1 << 19,
kToplevel = 1 << 20
kModule = 1 << 20,
kToplevel = 1 << 21
};
CompilationInfo(Handle<JSFunction> closure, Zone* zone);
......@@ -105,6 +106,7 @@ class CompilationInfo {
bool is_lazy() const { return GetFlag(kLazy); }
bool is_eval() const { return GetFlag(kEval); }
bool is_global() const { return GetFlag(kGlobal); }
bool is_module() const { return GetFlag(kModule); }
StrictMode strict_mode() const {
return GetFlag(kStrictMode) ? STRICT : SLOPPY;
}
......@@ -146,6 +148,11 @@ class CompilationInfo {
SetFlag(kGlobal);
}
void MarkAsModule() {
DCHECK(!is_lazy());
SetFlag(kModule);
}
void set_parameter_count(int parameter_count) {
DCHECK(IsStub());
parameter_count_ = parameter_count;
......
This diff is collapsed.
......@@ -696,7 +696,7 @@ class Parser : public ParserBase<ParserTraits> {
static const int kMaxNumFunctionLocals = 4194303; // 2^22-1
enum VariableDeclarationContext {
kModuleElement,
kStatementListItem,
kStatement,
kForStatement
};
......@@ -746,22 +746,14 @@ class Parser : public ParserBase<ParserTraits> {
// which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check
// for failure at the call sites.
void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
bool is_eval, bool is_global,
Scope** ad_hoc_eval_scope, bool* ok);
Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
void* ParseStatementList(ZoneList<Statement*>* processor, int end_token,
bool is_eval, Scope** ad_hoc_eval_scope, bool* ok);
Statement* ParseStatementListItem(bool* ok);
Module* ParseModule(bool* ok);
Module* ParseModuleLiteral(bool* ok);
Module* ParseModulePath(bool* ok);
Module* ParseModuleVariable(bool* ok);
Statement* ParseModuleItem(bool* ok);
Module* ParseModuleUrl(bool* ok);
Module* ParseModuleSpecifier(bool* ok);
Block* ParseImportDeclaration(bool* ok);
Statement* ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok);
Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
......
......@@ -77,10 +77,8 @@ Scope::Scope(Isolate* isolate, Zone* zone, Scope* outer_scope,
params_(4, zone),
unresolved_(16, zone),
decls_(4, zone),
interface_(FLAG_harmony_modules && (scope_type == MODULE_SCOPE ||
scope_type == SCRIPT_SCOPE)
? Interface::NewModule(zone)
: NULL),
interface_(scope_type == MODULE_SCOPE ? Interface::NewModule(zone)
: NULL),
already_resolved_(false),
ast_value_factory_(ast_value_factory),
zone_(zone) {
......
......@@ -63,6 +63,9 @@
# are actually 13 * 38 * 5 * 128 = 316160 individual tests hidden here.
'test-parsing/ParserSync': [PASS, NO_VARIANTS],
# Modules are busted
'test-parsing/ExportsMaybeAssigned': [SKIP],
# This tests only the type system, so there is no point in running several
# variants.
'test-hydrogen-types/*': [PASS, NO_VARIANTS],
......
......@@ -676,7 +676,6 @@ TEST(CrossScriptReferences_Simple2) {
TEST(CrossScriptReferencesHarmony) {
i::FLAG_harmony_scoping = true;
i::FLAG_harmony_modules = true;
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
......@@ -687,7 +686,6 @@ TEST(CrossScriptReferencesHarmony) {
"'use strict'; function x() { return 1 }; x()", "x()",
"'use strict'; let x = 1; x", "x",
"'use strict'; const x = 1; x", "x",
"'use strict'; module x { export let a = 1 }; x.a", "x.a",
NULL
};
......@@ -823,7 +821,6 @@ TEST(CrossScriptReferencesHarmony) {
TEST(GlobalLexicalOSR) {
i::FLAG_use_strict = true;
i::FLAG_harmony_scoping = true;
i::FLAG_harmony_modules = true;
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
......@@ -848,7 +845,6 @@ TEST(GlobalLexicalOSR) {
TEST(CrossScriptConflicts) {
i::FLAG_use_strict = true;
i::FLAG_harmony_scoping = true;
i::FLAG_harmony_modules = true;
HandleScope scope(CcTest::isolate());
......@@ -857,7 +853,6 @@ TEST(CrossScriptConflicts) {
"function x() { return 1 }; x()",
"let x = 1; x",
"const x = 1; x",
"module x { export let a = 1 }; x.a",
NULL
};
const char* seconds[] = {
......@@ -865,7 +860,6 @@ TEST(CrossScriptConflicts) {
"function x() { return 2 }; x()",
"let x = 2; x",
"const x = 2; x",
"module x { export let a = 2 }; x.a",
NULL
};
......
......@@ -4668,3 +4668,57 @@ TEST(ComputedPropertyNameShorthandError) {
RunParserSyncTest(context_data, error_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(BasicImportExportParsing) {
const char kSource[] =
"export let x = 0;"
"import y from 'http://module.com/foo.js';"
"function f() {};"
"f();";
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope handles(CcTest::isolate());
v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope context_scope(context);
isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
128 * 1024);
int kProgramByteSize = i::StrLength(kSource);
i::ScopedVector<char> program(kProgramByteSize + 1);
i::SNPrintF(program, "%s", kSource);
i::Handle<i::String> source =
factory->NewStringFromUtf8(i::CStrVector(program.start()))
.ToHandleChecked();
// Show that parsing as a module works
{
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(),
isolate->heap()->HashSeed(),
isolate->unicode_cache()};
i::Parser parser(&info, &parse_info);
parser.set_allow_harmony_modules(true);
parser.set_allow_harmony_scoping(true);
info.MarkAsModule();
CHECK(parser.Parse());
}
// And that parsing a script does not.
{
i::Handle<i::Script> script = factory->NewScript(source);
i::CompilationInfoWithZone info(script);
i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(),
isolate->heap()->HashSeed(),
isolate->unicode_cache()};
i::Parser parser(&info, &parse_info);
parser.set_allow_harmony_modules(true);
parser.set_allow_harmony_scoping(true);
info.MarkAsGlobal();
CHECK(!parser.Parse());
}
}
......@@ -27,164 +27,19 @@
// Flags: --harmony-modules
// Test basic module syntax, with and without automatic semicolon insertion.
module A {}
module A1 = A
module A2 = A;
module A3 = A2
module B {
export vx
export vy, lz, c, f
var vx
var vx, vy;
var vx = 0, vy
let lx, ly
let lz = 1
const c = 9
function f() {}
module C0 {}
export module C {
let x
export module D { export let x }
let y
}
let zz = ""
export var x0
export var x1, x2 = 6, x3
export let y0
export let y1 = 0, y2
export const z0 = 0
export const z1 = 2, z2 = 3
export function f0() {}
export module M1 {}
export module M2 = C.D
export module M3 at "http://where"
import i0 from I
import i1, i2, i3, M from I
//import i4, i5 from "http://where"
}
module I {
export let i0, i1, i2, i3;
export module M {}
}
module C1 = B.C;
module D1 = B.C.D
module D2 = C1.D
module D3 = D2
module E1 at "http://where"
module E2 at "http://where";
module E3 = E1
// Check that ASI does not interfere.
module X
{
let x
}
module Y
=
X
module Z
at
"file://local"
import
vx
,
vy
from
B
module Wrap {
export
x
,
y
var
x
,
y
export
var
v1 = 1
export
let
v2 = 2
export
const
v3 = 3
export
function
f
(
)
{
}
export
module V
{
}
}
export A, A1, A2, A3, B, I, C1, D1, D2, D3, E1, E2, E3, X, Y, Z, Wrap, x, y, UU
// Check that 'module' still works as an identifier.
var module
module = {}
module["a"] = 6
function module() {}
function f(module) { return module }
try {} catch (module) {}
module
v = 20
// Check that module declarations are rejected in eval or local scope.
module M { export let x; }
assertThrows("export x;", SyntaxError); // It's using eval, so should throw.
// Check that import/export declarations are rejected in eval or local scope.
assertThrows("export x;", SyntaxError);
assertThrows("export let x;", SyntaxError);
assertThrows("import x from M;", SyntaxError);
assertThrows("module M {};", SyntaxError);
assertThrows("import x from 'http://url';", SyntaxError);
assertThrows("{ export x; }", SyntaxError);
assertThrows("{ export let x; }", SyntaxError);
assertThrows("{ import x from M; }", SyntaxError);
assertThrows("{ module M {}; }", SyntaxError);
assertThrows("{ import x from 'http://url'; }", SyntaxError);
assertThrows("function f() { export x; }", SyntaxError);
assertThrows("function f() { export let x; }", SyntaxError);
assertThrows("function f() { import x from M; }", SyntaxError);
assertThrows("function f() { module M {}; }", SyntaxError);
assertThrows("function f() { import x from 'http://url'; }", SyntaxError);
assertThrows("function f() { { export x; } }", SyntaxError);
assertThrows("function f() { { export let x; } }", SyntaxError);
assertThrows("function f() { { import x from M; } }", SyntaxError);
assertThrows("function f() { { module M {}; } }", SyntaxError);
assertThrows("function f() { { import x from 'http://url'; } }", SyntaxError);
......@@ -80,6 +80,12 @@
'regress/regress-2185-2': [PASS, NO_VARIANTS],
'regress/regress-2612': [PASS, NO_VARIANTS],
# Modules are busted
'harmony/module-linking': [SKIP],
'harmony/module-recompile': [SKIP],
'harmony/module-resolution': [SKIP],
'harmony/regress/regress-343928': [SKIP],
# Issue 3660: Replacing activated TurboFan frames by unoptimized code does
# not work, but we expect it to not crash.
'debug-step-turbofan': [PASS, FAIL],
......
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