579c01072d
In ES2016, the Proxy enumerate trap is removed. This patch changes for-in iteration on Proxies to use the ownKeys trap. Due to the clean organization of that code, the patch basically consists of deletions. R=adamk LOG=Y BUG=v8:4768 Review URL: https://codereview.chromium.org/1717893002 Cr-Commit-Position: refs/heads/master@{#34200}
169 lines
3.0 KiB
JavaScript
169 lines
3.0 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.
|
|
|
|
// Flags: --harmony-proxies --allow-natives-syntax --expose-debug-as debug
|
|
|
|
"use strict";
|
|
|
|
// Test non-JSObject receiver.
|
|
function f(o) {
|
|
var result = [];
|
|
for (var i in o) {
|
|
result.push(i);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
assertEquals(["0"], f("a"));
|
|
assertEquals(["0"], f("a"));
|
|
|
|
%OptimizeFunctionOnNextCall(f);
|
|
assertEquals(["0","1","2"], f("bla"));
|
|
|
|
// Test the lazy deopt points.
|
|
var keys = ["a", "b", "c", "d"];
|
|
var has_keys = [];
|
|
var deopt_has = false;
|
|
var deopt_enum = false;
|
|
|
|
var handler = {
|
|
ownKeys() {
|
|
if (deopt_enum) {
|
|
%DeoptimizeFunction(f2);
|
|
deopt_enum = false;
|
|
}
|
|
return keys;
|
|
},
|
|
getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }},
|
|
|
|
has(target, k) {
|
|
if (deopt_has) {
|
|
%DeoptimizeFunction(f2);
|
|
deopt_has = false;
|
|
}
|
|
has_keys.push(k);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
var proxy = new Proxy({}, handler);
|
|
var o = {__proto__: proxy};
|
|
|
|
function f2(o) {
|
|
var result = [];
|
|
for (var i in o) {
|
|
result.push(i);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function check_f2() {
|
|
assertEquals(keys, f2(o));
|
|
assertEquals(keys, has_keys);
|
|
has_keys.length = 0;
|
|
}
|
|
|
|
check_f2();
|
|
check_f2();
|
|
|
|
// Test lazy deopt after ForInEnumerate
|
|
%OptimizeFunctionOnNextCall(f2);
|
|
deopt_enum = true;
|
|
check_f2();
|
|
|
|
// Test lazy deopt after FILTER_KEY
|
|
%OptimizeFunctionOnNextCall(f2);
|
|
deopt_has = true;
|
|
check_f2();
|
|
|
|
function f3(o) {
|
|
for (var i in o) {
|
|
}
|
|
}
|
|
|
|
f3({__proto__:{x:1}});
|
|
f3({__proto__:{x:1}});
|
|
|
|
%OptimizeFunctionOnNextCall(f3);
|
|
f3(undefined);
|
|
f3(null);
|
|
|
|
// Reliable repro for an issue previously flushed out by GC stress.
|
|
var handler2 = {
|
|
getPropertyDescriptor(target, k) {
|
|
has_keys.push(k);
|
|
return {value: 10, configurable: true, writable: false, enumerable: true};
|
|
}
|
|
}
|
|
var proxy2 = new Proxy({}, handler2);
|
|
var o2 = {__proto__: proxy2};
|
|
var p = {x: "x"}
|
|
|
|
function f4(o, p) {
|
|
var result = [];
|
|
for (var i in o) {
|
|
var j = p.x + "str";
|
|
result.push(i);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function check_f4() {
|
|
assertEquals(keys, f4(o, p));
|
|
assertEquals(keys, has_keys);
|
|
has_keys.length = 0;
|
|
}
|
|
|
|
check_f4();
|
|
check_f4();
|
|
|
|
%OptimizeFunctionOnNextCall(f4);
|
|
|
|
p.y = "y"; // Change map, cause eager deopt.
|
|
check_f4();
|
|
|
|
// Repro for Turbofan equivalent.
|
|
var x;
|
|
var count = 0;
|
|
|
|
var Debug = debug.Debug;
|
|
|
|
function listener(event, exec_state, event_data, data) {
|
|
if (event == Debug.DebugEvent.Break) {
|
|
%DeoptimizeFunction(f5);
|
|
}
|
|
}
|
|
|
|
var handler3 = {
|
|
ownKeys() { return ["a", "b"] },
|
|
getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }},
|
|
|
|
has(target, k) {
|
|
if (k == "a") count++;
|
|
if (x) %ScheduleBreak();
|
|
return true;
|
|
}
|
|
};
|
|
|
|
var proxy3 = new Proxy({}, handler3);
|
|
var o3 = {__proto__: proxy3};
|
|
|
|
function f5() {
|
|
for (var p in o3) {
|
|
print(p);
|
|
}
|
|
}
|
|
|
|
x = false;
|
|
|
|
f5(); f5(); f5();
|
|
%OptimizeFunctionOnNextCall(f5);
|
|
x = true;
|
|
count = 0;
|
|
Debug.setListener(listener);
|
|
f5();
|
|
Debug.setListener(null);
|
|
assertEquals(1, count);
|