Commit 1808badc authored by Andreas Rossberg's avatar Andreas Rossberg

Disable classes in sloppy mode unless --harmony-sloppy is set

Also clean up flag names a little.

Baseline: https://codereview.chromium.org/713413003/

R=arv@chromium.org, dslomov@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#25435}
parent fbcfce69
......@@ -1598,6 +1598,7 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_arrow_functions)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_numeric_literals)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_tostring)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_templates)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sloppy)
void Genesis::InstallNativeFunctions_harmony_proxies() {
......@@ -1625,6 +1626,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_numeric_literals)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_tostring)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_proxies)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_templates)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy)
void Genesis::InitializeGlobal_harmony_regexps() {
Handle<JSObject> builtins(native_context()->builtins());
......@@ -2180,6 +2182,7 @@ bool Genesis::InstallExperimentalNatives() {
NULL};
static const char* harmony_templates_natives[] = {
"native harmony-templates.js", NULL};
static const char* harmony_sloppy_natives[] = {NULL};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......
......@@ -173,7 +173,8 @@ DEFINE_IMPLICATION(harmony, es_staging)
V(harmony_arrow_functions, "harmony arrow functions") \
V(harmony_tostring, "harmony toString") \
V(harmony_proxies, "harmony proxies") \
V(harmony_templates, "harmony template literals")
V(harmony_templates, "harmony template literals") \
V(harmony_sloppy, "harmony features in sloppy mode")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) V(harmony_strings, "harmony string methods")
......
......@@ -181,7 +181,7 @@ var kMessages = {
extends_value_not_a_function: ["Class extends value ", "%0", " is not a function or null"],
prototype_parent_not_an_object: ["Class extends value does not have valid prototype property ", "%0"],
duplicate_constructor: ["A class may only have one constructor"],
lexical_strict_mode: ["Lexical declarations are currently only allowed in strict mode"],
sloppy_lexical: ["Block-scoped declarations (let, const, function, class) not yet supported outside strict mode"],
};
......
......@@ -795,15 +795,16 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
total_preparse_skipped_(0),
pre_parse_timer_(NULL) {
DCHECK(!script().is_null() || info->source_stream() != NULL);
set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
set_allow_modules(!info->is_native() && FLAG_harmony_modules);
set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
set_allow_lazy(false); // Must be explicitly enabled.
set_allow_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
set_allow_harmony_modules(!info->is_native() && FLAG_harmony_modules);
set_allow_harmony_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
set_allow_classes(FLAG_harmony_classes);
set_allow_harmony_classes(FLAG_harmony_classes);
set_allow_harmony_object_literals(FLAG_harmony_object_literals);
set_allow_harmony_templates(FLAG_harmony_templates);
set_allow_harmony_sloppy(FLAG_harmony_sloppy);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
......@@ -916,7 +917,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
// Compute the parsing mode.
Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
if (allow_natives_syntax() || extension_ != NULL ||
if (allow_natives() || extension_ != NULL ||
(*scope)->is_eval_scope()) {
mode = PARSE_EAGERLY;
}
......@@ -1992,6 +1993,12 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
// so rewrite it as such.
Expect(Token::CLASS, CHECK_OK);
if (!allow_harmony_sloppy() && strict_mode() == SLOPPY) {
ReportMessage("sloppy_lexical");
*ok = false;
return NULL;
}
int pos = position();
bool is_strict_reserved = false;
const AstRawString* name =
......@@ -2489,7 +2496,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
if (peek() == Token::IDENTIFIER && expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->raw_name() ==
ast_value_factory()->let_string()) {
ReportMessage("lexical_strict_mode", NULL);
ReportMessage("sloppy_lexical", NULL);
*ok = false;
return NULL;
}
......@@ -3373,7 +3380,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
// Detect attempts at 'let' declarations in sloppy mode.
if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
is_let_identifier_expression) {
ReportMessage("lexical_strict_mode", NULL);
ReportMessage("sloppy_lexical", NULL);
*ok = false;
return NULL;
}
......@@ -3964,17 +3971,19 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
if (reusable_preparser_ == NULL) {
reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit_);
reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
reusable_preparser_->set_allow_modules(allow_modules());
reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
reusable_preparser_->set_allow_lazy(true);
reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions());
reusable_preparser_->set_allow_natives(allow_natives());
reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
reusable_preparser_->set_allow_harmony_modules(allow_harmony_modules());
reusable_preparser_->set_allow_harmony_arrow_functions(
allow_harmony_arrow_functions());
reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals());
reusable_preparser_->set_allow_classes(allow_classes());
reusable_preparser_->set_allow_harmony_classes(allow_harmony_classes());
reusable_preparser_->set_allow_harmony_object_literals(
allow_harmony_object_literals());
reusable_preparser_->set_allow_harmony_templates(allow_harmony_templates());
reusable_preparser_->set_allow_harmony_sloppy(allow_harmony_sloppy());
}
PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(strict_mode(),
......@@ -5109,7 +5118,7 @@ bool Parser::Parse() {
DCHECK(info()->function() == NULL);
FunctionLiteral* result = NULL;
pre_parse_timer_ = isolate()->counters()->pre_parse();
if (FLAG_trace_parse || allow_natives_syntax() || extension_ != NULL) {
if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
// If intrinsics are allowed, the Parser cannot operate independent of the
// V8 heap because of Runtime. Tell the string table to internalize strings
// and values right after they're created.
......
......@@ -350,6 +350,12 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
Expect(Token::CLASS, CHECK_OK);
if (!allow_harmony_sloppy() && strict_mode() == SLOPPY) {
ReportMessage("sloppy_lexical");
*ok = false;
return Statement::Default();
}
int pos = position();
bool is_strict_reserved = false;
Identifier name =
......@@ -512,7 +518,7 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
// Detect attempts at 'let' declarations in sloppy mode.
if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
expr.IsIdentifier() && expr.AsIdentifier().IsLet()) {
ReportMessage("lexical_strict_mode", NULL);
ReportMessage("sloppy_lexical", NULL);
*ok = false;
return Statement::Default();
}
......@@ -733,7 +739,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
// Detect attempts at 'let' declarations in sloppy mode.
if (peek() == Token::IDENTIFIER && strict_mode() == SLOPPY &&
is_let_identifier_expression) {
ReportMessage("lexical_strict_mode", NULL);
ReportMessage("sloppy_lexical", NULL);
*ok = false;
return Statement::Default();
}
......@@ -998,7 +1004,7 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
// CallRuntime ::
// '%' Identifier Arguments
Expect(Token::MOD, CHECK_OK);
if (!allow_natives_syntax()) {
if (!allow_natives()) {
*ok = false;
return Expression::Default();
}
......
......@@ -83,46 +83,59 @@ class ParserBase : public Traits {
scanner_(scanner),
stack_overflow_(false),
allow_lazy_(false),
allow_natives_syntax_(false),
allow_arrow_functions_(false),
allow_natives_(false),
allow_harmony_arrow_functions_(false),
allow_harmony_object_literals_(false),
allow_harmony_sloppy_(false),
zone_(zone) {}
// Getters that indicate whether certain syntactical constructs are
// allowed to be parsed by this instance of the parser.
bool allow_lazy() const { return allow_lazy_; }
bool allow_natives_syntax() const { return allow_natives_syntax_; }
bool allow_arrow_functions() const { return allow_arrow_functions_; }
bool allow_modules() const { return scanner()->HarmonyModules(); }
bool allow_natives() const { return allow_natives_; }
bool allow_harmony_arrow_functions() const {
return allow_harmony_arrow_functions_;
}
bool allow_harmony_modules() const { return scanner()->HarmonyModules(); }
bool allow_harmony_scoping() const { return scanner()->HarmonyScoping(); }
bool allow_harmony_numeric_literals() const {
return scanner()->HarmonyNumericLiterals();
}
bool allow_classes() const { return scanner()->HarmonyClasses(); }
bool allow_harmony_classes() const { return scanner()->HarmonyClasses(); }
bool allow_harmony_object_literals() const {
return allow_harmony_object_literals_;
}
bool allow_harmony_templates() const { return scanner()->HarmonyTemplates(); }
bool allow_harmony_sloppy() const { return allow_harmony_sloppy_; }
// Setters that determine whether certain syntactical constructs are
// allowed to be parsed by this instance of the parser.
void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
void set_allow_arrow_functions(bool allow) { allow_arrow_functions_ = allow; }
void set_allow_modules(bool allow) { scanner()->SetHarmonyModules(allow); }
void set_allow_natives(bool allow) { allow_natives_ = allow; }
void set_allow_harmony_arrow_functions(bool allow) {
allow_harmony_arrow_functions_ = allow;
}
void set_allow_harmony_modules(bool allow) {
scanner()->SetHarmonyModules(allow);
}
void set_allow_harmony_scoping(bool allow) {
scanner()->SetHarmonyScoping(allow);
}
void set_allow_harmony_numeric_literals(bool allow) {
scanner()->SetHarmonyNumericLiterals(allow);
}
void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
void set_allow_harmony_classes(bool allow) {
scanner()->SetHarmonyClasses(allow);
}
void set_allow_harmony_object_literals(bool allow) {
allow_harmony_object_literals_ = allow;
}
void set_allow_harmony_templates(bool allow) {
scanner()->SetHarmonyTemplates(allow);
}
void set_allow_harmony_sloppy(bool allow) {
allow_harmony_sloppy_ = allow;
}
protected:
enum AllowEvalOrArgumentsAsIdentifier {
......@@ -577,9 +590,10 @@ class ParserBase : public Traits {
bool stack_overflow_;
bool allow_lazy_;
bool allow_natives_syntax_;
bool allow_arrow_functions_;
bool allow_natives_;
bool allow_harmony_arrow_functions_;
bool allow_harmony_object_literals_;
bool allow_harmony_sloppy_;
typename Traits::Type::Zone* zone_; // Only used by Parser.
};
......@@ -1823,7 +1837,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
case Token::LPAREN:
Consume(Token::LPAREN);
if (allow_arrow_functions() && peek() == Token::RPAREN) {
if (allow_harmony_arrow_functions() && peek() == Token::RPAREN) {
// Arrow functions are the only expression type constructions
// for which an empty parameter list "()" is valid input.
Consume(Token::RPAREN);
......@@ -1841,6 +1855,11 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
case Token::CLASS: {
Consume(Token::CLASS);
if (!allow_harmony_sloppy() && strict_mode() == SLOPPY) {
ReportMessage("sloppy_lexical", NULL);
*ok = false;
break;
}
int class_token_position = position();
IdentifierT name = this->EmptyIdentifier();
bool is_strict_reserved_name = false;
......@@ -1863,7 +1882,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
break;
case Token::MOD:
if (allow_natives_syntax() || extension_ != NULL) {
if (allow_natives() || extension_ != NULL) {
result = this->ParseV8Intrinsic(CHECK_OK);
break;
}
......@@ -2191,7 +2210,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
ExpressionT expression =
this->ParseConditionalExpression(accept_IN, CHECK_OK);
if (allow_arrow_functions() && peek() == Token::ARROW) {
if (allow_harmony_arrow_functions() && peek() == Token::ARROW) {
checkpoint.Restore();
expression = this->ParseArrowFunctionLiteral(lhs_location.beg_pos,
expression, CHECK_OK);
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-scoping
// Flags: --harmony-scoping --harmony-classes
function CheckError(source) {
var exception = null;
......@@ -13,7 +13,7 @@ function CheckError(source) {
}
assertNotNull(exception);
assertEquals(
"Lexical declarations are currently only allowed in strict mode",
"Block-scoped declarations (let, const, function, class) not yet supported outside strict mode",
exception.message);
}
......@@ -28,6 +28,12 @@ CheckError("function f() { let x = 1; }");
CheckError("for (let x = 1; x < 1; x++) {}");
CheckError("for (let x of []) {}");
CheckError("for (let x in []) {}");
CheckError("class C {}");
CheckError("class C extends Array {}");
CheckError("(class {});");
CheckError("(class extends Array {});");
CheckError("(class C {});");
CheckError("(class C exends Array {});");
CheckOk("let = 1;");
CheckOk("{ let = 1; }");
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-classes
// Flags: --harmony-classes --harmony-sloppy
(function TestBasics() {
var C = class C {}
......
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