v8/test/mjsunit/object-keys.js
Irina Yatsenko 37ff95adc0 Move empty elements canonicalization from call sites of
AllocateUninitializedJSArrayWithElements into the method.

Prior to the change, if the caller forgets to handle empty case on
their side, AllocateUninitializedJSArrayWithElements would allocate a
new empty FixedArray rather than return the canonical one. This refactor
shifts the burden of canonicalization from the callers to
AllocateUninitializedJSArrayWithElements.


Bug: v8:6777
Change-Id: I1246cb288861b65b51938414a454f21af78f8399
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1480330
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Irina Yatsenko <irinayat@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#60015}
2019-03-04 18:07:52 +00:00

118 lines
3.0 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
// Ensure empty keys are handled properly
(function() {
const a = {};
let k = Object.keys(a);
%HeapObjectVerify(k);
assertEquals(0, k.length);
})();
// Ensure non-enumerable keys are handled properly
(function() {
const a = {};
Object.defineProperty(a, 'x', {
value: 1,
enumerable: false
});
let k = Object.keys(a);
%HeapObjectVerify(k);
assertEquals(0, k.length);
a.y = 2;
k = Object.keys(a);
%HeapObjectVerify(k);
assertEquals(1, k.length);
})();
// Ensure that mutation of the Object.keys result doesn't affect the
// enumeration cache for fast-mode objects.
(function() {
const a = {x:1, y:2};
let k = Object.keys(a);
%HeapObjectVerify(k);
assertEquals(2, k.length);
assertEquals("x", k[0]);
assertEquals("y", k[1]);
k[0] = "y";
k[1] = "x";
k = Object.keys(a);
assertEquals(2, k.length);
assertEquals("x", k[0]);
assertEquals("y", k[1]);
})();
// Ensure that the copy-on-write keys are handled properly, even in
// the presence of Symbols.
(function() {
const s = Symbol();
const a = {[s]: 1};
let k = Object.keys(a);
%HeapObjectVerify(k);
assertEquals(0, k.length);
k.shift();
assertEquals(0, k.length);
})();
// Ensure we invoke all steps on proxies.
(function ObjectKeysProxy() {
let log = [];
let result = Object.keys(new Proxy({}, {
ownKeys(target) {
log.push('ownKeys');
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, key) {
log.push('getOwnPropertyDescriptor-' + key);
if (key === 'b') return {enumerable: false, configurable: true};
return {enumerable: true, configurable: true};
}
}));
assertEquals(['a', 'c'], result);
assertEquals(
[
'ownKeys', 'getOwnPropertyDescriptor-a', 'getOwnPropertyDescriptor-b',
'getOwnPropertyDescriptor-c'
],
log);
// Test normal target.
log = [];
let target = {a: 1, b: 1, c: 1};
let handler = {
getOwnPropertyDescriptor(target, key) {
log.push('getOwnPropertyDescriptor-' + key);
if (key === 'b') return {enumerable: false, configurable: true};
return {enumerable: true, configurable: true};
}
};
result = Object.keys(new Proxy(target, handler));
assertEquals(['a', 'c'], result);
assertEquals(
[
'getOwnPropertyDescriptor-a', 'getOwnPropertyDescriptor-b',
'getOwnPropertyDescriptor-c'
],
log);
// Test trap invocation with non-enumerable target properties.
log = [];
target = Object.create(Object.prototype, {
a: {enumerable: true, configurable: true},
b: {enumerable: false, configurable: true},
c: {enumerable: true, configurable: true}
});
result = Object.keys(new Proxy(target, handler));
assertEquals(['a', 'c'], result);
assertEquals(
[
'getOwnPropertyDescriptor-a', 'getOwnPropertyDescriptor-b',
'getOwnPropertyDescriptor-c'
],
log);
})();