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}
115 lines
2.7 KiB
JavaScript
115 lines
2.7 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 Reflect.apply with wrong number of arguments.
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return Reflect.apply(bar); }
|
|
|
|
assertThrows(foo);
|
|
assertThrows(foo);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo);
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return Reflect.apply(bar, this); }
|
|
|
|
assertThrows(foo);
|
|
assertThrows(foo);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo);
|
|
})();
|
|
(function() {
|
|
"use strict";
|
|
function bar() { return this; }
|
|
function foo() { return Reflect.apply(bar, this, arguments, this); }
|
|
|
|
assertEquals(42, foo.call(42));
|
|
assertEquals(42, foo.call(42));
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(42, foo.call(42));
|
|
})();
|
|
|
|
// Test Reflect.apply within try/catch.
|
|
(function() {
|
|
"use strict";
|
|
function foo(bar) {
|
|
try {
|
|
return Reflect.apply(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 Reflect.apply(bar, bar, bar);
|
|
} catch (e) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
assertEquals(1, foo());
|
|
assertEquals(1, foo());
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertEquals(1, foo());
|
|
})();
|
|
|
|
// Test proper order of callable check and array-like iteration
|
|
// in Reflect.apply.
|
|
(function() {
|
|
var dummy_length_counter = 0;
|
|
var dummy = { get length() { ++dummy_length_counter; return 0; } };
|
|
|
|
function foo() {
|
|
return Reflect.apply(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 Reflect.apply(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 Reflect.apply(null, this, dummy);
|
|
}
|
|
|
|
assertThrows(foo, TypeError);
|
|
assertThrows(foo, TypeError);
|
|
%OptimizeFunctionOnNextCall(foo);
|
|
assertThrows(foo, TypeError);
|
|
assertEquals(0, dummy_length_counter);
|
|
})();
|