Commit 904fbc30 authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

Revert of [es6] implement default parameters via desugaring (patchset #19...

Revert of [es6] implement default parameters via desugaring (patchset #19 id:380001 of https://codereview.chromium.org/1127063003/)

Reason for revert:
Broken on arm64

Original issue's description:
> [es6] implement default parameters via desugaring
>
> Stage 1 implementation:
>
> - Parameters can't be referenced before initialized (from left-to-right)
> - SingleNameBindings only, no support for BindingPatterns
>
> Known issues:
>
> - Incorrect scoping (parameter expressions may reference variables declared in function body)
> - Function arity is untouched
> - Hole-checking needs work
> - Rest parameters are broken when mixed with optional arguments
>
> BUG=v8:2160
> LOG=N
> R=arv@chromium.org, rossberg@chromium.org
>
> Committed: https://crrev.com/892c85485881f8be2f17bd83238980f858126576
> Cr-Commit-Position: refs/heads/master@{#28739}

TBR=rossberg@chromium.org,wingo@igalia.com,arv@chromium.org,dslomov@chromium.org,adamk@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:2160

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

Cr-Commit-Position: refs/heads/master@{#28740}
parent 892c8548
...@@ -1766,7 +1766,6 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_destructuring) ...@@ -1766,7 +1766,6 @@ EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_destructuring)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_object) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_object)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_spread_arrays) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_spread_arrays)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sharedarraybuffer) EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_sharedarraybuffer)
EMPTY_NATIVE_FUNCTIONS_FOR_FEATURE(harmony_default_parameters)
void Genesis::InstallNativeFunctions_harmony_proxies() { void Genesis::InstallNativeFunctions_harmony_proxies() {
...@@ -1798,7 +1797,6 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spreadcalls) ...@@ -1798,7 +1797,6 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spreadcalls)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_destructuring) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_destructuring)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spread_arrays) EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_spread_arrays)
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_default_parameters)
void Genesis::InitializeGlobal_harmony_regexps() { void Genesis::InitializeGlobal_harmony_regexps() {
Handle<JSObject> builtins(native_context()->builtins()); Handle<JSObject> builtins(native_context()->builtins());
...@@ -2443,7 +2441,6 @@ bool Genesis::InstallExperimentalNatives() { ...@@ -2443,7 +2441,6 @@ bool Genesis::InstallExperimentalNatives() {
static const char* harmony_spread_arrays_natives[] = {nullptr}; static const char* harmony_spread_arrays_natives[] = {nullptr};
static const char* harmony_sharedarraybuffer_natives[] = { static const char* harmony_sharedarraybuffer_natives[] = {
"native harmony-sharedarraybuffer.js", NULL}; "native harmony-sharedarraybuffer.js", NULL};
static const char* harmony_default_parameters_natives[] = {nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount(); for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) { i < ExperimentalNatives::GetBuiltinsCount(); i++) {
......
...@@ -194,8 +194,7 @@ DEFINE_IMPLICATION(es_staging, harmony) ...@@ -194,8 +194,7 @@ DEFINE_IMPLICATION(es_staging, harmony)
V(harmony_reflect, "harmony Reflect API") \ V(harmony_reflect, "harmony Reflect API") \
V(harmony_destructuring, "harmony destructuring") \ V(harmony_destructuring, "harmony destructuring") \
V(harmony_spread_arrays, "harmony spread in array literals") \ V(harmony_spread_arrays, "harmony spread in array literals") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \ V(harmony_sharedarraybuffer, "harmony sharedarraybuffer")
V(harmony_default_parameters, "harmony default parameters")
// Features that are complete (but still behind --harmony/es-staging flag). // Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \ #define HARMONY_STAGED(V) \
......
...@@ -331,8 +331,6 @@ class CallSite { ...@@ -331,8 +331,6 @@ class CallSite {
T(ParamAfterRest, "Rest parameter must be last formal parameter") \ T(ParamAfterRest, "Rest parameter must be last formal parameter") \
T(BadSetterRestParameter, \ T(BadSetterRestParameter, \
"Setter function argument must not be a rest parameter") \ "Setter function argument must not be a rest parameter") \
T(BadRestParameterInitializer, \
"Rest parameters must not have an initializer") \
T(ParenthesisInArgString, "Function arg string contains parenthesis") \ T(ParenthesisInArgString, "Function arg string contains parenthesis") \
T(SingleFunctionLiteral, "Single function literal required") \ T(SingleFunctionLiteral, "Single function literal required") \
T(SloppyLexical, \ T(SloppyLexical, \
......
...@@ -884,7 +884,6 @@ Parser::Parser(ParseInfo* info) ...@@ -884,7 +884,6 @@ Parser::Parser(ParseInfo* info)
set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls); set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls);
set_allow_harmony_destructuring(FLAG_harmony_destructuring); set_allow_harmony_destructuring(FLAG_harmony_destructuring);
set_allow_harmony_spread_arrays(FLAG_harmony_spread_arrays); set_allow_harmony_spread_arrays(FLAG_harmony_spread_arrays);
set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
set_allow_strong_mode(FLAG_strong_mode); set_allow_strong_mode(FLAG_strong_mode);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) { ++feature) {
...@@ -1149,16 +1148,9 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, ...@@ -1149,16 +1148,9 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
scope->set_start_position(shared_info->start_position()); scope->set_start_position(shared_info->start_position());
ExpressionClassifier formals_classifier; ExpressionClassifier formals_classifier;
bool has_rest = false; bool has_rest = false;
bool has_parameter_expressions = false;
// TODO(caitp): make default parameters work in arrow functions
ZoneList<Expression*>* initializers =
new (zone()) ZoneList<Expression*>(0, zone());
if (Check(Token::LPAREN)) { if (Check(Token::LPAREN)) {
// '(' StrictFormalParameters ')' // '(' StrictFormalParameters ')'
ParseFormalParameterList(scope, initializers, ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok);
&has_parameter_expressions, &has_rest,
&formals_classifier, &ok);
if (ok) ok = Check(Token::RPAREN); if (ok) ok = Check(Token::RPAREN);
} else { } else {
// BindingIdentifier // BindingIdentifier
...@@ -3412,114 +3404,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( ...@@ -3412,114 +3404,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
} }
ZoneList<Statement*>* Parser::DesugarInitializeParameters(
Scope* scope, bool has_parameter_expressions,
ZoneList<Expression*>* initializers) {
DCHECK(scope->is_function_scope());
if (has_parameter_expressions) {
// If has_parameter_expressions for the function is true, each parameter is
// desugared as follows:
//
// SingleNameBinding :
// let <name> = %_Arguments(<index>);
// SingleNameBinding Initializer
// let <name> = IS_UNDEFINED(%_Arguments(<index>)) ? <initializer>
// : %_Arguments(<index>);
//
// TODO(caitp, dslomov): support BindingPatterns & rest parameters
//
scope->UndeclareParametersForExpressions();
ZoneList<Statement*>* body =
new (zone()) ZoneList<Statement*>(initializers->length(), zone());
for (int i = 0; i < initializers->length(); ++i) {
Expression* initializer = initializers->at(i);
// Position of parameter VariableProxy, for hole-checking
int pos = scope->parameter_position(i);
static const int kCapacity = 1;
static const bool kIsInitializerBlock = true;
Block* param_block =
factory()->NewBlock(nullptr, kCapacity, kIsInitializerBlock, pos);
VariableProxy* proxy =
NewUnresolved(scope->parameter(i)->raw_name(), LET);
VariableDeclaration* declaration = factory()->NewVariableDeclaration(
proxy, LET, scope, RelocInfo::kNoPosition);
bool ok = true;
// All formal parameters have been removed from the scope VariableMap,
// and so Declare() should not be able to fail.
proxy = factory()->NewVariableProxy(Declare(declaration, true, &ok), pos);
DCHECK(ok);
const AstRawString* fn_name = ast_value_factory()->empty_string();
const Runtime::Function* arguments =
Runtime::FunctionForId(Runtime::kInlineArguments);
ZoneList<Expression*>* arguments_i0 =
new (zone()) ZoneList<Expression*>(1, zone());
arguments_i0->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
zone());
if (initializer == nullptr) {
// let <name> = %_Arguments(i)
Expression* assign = factory()->NewAssignment(
Token::INIT_LET, proxy,
factory()->NewCallRuntime(fn_name, arguments, arguments_i0,
RelocInfo::kNoPosition),
RelocInfo::kNoPosition);
param_block->AddStatement(
factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition),
zone());
proxy->var()->set_initializer_position(pos);
} else {
// IS_UNDEFINED(%_Arguments(i)) ? <initializer> : %_Arguments(i);
ZoneList<Expression*>* arguments_i1 =
new (zone()) ZoneList<Expression*>(1, zone());
arguments_i1->Add(factory()->NewSmiLiteral(i, RelocInfo::kNoPosition),
zone());
Expression* arg_or_default = factory()->NewConditional(
// condition:
factory()->NewCompareOperation(
Token::EQ_STRICT,
factory()->NewCallRuntime(fn_name, arguments, arguments_i0,
RelocInfo::kNoPosition),
factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
RelocInfo::kNoPosition),
// if true:
initializer,
// if false:
factory()->NewCallRuntime(fn_name, arguments, arguments_i1,
RelocInfo::kNoPosition),
RelocInfo::kNoPosition);
Expression* assign = factory()->NewAssignment(
Token::INIT_LET, proxy, arg_or_default, RelocInfo::kNoPosition);
param_block->AddStatement(
factory()->NewExpressionStatement(assign, RelocInfo::kNoPosition),
zone());
proxy->var()->set_initializer_position(initializer->position());
}
body->Add(param_block, zone());
}
return body;
} else {
// If has_parameter_expressions is false, remove the unnecessary parameter
// block scopes.
ZoneList<Scope*>* scopes = scope->inner_scopes();
for (int i = 0; i < scopes->length(); ++i) {
Scope* scope = scopes->at(i);
DCHECK(scope->is_block_scope());
scope->FinalizeBlockScope();
}
return nullptr;
}
}
Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
bool* ok) { bool* ok) {
// ForStatement :: // ForStatement ::
...@@ -3890,8 +3774,7 @@ void ParserTraits::DeclareArrowFunctionParameters( ...@@ -3890,8 +3774,7 @@ void ParserTraits::DeclareArrowFunctionParameters(
parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
bool is_rest = false; bool is_rest = false;
int pos = expr->position(); bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest, pos);
if (is_duplicate && !duplicate_loc->IsValid()) { if (is_duplicate && !duplicate_loc->IsValid()) {
*duplicate_loc = param_location; *duplicate_loc = param_location;
...@@ -4002,15 +3885,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -4002,15 +3885,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
} }
bool has_rest = false; bool has_rest = false;
bool has_parameter_expressions = false;
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos; int start_position = scanner()->location().beg_pos;
scope_->set_start_position(start_position); scope_->set_start_position(start_position);
ZoneList<Expression*>* initializers = num_parameters = ParseFormalParameterList(scope, &has_rest,
new (zone()) ZoneList<Expression*>(0, zone()); &formals_classifier, CHECK_OK);
num_parameters = ParseFormalParameterList(
scope, initializers, &has_parameter_expressions, &has_rest,
&formals_classifier, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos; int formals_end_position = scanner()->location().end_pos;
...@@ -4111,31 +3990,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -4111,31 +3990,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
} }
} }
if (!is_lazily_parsed) { if (!is_lazily_parsed) {
body = DesugarInitializeParameters(scope, has_parameter_expressions, body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
initializers); kind, CHECK_OK);
if (has_parameter_expressions) {
// TODO(caitp): Function body scope must be a declaration scope
Scope* function_body_scope = NewScope(scope, BLOCK_SCOPE);
function_body_scope->set_start_position(scope->start_position());
function_body_scope->SetScopeName(function_name);
BlockState function_body_state(&scope_, function_body_scope);
ZoneList<Statement*>* inner_body = ParseEagerFunctionBody(
function_name, pos, fvar, fvar_init_op, kind, CHECK_OK);
// Declare Block node
Block* block =
factory()->NewBlock(nullptr, inner_body->length(), false, pos);
block->set_scope(function_body_scope);
for (int i = 0; i < inner_body->length(); ++i) {
block->AddStatement(inner_body->at(i), zone());
}
scope->set_end_position(function_body_scope->end_position());
body->Add(block, zone());
} else {
body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
kind, CHECK_OK);
}
materialized_literal_count = function_state.materialized_literal_count(); materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count(); expected_property_count = function_state.expected_property_count();
handler_count = function_state.handler_count(); handler_count = function_state.handler_count();
...@@ -4419,8 +4275,6 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( ...@@ -4419,8 +4275,6 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
allow_harmony_destructuring()); allow_harmony_destructuring());
reusable_preparser_->set_allow_harmony_spread_arrays( reusable_preparser_->set_allow_harmony_spread_arrays(
allow_harmony_spread_arrays()); allow_harmony_spread_arrays());
reusable_preparser_->set_allow_harmony_default_parameters(
allow_harmony_default_parameters());
reusable_preparser_->set_allow_strong_mode(allow_strong_mode()); reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
} }
PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
......
...@@ -748,10 +748,9 @@ class ParserTraits { ...@@ -748,10 +748,9 @@ class ParserTraits {
FunctionKind kind = kNormalFunction); FunctionKind kind = kNormalFunction);
bool DeclareFormalParameter(Scope* scope, const AstRawString* name, bool DeclareFormalParameter(Scope* scope, const AstRawString* name,
bool is_rest, int pos) { bool is_rest) {
bool is_duplicate = false; bool is_duplicate = false;
Variable* var = Variable* var = scope->DeclareParameter(name, VAR, is_rest, &is_duplicate);
scope->DeclareParameter(name, VAR, is_rest, &is_duplicate, pos);
if (is_sloppy(scope->language_mode())) { if (is_sloppy(scope->language_mode())) {
// TODO(sigurds) Mark every parameter as maybe assigned. This is a // TODO(sigurds) Mark every parameter as maybe assigned. This is a
// conservative approximation necessary to account for parameters // conservative approximation necessary to account for parameters
...@@ -1026,6 +1025,7 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -1026,6 +1025,7 @@ class Parser : public ParserBase<ParserTraits> {
bool* ok_; bool* ok_;
}; };
void ParseVariableDeclarations(VariableDeclarationContext var_context, void ParseVariableDeclarations(VariableDeclarationContext var_context,
DeclarationParsingResult* parsing_result, DeclarationParsingResult* parsing_result,
bool* ok); bool* ok);
...@@ -1071,10 +1071,6 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -1071,10 +1071,6 @@ class Parser : public ParserBase<ParserTraits> {
ForStatement* loop, Statement* init, Expression* cond, Statement* next, ForStatement* loop, Statement* init, Expression* cond, Statement* next,
Statement* body, bool* ok); Statement* body, bool* ok);
ZoneList<Statement*>* DesugarInitializeParameters(
Scope* scope, bool has_parameter_expressions,
ZoneList<Expression*>* initializers);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
const AstRawString* name, Scanner::Location function_name_location, const AstRawString* name, Scanner::Location function_name_location,
bool name_is_strict_reserved, FunctionKind kind, bool name_is_strict_reserved, FunctionKind kind,
......
...@@ -1035,17 +1035,14 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -1035,17 +1035,14 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
ExpressionClassifier formals_classifier; ExpressionClassifier formals_classifier;
bool has_rest = false; bool has_rest = false;
bool has_parameter_expressions = false;
PreParserExpressionList initializers = NewExpressionList(0, zone());
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos; int start_position = scanner()->location().beg_pos;
function_scope->set_start_position(start_position); function_scope->set_start_position(start_position);
int num_parameters; int num_parameters;
{ {
DuplicateFinder duplicate_finder(scanner()->unicode_cache()); DuplicateFinder duplicate_finder(scanner()->unicode_cache());
num_parameters = ParseFormalParameterList( num_parameters = ParseFormalParameterList(&duplicate_finder, &has_rest,
&duplicate_finder, initializers, &has_parameter_expressions, &has_rest, &formals_classifier, CHECK_OK);
&formals_classifier, CHECK_OK);
} }
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos; int formals_end_position = scanner()->location().end_pos;
......
...@@ -66,7 +66,6 @@ class ParserBase : public Traits { ...@@ -66,7 +66,6 @@ class ParserBase : public Traits {
public: public:
// Shorten type names defined by Traits. // Shorten type names defined by Traits.
typedef typename Traits::Type::Expression ExpressionT; typedef typename Traits::Type::Expression ExpressionT;
typedef typename Traits::Type::ExpressionList ExpressionListT;
typedef typename Traits::Type::Identifier IdentifierT; typedef typename Traits::Type::Identifier IdentifierT;
typedef typename Traits::Type::FormalParameter FormalParameterT; typedef typename Traits::Type::FormalParameter FormalParameterT;
typedef typename Traits::Type::FormalParameterScope FormalParameterScopeT; typedef typename Traits::Type::FormalParameterScope FormalParameterScopeT;
...@@ -98,7 +97,6 @@ class ParserBase : public Traits { ...@@ -98,7 +97,6 @@ class ParserBase : public Traits {
allow_harmony_computed_property_names_(false), allow_harmony_computed_property_names_(false),
allow_harmony_rest_params_(false), allow_harmony_rest_params_(false),
allow_harmony_spreadcalls_(false), allow_harmony_spreadcalls_(false),
allow_harmony_default_parameters_(false),
allow_strong_mode_(false) {} allow_strong_mode_(false) {}
// Getters that indicate whether certain syntactical constructs are // Getters that indicate whether certain syntactical constructs are
...@@ -128,9 +126,6 @@ class ParserBase : public Traits { ...@@ -128,9 +126,6 @@ class ParserBase : public Traits {
bool allow_harmony_spread_arrays() const { bool allow_harmony_spread_arrays() const {
return allow_harmony_spread_arrays_; return allow_harmony_spread_arrays_;
} }
bool allow_harmony_default_parameters() const {
return allow_harmony_default_parameters_;
}
bool allow_strong_mode() const { return allow_strong_mode_; } bool allow_strong_mode() const { return allow_strong_mode_; }
...@@ -172,10 +167,6 @@ class ParserBase : public Traits { ...@@ -172,10 +167,6 @@ class ParserBase : public Traits {
void set_allow_harmony_spread_arrays(bool allow) { void set_allow_harmony_spread_arrays(bool allow) {
allow_harmony_spread_arrays_ = allow; allow_harmony_spread_arrays_ = allow;
} }
void set_allow_harmony_default_parameters(bool allow) {
allow_harmony_default_parameters_ = allow;
}
protected: protected:
enum AllowRestrictedIdentifiers { enum AllowRestrictedIdentifiers {
...@@ -928,9 +919,7 @@ class ParserBase : public Traits { ...@@ -928,9 +919,7 @@ class ParserBase : public Traits {
void ParseFormalParameter(FormalParameterScopeT* scope, bool is_rest, void ParseFormalParameter(FormalParameterScopeT* scope, bool is_rest,
ExpressionClassifier* classifier, bool* ok); ExpressionClassifier* classifier, bool* ok);
int ParseFormalParameterList(FormalParameterScopeT* scope, int ParseFormalParameterList(FormalParameterScopeT* scope, bool* has_rest,
ExpressionListT initializers,
bool* has_parameter_expressions, bool* has_rest,
ExpressionClassifier* classifier, bool* ok); ExpressionClassifier* classifier, bool* ok);
void CheckArityRestrictions( void CheckArityRestrictions(
int param_count, FunctionLiteral::ArityRestriction arity_restriction, int param_count, FunctionLiteral::ArityRestriction arity_restriction,
...@@ -1033,7 +1022,6 @@ class ParserBase : public Traits { ...@@ -1033,7 +1022,6 @@ class ParserBase : public Traits {
bool allow_harmony_spreadcalls_; bool allow_harmony_spreadcalls_;
bool allow_harmony_destructuring_; bool allow_harmony_destructuring_;
bool allow_harmony_spread_arrays_; bool allow_harmony_spread_arrays_;
bool allow_harmony_default_parameters_;
bool allow_strong_mode_; bool allow_strong_mode_;
}; };
...@@ -1811,8 +1799,8 @@ class PreParserTraits { ...@@ -1811,8 +1799,8 @@ class PreParserTraits {
} }
V8_INLINE bool DeclareFormalParameter(DuplicateFinder* scope, V8_INLINE bool DeclareFormalParameter(DuplicateFinder* scope,
PreParserIdentifier param, bool is_rest, PreParserIdentifier param,
int pos); bool is_rest);
void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
...@@ -2008,7 +1996,7 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function, ...@@ -2008,7 +1996,7 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
bool PreParserTraits::DeclareFormalParameter( bool PreParserTraits::DeclareFormalParameter(
DuplicateFinder* duplicate_finder, PreParserIdentifier current_identifier, DuplicateFinder* duplicate_finder, PreParserIdentifier current_identifier,
bool is_rest, int pos) { bool is_rest) {
return pre_parser_->scanner()->FindSymbol(duplicate_finder, 1) != 0; return pre_parser_->scanner()->FindSymbol(duplicate_finder, 1) != 0;
} }
...@@ -3685,11 +3673,10 @@ void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope, ...@@ -3685,11 +3673,10 @@ void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope,
bool* ok) { bool* ok) {
// FormalParameter[Yield,GeneratorParameter] : // FormalParameter[Yield,GeneratorParameter] :
// BindingElement[?Yield, ?GeneratorParameter] // BindingElement[?Yield, ?GeneratorParameter]
int pos = peek_position();
IdentifierT name = ParseAndClassifyIdentifier(classifier, ok); IdentifierT name = ParseAndClassifyIdentifier(classifier, ok);
if (!*ok) return; if (!*ok) return;
bool was_declared = Traits::DeclareFormalParameter(scope, name, is_rest, pos); bool was_declared = Traits::DeclareFormalParameter(scope, name, is_rest);
if (was_declared) { if (was_declared) {
classifier->RecordDuplicateFormalParameterError(scanner()->location()); classifier->RecordDuplicateFormalParameterError(scanner()->location());
} }
...@@ -3698,8 +3685,7 @@ void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope, ...@@ -3698,8 +3685,7 @@ void ParserBase<Traits>::ParseFormalParameter(FormalParameterScopeT* scope,
template <class Traits> template <class Traits>
int ParserBase<Traits>::ParseFormalParameterList( int ParserBase<Traits>::ParseFormalParameterList(
FormalParameterScopeT* scope, ExpressionListT initializers, FormalParameterScopeT* scope, bool* is_rest,
bool* has_parameter_expressions, bool* is_rest,
ExpressionClassifier* classifier, bool* ok) { ExpressionClassifier* classifier, bool* ok) {
// FormalParameters[Yield,GeneratorParameter] : // FormalParameters[Yield,GeneratorParameter] :
// [empty] // [empty]
...@@ -3719,43 +3705,14 @@ int ParserBase<Traits>::ParseFormalParameterList( ...@@ -3719,43 +3705,14 @@ int ParserBase<Traits>::ParseFormalParameterList(
if (peek() != Token::RPAREN) { if (peek() != Token::RPAREN) {
do { do {
Scope* param_scope = NewScope(scope_, BLOCK_SCOPE);
BlockState param_state(&scope_, param_scope);
param_scope->set_start_position(peek_position());
if (++parameter_count > Code::kMaxArguments) { if (++parameter_count > Code::kMaxArguments) {
ReportMessage(MessageTemplate::kTooManyParameters); ReportMessage(MessageTemplate::kTooManyParameters);
*ok = false; *ok = false;
return -1; return -1;
} }
int start_pos = peek_position();
*is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS); *is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS);
ParseFormalParameter(scope, *is_rest, classifier, ok); ParseFormalParameter(scope, *is_rest, classifier, ok);
if (!*ok) return -1; if (!*ok) return -1;
// TODO(caitp, dslomov): set *has_parameter_expressions to true if
// formal parameter is an ObjectBindingPattern containing computed
// property keys
ExpressionT initializer = this->EmptyExpression();
if (allow_harmony_default_parameters() && Check(Token::ASSIGN)) {
// Default parameter initializer
static const bool accept_IN = true;
ExpressionClassifier classifier;
initializer = ParseAssignmentExpression(accept_IN, &classifier, ok);
if (!*ok) return -1;
*has_parameter_expressions = true;
// A rest parameter cannot be initialized.
if (*is_rest) {
Scanner::Location loc(start_pos, scanner()->location().end_pos);
ReportMessageAt(loc, MessageTemplate::kBadRestParameterInitializer);
*ok = false;
return -1;
}
}
param_scope->set_end_position(scanner()->location().end_pos);
initializers->Add(initializer, zone());
} while (!*is_rest && Check(Token::COMMA)); } while (!*is_rest && Check(Token::COMMA));
if (*is_rest && peek() == Token::COMMA) { if (*is_rest && peek() == Token::COMMA) {
......
...@@ -77,7 +77,6 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, ...@@ -77,7 +77,6 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
internals_(4, zone), internals_(4, zone),
temps_(4, zone), temps_(4, zone),
params_(4, zone), params_(4, zone),
param_positions_(4, zone),
unresolved_(16, zone), unresolved_(16, zone),
decls_(4, zone), decls_(4, zone),
module_descriptor_( module_descriptor_(
...@@ -101,7 +100,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, ...@@ -101,7 +100,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type,
internals_(4, zone), internals_(4, zone),
temps_(4, zone), temps_(4, zone),
params_(4, zone), params_(4, zone),
param_positions_(4, zone),
unresolved_(16, zone), unresolved_(16, zone),
decls_(4, zone), decls_(4, zone),
module_descriptor_(NULL), module_descriptor_(NULL),
...@@ -128,7 +126,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ...@@ -128,7 +126,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope,
internals_(0, zone), internals_(0, zone),
temps_(0, zone), temps_(0, zone),
params_(0, zone), params_(0, zone),
param_positions_(0, zone),
unresolved_(0, zone), unresolved_(0, zone),
decls_(0, zone), decls_(0, zone),
module_descriptor_(NULL), module_descriptor_(NULL),
...@@ -186,7 +183,6 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, ...@@ -186,7 +183,6 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
module_var_ = NULL, module_var_ = NULL,
rest_parameter_ = NULL; rest_parameter_ = NULL;
rest_index_ = -1; rest_index_ = -1;
has_parameter_expressions_ = false;
scope_info_ = scope_info; scope_info_ = scope_info;
start_position_ = RelocInfo::kNoPosition; start_position_ = RelocInfo::kNoPosition;
end_position_ = RelocInfo::kNoPosition; end_position_ = RelocInfo::kNoPosition;
...@@ -474,7 +470,7 @@ Variable* Scope::Lookup(const AstRawString* name) { ...@@ -474,7 +470,7 @@ Variable* Scope::Lookup(const AstRawString* name) {
Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
bool is_rest, bool* is_duplicate, int pos) { bool is_rest, bool* is_duplicate) {
DCHECK(!already_resolved()); DCHECK(!already_resolved());
DCHECK(is_function_scope()); DCHECK(is_function_scope());
Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL,
...@@ -487,7 +483,6 @@ Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, ...@@ -487,7 +483,6 @@ Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
// TODO(wingo): Avoid O(n^2) check. // TODO(wingo): Avoid O(n^2) check.
*is_duplicate = IsDeclaredParameter(name); *is_duplicate = IsDeclaredParameter(name);
params_.Add(var, zone()); params_.Add(var, zone());
param_positions_.Add(pos, zone());
return var; return var;
} }
...@@ -558,18 +553,6 @@ void Scope::AddDeclaration(Declaration* declaration) { ...@@ -558,18 +553,6 @@ void Scope::AddDeclaration(Declaration* declaration) {
} }
void Scope::UndeclareParametersForExpressions() {
DCHECK(is_function_scope());
DCHECK(!has_parameter_expressions_);
has_parameter_expressions_ = true;
for (int i = 0; i < num_parameters(); ++i) {
Variable* p = parameter(i);
const AstRawString* name = p->raw_name();
variables_.Remove(const_cast<AstRawString*>(name), name->hash());
}
}
void Scope::SetIllegalRedeclaration(Expression* expression) { void Scope::SetIllegalRedeclaration(Expression* expression) {
// Record only the first illegal redeclaration. // Record only the first illegal redeclaration.
if (!HasIllegalRedeclaration()) { if (!HasIllegalRedeclaration()) {
...@@ -1436,21 +1419,16 @@ void Scope::AllocateParameterLocals(Isolate* isolate) { ...@@ -1436,21 +1419,16 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
// If it does, and if it is not copied into the context object, it must // If it does, and if it is not copied into the context object, it must
// receive the highest parameter index for that parameter; thus iteration // receive the highest parameter index for that parameter; thus iteration
// order is relevant! // order is relevant!
// for (int i = params_.length() - 1; i >= 0; --i) {
// If hasParameterExpressions is true, parameters are redeclared during Variable* var = params_[i];
// desugaring, and must not be allocated here. if (var == rest_parameter_) continue;
if (!has_parameter_expressions_) {
for (int i = params_.length() - 1; i >= 0; --i) { DCHECK(var->scope() == this);
Variable* var = params_[i]; if (uses_sloppy_arguments || has_forced_context_allocation()) {
if (var == rest_parameter_) continue; // Force context allocation of the parameter.
var->ForceContextAllocation();
DCHECK(var->scope() == this);
if (uses_sloppy_arguments || has_forced_context_allocation()) {
// Force context allocation of the parameter.
var->ForceContextAllocation();
}
AllocateParameter(var, i);
} }
AllocateParameter(var, i);
} }
} }
......
...@@ -126,7 +126,7 @@ class Scope: public ZoneObject { ...@@ -126,7 +126,7 @@ class Scope: public ZoneObject {
// parameters the rightmost one 'wins'. However, the implementation // parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right. // expects all parameters to be declared and from left to right.
Variable* DeclareParameter(const AstRawString* name, VariableMode mode, Variable* DeclareParameter(const AstRawString* name, VariableMode mode,
bool is_rest, bool* is_duplicate, int pos); bool is_rest, bool* is_duplicate);
// Declare a local variable in this scope. If the variable has been // Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned. // declared before, the previously declared variable is returned.
...@@ -182,10 +182,6 @@ class Scope: public ZoneObject { ...@@ -182,10 +182,6 @@ class Scope: public ZoneObject {
// the scope; see codegen.cc:ProcessDeclarations. // the scope; see codegen.cc:ProcessDeclarations.
void AddDeclaration(Declaration* declaration); void AddDeclaration(Declaration* declaration);
// Formal parameters may be re-declared as lexical declarations in order to
// support TDZ semantics specified in ECMAScript 6.
void UndeclareParametersForExpressions();
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Illegal redeclaration support. // Illegal redeclaration support.
...@@ -377,13 +373,6 @@ class Scope: public ZoneObject { ...@@ -377,13 +373,6 @@ class Scope: public ZoneObject {
return params_[index]; return params_[index];
} }
// TODO(caitp): This probably won't work when BindingPatterns are supported
// in function parameters. Need a better way.
int parameter_position(int index) const {
DCHECK(is_function_scope());
return param_positions_[index];
}
// Returns the default function arity --- does not include rest parameters. // Returns the default function arity --- does not include rest parameters.
int default_function_length() const { int default_function_length() const {
int count = params_.length(); int count = params_.length();
...@@ -574,7 +563,6 @@ class Scope: public ZoneObject { ...@@ -574,7 +563,6 @@ class Scope: public ZoneObject {
ZoneList<Variable*> temps_; ZoneList<Variable*> temps_;
// Parameter list in source order. // Parameter list in source order.
ZoneList<Variable*> params_; ZoneList<Variable*> params_;
ZoneList<int> param_positions_;
// Variables that must be looked up dynamically. // Variables that must be looked up dynamically.
DynamicScopePart* dynamics_; DynamicScopePart* dynamics_;
// Unresolved variables referred to from this scope. // Unresolved variables referred to from this scope.
...@@ -649,8 +637,6 @@ class Scope: public ZoneObject { ...@@ -649,8 +637,6 @@ class Scope: public ZoneObject {
Variable* rest_parameter_; Variable* rest_parameter_;
int rest_index_; int rest_index_;
bool has_parameter_expressions_;
// Serialized scope info support. // Serialized scope info support.
Handle<ScopeInfo> scope_info_; Handle<ScopeInfo> scope_info_;
bool already_resolved() { return already_resolved_; } bool already_resolved() { return already_resolved_; }
......
...@@ -67,10 +67,6 @@ class Variable: public ZoneObject { ...@@ -67,10 +67,6 @@ class Variable: public ZoneObject {
Handle<String> name() const { return name_->string(); } Handle<String> name() const { return name_->string(); }
const AstRawString* raw_name() const { return name_; } const AstRawString* raw_name() const { return name_; }
VariableMode mode() const { return mode_; } VariableMode mode() const { return mode_; }
void set_mode(VariableMode mode) {
// Don't use this unless you have a very good reason
mode_ = mode;
}
bool has_forced_context_allocation() const { bool has_forced_context_allocation() const {
return force_context_allocation_; return force_context_allocation_;
} }
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-debug-as debug --harmony-default-parameters
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
listenerComplete = false;
breakPointCount = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
breakPointCount++;
if (breakPointCount == 1) {
// Break point in initializer for parameter `a`, invoked by
// initializer for parameter `b`
assertEquals('default', exec_state.frame(1).evaluate('mode').value());
// initializer for `b` can't refer to `b`
assertThrows(function() {
return exec_state.frame(1).evaluate('b').value();
}, ReferenceError);
assertThrows(function() {
return exec_state.frame(1).evaluate('c');
}, ReferenceError);
} else if (breakPointCount == 2) {
// Break point in IIFE initializer for parameter `c`
assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value());
assertEquals('default', exec_state.frame(1).evaluate('b').value());
assertThrows(function() {
return exec_state.frame(1).evaluate('c');
}, ReferenceError);
} else if (breakPointCount == 3) {
// Break point in function body --- `c` parameter is shadowed
assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value());
assertEquals('default', exec_state.frame(0).evaluate('b').value());
// TODO(caitp): fix scoping so that parameter `c` can be shadowed by vars
//assertEquals(true, exec_state.frame(0).evaluate('c').value());
}
}
};
// Add the debug event listener.
Debug.setListener(listener);
function f(a = function modeFn(mode) {
debugger;
return mode;
},
b = a("default"),
c = (function() {
debugger;
})()) {
// TODO(caitp): fix scoping so that parameter `c` can be shadowed by vars
//var c = true;
debugger;
};
f();
// Make sure that the debug event listener vas invoked.
assertEquals(3, breakPointCount);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-default-parameters --min-preparse-length=0
var i = 0;
function f(handler = function(b) { return b + "#" + (++i); }, b = "red") {
return handler(b);
}
assertEquals([
"blue#1",
"red#2",
"red",
"yellow#3"
], [
f(undefined, "blue"),
f(),
f(function(b) { return b; }),
f(undefined, "yellow")
]);
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-default-parameters --harmony-arrow-functions
function return_specified() { return "specified"; }
var method_returns_specified = {
method() { return "specified"; }
};
(function testDefaultFunctions() {
function optional_function(handler = function() { }) {
assertEquals("function", typeof handler);
// TODO(caitp): infer function name correctly
// (https://code.google.com/p/v8/issues/detail?id=3699)
// assertEquals("handler", handler.name);
return handler();
}
assertEquals(undefined, optional_function());
assertEquals(undefined, optional_function(undefined));
assertEquals("specified", optional_function(return_specified));
})();
(function testDefaultFunctionReferencesParameters() {
function fn1(handler = function() { return value; }, value) {
return handler();
}
assertEquals(undefined, fn1());
assertEquals(undefined, fn1(undefined, undefined));
assertEquals(1, fn1(undefined, 1));
function fn2(value, handler = function() { return value; }) {
return handler();
}
assertEquals(undefined, fn2());
assertEquals(undefined, fn2(undefined));
assertEquals(1, fn2(1));
})();
(function testDefaultObjects() {
function optional_object(object = { method() { return "method"; } }) {
assertEquals("object", typeof object);
assertEquals("function", typeof object.method);
return object.method();
}
assertEquals("method", optional_object());
assertEquals("method", optional_object(undefined));
assertEquals("specified", optional_object(method_returns_specified));
assertEquals(4, (function(x = { a: 4 }) { return x.a; })());
assertEquals(5, (function(x, y = { a: x }) { return y.a; })(5));
assertEquals(6, (function(x, y = { a: eval("x") }) { return y.a; })(6));
})();
// TDZ
(function testReferencesUninitializedParameter() {
assertThrows(function(a = b, b) {}, ReferenceError);
})();
(function testEvalReferencesUninitializedParameter() {
assertThrows( function(x = { a: y }, y) { return x.a; }, ReferenceError);
assertThrows(function(a = eval("b"), b = 0) { return a; }, ReferenceError);
assertThrows(
function(x = { a: eval("y") }, y) { return x.a; }, ReferenceError);
})();
(function testReferencesInitializedParameter() {
assertEquals(1, (function(a = 1, b = a) { return b; })());
})();
// Scoping
//
// TODO(caitp): fix scoping --- var declarations in function body can't be
// resolved in formal parameters
// assertThrows(function referencesVariableBodyDeclaration(a = body_var) {
// var body_var = true;
// return a;
// }, ReferenceError);
// TODO(caitp): default function length does not include any parameters
// following the first optional parameter
// assertEquals(0, (function(a = 1) {}).length);
// assertEquals(1, (function(a, b = 1) {}).length);
// assertEquals(2, (function(a, b, c = 1) {}).length);
// assertEquals(3, (function(a, b, c, d = 1) {}).length);
// assertEquals(1, (function(a, b = 1, c, d = 1) {}).length);
(function testInitializerReferencesThis() {
var O = {};
function fn(x = this) { return x; }
assertEquals(O, fn.call(O));
function fn2(x = () => this) { return x(); }
assertEquals(O, fn2.call(O));
})();
(function testInitializerReferencesSelf() {
function fn(x, y = fn) { return x ? y(false) + 1 : 0 }
assertEquals(1, fn(true));
})();
(function testInitializerEvalParameter() {
assertEquals(7, (function(x, y = eval("x")) { return y; })(7));
assertEquals(9, (function(x = () => eval("y"), y = 9) { return x(); })());
})();
(function testContextAllocatedUsedInBody() {
assertEquals("Monkey!Monkey!Monkey!", (function(x, y = eval("x")) {
return "Mon" + x + "Mon" + eval("y") + "Mon" + y;
})("key!"));
assertEquals("Monkey!", (function(x = "Mon", y = "key!") {
return eval("x") + eval("y");
})());
})();
(function testContextAllocatedEscapesFunction() {
assertEquals("Monkey!", (function(x = "Monkey!") {
return function() {
return x;
};
})()());
})();
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