| OLD | NEW |
| 1 // Flags: --harmony-proxies | 1 // Flags: --harmony-proxies |
| 2 | 2 |
| 3 // Copyright 2008 the V8 project authors. All rights reserved. | 3 // Copyright 2008 the V8 project authors. All rights reserved. |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 | 30 |
| 31 // TODO(rossberg): test exception cases. |
| 32 |
| 31 | 33 |
| 32 // Getters. | 34 // Getters. |
| 33 | 35 |
| 34 function TestGet(handler) { | 36 function TestGet(handler) { |
| 35 var o = Proxy.create(handler) | 37 var o = Proxy.create(handler) |
| 36 assertEquals(42, o.a) | 38 assertEquals(42, o.a) |
| 37 assertEquals(42, o["b"]) | 39 assertEquals(42, o["b"]) |
| 38 // assertEquals(Object.getOwnPropertyDescriptor(o, "b").value, 42) | |
| 39 } | 40 } |
| 40 | 41 |
| 41 TestGet({ | 42 TestGet({ |
| 42 get: function(r, k) { return 42 } | 43 get: function(r, k) { return 42 } |
| 43 }) | 44 }) |
| 45 |
| 44 TestGet({ | 46 TestGet({ |
| 45 get: function(r, k) { return this.get2(r, k) }, | 47 get: function(r, k) { return this.get2(r, k) }, |
| 46 get2: function(r, k) { return 42 } | 48 get2: function(r, k) { return 42 } |
| 47 }) | 49 }) |
| 50 |
| 48 TestGet({ | 51 TestGet({ |
| 49 getPropertyDescriptor: function(k) { return {value: 42} } | 52 getPropertyDescriptor: function(k) { return {value: 42} } |
| 50 }) | 53 }) |
| 54 |
| 51 TestGet({ | 55 TestGet({ |
| 52 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, | 56 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, |
| 53 getPropertyDescriptor2: function(k) { return {value: 42} } | 57 getPropertyDescriptor2: function(k) { return {value: 42} } |
| 54 }) | 58 }) |
| 59 |
| 55 TestGet({ | 60 TestGet({ |
| 56 getPropertyDescriptor: function(k) { | 61 getPropertyDescriptor: function(k) { |
| 57 return {get value() { return 42 }} | 62 return {get value() { return 42 }} |
| 58 } | 63 } |
| 59 }) | 64 }) |
| 65 |
| 60 TestGet({ | 66 TestGet({ |
| 61 get: undefined, | 67 get: undefined, |
| 62 getPropertyDescriptor: function(k) { return {value: 42} } | 68 getPropertyDescriptor: function(k) { return {value: 42} } |
| 63 }) | 69 }) |
| 64 | 70 |
| 65 TestGet(Proxy.create({ | 71 TestGet(Proxy.create({ |
| 66 get: function(pr, pk) { | 72 get: function(pr, pk) { |
| 67 return function(r, k) { return 42 } | 73 return function(r, k) { return 42 } |
| 68 } | 74 } |
| 69 })) | 75 })) |
| 70 | 76 |
| 71 | 77 |
| 78 function TestGetCall(handler) { |
| 79 var p = Proxy.create(handler) |
| 80 assertEquals(55, p.f()) |
| 81 assertEquals(55, p.f("unused", "arguments")) |
| 82 assertEquals(55, p.f.call(p)) |
| 83 assertEquals(55, p.withargs(45, 5)) |
| 84 assertEquals(55, p.withargs.call(p, 11, 22)) |
| 85 assertEquals("6655", "66" + p) // calls p.toString |
| 86 } |
| 87 |
| 88 TestGetCall({ |
| 89 get: function(r, k) { return function() { return 55 } } |
| 90 }) |
| 91 |
| 92 TestGetCall({ |
| 93 get: function(r, k) { return this.get2(r, k) }, |
| 94 get2: function(r, k) { return function() { return 55 } } |
| 95 }) |
| 96 |
| 97 TestGetCall({ |
| 98 getPropertyDescriptor: function(k) { |
| 99 return {value: function() { return 55 }} |
| 100 } |
| 101 }) |
| 102 |
| 103 TestGetCall({ |
| 104 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, |
| 105 getPropertyDescriptor2: function(k) { |
| 106 return {value: function() { return 55 }} |
| 107 } |
| 108 }) |
| 109 |
| 110 TestGetCall({ |
| 111 getPropertyDescriptor: function(k) { |
| 112 return {get value() { return function() { return 55 } }} |
| 113 } |
| 114 }) |
| 115 |
| 116 TestGetCall({ |
| 117 get: undefined, |
| 118 getPropertyDescriptor: function(k) { |
| 119 return {value: function() { return 55 }} |
| 120 } |
| 121 }) |
| 122 |
| 123 TestGetCall({ |
| 124 get: function(r, k) { |
| 125 if (k == "gg") { |
| 126 return function() { return 55 } |
| 127 } else if (k == "withargs") { |
| 128 return function(n, m) { return n + m * 2 } |
| 129 } else { |
| 130 return function() { return this.gg() } |
| 131 } |
| 132 } |
| 133 }) |
| 134 |
| 135 TestGetCall(Proxy.create({ |
| 136 get: function(pr, pk) { |
| 137 return function(r, k) { return function() { return 55 } } |
| 138 } |
| 139 })) |
| 140 |
| 141 |
| 72 | 142 |
| 73 // Setters. | 143 // Setters. |
| 74 | 144 |
| 75 var key | 145 var key |
| 76 var val | 146 var val |
| 77 function TestSet(handler) { | 147 function TestSet(handler) { |
| 78 var o = Proxy.create(handler) | 148 var o = Proxy.create(handler) |
| 79 assertEquals(42, o.a = 42) | 149 assertEquals(42, o.a = 42) |
| 80 assertEquals("a", key) | 150 assertEquals("a", key) |
| 81 assertEquals(42, val) | 151 assertEquals(42, val) |
| 82 assertEquals(43, o["b"] = 43) | 152 assertEquals(43, o["b"] = 43) |
| 83 assertEquals("b", key) | 153 assertEquals("b", key) |
| 84 assertEquals(43, val) | 154 assertEquals(43, val) |
| 85 // assertTrue(Object.defineProperty(o, "c", {value: 44})) | |
| 86 // assertEquals("c", key) | |
| 87 // assertEquals(44, val) | |
| 88 } | 155 } |
| 89 | 156 |
| 90 TestSet({ | 157 TestSet({ |
| 91 set: function(r, k, v) { key = k; val = v; return true } | 158 set: function(r, k, v) { key = k; val = v; return true } |
| 92 }) | 159 }) |
| 160 |
| 93 TestSet({ | 161 TestSet({ |
| 94 set: function(r, k, v) { return this.set2(r, k, v) }, | 162 set: function(r, k, v) { return this.set2(r, k, v) }, |
| 95 set2: function(r, k, v) { key = k; val = v; return true } | 163 set2: function(r, k, v) { key = k; val = v; return true } |
| 96 }) | 164 }) |
| 165 |
| 97 TestSet({ | 166 TestSet({ |
| 98 getOwnPropertyDescriptor: function(k) { return {writable: true} }, | 167 getOwnPropertyDescriptor: function(k) { return {writable: true} }, |
| 99 defineProperty: function(k, desc) { key = k; val = desc.value } | 168 defineProperty: function(k, desc) { key = k; val = desc.value } |
| 100 }) | 169 }) |
| 170 |
| 101 TestSet({ | 171 TestSet({ |
| 102 getOwnPropertyDescriptor: function(k) { | 172 getOwnPropertyDescriptor: function(k) { |
| 103 return this.getOwnPropertyDescriptor2(k) | 173 return this.getOwnPropertyDescriptor2(k) |
| 104 }, | 174 }, |
| 105 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, | 175 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, |
| 106 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, | 176 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, |
| 107 defineProperty2: function(k, desc) { key = k; val = desc.value } | 177 defineProperty2: function(k, desc) { key = k; val = desc.value } |
| 108 }) | 178 }) |
| 179 |
| 109 TestSet({ | 180 TestSet({ |
| 110 getOwnPropertyDescriptor: function(k) { | 181 getOwnPropertyDescriptor: function(k) { |
| 111 return {get writable() { return true }} | 182 return {get writable() { return true }} |
| 112 }, | 183 }, |
| 113 defineProperty: function(k, desc) { key = k; val = desc.value } | 184 defineProperty: function(k, desc) { key = k; val = desc.value } |
| 114 }) | 185 }) |
| 186 |
| 115 TestSet({ | 187 TestSet({ |
| 116 getOwnPropertyDescriptor: function(k) { | 188 getOwnPropertyDescriptor: function(k) { |
| 117 return {set: function(v) { key = k; val = v }} | 189 return {set: function(v) { key = k; val = v }} |
| 118 } | 190 } |
| 119 }) | 191 }) |
| 192 |
| 120 TestSet({ | 193 TestSet({ |
| 121 getOwnPropertyDescriptor: function(k) { return null }, | 194 getOwnPropertyDescriptor: function(k) { return null }, |
| 122 getPropertyDescriptor: function(k) { return {writable: true} }, | 195 getPropertyDescriptor: function(k) { return {writable: true} }, |
| 123 defineProperty: function(k, desc) { key = k; val = desc.value } | 196 defineProperty: function(k, desc) { key = k; val = desc.value } |
| 124 }) | 197 }) |
| 198 |
| 125 TestSet({ | 199 TestSet({ |
| 126 getOwnPropertyDescriptor: function(k) { return null }, | 200 getOwnPropertyDescriptor: function(k) { return null }, |
| 127 getPropertyDescriptor: function(k) { | 201 getPropertyDescriptor: function(k) { |
| 128 return {get writable() { return true }} | 202 return {get writable() { return true }} |
| 129 }, | 203 }, |
| 130 defineProperty: function(k, desc) { key = k; val = desc.value } | 204 defineProperty: function(k, desc) { key = k; val = desc.value } |
| 131 }) | 205 }) |
| 206 |
| 132 TestSet({ | 207 TestSet({ |
| 133 getOwnPropertyDescriptor: function(k) { return null }, | 208 getOwnPropertyDescriptor: function(k) { return null }, |
| 134 getPropertyDescriptor: function(k) { | 209 getPropertyDescriptor: function(k) { |
| 135 return {set: function(v) { key = k; val = v }} | 210 return {set: function(v) { key = k; val = v }} |
| 136 } | 211 } |
| 137 }) | 212 }) |
| 213 |
| 138 TestSet({ | 214 TestSet({ |
| 139 getOwnPropertyDescriptor: function(k) { return null }, | 215 getOwnPropertyDescriptor: function(k) { return null }, |
| 140 getPropertyDescriptor: function(k) { return null }, | 216 getPropertyDescriptor: function(k) { return null }, |
| 141 defineProperty: function(k, desc) { key = k, val = desc.value } | 217 defineProperty: function(k, desc) { key = k, val = desc.value } |
| 142 }) | 218 }) |
| 143 | 219 |
| 144 TestSet(Proxy.create({ | 220 TestSet(Proxy.create({ |
| 145 get: function(pr, pk) { | 221 get: function(pr, pk) { |
| 146 return function(r, k, v) { key = k; val = v; return true } | 222 return function(r, k, v) { key = k; val = v; return true } |
| 147 } | 223 } |
| 148 })) | 224 })) |
| 149 | 225 |
| 150 | 226 |
| 151 | 227 |
| 152 // Property definition (Object.defineProperty). | 228 // Property definition (Object.defineProperty and Object.defineProperties). |
| 153 | 229 |
| 154 var key | 230 var key |
| 155 var desc | 231 var desc |
| 156 function TestDefine(handler) { | 232 function TestDefine(handler) { |
| 157 var o = Proxy.create(handler) | 233 var o = Proxy.create(handler) |
| 158 assertEquals(o, Object.defineProperty(o, "a", {value: 44})) | 234 assertEquals(o, Object.defineProperty(o, "a", {value: 44})) |
| 159 assertEquals("a", key) | 235 assertEquals("a", key) |
| 160 assertEquals(1, Object.getOwnPropertyNames(desc).length) | 236 assertEquals(1, Object.getOwnPropertyNames(desc).length) |
| 161 assertEquals(44, desc.value) | 237 assertEquals(44, desc.value) |
| 162 | 238 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 186 | 262 |
| 187 assertEquals(o, Object.defineProperty(o, "e", {get: function(){ return 5 }})) | 263 assertEquals(o, Object.defineProperty(o, "e", {get: function(){ return 5 }})) |
| 188 assertEquals("e", key) | 264 assertEquals("e", key) |
| 189 assertEquals(1, Object.getOwnPropertyNames(desc).length) | 265 assertEquals(1, Object.getOwnPropertyNames(desc).length) |
| 190 assertEquals(5, desc.get()) | 266 assertEquals(5, desc.get()) |
| 191 | 267 |
| 192 assertEquals(o, Object.defineProperty(o, "zzz", {})) | 268 assertEquals(o, Object.defineProperty(o, "zzz", {})) |
| 193 assertEquals("zzz", key) | 269 assertEquals("zzz", key) |
| 194 assertEquals(0, Object.getOwnPropertyNames(desc).length) | 270 assertEquals(0, Object.getOwnPropertyNames(desc).length) |
| 195 | 271 |
| 196 // This test requires [s in proxy] to be implemented first. | 272 // TODO(rossberg): This test requires [s in proxy] to be implemented first. |
| 197 // var d = Proxy.create({ | 273 // var d = Proxy.create({ |
| 198 // get: function(r, k) { return (k === "value") ? 77 : void 0 }, | 274 // get: function(r, k) { return (k === "value") ? 77 : void 0 }, |
| 199 // getOwnPropertyNames: function() { return ["value"] } | 275 // getOwnPropertyNames: function() { return ["value"] } |
| 200 // }) | 276 // }) |
| 201 // assertEquals(1, Object.getOwnPropertyNames(d).length) | 277 // assertEquals(1, Object.getOwnPropertyNames(d).length) |
| 202 // assertEquals(77, d.value) | 278 // assertEquals(77, d.value) |
| 203 // assertEquals(o, Object.defineProperty(o, "p", d)) | 279 // assertEquals(o, Object.defineProperty(o, "p", d)) |
| 204 // assertEquals("p", key) | 280 // assertEquals("p", key) |
| 205 // assertEquals(1, Object.getOwnPropertyNames(desc).length) | 281 // assertEquals(1, Object.getOwnPropertyNames(desc).length) |
| 206 // assertEquals(77, desc.value) | 282 // assertEquals(77, desc.value) |
| 283 |
| 284 var props = { |
| 285 'bla': {}, |
| 286 blub: {get: function() { return true }}, |
| 287 '': {get value() { return 20 }}, |
| 288 last: {value: 21, configurable: true, mine: "eyes"} |
| 289 } |
| 290 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) |
| 291 assertEquals(o, Object.defineProperties(o, props)) |
| 292 assertEquals("last", key) |
| 293 assertEquals(2, Object.getOwnPropertyNames(desc).length) |
| 294 assertEquals(21, desc.value) |
| 295 assertEquals(true, desc.configurable) |
| 296 assertEquals(undefined, desc.mine) // Arguably a bug in the spec... |
| 207 } | 297 } |
| 208 | 298 |
| 209 TestDefine({ | 299 TestDefine({ |
| 210 defineProperty: function(k, d) { key = k; desc = d; return true } | 300 defineProperty: function(k, d) { key = k; desc = d; return true } |
| 211 }) | 301 }) |
| 302 |
| 212 TestDefine({ | 303 TestDefine({ |
| 213 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, | 304 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, |
| 214 defineProperty2: function(k, d) { key = k; desc = d; return true } | 305 defineProperty2: function(k, d) { key = k; desc = d; return true } |
| 215 }) | 306 }) |
| 307 |
| 216 TestDefine(Proxy.create({ | 308 TestDefine(Proxy.create({ |
| 217 get: function(pr, pk) { | 309 get: function(pr, pk) { |
| 218 return function(k, d) { key = k; desc = d; return true } | 310 return function(k, d) { key = k; desc = d; return true } |
| 219 } | 311 } |
| 220 })) | 312 })) |
| 221 | 313 |
| 222 | 314 |
| 223 | 315 |
| 316 // Property deletion (delete). |
| 317 |
| 318 var key |
| 319 function TestDelete(handler) { |
| 320 var o = Proxy.create(handler) |
| 321 assertEquals(true, delete o.a) |
| 322 assertEquals("a", key) |
| 323 assertEquals(true, delete o["b"]) |
| 324 assertEquals("b", key) |
| 325 |
| 326 assertEquals(false, delete o.z1) |
| 327 assertEquals("z1", key) |
| 328 assertEquals(false, delete o["z2"]) |
| 329 assertEquals("z2", key); |
| 330 |
| 331 (function() { |
| 332 "use strict" |
| 333 assertEquals(true, delete o.c) |
| 334 assertEquals("c", key) |
| 335 assertEquals(true, delete o["d"]) |
| 336 assertEquals("d", key) |
| 337 |
| 338 assertThrows(function() { delete o.z3 }, TypeError) |
| 339 assertEquals("z3", key) |
| 340 assertThrows(function() { delete o["z4"] }, TypeError) |
| 341 assertEquals("z4", key) |
| 342 })() |
| 343 } |
| 344 |
| 345 TestDelete({ |
| 346 'delete': function(k) { key = k; return k < "z" } |
| 347 }) |
| 348 |
| 349 TestDelete({ |
| 350 'delete': function(k) { return this.delete2(k) }, |
| 351 delete2: function(k) { key = k; return k < "z" } |
| 352 }) |
| 353 |
| 354 TestDelete(Proxy.create({ |
| 355 get: function(pr, pk) { |
| 356 return function(k) { key = k; return k < "z" } |
| 357 } |
| 358 })) |
| 359 |
| 360 |
| 361 |
| 362 // Property descriptors (Object.getOwnPropertyDescriptor). |
| 363 |
| 364 function TestDescriptor(handler) { |
| 365 var o = Proxy.create(handler) |
| 366 var descs = [ |
| 367 {configurable: true}, |
| 368 {value: 34, enumerable: true, configurable: true}, |
| 369 {value: 3, writable: false, mine: "eyes", configurable: true}, |
| 370 {get value() { return 20 }, get configurable() { return true }}, |
| 371 {get: function() { "get" }, set: function() { "set" }, configurable: true} |
| 372 ] |
| 373 for (var i = 0; i < descs.length; ++i) { |
| 374 assertEquals(o, Object.defineProperty(o, i, descs[i])) |
| 375 var desc = Object.getOwnPropertyDescriptor(o, i) |
| 376 for (p in descs[i]) { |
| 377 // TODO(rossberg): Ignore user attributes as long as the spec isn't |
| 378 // fixed suitably. |
| 379 if (p != "mine") assertEquals(descs[i][p], desc[p]) |
| 380 } |
| 381 assertEquals(undefined, Object.getOwnPropertyDescriptor(o, "absent")) |
| 382 } |
| 383 } |
| 384 |
| 385 |
| 386 TestDescriptor({ |
| 387 defineProperty: function(k, d) { this["__" + k] = d; return true }, |
| 388 getOwnPropertyDescriptor: function(k) { return this["__" + k] } |
| 389 }) |
| 390 |
| 391 TestDescriptor({ |
| 392 defineProperty: function(k, d) { this["__" + k] = d; return true }, |
| 393 getOwnPropertyDescriptor: function(k) { |
| 394 return this.getOwnPropertyDescriptor2(k) |
| 395 }, |
| 396 getOwnPropertyDescriptor2: function(k) { return this["__" + k] } |
| 397 }) |
| 398 |
| 399 |
| 400 |
| 224 // Comparison. | 401 // Comparison. |
| 225 | 402 |
| 226 function TestComparison(eq) { | 403 function TestComparison(eq) { |
| 227 var o1 = Proxy.create({}) | 404 var o1 = Proxy.create({}) |
| 228 var o2 = Proxy.create({}) | 405 var o2 = Proxy.create({}) |
| 229 | 406 |
| 230 assertTrue(eq(o1, o1)) | 407 assertTrue(eq(o1, o1)) |
| 231 assertTrue(eq(o2, o2)) | 408 assertTrue(eq(o2, o2)) |
| 232 assertTrue(!eq(o1, o2)) | 409 assertTrue(!eq(o1, o2)) |
| 233 assertTrue(!eq(o1, {})) | 410 assertTrue(!eq(o1, {})) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 245 // Type. | 422 // Type. |
| 246 | 423 |
| 247 assertEquals("object", typeof Proxy.create({})) | 424 assertEquals("object", typeof Proxy.create({})) |
| 248 assertTrue(typeof Proxy.create({}) == "object") | 425 assertTrue(typeof Proxy.create({}) == "object") |
| 249 assertTrue("object" == typeof Proxy.create({})) | 426 assertTrue("object" == typeof Proxy.create({})) |
| 250 | 427 |
| 251 // No function proxies yet. | 428 // No function proxies yet. |
| 252 | 429 |
| 253 | 430 |
| 254 | 431 |
| 255 // Instanceof (instanceof). | 432 // Membership test (in). |
| 433 |
| 434 var key |
| 435 function TestIn(handler) { |
| 436 var o = Proxy.create(handler) |
| 437 assertTrue("a" in o) |
| 438 assertEquals("a", key) |
| 439 assertTrue(99 in o) |
| 440 assertEquals("99", key) |
| 441 assertFalse("z" in o) |
| 442 assertEquals("z", key) |
| 443 |
| 444 if ("b" in o) { |
| 445 } else { |
| 446 assertTrue(false) |
| 447 } |
| 448 assertEquals("b", key) |
| 449 |
| 450 if ("zz" in o) { |
| 451 assertTrue(false) |
| 452 } |
| 453 assertEquals("zz", key) |
| 454 |
| 455 if (!("c" in o)) { |
| 456 assertTrue(false) |
| 457 } |
| 458 assertEquals("c", key) |
| 459 |
| 460 if (!("zzz" in o)) { |
| 461 } else { |
| 462 assertTrue(false) |
| 463 } |
| 464 assertEquals("zzz", key) |
| 465 } |
| 466 |
| 467 TestIn({ |
| 468 has: function(k) { key = k; return k < "z" } |
| 469 }) |
| 470 |
| 471 TestIn({ |
| 472 has: function(k) { return this.has2(k) }, |
| 473 has2: function(k) { key = k; return k < "z" } |
| 474 }) |
| 475 |
| 476 TestIn({ |
| 477 getPropertyDescriptor: function(k) { |
| 478 key = k; return k < "z" ? {value: 42} : void 0 |
| 479 } |
| 480 }) |
| 481 |
| 482 TestIn({ |
| 483 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, |
| 484 getPropertyDescriptor2: function(k) { |
| 485 key = k; return k < "z" ? {value: 42} : void 0 |
| 486 } |
| 487 }) |
| 488 |
| 489 TestIn({ |
| 490 getPropertyDescriptor: function(k) { |
| 491 key = k; return k < "z" ? {get value() { return 42 }} : void 0 |
| 492 } |
| 493 }) |
| 494 |
| 495 TestIn({ |
| 496 get: undefined, |
| 497 getPropertyDescriptor: function(k) { |
| 498 key = k; return k < "z" ? {value: 42} : void 0 |
| 499 } |
| 500 }) |
| 501 |
| 502 TestIn(Proxy.create({ |
| 503 get: function(pr, pk) { |
| 504 return function(k) { key = k; return k < "z" } |
| 505 } |
| 506 })) |
| 507 |
| 508 |
| 509 |
| 510 // Own Properties (Object.prototype.hasOwnProperty). |
| 511 |
| 512 var key |
| 513 function TestHasOwn(handler) { |
| 514 var o = Proxy.create(handler) |
| 515 assertTrue(Object.prototype.hasOwnProperty.call(o, "a")) |
| 516 assertEquals("a", key) |
| 517 assertTrue(Object.prototype.hasOwnProperty.call(o, 99)) |
| 518 assertEquals("99", key) |
| 519 assertFalse(Object.prototype.hasOwnProperty.call(o, "z")) |
| 520 assertEquals("z", key) |
| 521 } |
| 522 |
| 523 TestHasOwn({ |
| 524 hasOwn: function(k) { key = k; return k < "z" } |
| 525 }) |
| 526 |
| 527 TestHasOwn({ |
| 528 hasOwn: function(k) { return this.hasOwn2(k) }, |
| 529 hasOwn2: function(k) { key = k; return k < "z" } |
| 530 }) |
| 531 |
| 532 TestHasOwn({ |
| 533 getOwnPropertyDescriptor: function(k) { |
| 534 key = k; return k < "z" ? {value: 42} : void 0 |
| 535 } |
| 536 }) |
| 537 |
| 538 TestHasOwn({ |
| 539 getOwnPropertyDescriptor: function(k) { |
| 540 return this.getOwnPropertyDescriptor2(k) |
| 541 }, |
| 542 getOwnPropertyDescriptor2: function(k) { |
| 543 key = k; return k < "z" ? {value: 42} : void 0 |
| 544 } |
| 545 }) |
| 546 |
| 547 TestHasOwn({ |
| 548 getOwnPropertyDescriptor: function(k) { |
| 549 key = k; return k < "z" ? {get value() { return 42 }} : void 0 |
| 550 } |
| 551 }) |
| 552 |
| 553 TestHasOwn({ |
| 554 hasOwn: undefined, |
| 555 getOwnPropertyDescriptor: function(k) { |
| 556 key = k; return k < "z" ? {value: 42} : void 0 |
| 557 } |
| 558 }) |
| 559 |
| 560 TestHasOwn(Proxy.create({ |
| 561 get: function(pr, pk) { |
| 562 return function(k) { key = k; return k < "z" } |
| 563 } |
| 564 })) |
| 565 |
| 566 |
| 567 |
| 568 // Instanceof (instanceof) |
| 256 | 569 |
| 257 function TestInstanceof() { | 570 function TestInstanceof() { |
| 258 var o = {} | 571 var o = {} |
| 259 var p1 = Proxy.create({}) | 572 var p1 = Proxy.create({}) |
| 260 var p2 = Proxy.create({}, o) | 573 var p2 = Proxy.create({}, o) |
| 261 var p3 = Proxy.create({}, p2) | 574 var p3 = Proxy.create({}, p2) |
| 262 | 575 |
| 263 var f = function() {} | 576 var f = function() {} |
| 264 f.prototype = o | 577 f.prototype = o |
| 265 var f1 = function() {} | 578 var f1 = function() {} |
| (...skipping 16 matching lines...) Expand all Loading... |
| 282 assertTrue(p3 instanceof Object) | 595 assertTrue(p3 instanceof Object) |
| 283 assertTrue(p3 instanceof f) | 596 assertTrue(p3 instanceof f) |
| 284 assertFalse(p3 instanceof f1) | 597 assertFalse(p3 instanceof f1) |
| 285 assertTrue(p3 instanceof f2) | 598 assertTrue(p3 instanceof f2) |
| 286 } | 599 } |
| 287 | 600 |
| 288 TestInstanceof() | 601 TestInstanceof() |
| 289 | 602 |
| 290 | 603 |
| 291 | 604 |
| 292 // Prototype (Object.getPrototypeOf). | 605 // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). |
| 293 | 606 |
| 294 function TestPrototype() { | 607 function TestPrototype() { |
| 295 var o = {} | 608 var o = {} |
| 296 var p1 = Proxy.create({}) | 609 var p1 = Proxy.create({}) |
| 297 var p2 = Proxy.create({}, o) | 610 var p2 = Proxy.create({}, o) |
| 298 var p3 = Proxy.create({}, p2) | 611 var p3 = Proxy.create({}, p2) |
| 299 var p4 = Proxy.create({}, 666) | 612 var p4 = Proxy.create({}, 666) |
| 300 | 613 |
| 301 assertSame(Object.getPrototypeOf(o), Object.prototype) | 614 assertSame(Object.getPrototypeOf(o), Object.prototype) |
| 302 assertSame(Object.getPrototypeOf(p1), null) | 615 assertSame(Object.getPrototypeOf(p1), null) |
| 303 assertSame(Object.getPrototypeOf(p2), o) | 616 assertSame(Object.getPrototypeOf(p2), o) |
| 304 assertSame(Object.getPrototypeOf(p3), p2) | 617 assertSame(Object.getPrototypeOf(p3), p2) |
| 305 assertSame(Object.getPrototypeOf(p4), null) | 618 assertSame(Object.getPrototypeOf(p4), null) |
| 619 |
| 620 assertTrue(Object.prototype.isPrototypeOf(o)) |
| 621 assertFalse(Object.prototype.isPrototypeOf(p1)) |
| 622 assertTrue(Object.prototype.isPrototypeOf(p2)) |
| 623 assertTrue(Object.prototype.isPrototypeOf(p3)) |
| 624 assertFalse(Object.prototype.isPrototypeOf(p4)) |
| 625 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o)) |
| 626 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) |
| 627 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) |
| 628 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) |
| 629 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4)) |
| 630 assertFalse(Object.prototype.isPrototypeOf.call(o, o)) |
| 631 assertFalse(Object.prototype.isPrototypeOf.call(o, p1)) |
| 632 assertTrue(Object.prototype.isPrototypeOf.call(o, p2)) |
| 633 assertTrue(Object.prototype.isPrototypeOf.call(o, p3)) |
| 634 assertFalse(Object.prototype.isPrototypeOf.call(o, p4)) |
| 635 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) |
| 636 assertFalse(Object.prototype.isPrototypeOf.call(p1, o)) |
| 637 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) |
| 638 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) |
| 639 assertFalse(Object.prototype.isPrototypeOf.call(p1, p4)) |
| 640 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) |
| 641 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) |
| 642 assertTrue(Object.prototype.isPrototypeOf.call(p2, p3)) |
| 643 assertFalse(Object.prototype.isPrototypeOf.call(p2, p4)) |
| 644 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) |
| 306 } | 645 } |
| 307 | 646 |
| 308 TestPrototype() | 647 TestPrototype() |
| 309 | 648 |
| 310 | 649 |
| 311 | 650 |
| 312 // Property names (Object.getOwnPropertyNames). | 651 // Property names (Object.getOwnPropertyNames, Object.keys). |
| 313 | 652 |
| 314 function TestPropertyNames(names, handler) { | 653 function TestPropertyNames(names, handler) { |
| 315 var p = Proxy.create(handler) | 654 var p = Proxy.create(handler) |
| 316 assertArrayEquals(names, Object.getOwnPropertyNames(p)) | 655 assertArrayEquals(names, Object.getOwnPropertyNames(p)) |
| 317 } | 656 } |
| 318 | 657 |
| 319 TestPropertyNames([], { | 658 TestPropertyNames([], { |
| 320 getOwnPropertyNames: function() { return [] } | 659 getOwnPropertyNames: function() { return [] } |
| 321 }) | 660 }) |
| 661 |
| 322 TestPropertyNames(["a", "zz", " ", "0"], { | 662 TestPropertyNames(["a", "zz", " ", "0"], { |
| 323 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } | 663 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } |
| 324 }) | 664 }) |
| 665 |
| 325 TestPropertyNames(["throw", "function "], { | 666 TestPropertyNames(["throw", "function "], { |
| 326 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, | 667 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, |
| 327 getOwnPropertyNames2: function() { return ["throw", "function "] } | 668 getOwnPropertyNames2: function() { return ["throw", "function "] } |
| 328 }) | 669 }) |
| 670 |
| 329 TestPropertyNames(["[object Object]"], { | 671 TestPropertyNames(["[object Object]"], { |
| 330 get getOwnPropertyNames() { | 672 get getOwnPropertyNames() { |
| 331 return function() { return [{}] } | 673 return function() { return [{}] } |
| 332 } | 674 } |
| 333 }) | 675 }) |
| 676 |
| 677 |
| 678 function TestKeys(names, handler) { |
| 679 var p = Proxy.create(handler) |
| 680 assertArrayEquals(names, Object.keys(p)) |
| 681 } |
| 682 |
| 683 TestKeys([], { |
| 684 keys: function() { return [] } |
| 685 }) |
| 686 |
| 687 TestKeys(["a", "zz", " ", "0"], { |
| 688 keys: function() { return ["a", "zz", " ", 0] } |
| 689 }) |
| 690 |
| 691 TestKeys(["throw", "function "], { |
| 692 keys: function() { return this.keys2() }, |
| 693 keys2: function() { return ["throw", "function "] } |
| 694 }) |
| 695 |
| 696 TestKeys(["[object Object]"], { |
| 697 get keys() { |
| 698 return function() { return [{}] } |
| 699 } |
| 700 }) |
| 701 |
| 702 TestKeys(["a", "0"], { |
| 703 getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] }, |
| 704 getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} } |
| 705 }) |
| 706 |
| 707 TestKeys(["23", "zz", ""], { |
| 708 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, |
| 709 getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] }, |
| 710 getOwnPropertyDescriptor: function(k) { |
| 711 return this.getOwnPropertyDescriptor2(k) |
| 712 }, |
| 713 getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} } |
| 714 }) |
| 715 |
| 716 TestKeys(["a", "b", "c", "5"], { |
| 717 get getOwnPropertyNames() { |
| 718 return function() { return ["0", 4, "a", "b", "c", 5] } |
| 719 }, |
| 720 get getOwnPropertyDescriptor() { |
| 721 return function(k) { return {enumerable: k >= "44"} } |
| 722 } |
| 723 }) |
| 724 |
| 725 TestKeys([], { |
| 726 get getOwnPropertyNames() { |
| 727 return function() { return ["a", "b", "c"] } |
| 728 }, |
| 729 getOwnPropertyDescriptor: function(k) { return {} } |
| 730 }) |
| 731 |
| 732 |
| 733 |
| 734 // Fixing (Object.freeze, Object.seal, Object.preventExtensions, |
| 735 // Object.isFrozen, Object.isSealed, Object.isExtensible) |
| 736 |
| 737 function TestFix(names, handler) { |
| 738 var proto = {p: 77} |
| 739 var assertFixing = function(o, s, f, e) { |
| 740 assertEquals(s, Object.isSealed(o)) |
| 741 assertEquals(f, Object.isFrozen(o)) |
| 742 assertEquals(e, Object.isExtensible(o)) |
| 743 } |
| 744 |
| 745 var o1 = Proxy.create(handler, proto) |
| 746 assertFixing(o1, false, false, true) |
| 747 Object.seal(o1) |
| 748 assertFixing(o1, true, names.length === 0, false) |
| 749 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o1).sort()) |
| 750 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), |
| 751 Object.keys(o1).sort()) |
| 752 assertEquals(proto, Object.getPrototypeOf(o1)) |
| 753 assertEquals(77, o1.p) |
| 754 for (var n in o1) { |
| 755 var desc = Object.getOwnPropertyDescriptor(o1, n) |
| 756 if (desc !== undefined) assertFalse(desc.configurable) |
| 757 } |
| 758 |
| 759 var o2 = Proxy.create(handler, proto) |
| 760 assertFixing(o2, false, false, true) |
| 761 Object.freeze(o2) |
| 762 assertFixing(o2, true, true, false) |
| 763 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o2).sort()) |
| 764 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), |
| 765 Object.keys(o2).sort()) |
| 766 assertEquals(proto, Object.getPrototypeOf(o2)) |
| 767 assertEquals(77, o2.p) |
| 768 for (var n in o2) { |
| 769 var desc = Object.getOwnPropertyDescriptor(o2, n) |
| 770 if (desc !== undefined) assertFalse(desc.writable) |
| 771 if (desc !== undefined) assertFalse(desc.configurable) |
| 772 } |
| 773 |
| 774 var o3 = Proxy.create(handler, proto) |
| 775 assertFixing(o3, false, false, true) |
| 776 Object.preventExtensions(o3) |
| 777 assertFixing(o3, names.length === 0, names.length === 0, false) |
| 778 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o3).sort()) |
| 779 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), |
| 780 Object.keys(o3).sort()) |
| 781 assertEquals(proto, Object.getPrototypeOf(o3)) |
| 782 assertEquals(77, o3.p) |
| 783 } |
| 784 |
| 785 TestFix([], { |
| 786 fix: function() { return {} } |
| 787 }) |
| 788 |
| 789 TestFix(["a", "b", "c", "d", "zz"], { |
| 790 fix: function() { |
| 791 return { |
| 792 a: {value: "a", writable: true, configurable: false, enumerable: true}, |
| 793 b: {value: 33, writable: false, configurable: false, enumerable: true}, |
| 794 c: {value: 0, writable: true, configurable: true, enumerable: true}, |
| 795 d: {value: true, writable: false, configurable: true, enumerable: true}, |
| 796 zz: {value: 0, enumerable: false} |
| 797 } |
| 798 } |
| 799 }) |
| 800 |
| 801 TestFix(["a"], { |
| 802 fix: function() { return this.fix2() }, |
| 803 fix2: function() { |
| 804 return {a: {value: 4, writable: true, configurable: true, enumerable: true}} |
| 805 } |
| 806 }) |
| 807 |
| 808 TestFix(["b"], { |
| 809 get fix() { |
| 810 return function() { |
| 811 return {b: {configurable: true, writable: true, enumerable: true}} |
| 812 } |
| 813 } |
| 814 }) |
| 815 |
| 816 |
| 817 |
| 818 // String conversion (Object.prototype.toString, Object.prototype.toLocaleString
) |
| 819 |
| 820 var key |
| 821 function TestToString(handler) { |
| 822 var o = Proxy.create(handler) |
| 823 key = "" |
| 824 assertEquals("[object Object]", Object.prototype.toString.call(o)) |
| 825 assertEquals("", key) |
| 826 assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) |
| 827 assertEquals("toString", key) |
| 828 } |
| 829 |
| 830 TestToString({ |
| 831 get: function(r, k) { key = k; return function() { return "my_proxy" } } |
| 832 }) |
| 833 |
| 834 TestToString({ |
| 835 get: function(r, k) { return this.get2(r, k) }, |
| 836 get2: function(r, k) { key = k; return function() { return "my_proxy" } } |
| 837 }) |
| 838 |
| 839 TestToString(Proxy.create({ |
| 840 get: function(pr, pk) { |
| 841 return function(r, k) { key = k; return function() { return "my_proxy" } } |
| 842 } |
| 843 })) |
| 844 |
| 845 |
| 846 |
| 847 // Value conversion (Object.prototype.toValue) |
| 848 |
| 849 function TestValueOf(handler) { |
| 850 var o = Proxy.create(handler) |
| 851 assertSame(o, Object.prototype.valueOf.call(o)) |
| 852 } |
| 853 |
| 854 TestValueOf({}) |
| 855 |
| 856 |
| 857 |
| 858 // Enumerability (Object.prototype.propertyIsEnumerable) |
| 859 |
| 860 var key |
| 861 function TestIsEnumerable(handler) { |
| 862 var o = Proxy.create(handler) |
| 863 assertTrue(Object.prototype.propertyIsEnumerable.call(o, "a")) |
| 864 assertEquals("a", key) |
| 865 assertTrue(Object.prototype.propertyIsEnumerable.call(o, 2)) |
| 866 assertEquals("2", key) |
| 867 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "z")) |
| 868 assertEquals("z", key) |
| 869 } |
| 870 |
| 871 TestIsEnumerable({ |
| 872 getOwnPropertyDescriptor: function(k) { |
| 873 key = k; return {enumerable: k < "z", configurable: true} |
| 874 }, |
| 875 }) |
| 876 |
| 877 TestIsEnumerable({ |
| 878 getOwnPropertyDescriptor: function(k) { |
| 879 return this.getOwnPropertyDescriptor2(k) |
| 880 }, |
| 881 getOwnPropertyDescriptor2: function(k) { |
| 882 key = k; return {enumerable: k < "z", configurable: true} |
| 883 }, |
| 884 }) |
| 885 |
| 886 TestIsEnumerable({ |
| 887 getOwnPropertyDescriptor: function(k) { |
| 888 key = k; return {get enumerable() { return k < "z" }, configurable: true} |
| 889 }, |
| 890 }) |
| 891 |
| 892 TestIsEnumerable(Proxy.create({ |
| 893 get: function(pr, pk) { |
| 894 return function(k) { |
| 895 key = k; return {enumerable: k < "z", configurable: true} |
| 896 } |
| 897 } |
| 898 })) |
| OLD | NEW |