767ce78871
Add a new JSCallWithArrayLike operator that is backed by the CallWithArrayLike builtin, and use that operator for both Function.prototype.apply and Reflect.apply inlining. Also unify the handling of JSCallWithArrayLike and JSCallWithSpread in the JSCallReducer to reduce the copy&paste overhead. Drive-by-fix: Add a lot of test coverage for Reflect.apply and Function.prototype.apply in optimized code, especially for some corner cases, which was missing so far. BUG=v8:4587,v8:5269 R=petermarshall@chromium.org Review-Url: https://codereview.chromium.org/2950773002 Cr-Commit-Position: refs/heads/master@{#46041}
137 lines
3.4 KiB
JavaScript
137 lines
3.4 KiB
JavaScript
// Copyright 2017 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: --allow-natives-syntax
|
|
|
|
// Test Function.prototype.apply with null/undefined argumentsList
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return bar.apply(this, null); }
|
|
|
|
assertEquals(42, foo.call(42));
|
|
assertEquals(42, foo.call(42));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(42, foo.call(42));
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return bar.apply(this, undefined); }
|
|
|
|
assertEquals(42, foo.call(42));
|
|
assertEquals(42, foo.call(42));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(42, foo.call(42));
|
|
})();
|
|
|
|
// Test Function.prototype.apply within try/catch.
|
|
(function() {
|
|
"use strict";
|
|
function foo(bar) {
|
|
try {
|
|
return Function.prototype.apply.call(bar, bar, arguments);
|
|
} catch (e) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
assertEquals(1, foo());
|
|
assertEquals(1, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(1, foo());
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function foo(bar) {
|
|
try {
|
|
return Function.prototype.apply.call(bar, bar, bar);
|
|
} catch (e) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
assertEquals(1, foo());
|
|
assertEquals(1, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(1, foo());
|
|
})();
|
|
|
|
// Test Function.prototype.apply with wrong number of arguments.
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return bar.apply(); }
|
|
|
|
assertEquals(undefined, foo());
|
|
assertEquals(undefined, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(undefined, foo());
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return bar.apply(this); }
|
|
|
|
assertEquals(42, foo.call(42));
|
|
assertEquals(42, foo.call(42));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(42, foo.call(42));
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return bar.apply(this, arguments, this); }
|
|
|
|
assertEquals(42, foo.call(42));
|
|
assertEquals(42, foo.call(42));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(42, foo.call(42));
|
|
})();
|
|
|
|
// Test proper order of callable check and array-like iteration
|
|
// in Function.prototype.apply.
|
|
(function() {
|
|
var dummy_length_counter = 0;
|
|
var dummy = { get length() { ++dummy_length_counter; return 0; } };
|
|
|
|
function foo() {
|
|
return Function.prototype.apply.call(undefined, this, dummy);
|
|
}
|
|
|
|
assertThrows(foo, TypeError);
|
|
assertThrows(foo, TypeError);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo, TypeError);
|
|
assertEquals(0, dummy_length_counter);
|
|
})();
|
|
(function() {
|
|
var dummy_length_counter = 0;
|
|
var dummy = { get length() { ++dummy_length_counter; return 0; } };
|
|
|
|
function foo() {
|
|
return Function.prototype.apply.call(null, this, dummy);
|
|
}
|
|
|
|
assertThrows(foo, TypeError);
|
|
assertThrows(foo, TypeError);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo, TypeError);
|
|
assertEquals(0, dummy_length_counter);
|
|
})();
|
|
(function() {
|
|
var dummy_length_counter = 0;
|
|
var dummy = { get length() { ++dummy_length_counter; return 0; } };
|
|
|
|
function foo() {
|
|
return Function.prototype.apply.call(null, this, dummy);
|
|
}
|
|
|
|
assertThrows(foo, TypeError);
|
|
assertThrows(foo, TypeError);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo, TypeError);
|
|
assertEquals(0, dummy_length_counter);
|
|
})();
|