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}
This commit is contained in:
parent
9b09a28d5c
commit
635b5fea98
@ -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_; }
|
||||
|
158
test/mjsunit/harmony/arrow-functions-lexical-arguments.js
Normal file
158
test/mjsunit/harmony/arrow-functions-lexical-arguments.js
Normal file
@ -0,0 +1,158 @@
|
||||
// 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);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user