strong_super_call_missing: ["Please always invoke the super constructor in subclasses in strong mode"],
strong_super_call_duplicate: ["Please don't invoke the super constructor multiple times in strong mode"],
strong_super_call_nested: ["Please don't invoke the super constructor nested inside another statement or expression in strong mode"],
+ strong_constructor_return_value: ["Please do not return a value from a constructor in strong mode"],
+ strong_constructor_return_misplaced: ["Please do not return from a constructor before its super constructor invocation in strong mode"],
sloppy_lexical: ["Block-scoped declarations (let, const, function, class) not yet supported outside strict mode"],
malformed_arrow_function_parameter_list: ["Malformed arrow function parameter list"],
generator_poison_pill: ["'caller' and 'arguments' properties may not be accessed on generator functions."],
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
Scanner::Location loc = scanner()->location();
+ function_state_->set_return_location(loc);
Token::Value tok = peek();
Statement* result;
return_value = GetLiteralUndefined(position());
}
} else {
+ if (is_strong(language_mode()) &&
+ i::IsConstructor(function_state_->kind())) {
+ int pos = peek_position();
+ ReportMessageAt(Scanner::Location(pos, pos + 1),
+ "strong_constructor_return_value");
+ *ok = false;
+ return NULL;
+ }
return_value = ParseExpression(true, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
// reporting any errors on it, because of the way errors are
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
+ function_state_->set_return_location(scanner()->location());
// An ECMAScript program is considered syntactically incorrect if it
// contains a return statement that is not within the body of a
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
+ if (is_strong(language_mode()) &&
+ i::IsConstructor(function_state_->kind())) {
+ int pos = peek_position();
+ ReportMessageAt(Scanner::Location(pos, pos + 1),
+ "strong_constructor_return_value");
+ *ok = false;
+ return Statement::Default();
+ }
ParseExpression(true, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; }
+ Scanner::Location return_location() const { return return_location_; }
Scanner::Location super_call_location() const {
return super_call_location_;
}
+ void set_return_location(Scanner::Location location) {
+ return_location_ = location;
+ }
void set_super_call_location(Scanner::Location location) {
super_call_location_ = location;
}
// Properties count estimation.
int expected_property_count_;
+ // Location of most recent 'return' statement (invalid if none).
+ Scanner::Location return_location_;
+
// Location of call to the "super" constructor (invalid if none).
Scanner::Location super_call_location_;
: next_materialized_literal_index_(0),
next_handler_index_(0),
expected_property_count_(0),
+ return_location_(Scanner::Location::invalid()),
super_call_location_(Scanner::Location::invalid()),
kind_(kind),
generator_object_variable_(NULL),
// new super() is never allowed.
// super() is only allowed in derived constructor
if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) {
- if (is_strong(language_mode()) &&
- function_state->super_call_location().IsValid()) {
- ReportMessageAt(scanner()->location(), "strong_super_call_duplicate");
- *ok = false;
- return this->EmptyExpression();
+ if (is_strong(language_mode())) {
+ if (function_state->super_call_location().IsValid()) {
+ ReportMessageAt(scanner()->location(), "strong_super_call_duplicate");
+ *ok = false;
+ return this->EmptyExpression();
+ } else if (function_state->return_location().IsValid()) {
+ ReportMessageAt(function_state->return_location(),
+ "strong_constructor_return_misplaced");
+ *ok = false;
+ return this->EmptyExpression();
+ }
}
function_state->set_super_call_location(scanner()->location());
return this->SuperReference(scope_, factory());
}
+TEST(StrongConstructorReturns) {
+ const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
+ const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
+ const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
+
+ const char* data[] = {
+ "class C extends Object { constructor() { super(); return {}; } }",
+ "class C extends Object { constructor() { super(); { return {}; } } }",
+ "class C extends Object { constructor() { super(); if (1) return {}; } }",
+ "class C extends Object { constructor() { return; super(); } }",
+ "class C extends Object { constructor() { { return; } super(); } }",
+ "class C extends Object { constructor() { if (0) return; super(); } }",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals
+ };
+ RunParserSyncTest(sloppy_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
+ arraysize(always_flags));
+ RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
TEST(ArrowFunctionASIErrors) {
const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
{NULL, NULL}};
})();
(function NoNestedSuper() {
- assertSyntaxError(constructor("(super())"));
- assertSyntaxError(constructor("(() => super())(); } })"));
- assertSyntaxError(constructor("{ super();"));
+ assertSyntaxError(constructor("(super());"));
+ assertSyntaxError(constructor("(() => super())();"));
+ assertSyntaxError(constructor("{ super(); }"));
assertSyntaxError(constructor("if (1) super();"));
})();
assertSyntaxError(constructor("super(); super();"));
assertSyntaxError(constructor("super(); (super());"));
assertSyntaxError(constructor("super(); { super() }"));
+ assertSyntaxError(constructor("super(); (() => super())();"));
+})();
+
+(function NoReturnValue() {
+ assertSyntaxError(constructor("return {};"));
+ assertSyntaxError(constructor("return undefined;"));
+ assertSyntaxError(constructor("{ return {}; }"));
+ assertSyntaxError(constructor("if (1) return {};"));
+})();
+
+(function NoReturnBeforeSuper() {
+ assertSyntaxError(constructor("return; super();"));
+ assertSyntaxError(constructor("if (0) return; super();"));
+ assertSyntaxError(constructor("{ return; } super();"));
})();