1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Flags: --harmony-proxies
29
30
31// Helper.
32
33function TestWithProxies(test, x, y, z) {
34  test(Proxy.create, x, y, z)
35  test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z)
36}
37
38
39
40// Getting.
41
42function TestWithGet(handler) {
43  TestWithProxies(TestWithGet2, handler)
44}
45
46var c = "global"
47var key = ""
48
49function TestWithGet2(create, handler) {
50  var b = "local"
51
52  var p = create(handler)
53  with (p) {
54    assertEquals("onproxy", a)
55    assertEquals("local", b)
56    assertEquals("global", c)
57  }
58
59  var o = Object.create(p, {d: {value: "own"}})
60  with (o) {
61    assertEquals("onproxy", a)
62    assertEquals("local", b)
63    assertEquals("global", c)
64    assertEquals("own", d)
65  }
66}
67
68TestWithGet({
69  get: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined },
70  getPropertyDescriptor: function(k) {
71    key = k;
72    return k === "a" ? {value: "onproxy", configurable: true} : undefined
73  }
74})
75
76TestWithGet({
77  get: function(r, k) { return this.get2(r, k) },
78  get2: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined },
79  getPropertyDescriptor: function(k) {
80    key = k;
81    return k === "a" ? {value: "onproxy", configurable: true} : undefined
82  }
83})
84
85TestWithGet({
86  getPropertyDescriptor: function(k) {
87    key = k;
88    return k === "a" ? {value: "onproxy", configurable: true} : undefined
89  }
90})
91
92TestWithGet({
93  getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
94  getPropertyDescriptor2: function(k) {
95    key = k;
96    return k === "a" ? {value: "onproxy", configurable: true} : undefined
97  }
98})
99
100TestWithGet({
101  getPropertyDescriptor: function(k) {
102    key = k;
103    return k === "a" ?
104        {get value() { return "onproxy" }, configurable: true} : undefined
105  }
106})
107
108TestWithGet({
109  get: undefined,
110  getPropertyDescriptor: function(k) {
111    key = k;
112    return k === "a" ? {value: "onproxy", configurable: true} : undefined
113  }
114})
115
116
117
118// Invoking.
119
120function TestWithGetCall(handler) {
121  TestWithProxies(TestWithGetCall2, handler)
122}
123
124var receiver = null
125var c = function() { return "global" }
126
127function TestWithGetCall2(create, handler) {
128  var b = function() { return "local" }
129
130  var p = create(handler)
131  with (p) {
132    receiver = null
133    assertEquals("onproxy", a())
134    assertSame(p, receiver)
135    assertEquals("local", b())
136    assertEquals("global", c())
137  }
138
139  var o = Object.create(p, {d: {value: function() { return "own" }}})
140  with (o) {
141    receiver = null
142    assertEquals("onproxy", a())
143    assertSame(o, receiver)
144    assertEquals("local", b())
145    assertEquals("global", c())
146    assertEquals("own", d())
147  }
148}
149
150function onproxy() { receiver = this; return "onproxy" }
151
152TestWithGetCall({
153  get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
154  getPropertyDescriptor: function(k) {
155    key = k;
156    return k === "a" ? {value: onproxy, configurable: true} : undefined
157  }
158})
159
160TestWithGetCall({
161  get: function(r, k) { return this.get2(r, k) },
162  get2: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
163  getPropertyDescriptor: function(k) {
164    key = k;
165    return k === "a" ? {value: onproxy, configurable: true} : undefined
166  }
167})
168
169TestWithGetCall({
170  getPropertyDescriptor: function(k) {
171    key = k;
172    return k === "a" ? {value: onproxy, configurable: true} : undefined
173  }
174})
175
176TestWithGetCall({
177  getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
178  getPropertyDescriptor2: function(k) {
179    key = k;
180    return k === "a" ? {value: onproxy, configurable: true} : undefined
181  }
182})
183
184TestWithGetCall({
185  getPropertyDescriptor: function(k) {
186    key = k;
187    return k === "a" ?
188        {get value() { return onproxy }, configurable: true} : undefined
189  }
190})
191
192TestWithGetCall({
193  get: undefined,
194  getPropertyDescriptor: function(k) {
195    key = k;
196    return k === "a" ? {value: onproxy, configurable: true} : undefined
197  }
198})
199
200
201function TestWithGetCallThrow(handler) {
202  TestWithProxies(TestWithGetCallThrow2, handler)
203}
204
205function TestWithGetCallThrow2(create, handler) {
206  var b = function() { return "local" }
207
208  var p = create(handler)
209  with (p) {
210    assertThrows(function(){ a() }, "myexn")
211    assertEquals("local", b())
212    assertEquals("global", c())
213  }
214
215  var o = Object.create(p, {d: {value: function() { return "own" }}})
216  with (o) {
217    assertThrows(function(){ a() }, "myexn")
218    assertEquals("local", b())
219    assertEquals("global", c())
220    assertEquals("own", d())
221  }
222}
223
224function onproxythrow() { throw "myexn" }
225
226TestWithGetCallThrow({
227  get: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
228  getPropertyDescriptor: function(k) {
229    key = k;
230    return k === "a" ? {value: onproxythrow, configurable: true} : undefined
231  }
232})
233
234TestWithGetCallThrow({
235  get: function(r, k) { return this.get2(r, k) },
236  get2: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
237  getPropertyDescriptor: function(k) {
238    key = k;
239    return k === "a" ? {value: onproxythrow, configurable: true} : undefined
240  }
241})
242
243TestWithGetCallThrow({
244  getPropertyDescriptor: function(k) {
245    key = k;
246    return k === "a" ? {value: onproxythrow, configurable: true} : undefined
247  }
248})
249
250TestWithGetCallThrow({
251  getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
252  getPropertyDescriptor2: function(k) {
253    key = k;
254    return k === "a" ? {value: onproxythrow, configurable: true} : undefined
255  }
256})
257
258TestWithGetCallThrow({
259  getPropertyDescriptor: function(k) {
260    key = k;
261    return k === "a" ?
262        {get value() { return onproxythrow }, configurable: true} : undefined
263  }
264})
265
266TestWithGetCallThrow({
267  get: undefined,
268  getPropertyDescriptor: function(k) {
269    key = k;
270    return k === "a" ? {value: onproxythrow, configurable: true} : undefined
271  }
272})
273
274
275
276// Setting.
277
278var key
279var val
280
281function TestWithSet(handler, hasSetter) {
282  TestWithProxies(TestWithSet2, handler, hasSetter)
283}
284
285var c = "global"
286
287function TestWithSet2(create, handler, hasSetter) {
288  var b = "local"
289
290  var p = create(handler)
291  key = val = undefined
292  with (p) {
293    a = "set"
294    assertEquals("a", key)
295    assertEquals("set", val)
296    assertEquals("local", b)
297    assertEquals("global", c)
298    b = "local"
299    c = "global"
300    assertEquals("a", key)
301    assertEquals("set", val)
302  }
303
304  if (!hasSetter) return
305
306  var o = Object.create(p, {d: {value: "own"}})
307  key = val = undefined
308  with (o) {
309    a = "set"
310    assertEquals("a", key)
311    assertEquals("set", val)
312    assertEquals("local", b)
313    assertEquals("global", c)
314    assertEquals("own", d)
315    b = "local"
316    c = "global"
317    d = "own"
318    assertEquals("a", key)
319    assertEquals("set", val)
320  }
321}
322
323TestWithSet({
324  set: function(r, k, v) { key = k; val = v; return true },
325  getPropertyDescriptor: function(k) {
326    return k === "a" ? {writable: true, configurable: true} : undefined
327  }
328})
329
330TestWithSet({
331  set: function(r, k, v) { return this.set2(r, k, v) },
332  set2: function(r, k, v) { key = k; val = v; return true },
333  getPropertyDescriptor: function(k) {
334    return k === "a" ? {writable: true, configurable: true} : undefined
335  }
336})
337
338TestWithSet({
339  getPropertyDescriptor: function(k) {
340    return this.getOwnPropertyDescriptor(k)
341  },
342  getOwnPropertyDescriptor: function(k) {
343    return k === "a" ? {writable: true, configurable: true} : undefined
344  },
345  defineProperty: function(k, desc) { key = k; val = desc.value }
346})
347
348TestWithSet({
349  getOwnPropertyDescriptor: function(k) {
350    return this.getPropertyDescriptor2(k)
351  },
352  getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
353  getPropertyDescriptor2: function(k) {
354    return k === "a" ? {writable: true, configurable: true} : undefined
355  },
356  defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
357  defineProperty2: function(k, desc) { key = k; val = desc.value }
358})
359
360TestWithSet({
361  getOwnPropertyDescriptor: function(k) {
362    return this.getPropertyDescriptor(k)
363  },
364  getPropertyDescriptor: function(k) {
365    return k === "a" ?
366        {get writable() { return true }, configurable: true} : undefined
367  },
368  defineProperty: function(k, desc) { key = k; val = desc.value }
369})
370
371TestWithSet({
372  getOwnPropertyDescriptor: function(k) {
373    return this.getPropertyDescriptor(k)
374  },
375  getPropertyDescriptor: function(k) {
376    return k === "a" ?
377        {set: function(v) { key = k; val = v }, configurable: true} : undefined
378  }
379}, true)
380
381TestWithSet({
382  getOwnPropertyDescriptor: function(k) {
383    return this.getPropertyDescriptor(k)
384  },
385  getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
386  getPropertyDescriptor2: function(k) {
387    return k === "a" ?
388        {set: function(v) { key = k; val = v }, configurable: true} : undefined
389  }
390}, true)
391
392TestWithSet({
393  getOwnPropertyDescriptor: function(k) { return null },
394  getPropertyDescriptor: function(k) {
395    return k === "a" ? {writable: true, configurable: true} : undefined
396  },
397  defineProperty: function(k, desc) { key = k; val = desc.value }
398})
399
400
401function TestWithSetThrow(handler, hasSetter) {
402  TestWithProxies(TestWithSetThrow2, handler, hasSetter)
403}
404
405function TestWithSetThrow2(create, handler, hasSetter) {
406  var p = create(handler)
407  assertThrows(function(){
408    with (p) {
409      a = 1
410    }
411  }, "myexn")
412
413  if (!hasSetter) return
414
415  var o = Object.create(p, {})
416  assertThrows(function(){
417    with (o) {
418      a = 1
419    }
420  }, "myexn")
421}
422
423TestWithSetThrow({
424  set: function(r, k, v) { throw "myexn" },
425  getPropertyDescriptor: function(k) {
426    return k === "a" ? {writable: true, configurable: true} : undefined
427  }
428})
429
430TestWithSetThrow({
431  getPropertyDescriptor: function(k) { throw "myexn" },
432})
433
434TestWithSetThrow({
435  getPropertyDescriptor: function(k) {
436    return k === "a" ? {writable: true, configurable: true} : undefined
437  },
438  defineProperty: function(k, desc) { throw "myexn" }
439})
440
441TestWithSetThrow({
442  getPropertyDescriptor: function(k) {
443    return k === "a" ?
444        {set: function() { throw "myexn" }, configurable: true} : undefined
445  }
446}, true)
447