v8/test/mjsunit/es6/proxies-prevent-extensions.js
Z Nguyen-Huu 8e0ef9b9a0 Add fast path for proxy with preventExtensions trap
ObjectPreventExtensions and ReflectPreventExtensions are now Torque builtins (previously CPP) and the Proxy path is implemented completely in Torque while everything else calls into runtime (and is thus a bit slower than previously).

Perf improvement in micro-benchmark JSTests/Proxies
Before:
PreventExtensionsWithoutTrap-Proxies(Score): 1978
PreventExtensionsWithTrap-Proxies(Score): 739

After:
PreventExtensionsWithoutTrap-Proxies(Score): 3017
PreventExtensionsWithTrap-Proxies(Score): 2044

Bug: v8:6664
Change-Id: I6505d730cea6b0d197f6f5d0540b39056c8b763d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1652688
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62130}
2019-06-12 20:57:31 +00:00

204 lines
5.1 KiB
JavaScript

// 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.
// Reflect.
(function () {
// No trap.
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
assertTrue(Reflect.isExtensible(target));
assertTrue(Reflect.isExtensible(proxy));
assertTrue(Reflect.preventExtensions(proxy));
assertFalse(Reflect.isExtensible(target));
assertFalse(Reflect.isExtensible(proxy));
})();
(function () {
// "Undefined" trap.
var target = {};
var handler = { preventExtensions: null };
var proxy = new Proxy(target, handler);
assertTrue(Reflect.isExtensible(target));
assertTrue(Reflect.isExtensible(proxy));
assertTrue(Reflect.preventExtensions(proxy));
assertFalse(Reflect.isExtensible(target));
assertFalse(Reflect.isExtensible(proxy));
})();
(function () {
// Invalid trap.
var target = {};
var handler = { preventExtensions: 42 };
var proxy = new Proxy(target, handler);
assertThrows(() => { Reflect.preventExtensions(proxy) }, TypeError);
})();
(function () {
var target = {};
var handler = { isExtensible() { return "bla" } };
var proxy = new Proxy(target, handler);
// Trap returns trueish and target is extensible.
assertTrue(Reflect.isExtensible(proxy));
// Trap returns trueish but target is not extensible.
Reflect.preventExtensions(target);
assertThrows(() => { Reflect.isExtensible(proxy) }, TypeError);
})();
(function () {
// Trap returns falsish.
var target = {};
var handler = { preventExtensions() { return 0 } };
var proxy = new Proxy(target, handler);
assertFalse(Reflect.preventExtensions(proxy));
Reflect.preventExtensions(target);
assertFalse(Reflect.preventExtensions(proxy));
})();
(function () {
var target = {};
var handler = { preventExtensions() { return Symbol() } };
var proxy = new Proxy(target, handler);
// Trap returns trueish but target is extensible.
assertThrows(() => { Reflect.preventExtensions(proxy) }, TypeError);
// Trap returns trueish and target is not extensible.
Reflect.preventExtensions(target);
assertTrue(Reflect.preventExtensions(proxy));
})();
(function () {
// Target is proxy
var object = {};
assertTrue(Reflect.preventExtensions(object));
var target = new Proxy(object, {});
var proxy = new Proxy(target, {});
assertFalse(Reflect.isExtensible(object));
assertFalse(Reflect.isExtensible(target));
assertFalse(Reflect.isExtensible(proxy));
})();
// Object.
(function () {
// No trap.
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
assertTrue(Object.isExtensible(target));
assertTrue(Object.isExtensible(proxy));
Object.preventExtensions(proxy);
assertFalse(Object.isExtensible(target));
assertFalse(Object.isExtensible(proxy));
})();
(function () {
// "Undefined" trap.
var target = {};
var handler = { preventExtensions: null };
var proxy = new Proxy(target, handler);
assertTrue(Object.isExtensible(target));
assertTrue(Object.isExtensible(proxy));
Object.preventExtensions(proxy);
assertFalse(Object.isExtensible(target));
assertFalse(Object.isExtensible(proxy));
})();
(function () {
// Invalid trap.
var target = {};
var handler = { preventExtensions: 42 };
var proxy = new Proxy(target, handler);
assertThrows(() => { Object.preventExtensions(proxy) }, TypeError);
})();
(function () {
var target = {};
var handler = { isExtensible() { return "bla" } };
var proxy = new Proxy(target, handler);
// Trap returns trueish and target is extensible.
assertTrue(Object.isExtensible(proxy));
// Trap returns trueish but target is not extensible.
Object.preventExtensions(target);
assertThrows(() => { Object.isExtensible(proxy) }, TypeError);
})();
(function () {
// Trap returns falsish.
var target = {};
var handler = { isExtensible() { return false } };
var proxy = new Proxy(target, handler);
assertThrows(() => { Object.isExtensible(proxy) }, TypeError);
Object.preventExtensions(target);
assertFalse(Object.isExtensible(proxy));
})();
(function () {
// Trap returns falsish.
var target = {};
var handler = { preventExtensions() { return 0 } };
var proxy = new Proxy(target, handler);
assertFalse(Reflect.preventExtensions(proxy));
Object.preventExtensions(target);
assertFalse(Reflect.preventExtensions(proxy));
assertThrows(() => { Object.preventExtensions(proxy) }, TypeError);
})();
(function () {
var target = {};
var handler = { preventExtensions() { return Symbol() } };
var proxy = new Proxy(target, handler);
// Trap returns trueish but target is extensible.
assertThrows(() => { Object.preventExtensions(proxy) }, TypeError);
// Trap returns trueish and target is not extensible.
Object.preventExtensions(target);
assertTrue(Reflect.preventExtensions(proxy));
})();
(function () {
// Target is proxy
var object = {};
Object.preventExtensions(object);
var target = new Proxy(object, {});
var proxy = new Proxy(target, {});
assertFalse(Object.isExtensible(object));
assertFalse(Object.isExtensible(target));
assertFalse(Object.isExtensible(proxy));
})();