From b3875aacbbf53ed7a743ce07526cce8c460ade40 Mon Sep 17 00:00:00 2001 From: machenbach Date: Wed, 22 Apr 2015 01:00:39 -0700 Subject: [PATCH] Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) Reason for revert: [Sheriff] Breaks mac gc stress: http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 Original issue's description: > [strong] checking of this & super in constructors > > R=dslomov@chromium.org, marja@chromium.org > BUG=v8:3956 > LOG=N > > Enforces for constructors that > - the only use of 'super' is the super constructor call > - the only use of 'this' is a property assignment > - both of these must happen at the top-level of the body > - 'this' may only be assigned after the 'super' call > - 'return' may only be used after the last assignment to 'this' > > Not yet working for arrow functions (there might be deeper bugs with those). > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > Cr-Commit-Position: refs/heads/master@{#27977} TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1105453002 Cr-Commit-Position: refs/heads/master@{#27991} --- src/messages.js | 6 +- src/parser.cc | 91 ++++++------------- src/parser.h | 11 ++- src/preparser.cc | 72 +++------------ src/preparser.h | 194 ++++++----------------------------------- test/cctest/test-parsing.cc | 129 ++++----------------------- test/mjsunit/strong/classes.js | 57 ------------ 7 files changed, 91 insertions(+), 469 deletions(-) diff --git a/src/messages.js b/src/messages.js index f50e8e7..04e107d 100644 --- a/src/messages.js +++ b/src/messages.js @@ -143,11 +143,9 @@ var kMessages = { strong_unbound_global: ["In strong mode, using an undeclared global variable '", "%0", "' is not allowed"], strong_super_call_missing: ["In strong mode, invoking the super constructor in a subclass is required"], strong_super_call_duplicate: ["In strong mode, invoking the super constructor multiple times is deprecated"], - strong_super_call_misplaced: ["In strong mode, the super constructor must be invoked before any assignment to 'this'"], - strong_constructor_super: ["In strong mode, 'super' can only be used to invoke the super constructor, and cannot be nested inside another statement or expression"], - strong_constructor_this: ["In strong mode, 'this' can only be used to initialize properties, and cannot be nested inside another statement or expression"], + strong_super_call_nested: ["In strong mode, invoking the super constructor nested inside another statement or expression is deprecated"], strong_constructor_return_value: ["In strong mode, returning a value from a constructor is deprecated"], - strong_constructor_return_misplaced: ["In strong mode, returning from a constructor before its super constructor invocation or all assignments to 'this' is deprecated"], + strong_constructor_return_misplaced: ["In strong mode, returning from a constructor before its super constructor invocation is deprecated"], 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"], cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"], diff --git a/src/parser.cc b/src/parser.cc index 2961a1a..c73b6d8 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1210,28 +1210,25 @@ void* Parser::ParseStatementList(ZoneList* body, int end_token, directive_prologue = false; } + Token::Value token = peek(); Scanner::Location token_loc = scanner()->peek_location(); - Scanner::Location old_this_loc = function_state_->this_location(); - Scanner::Location old_super_loc = function_state_->super_location(); + Scanner::Location old_super_loc = function_state_->super_call_location(); Statement* stat = ParseStatementListItem(CHECK_OK); + Scanner::Location super_loc = function_state_->super_call_location(); if (is_strong(language_mode()) && - scope_->is_function_scope() && - i::IsConstructor(function_state_->kind())) { - Scanner::Location this_loc = function_state_->this_location(); - Scanner::Location super_loc = function_state_->super_location(); - if (this_loc.beg_pos != old_this_loc.beg_pos && - this_loc.beg_pos != token_loc.beg_pos) { - ReportMessageAt(this_loc, "strong_constructor_this"); - *ok = false; - return nullptr; - } - if (super_loc.beg_pos != old_super_loc.beg_pos && - super_loc.beg_pos != token_loc.beg_pos) { - ReportMessageAt(super_loc, "strong_constructor_super"); - *ok = false; - return nullptr; - } + i::IsConstructor(function_state_->kind()) && + !old_super_loc.IsValid() && super_loc.IsValid() && + token != Token::SUPER) { + // TODO(rossberg): This is more permissive than spec'ed, it allows e.g. + // super(), 1; + // super() + ""; + // super() = 0; + // That should still be safe, though, thanks to left-to-right evaluation. + // The proper check would be difficult to implement in the preparser. + ReportMessageAt(super_loc, "strong_super_call_nested"); + *ok = false; + return NULL; } if (stat == NULL || stat->IsEmpty()) { @@ -2596,8 +2593,6 @@ Statement* Parser::ParseExpressionOrLabelledStatement( // ExpressionStatement[Yield] : // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; - int pos = peek_position(); - switch (peek()) { case Token::FUNCTION: case Token::LBRACE: @@ -2607,37 +2602,6 @@ Statement* Parser::ParseExpressionOrLabelledStatement( *ok = false; return nullptr; - case Token::THIS: - case Token::SUPER: - if (is_strong(language_mode()) && - i::IsConstructor(function_state_->kind())) { - bool is_this = peek() == Token::THIS; - Expression* expr; - if (is_this) { - expr = ParseStrongInitializationExpression(CHECK_OK); - } else { - expr = ParseStrongSuperCallExpression(CHECK_OK); - } - switch (peek()) { - case Token::SEMICOLON: - Consume(Token::SEMICOLON); - break; - case Token::RBRACE: - case Token::EOS: - break; - default: - if (!scanner()->HasAnyLineTerminatorBeforeNext()) { - ReportMessageAt(function_state_->this_location(), - is_this ? "strong_constructor_this" - : "strong_constructor_super"); - *ok = false; - return nullptr; - } - } - return factory()->NewExpressionStatement(expr, pos); - } - break; - // TODO(arv): Handle `let [` // https://code.google.com/p/v8/issues/detail?id=3847 @@ -2645,6 +2609,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement( break; } + int pos = peek_position(); bool starts_with_idenfifier = peek_any_identifier(); Expression* expr = ParseExpression(true, CHECK_OK); if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && @@ -4038,7 +4003,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( parenthesized_function_ = false; // The bit was set for this function only. if (is_lazily_parsed) { - SkipLazyFunctionBody(&materialized_literal_count, + SkipLazyFunctionBody(function_name, &materialized_literal_count, &expected_property_count, CHECK_OK); } else { body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, @@ -4046,15 +4011,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral( materialized_literal_count = function_state.materialized_literal_count(); expected_property_count = function_state.expected_property_count(); handler_count = function_state.handler_count(); - - if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { - if (!function_state.super_location().IsValid()) { - ReportMessageAt(function_name_location, - "strong_super_call_missing", kReferenceError); - *ok = false; - return nullptr; - } - } } // Validate name and parameter names. We can do this only after parsing the @@ -4069,8 +4025,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (is_strict(language_mode())) { CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), CHECK_OK); + } + if (is_strict(language_mode())) { CheckConflictingVarDeclarations(scope, CHECK_OK); } + if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { + if (!function_state.super_call_location().IsValid()) { + ReportMessageAt(function_name_location, "strong_super_call_missing", + kReferenceError); + *ok = false; + return nullptr; + } + } } FunctionLiteral::ParameterFlag duplicate_parameters = @@ -4094,7 +4060,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } -void Parser::SkipLazyFunctionBody(int* materialized_literal_count, +void Parser::SkipLazyFunctionBody(const AstRawString* function_name, + int* materialized_literal_count, int* expected_property_count, bool* ok) { if (produce_cached_parse_data()) CHECK(log_); diff --git a/src/parser.h b/src/parser.h index b4c628e..3b3144e 100644 --- a/src/parser.h +++ b/src/parser.h @@ -773,7 +773,8 @@ class ParserTraits { bool name_is_strict_reserved, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, FunctionLiteral::ArityRestriction arity_restriction, bool* ok); - V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, + V8_INLINE void SkipLazyFunctionBody(const AstRawString* name, + int* materialized_literal_count, int* expected_property_count, bool* ok); V8_INLINE ZoneList* ParseEagerFunctionBody( const AstRawString* name, int pos, Variable* fvar, @@ -1024,7 +1025,8 @@ class Parser : public ParserBase { // Skip over a lazy function, either using cached data if we have it, or // by parsing the function with PreParser. Consumes the ending }. - void SkipLazyFunctionBody(int* materialized_literal_count, + void SkipLazyFunctionBody(const AstRawString* function_name, + int* materialized_literal_count, int* expected_property_count, bool* ok); @@ -1089,11 +1091,12 @@ const AstRawString* ParserTraits::EmptyIdentifierString() { } -void ParserTraits::SkipLazyFunctionBody(int* materialized_literal_count, +void ParserTraits::SkipLazyFunctionBody(const AstRawString* function_name, + int* materialized_literal_count, int* expected_property_count, bool* ok) { return parser_->SkipLazyFunctionBody( - materialized_literal_count, expected_property_count, ok); + function_name, materialized_literal_count, expected_property_count, ok); } diff --git a/src/preparser.cc b/src/preparser.cc index caa383a..4a8c37d 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -123,15 +123,6 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( if (is_strict(scope_->language_mode())) { int end_pos = scanner()->location().end_pos; CheckStrictOctalLiteral(start_position, end_pos, &ok); - if (!ok) return kPreParseSuccess; - - if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) { - if (!function_state.super_location().IsValid()) { - ReportMessageAt(Scanner::Location(start_position, start_position + 1), - "strong_super_call_missing", kReferenceError); - return kPreParseSuccess; - } - } } } return kPreParseSuccess; @@ -205,31 +196,19 @@ void PreParser::ParseStatementList(int end_token, bool* ok) { if (directive_prologue && peek() != Token::STRING) { directive_prologue = false; } - Scanner::Location token_loc = scanner()->peek_location(); - Scanner::Location old_this_loc = function_state_->this_location(); - Scanner::Location old_super_loc = function_state_->super_location(); + Token::Value token = peek(); + Scanner::Location old_super_loc = function_state_->super_call_location(); Statement statement = ParseStatementListItem(ok); if (!*ok) return; - + Scanner::Location super_loc = function_state_->super_call_location(); if (is_strong(language_mode()) && - scope_->is_function_scope() && - i::IsConstructor(function_state_->kind())) { - Scanner::Location this_loc = function_state_->this_location(); - Scanner::Location super_loc = function_state_->super_location(); - if (this_loc.beg_pos != old_this_loc.beg_pos && - this_loc.beg_pos != token_loc.beg_pos) { - ReportMessageAt(this_loc, "strong_constructor_this"); - *ok = false; - return; - } - if (super_loc.beg_pos != old_super_loc.beg_pos && - super_loc.beg_pos != token_loc.beg_pos) { - ReportMessageAt(super_loc, "strong_constructor_super"); - *ok = false; - return; - } + i::IsConstructor(function_state_->kind()) && + !old_super_loc.IsValid() && super_loc.IsValid() && + token != Token::SUPER) { + ReportMessageAt(super_loc, "strong_super_call_nested"); + *ok = false; + return; } - if (directive_prologue) { if (statement.IsUseStrictLiteral()) { scope_->SetLanguageMode( @@ -553,37 +532,6 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { *ok = false; return Statement::Default(); - case Token::THIS: - case Token::SUPER: - if (is_strong(language_mode()) && - i::IsConstructor(function_state_->kind())) { - bool is_this = peek() == Token::THIS; - Expression expr = Expression::Default(); - if (is_this) { - expr = ParseStrongInitializationExpression(CHECK_OK); - } else { - expr = ParseStrongSuperCallExpression(CHECK_OK); - } - switch (peek()) { - case Token::SEMICOLON: - Consume(Token::SEMICOLON); - break; - case Token::RBRACE: - case Token::EOS: - break; - default: - if (!scanner()->HasAnyLineTerminatorBeforeNext()) { - ReportMessageAt(function_state_->this_location(), - is_this ? "strong_constructor_this" - : "strong_constructor_super"); - *ok = false; - return Statement::Default(); - } - } - return Statement::ExpressionStatement(expr); - } - break; - // TODO(arv): Handle `let [` // https://code.google.com/p/v8/issues/detail?id=3847 @@ -1024,7 +972,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( } if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { - if (!function_state.super_location().IsValid()) { + if (!function_state.super_call_location().IsValid()) { ReportMessageAt(function_name_location, "strong_super_call_missing", kReferenceError); *ok = false; diff --git a/src/preparser.h b/src/preparser.h index 0d71d93..0643c30 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -233,18 +233,16 @@ class ParserBase : public Traits { void AddProperty() { expected_property_count_++; } int expected_property_count() { return expected_property_count_; } - Scanner::Location this_location() const { return this_location_; } - Scanner::Location super_location() const { return super_location_; } Scanner::Location return_location() const { return return_location_; } - void set_this_location(Scanner::Location location) { - this_location_ = location; - } - void set_super_location(Scanner::Location location) { - super_location_ = 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; + } bool is_generator() const { return IsGeneratorFunction(kind_); } @@ -276,14 +274,11 @@ class ParserBase : public Traits { // Properties count estimation. int expected_property_count_; - // Location of most recent use of 'this' (invalid if none). - Scanner::Location this_location_; - // 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_location_; + Scanner::Location super_call_location_; FunctionKind kind_; // For generators, this variable may hold the generator object. It variable @@ -632,8 +627,6 @@ class ParserBase : public Traits { ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok); void AddTemplateExpression(ExpressionT); ExpressionT ParseSuperExpression(bool is_new, bool* ok); - ExpressionT ParseStrongInitializationExpression(bool* ok); - ExpressionT ParseStrongSuperCallExpression(bool* ok); void ParseFormalParameter(FormalParameterScopeT* scope, FormalParameterErrorLocations* locs, bool is_rest, @@ -1555,7 +1548,8 @@ class PreParserTraits { return PreParserExpressionList(); } - V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, + V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, + int* materialized_literal_count, int* expected_property_count, bool* ok) { UNREACHABLE(); } @@ -1738,7 +1732,8 @@ class PreParser : public ParserBase { Expression ParseObjectLiteral(bool* ok); Expression ParseV8Intrinsic(bool* ok); - V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count, + V8_INLINE void SkipLazyFunctionBody(PreParserIdentifier function_name, + int* materialized_literal_count, int* expected_property_count, bool* ok); V8_INLINE PreParserStatementList ParseEagerFunctionBody(PreParserIdentifier function_name, int pos, @@ -1834,9 +1829,8 @@ ParserBase::FunctionState::FunctionState( : next_materialized_literal_index_(0), next_handler_index_(0), expected_property_count_(0), - this_location_(Scanner::Location::invalid()), return_location_(Scanner::Location::invalid()), - super_location_(Scanner::Location::invalid()), + super_call_location_(Scanner::Location::invalid()), kind_(kind), generator_object_variable_(NULL), function_state_stack_(function_state_stack), @@ -2051,15 +2045,6 @@ ParserBase::ParsePrimaryExpression(bool* ok) { switch (token) { case Token::THIS: { Consume(Token::THIS); - if (is_strong(language_mode())) { - // Constructors' usages of 'this' in strong mode are parsed separately. - // TODO(rossberg): this does not work with arrow functions yet. - if (i::IsConstructor(function_state_->kind())) { - ReportMessage("strong_constructor_this"); - *ok = false; - break; - } - } scope_->RecordThisUsage(); result = this->ThisExpression(scope_, factory(), beg_pos); break; @@ -2132,7 +2117,7 @@ ParserBase::ParsePrimaryExpression(bool* ok) { case Token::CLASS: { Consume(Token::CLASS); if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { - ReportMessage("sloppy_lexical"); + ReportMessage("sloppy_lexical", NULL); *ok = false; break; } @@ -3020,141 +3005,9 @@ ParserBase::ParseMemberExpression(bool* ok) { template typename ParserBase::ExpressionT -ParserBase::ParseStrongInitializationExpression(bool* ok) { - // InitializationExpression :: (strong mode) - // 'this' '.' IdentifierName '=' AssignmentExpression - // 'this' '[' Expression ']' '=' AssignmentExpression - - if (fni_ != NULL) fni_->Enter(); - - Consume(Token::THIS); - int pos = position(); - function_state_->set_this_location(scanner()->location()); - scope_->RecordThisUsage(); - ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); - - ExpressionT left = this->EmptyExpression(); - switch (peek()) { - case Token::LBRACK: { - Consume(Token::LBRACK); - int pos = position(); - ExpressionT index = this->ParseExpression(true, CHECK_OK); - left = factory()->NewProperty(this_expr, index, pos); - if (fni_ != NULL) { - this->PushPropertyName(fni_, index); - } - Expect(Token::RBRACK, CHECK_OK); - break; - } - case Token::PERIOD: { - Consume(Token::PERIOD); - int pos = position(); - IdentifierT name = ParseIdentifierName(CHECK_OK); - left = factory()->NewProperty( - this_expr, factory()->NewStringLiteral(name, pos), pos); - if (fni_ != NULL) { - this->PushLiteralName(fni_, name); - } - break; - } - default: - ReportMessage("strong_constructor_this"); - *ok = false; - return this->EmptyExpression(); - } - - if (peek() != Token::ASSIGN) { - ReportMessageAt(function_state_->this_location(), - "strong_constructor_this"); - *ok = false; - return this->EmptyExpression(); - } - Consume(Token::ASSIGN); - left = this->MarkExpressionAsAssigned(left); - - ExpressionT right = this->ParseAssignmentExpression(true, CHECK_OK); - this->CheckAssigningFunctionLiteralToProperty(left, right); - function_state_->AddProperty(); - if (fni_ != NULL) { - // Check if the right hand side is a call to avoid inferring a - // name if we're dealing with "this.a = function(){...}();"-like - // expression. - if (!right->IsCall() && !right->IsCallNew()) { - fni_->Infer(); - } else { - fni_->RemoveLastFunction(); - } - fni_->Leave(); - } - - if (function_state_->return_location().IsValid()) { - ReportMessageAt(function_state_->return_location(), - "strong_constructor_return_misplaced"); - *ok = false; - return this->EmptyExpression(); - } - - return factory()->NewAssignment(Token::ASSIGN, left, right, pos); -} - - -template -typename ParserBase::ExpressionT -ParserBase::ParseStrongSuperCallExpression(bool* ok) { - // SuperCallExpression :: (strong mode) - // 'super' '(' ExpressionList ')' - - Consume(Token::SUPER); - int pos = position(); - Scanner::Location super_loc = scanner()->location(); - ExpressionT expr = this->SuperReference(scope_, factory()); - - if (peek() != Token::LPAREN) { - ReportMessage("strong_constructor_super"); - *ok = false; - return this->EmptyExpression(); - } - - Scanner::Location spread_pos; - typename Traits::Type::ExpressionList args = - ParseArguments(&spread_pos, CHECK_OK); - - // TODO(rossberg): This doesn't work with arrow functions yet. - if (!IsSubclassConstructor(function_state_->kind())) { - ReportMessage("unexpected_super"); - *ok = false; - return this->EmptyExpression(); - } else if (function_state_->super_location().IsValid()) { - ReportMessageAt(scanner()->location(), "strong_super_call_duplicate"); - *ok = false; - return this->EmptyExpression(); - } else if (function_state_->this_location().IsValid()) { - ReportMessageAt(scanner()->location(), "strong_super_call_misplaced"); - *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_location(super_loc); - if (spread_pos.IsValid()) { - args = Traits::PrepareSpreadArguments(args); - return Traits::SpreadCall(expr, args, pos); - } else { - return factory()->NewCall(expr, args, pos); - } -} - - -template -typename ParserBase::ExpressionT ParserBase::ParseSuperExpression(bool is_new, bool* ok) { Expect(Token::SUPER, CHECK_OK); - // TODO(wingo): Does this actually work with lazily compiled arrows? FunctionState* function_state = function_state_; while (IsArrowFunction(function_state->kind())) { function_state = function_state->outer(); @@ -3172,12 +3025,18 @@ ParserBase::ParseSuperExpression(bool is_new, bool* ok) { // super() is only allowed in derived constructor if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { if (is_strong(language_mode())) { - // Super calls in strong mode are parsed separately. - ReportMessageAt(scanner()->location(), "strong_constructor_super"); - *ok = false; - return this->EmptyExpression(); + 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_location(scanner()->location()); + function_state->set_super_call_location(scanner()->location()); return this->SuperReference(scope_, factory()); } } @@ -3374,7 +3233,8 @@ ParserBase::ParseArrowFunctionLiteral( (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); if (is_lazily_parsed) { body = this->NewStatementList(0, zone()); - this->SkipLazyFunctionBody(&materialized_literal_count, + this->SkipLazyFunctionBody(this->EmptyIdentifier(), + &materialized_literal_count, &expected_property_count, CHECK_OK); } else { body = this->ParseEagerFunctionBody( @@ -3396,7 +3256,7 @@ ParserBase::ParseArrowFunctionLiteral( expected_property_count = function_state.expected_property_count(); handler_count = function_state.handler_count(); } - super_loc = function_state.super_location(); + super_loc = function_state.super_call_location(); scope->set_end_position(scanner()->location().end_pos); @@ -3425,7 +3285,7 @@ ParserBase::ParseArrowFunctionLiteral( scope->start_position()); function_literal->set_function_token_position(scope->start_position()); - if (super_loc.IsValid()) function_state_->set_super_location(super_loc); + if (super_loc.IsValid()) function_state_->set_super_call_location(super_loc); if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index ba84258..86e042e 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -5866,109 +5866,33 @@ TEST(StrongForIn) { } -TEST(StrongConstructorThis) { +TEST(StrongSuperCalls) { 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* error_data[] = { - "class C { constructor() { this; } }", - "class C { constructor() { this.a; } }", - "class C { constructor() { this['a']; } }", - "class C { constructor() { (this); } }", - "class C { constructor() { this(); } }", - // TODO(rossberg): arrow functions not handled yet. - // "class C { constructor() { () => this; } }", - "class C { constructor() { this.a = 0, 0; } }", - "class C { constructor() { (this.a = 0); } }", - // "class C { constructor() { (() => this.a = 0)(); } }", - "class C { constructor() { { this.a = 0; } } }", - "class C { constructor() { if (1) this.a = 0; } }", - "class C { constructor() { label: this.a = 0; } }", - "class C { constructor() { this.a = this.b; } }", - "class C { constructor() { this.a = {b: 1}; this.a.b } }", - "class C { constructor() { this.a = {b: 1}; this.a.b = 0 } }", - "class C { constructor() { this.a = function(){}; this.a() } }", - NULL}; - - const char* success_data[] = { - "class C { constructor() { this.a = 0; } }", - "class C { constructor() { label: 0; this.a = 0; this.b = 6; } }", - NULL}; - - static const ParserFlag always_flags[] = { - kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, - kAllowHarmonyArrowFunctions - }; - RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - - RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); -} - - -TEST(StrongConstructorSuper) { - 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* error_data[] = { + const char* data[] = { "class C extends Object { constructor() {} }", - "class C extends Object { constructor() { super.a; } }", - "class C extends Object { constructor() { super['a']; } }", - "class C extends Object { constructor() { super.a = 0; } }", - "class C extends Object { constructor() { (super.a); } }", - // TODO(rossberg): arrow functions do not handle super yet. - // "class C extends Object { constructor() { () => super.a; } }", - "class C extends Object { constructor() { super(), 0; } }", "class C extends Object { constructor() { (super()); } }", - // "class C extends Object { constructor() { (() => super())(); } }", + "class C extends Object { constructor() { (() => super())(); } }", "class C extends Object { constructor() { { super(); } } }", "class C extends Object { constructor() { if (1) super(); } }", - "class C extends Object { constructor() { label: super(); } }", "class C extends Object { constructor() { super(), super(); } }", "class C extends Object { constructor() { super(); super(); } }", "class C extends Object { constructor() { super(); (super()); } }", "class C extends Object { constructor() { super(); { super() } } }", - "class C extends Object { constructor() { this.a = 0, super(); } }", - "class C extends Object { constructor() { this.a = 0; super(); } }", - "class C extends Object { constructor() { super(this.a = 0); } }", - "class C extends Object { constructor() { super().a; } }", - NULL}; - - const char* success_data[] = { - "class C extends Object { constructor() { super(); } }", - "class C extends Object { constructor() { label: 66; super(); } }", - "class C extends Object { constructor() { super(3); this.x = 0; } }", - "class C extends Object { constructor() { 3; super(3); this.x = 0; } }", NULL}; static const ParserFlag always_flags[] = { kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, kAllowHarmonyArrowFunctions }; - RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - - RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + 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)); } @@ -5977,45 +5901,24 @@ TEST(StrongConstructorReturns) { const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}}; const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}}; - const char* error_data[] = { + 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(); } }", - "class C { constructor() { return; this.a = 0; } }", - "class C { constructor() { { return; } this.a = 0; } }", - "class C { constructor() { if (0) return; this.a = 0; } }", - "class C { constructor() { this.a = 0; if (0) return; this.b = 0; } }", - NULL}; - - const char* success_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 { constructor() { this.a = 0; return; } }", - "class C { constructor() { this.a = 0; { return; } } }", - "class C { constructor() { this.a = 0; if (0) return; 65; } }", - "class C extends Array { constructor() { super(); this.a = 9; return } }", NULL}; static const ParserFlag always_flags[] = { kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals }; - RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - - RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + 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)); } diff --git a/test/mjsunit/strong/classes.js b/test/mjsunit/strong/classes.js index c329043..50fe5a1 100644 --- a/test/mjsunit/strong/classes.js +++ b/test/mjsunit/strong/classes.js @@ -28,32 +28,16 @@ function constructor(body) { "(class extends Object { constructor() { " + body + " } })"; } -(function NoSuperExceptCall() { - assertSyntaxError(constructor("super.a;")); - assertSyntaxError(constructor("super['a'];")); - assertSyntaxError(constructor("super.f();")); - assertSyntaxError(constructor("super.a;")); - assertSyntaxError(constructor("{ super.a }")); - assertSyntaxError(constructor("if (0) super.a;")); - // TODO(rossberg): arrow functions do not handle 'super' yet. - // assertSyntaxError(constructor("() => super.a;")); - // assertSyntaxError(constructor("() => () => super.a;")); - // assertSyntaxError(constructor("() => { () => if (0) { super.a; } }")); -})(); - (function NoMissingSuper() { assertReferenceError(constructor("")); assertReferenceError(constructor("1")); })(); (function NoNestedSuper() { - assertSyntaxError(constructor("super(), 0;")); assertSyntaxError(constructor("(super());")); - assertSyntaxError(constructor("super().a;")); assertSyntaxError(constructor("(() => super())();")); assertSyntaxError(constructor("{ super(); }")); assertSyntaxError(constructor("if (1) super();")); - assertSyntaxError(constructor("label: super();")); })(); (function NoDuplicateSuper() { @@ -64,19 +48,9 @@ function constructor(body) { assertSyntaxError(constructor("super(); (() => super())();")); })(); -(function NoSuperAfterThis() { - assertSyntaxError(constructor("this.a = 0, super();")); - assertSyntaxError(constructor("this.a = 0; super();")); - assertSyntaxError(constructor("this.a = 0; super(); this.b = 0;")); - assertSyntaxError(constructor("this.a = 0; (super());")); - assertSyntaxError(constructor("super(this.a = 0);")); -})(); - (function NoReturnValue() { assertSyntaxError(constructor("return {};")); assertSyntaxError(constructor("return undefined;")); - assertSyntaxError(constructor("return this;")); - assertSyntaxError(constructor("return this.a = 0;")); assertSyntaxError(constructor("{ return {}; }")); assertSyntaxError(constructor("if (1) return {};")); })(); @@ -86,34 +60,3 @@ function constructor(body) { assertSyntaxError(constructor("if (0) return; super();")); assertSyntaxError(constructor("{ return; } super();")); })(); - -(function NoReturnBeforeThis() { - assertSyntaxError(constructor("return; this.a = 0;")); - assertSyntaxError(constructor("if (0) return; this.a = 0;")); - assertSyntaxError(constructor("{ return; } this.a = 0;")); -})(); - -(function NoThisExceptInitialization() { - assertSyntaxError(constructor("this;")); - assertSyntaxError(constructor("this.a;")); - assertSyntaxError(constructor("this['a'];")); - assertSyntaxError(constructor("this();")); - assertSyntaxError(constructor("this.a();")); - assertSyntaxError(constructor("this.a.b = 0;")); - assertSyntaxError(constructor("{ this }")); - assertSyntaxError(constructor("if (0) this;")); - // TODO(rossberg): this does not handle arrow functions yet. - // assertSyntaxError(constructor("() => this;")); - // assertSyntaxError(constructor("() => () => this;")); - // assertSyntaxError(constructor("() => { () => if (0) { this; } }")); -})(); - -(function NoNestedThis() { - assertSyntaxError(constructor("(this.a = 0);")); - assertSyntaxError(constructor("{ this.a = 0; }")); - assertSyntaxError(constructor("if (0) this.a = 0;")); - // TODO(rossberg): this does not handle arrow functions yet. - // assertSyntaxError(constructor("() => this.a = 0;")); - // assertSyntaxError(constructor("() => { this.a = 0; }")); - assertSyntaxError(constructor("label: this.a = 0;")); -})(); -- 2.7.4