1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Flags: --harmony-proxies --allow-natives-syntax --expose-debug-as debug
6
7"use strict";
8
9// Test non-JSObject receiver.
10function f(o) {
11  var result = [];
12  for (var i in o) {
13    result.push(i);
14  }
15  return result;
16}
17
18assertEquals(["0"], f("a"));
19assertEquals(["0"], f("a"));
20
21%OptimizeFunctionOnNextCall(f);
22assertEquals(["0","1","2"], f("bla"));
23
24// Test the lazy deopt points.
25var keys = ["a", "b", "c", "d"];
26var has_keys = [];
27var deopt_has = false;
28var deopt_enum = false;
29
30var handler = {
31  enumerate(target) {
32    if (deopt_enum) {
33      %DeoptimizeFunction(f2);
34      deopt_enum = false;
35    }
36    return keys[Symbol.iterator]();
37  },
38
39  has(target, k) {
40    if (deopt_has) {
41      %DeoptimizeFunction(f2);
42      deopt_has = false;
43    }
44    has_keys.push(k);
45    return {value: 10, configurable: true, writable: false, enumerable: true};
46  }
47};
48
49
50var proxy = new Proxy({}, handler);
51var o = {__proto__: proxy};
52
53function f2(o) {
54  var result = [];
55  for (var i in o) {
56    result.push(i);
57  }
58  return result;
59}
60
61function check_f2() {
62  assertEquals(keys, f2(o));
63  assertEquals(keys, has_keys);
64  has_keys.length = 0;
65}
66
67check_f2();
68check_f2();
69
70// Test lazy deopt after GetPropertyNamesFast
71%OptimizeFunctionOnNextCall(f2);
72deopt_enum = true;
73check_f2();
74
75// Test lazy deopt after FILTER_KEY
76%OptimizeFunctionOnNextCall(f2);
77deopt_has = true;
78check_f2();
79
80function f3(o) {
81  for (var i in o) {
82  }
83}
84
85f3({__proto__:{x:1}});
86f3({__proto__:{x:1}});
87
88%OptimizeFunctionOnNextCall(f3);
89f3(undefined);
90f3(null);
91
92// Reliable repro for an issue previously flushed out by GC stress.
93var handler2 = {
94  getPropertyDescriptor(target, k) {
95    has_keys.push(k);
96    return {value: 10, configurable: true, writable: false, enumerable: true};
97  }
98}
99var proxy2 = new Proxy({}, handler2);
100var o2 = {__proto__: proxy2};
101var p = {x: "x"}
102
103function f4(o, p) {
104  var result = [];
105  for (var i in o) {
106    var j = p.x + "str";
107    result.push(i);
108  }
109  return result;
110}
111
112function check_f4() {
113  assertEquals(keys, f4(o, p));
114  assertEquals(keys, has_keys);
115  has_keys.length = 0;
116}
117
118check_f4();
119check_f4();
120
121%OptimizeFunctionOnNextCall(f4);
122
123p.y = "y";  // Change map, cause eager deopt.
124check_f4();
125
126// Repro for Turbofan equivalent.
127var x;
128var count = 0;
129
130var Debug = debug.Debug;
131
132function listener(event, exec_state, event_data, data) {
133  if (event == Debug.DebugEvent.Break) {
134    %DeoptimizeFunction(f5);
135  }
136}
137
138var handler3 = {
139  enumerate(target) {
140    return ["a", "b"][Symbol.iterator]();
141  },
142
143  has(target, k) {
144    if (k == "a") count++;
145    if (x) %ScheduleBreak();
146    return {value: 10, configurable: true, writable: false, enumerable: true};
147  }
148};
149
150var proxy3 = new Proxy({}, handler3);
151var o3 = {__proto__: proxy3};
152
153function f5() {
154  for (var p in o3) {
155    print(p);
156  }
157}
158
159x = false;
160
161f5(); f5(); f5();
162%OptimizeFunctionOnNextCall(f5);
163x = true;
164count = 0;
165Debug.setListener(listener);
166f5();
167Debug.setListener(null);
168assertEquals(1, count);
169