Commit 635b5fea authored by arv's avatar arv Committed by Commit bot

Lexical arguments for arrow functions

Only allocate 'arguments' if the scope is not an arrow scope.

BUG=v8:2700
LOG=N
R=adamk@chromium.org, wingo@igalia.cmo

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

Cr-Commit-Position: refs/heads/master@{#27716}
parent 9b09a28d
......@@ -328,8 +328,8 @@ void Scope::Initialize() {
receiver_ = outer_scope()->receiver();
}
if (is_function_scope()) {
// Declare 'arguments' variable which exists in all functions.
if (is_function_scope() && !is_arrow_scope()) {
// Declare 'arguments' variable which exists in all non arrow functions.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this,
......@@ -1295,11 +1295,13 @@ void Scope::AllocateHeapSlot(Variable* var) {
void Scope::AllocateParameterLocals(Isolate* isolate) {
DCHECK(is_function_scope());
Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
DCHECK(arguments != NULL); // functions have 'arguments' declared implicitly
// Functions have 'arguments' declared implicitly in all non arrow functions.
DCHECK(arguments != nullptr || is_arrow_scope());
bool uses_sloppy_arguments = false;
if (MustAllocate(arguments) && !HasArgumentsParameter(isolate)) {
if (arguments != nullptr && MustAllocate(arguments) &&
!HasArgumentsParameter(isolate)) {
// 'arguments' is used. Unless there is also a parameter called
// 'arguments', we must be conservative and allocate all parameters to
// the context assuming they will be captured by the arguments object.
......
......@@ -394,7 +394,10 @@ class Scope: public ZoneObject {
}
// The local variable 'arguments' if we need to allocate it; NULL otherwise.
Variable* arguments() const { return arguments_; }
Variable* arguments() const {
DCHECK(!is_arrow_scope() || arguments_ == nullptr);
return arguments_;
}
// Declarations list.
ZoneList<Declaration*>* declarations() { return &decls_; }
......
// 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-arrow-functions --harmony-classes
(function testInFunctionDeclaration() {
var calls = 0;
function f() {
(() => {
calls++;
assertEquals(2, arguments.length);
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
})();
}
f('a', 'b');
assertEquals(1, calls);
calls = 0;
new f('a', 'b');
assertEquals(1, calls);
})();
(function testInFunctionExpression() {
var calls = 0;
var f = function() {
(() => {
calls++;
assertEquals(2, arguments.length);
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
})();
}
f('a', 'b');
assertEquals(1, calls);
})();
(function testInConstructor() {
'use strict';
var calls = 0;
class C {
constructor() {
(() => {
calls++;
assertEquals(2, arguments.length);
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
})();
}
}
new C('a', 'b');
assertEquals(1, calls);
})();
(function testInSetter() {
'use strict';
var calls = 0;
var o = {
set x(_) {
(() => {
calls++;
assertEquals(1, arguments.length);
assertEquals('a', arguments[0]);
})();
}
}
o.x = 'a';
assertEquals(1, calls);
})();
(function testMappedArguments() {
var calls = 0;
function f(x) {
x = 'c';
(() => {
calls++;
assertEquals(2, arguments.length);
assertEquals('c', arguments[0]);
x = 'a';
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
})();
}
f('a', 'b');
assertEquals(1, calls);
})();
(function testUnMappedArguments() {
'use strict';
var calls = 0;
function f(x) {
x = 'c';
(() => {
calls++;
assertEquals(2, arguments.length);
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
})();
}
f('a', 'b');
assertEquals(1, calls);
})();
(function testClosure() {
var calls = 0;
function f(x) {
return () => {
calls++;
assertEquals(2, arguments.length);
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
};
}
f('a', 'b')();
assertEquals(1, calls);
})();
(function testClosureMappedArguments() {
var calls = 0;
function f(x) {
x = 'c';
return () => {
calls++;
assertEquals(2, arguments.length);
assertEquals('c', arguments[0]);
x = 'a';
assertEquals('a', arguments[0]);
assertEquals('b', arguments[1]);
};
}
f('a', 'b')();
assertEquals(1, calls);
})();
(function testParamNamedArguments() {
var calls = 0;
function f(arguments) {
(() => {
calls++;
assertEquals('a', arguments);
})();
}
f('a');
assertEquals(1, calls);
})();
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