OLD | NEW |
(Empty) | |
| 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 |
| 33 function CreateFrozen(handler, callTrap, constructTrap) { |
| 34 if (handler.fix === undefined) handler.fix = function() { return {} } |
| 35 var f = Proxy.createFunction(handler, callTrap, constructTrap) |
| 36 Object.freeze(f) |
| 37 return f |
| 38 } |
| 39 |
| 40 |
| 41 // Calling (call, Function.prototype.call, Function.prototype.apply, |
| 42 // Function.prototype.bind). |
| 43 |
| 44 var global_object = this |
| 45 var receiver |
| 46 |
| 47 function TestCall(isStrict, callTrap) { |
| 48 assertEquals(42, callTrap(5, 37)) |
| 49 // TODO(rossberg): unrelated bug: this does not succeed for optimized code: |
| 50 // assertEquals(isStrict ? undefined : global_object, receiver) |
| 51 |
| 52 var f = Proxy.createFunction({}, callTrap) |
| 53 receiver = 333 |
| 54 assertEquals(42, f(11, 31)) |
| 55 assertEquals(isStrict ? undefined : global_object, receiver) |
| 56 var o = {} |
| 57 assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) |
| 58 assertEquals(o, receiver) |
| 59 assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) |
| 60 assertEquals(isStrict ? null : global_object, receiver) |
| 61 assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) |
| 62 assertEquals(2, receiver.valueOf()) |
| 63 receiver = 333 |
| 64 assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) |
| 65 assertEquals(o, receiver) |
| 66 var ff = Function.prototype.bind.call(f, o, 12) |
| 67 receiver = 333 |
| 68 assertEquals(42, ff(30)) |
| 69 assertEquals(o, receiver) |
| 70 receiver = 333 |
| 71 assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) |
| 72 assertEquals(o, receiver) |
| 73 |
| 74 var f = CreateFrozen({}, callTrap) |
| 75 receiver = 333 |
| 76 assertEquals(42, f(11, 31)) |
| 77 // TODO(rossberg): unrelated bug: this does not succeed for optimized code. |
| 78 // assertEquals(isStrict ? undefined : global, receiver) |
| 79 receiver = 333 |
| 80 assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) |
| 81 assertEquals(o, receiver) |
| 82 receiver = 333 |
| 83 assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) |
| 84 assertEquals(o, receiver) |
| 85 receiver = 333 |
| 86 assertEquals(42, ff(30)) |
| 87 assertEquals(o, receiver) |
| 88 receiver = 333 |
| 89 assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) |
| 90 assertEquals(o, receiver) |
| 91 } |
| 92 |
| 93 TestCall(false, function(x, y) { |
| 94 receiver = this; return x + y |
| 95 }) |
| 96 |
| 97 TestCall(true, function(x, y) { |
| 98 "use strict"; |
| 99 receiver = this; return x + y |
| 100 }) |
| 101 |
| 102 TestCall(false, Proxy.createFunction({}, function(x, y) { |
| 103 receiver = this; return x + y |
| 104 })) |
| 105 |
| 106 TestCall(true, Proxy.createFunction({}, function(x, y) { |
| 107 "use strict"; |
| 108 receiver = this; return x + y |
| 109 })) |
| 110 |
| 111 TestCall(false, CreateFrozen({}, function(x, y) { |
| 112 receiver = this; return x + y |
| 113 })) |
| 114 |
| 115 |
| 116 function TestCallThrow(callTrap) { |
| 117 var f = Proxy.createFunction({}, callTrap) |
| 118 assertThrows(function(){ f(11) }, "myexn") |
| 119 assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") |
| 120 assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") |
| 121 |
| 122 var f = CreateFrozen({}, callTrap) |
| 123 assertThrows(function(){ f(11) }, "myexn") |
| 124 assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") |
| 125 assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") |
| 126 } |
| 127 |
| 128 TestCallThrow(function() { throw "myexn" }) |
| 129 TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) |
| 130 TestCallThrow(CreateFrozen({}, function() { throw "myexn" })) |
| 131 |
| 132 |
| 133 |
| 134 // Construction (new). |
| 135 |
| 136 var prototype = {} |
| 137 var receiver |
| 138 |
| 139 var handlerWithPrototype = { |
| 140 fix: function() { return {prototype: prototype} }, |
| 141 get: function(r, n) { assertEquals("prototype", n); return prototype } |
| 142 } |
| 143 |
| 144 var handlerSansPrototype = { |
| 145 fix: function() { return {} }, |
| 146 get: function(r, n) { assertEquals("prototype", n); return undefined } |
| 147 } |
| 148 |
| 149 function ReturnUndef(x, y) { "use strict"; receiver = this; this.sum = x + y } |
| 150 function ReturnThis(x, y) { "use strict"; receiver = this; this.sum = x + y; ret
urn this } |
| 151 function ReturnNew(x, y) { "use strict"; receiver = this; return {sum: x + y} } |
| 152 function ReturnNewWithProto(x, y) { |
| 153 "use strict"; |
| 154 receiver = this; |
| 155 var result = Object.create(prototype) |
| 156 result.sum = x + y |
| 157 return result |
| 158 } |
| 159 |
| 160 function TestConstruct(proto, constructTrap) { |
| 161 TestConstruct2(proto, constructTrap, handlerWithPrototype) |
| 162 TestConstruct2(proto, constructTrap, handlerSansPrototype) |
| 163 } |
| 164 |
| 165 function TestConstruct2(proto, constructTrap, handler) { |
| 166 var f = Proxy.createFunction(handler, function() {}, constructTrap) |
| 167 var o = new f(11, 31) |
| 168 // TODO(rossberg): doesn't hold, due to unrelated bug. |
| 169 // assertEquals(undefined, receiver) |
| 170 assertEquals(42, o.sum) |
| 171 assertSame(proto, Object.getPrototypeOf(o)) |
| 172 |
| 173 var f = CreateFrozen(handler, function() {}, constructTrap) |
| 174 var o = new f(11, 32) |
| 175 // TODO(rossberg): doesn't hold, due to unrelated bug. |
| 176 // assertEquals(undefined, receiver) |
| 177 assertEquals(43, o.sum) |
| 178 assertSame(proto, Object.getPrototypeOf(o)) |
| 179 } |
| 180 |
| 181 TestConstruct(Object.prototype, ReturnNew) |
| 182 TestConstruct(prototype, ReturnNewWithProto) |
| 183 |
| 184 TestConstruct(Object.prototype, Proxy.createFunction({}, ReturnNew)) |
| 185 TestConstruct(prototype, Proxy.createFunction({}, ReturnNewWithProto)) |
| 186 |
| 187 TestConstruct(Object.prototype, CreateFrozen({}, ReturnNew)) |
| 188 TestConstruct(prototype, CreateFrozen({}, ReturnNewWithProto)) |
| 189 |
| 190 |
| 191 function TestConstructFromCall(proto, returnsThis, callTrap) { |
| 192 TestConstructFromCall2(proto, returnsThis, callTrap, handlerWithPrototype) |
| 193 TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype) |
| 194 } |
| 195 |
| 196 function TestConstructFromCall2(proto, returnsThis, callTrap, handler) { |
| 197 var f = Proxy.createFunction(handler, callTrap) |
| 198 var o = new f(11, 31) |
| 199 if (returnsThis) assertEquals(o, receiver) |
| 200 assertEquals(42, o.sum) |
| 201 assertSame(proto, Object.getPrototypeOf(o)) |
| 202 |
| 203 var f = CreateFrozen(handler, callTrap) |
| 204 var o = new f(11, 32) |
| 205 if (returnsThis) assertEquals(o, receiver) |
| 206 assertEquals(43, o.sum) |
| 207 assertSame(proto, Object.getPrototypeOf(o)) |
| 208 } |
| 209 |
| 210 TestConstructFromCall(Object.prototype, true, ReturnUndef) |
| 211 TestConstructFromCall(Object.prototype, true, ReturnThis) |
| 212 TestConstructFromCall(Object.prototype, false, ReturnNew) |
| 213 TestConstructFromCall(prototype, false, ReturnNewWithProto) |
| 214 |
| 215 TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUnd
ef)) |
| 216 TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThi
s)) |
| 217 TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNe
w)) |
| 218 TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithPr
oto)) |
| 219 |
| 220 TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef)) |
| 221 TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis)) |
| 222 TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew)) |
| 223 TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto)) |
| 224 |
| 225 ReturnUndef.prototype = prototype |
| 226 ReturnThis.prototype = prototype |
| 227 ReturnNew.prototype = prototype |
| 228 ReturnNewWithProto.prototype = prototype |
| 229 |
| 230 TestConstructFromCall(prototype, true, ReturnUndef) |
| 231 TestConstructFromCall(prototype, true, ReturnThis) |
| 232 TestConstructFromCall(Object.prototype, false, ReturnNew) |
| 233 TestConstructFromCall(prototype, false, ReturnNewWithProto) |
| 234 |
| 235 TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUnd
ef)) |
| 236 TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThi
s)) |
| 237 TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNe
w)) |
| 238 TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithPr
oto)) |
| 239 |
| 240 TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype
, ReturnUndef)) |
| 241 TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype
, ReturnThis)) |
| 242 TestConstructFromCall(Object.prototype, false, Proxy.createFunction(handlerWithP
rototype, ReturnNew)) |
| 243 TestConstructFromCall(prototype, false, Proxy.createFunction(handlerWithPrototyp
e, ReturnNewWithProto)) |
| 244 |
| 245 TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, Return
Undef)) |
| 246 TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, Return
This)) |
| 247 TestConstructFromCall(Object.prototype, false, CreateFrozen(handlerWithPrototype
, ReturnNew)) |
| 248 TestConstructFromCall(prototype, false, CreateFrozen(handlerWithPrototype, Retur
nNewWithProto)) |
| 249 |
| 250 |
| 251 function TestConstructThrow(trap) { |
| 252 TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}}, trap)) |
| 253 TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}}, |
| 254 function() {}, trap)) |
| 255 } |
| 256 |
| 257 function TestConstructThrow2(f) { |
| 258 assertThrows(function(){ new f(11) }, "myexn") |
| 259 Object.freeze(f) |
| 260 assertThrows(function(){ new f(11) }, "myexn") |
| 261 } |
| 262 |
| 263 TestConstructThrow(function() { throw "myexn" }) |
| 264 TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" })) |
| 265 TestConstructThrow(CreateFrozen({}, function() { throw "myexn" })) |
| 266 |
| 267 |
| 268 |
| 269 // Getters and setters. |
| 270 |
| 271 var value |
| 272 var receiver |
| 273 |
| 274 function TestAccessorCall(getterCallTrap, setterCallTrap) { |
| 275 var handler = {fix: function() { return {} }} |
| 276 var pgetter = Proxy.createFunction(handler, getterCallTrap) |
| 277 var psetter = Proxy.createFunction(handler, setterCallTrap) |
| 278 |
| 279 var o = {} |
| 280 var oo = Object.create(o) |
| 281 Object.defineProperty(o, "a", {get: pgetter, set: psetter}) |
| 282 Object.defineProperty(o, "b", {get: pgetter}) |
| 283 Object.defineProperty(o, "c", {set: psetter}) |
| 284 Object.defineProperty(o, "3", {get: pgetter, set: psetter}) |
| 285 Object.defineProperty(oo, "a", {value: 43}) |
| 286 |
| 287 receiver = "" |
| 288 assertEquals(42, o.a) |
| 289 assertSame(o, receiver) |
| 290 receiver = "" |
| 291 assertEquals(42, o.b) |
| 292 assertSame(o, receiver) |
| 293 receiver = "" |
| 294 assertEquals(undefined, o.c) |
| 295 assertEquals("", receiver) |
| 296 receiver = "" |
| 297 assertEquals(42, o["a"]) |
| 298 assertSame(o, receiver) |
| 299 receiver = "" |
| 300 assertEquals(42, o[3]) |
| 301 assertSame(o, receiver) |
| 302 |
| 303 receiver = "" |
| 304 assertEquals(43, oo.a) |
| 305 assertEquals("", receiver) |
| 306 receiver = "" |
| 307 assertEquals(42, oo.b) |
| 308 assertSame(o, receiver) |
| 309 receiver = "" |
| 310 assertEquals(undefined, oo.c) |
| 311 assertEquals("", receiver) |
| 312 receiver = "" |
| 313 assertEquals(43, oo["a"]) |
| 314 assertEquals("", receiver) |
| 315 receiver = "" |
| 316 assertEquals(42, oo[3]) |
| 317 assertSame(o, receiver) |
| 318 |
| 319 receiver = "" |
| 320 assertEquals(50, o.a = 50) |
| 321 assertSame(o, receiver) |
| 322 assertEquals(50, value) |
| 323 receiver = "" |
| 324 assertEquals(51, o.b = 51) |
| 325 assertEquals("", receiver) |
| 326 assertEquals(50, value) // no setter |
| 327 assertThrows(function() { "use strict"; o.b = 51 }, TypeError) |
| 328 receiver = "" |
| 329 assertEquals(52, o.c = 52) |
| 330 assertSame(o, receiver) |
| 331 assertEquals(52, value) |
| 332 receiver = "" |
| 333 assertEquals(53, o["a"] = 53) |
| 334 assertSame(o, receiver) |
| 335 assertEquals(53, value) |
| 336 receiver = "" |
| 337 assertEquals(54, o[3] = 54) |
| 338 assertSame(o, receiver) |
| 339 assertEquals(54, value) |
| 340 |
| 341 value = 0 |
| 342 receiver = "" |
| 343 assertEquals(60, oo.a = 60) |
| 344 assertEquals("", receiver) |
| 345 assertEquals(0, value) // oo has own 'a' |
| 346 assertEquals(61, oo.b = 61) |
| 347 assertSame("", receiver) |
| 348 assertEquals(0, value) // no setter |
| 349 assertThrows(function() { "use strict"; oo.b = 61 }, TypeError) |
| 350 receiver = "" |
| 351 assertEquals(62, oo.c = 62) |
| 352 assertSame(oo, receiver) |
| 353 assertEquals(62, value) |
| 354 receiver = "" |
| 355 assertEquals(63, oo["c"] = 63) |
| 356 assertSame(oo, receiver) |
| 357 assertEquals(63, value) |
| 358 receiver = "" |
| 359 assertEquals(64, oo[3] = 64) |
| 360 assertSame(oo, receiver) |
| 361 assertEquals(64, value) |
| 362 } |
| 363 |
| 364 TestAccessorCall( |
| 365 function() { receiver = this; return 42 }, |
| 366 function(x) { receiver = this; value = x } |
| 367 ) |
| 368 |
| 369 TestAccessorCall( |
| 370 function() { "use strict"; receiver = this; return 42 }, |
| 371 function(x) { "use strict"; receiver = this; value = x } |
| 372 ) |
| 373 |
| 374 TestAccessorCall( |
| 375 Proxy.createFunction({}, function() { receiver = this; return 42 }), |
| 376 Proxy.createFunction({}, function(x) { receiver = this; value = x }) |
| 377 ) |
| 378 |
| 379 TestAccessorCall( |
| 380 CreateFrozen({}, function() { receiver = this; return 42 }), |
| 381 CreateFrozen({}, function(x) { receiver = this; value = x }) |
| 382 ) |
OLD | NEW |