1 // Copyright 2014 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.
5 // Flags: --harmony-unscopables
6 // Flags: --harmony-collections
9 var globalProto = Object.getPrototypeOf(global);
11 // Number of objects being tested. There is an assert ensuring this is correct.
16 function restore(object, oldProto) {
17 delete object[Symbol.unscopables];
22 Object.setPrototypeOf(object, oldProto);
25 function getObject(i) {
55 assertEquals(objectCount, objects.length);
59 // Tests depends on this not being there to start with.
60 delete Array.prototype[Symbol.unscopables];
63 for (var i = 0; i < objectCount; i++) {
64 var object = getObject(i);
65 var oldObjectProto = Object.getPrototypeOf(object);
67 restore(object, oldObjectProto);
70 for (var i = 0; i < objectCount; i++) {
71 for (var j = 0; j < objectCount; j++) {
72 var object = getObject(i);
73 var proto = getObject(j);
74 if (object === proto) {
77 var oldObjectProto = Object.getPrototypeOf(object);
78 var oldProtoProto = Object.getPrototypeOf(proto);
80 restore(object, oldObjectProto);
81 restore(proto, oldProtoProto);
87 // Test array first, since other tests are changing
88 // Array.prototype[Symbol.unscopables].
89 function TestArrayPrototypeUnscopables() {
90 var descr = Object.getOwnPropertyDescriptor(Array.prototype,
92 assertFalse(descr.enumerable);
93 assertFalse(descr.writable);
94 assertTrue(descr.configurable);
95 assertEquals(null, Object.getPrototypeOf(descr.value));
97 var copyWithin = 'local copyWithin';
98 var entries = 'local entries';
99 var fill = 'local fill';
100 var find = 'local find';
101 var findIndex = 'local findIndex';
102 var keys = 'local keys';
103 var values = 'local values';
109 assertEquals('local copyWithin', copyWithin);
110 assertEquals('local entries', entries);
111 assertEquals('local fill', fill);
112 assertEquals('local find', find);
113 assertEquals('local findIndex', findIndex);
114 assertEquals('local keys', keys);
115 assertEquals('local values', values);
116 assertEquals(42, toString);
119 TestArrayPrototypeUnscopables();
123 function TestBasics(object) {
136 object[Symbol.unscopables] = {x: true};
143 object[Symbol.unscopables] = {x: 0, y: true};
153 function TestUnscopableChain(object) {
161 object[Symbol.unscopables] = {
168 runTest(TestUnscopableChain);
171 function TestBasicsSet(object) {
179 object[Symbol.unscopables] = {x: true};
187 assertEquals(2, object.x);
189 runTest(TestBasicsSet);
192 function TestOnProto(object, proto) {
198 Object.setPrototypeOf(object, proto);
207 proto[Symbol.unscopables] = {x: true};
214 object[Symbol.unscopables] = {y: true};
221 proto[Symbol.unscopables] = {y: true};
222 object[Symbol.unscopables] = {x: true};
229 runTest(TestOnProto);
232 function TestSetBlockedOnProto(object, proto) {
240 Object.setPrototypeOf(object, proto);
241 proto[Symbol.unscopables] = {x: true};
249 assertEquals(2, object.x);
251 runTest(TestSetBlockedOnProto);
254 function TestNonObject(object) {
260 object[Symbol.unscopables] = 'xy';
266 object[Symbol.unscopables] = null;
272 runTest(TestNonObject);
275 function TestChangeDuringWith(object) {
284 object[Symbol.unscopables] = {x: true};
289 runTest(TestChangeDuringWith);
292 function TestChangeDuringWithWithPossibleOptimization(object) {
296 for (var i = 0; i < 1000; i++) {
297 if (i === 500) object[Symbol.unscopables] = {x: true};
298 assertEquals(i < 500 ? 2: 1, x);
302 TestChangeDuringWithWithPossibleOptimization({});
305 function TestChangeDuringWithWithPossibleOptimization2(object) {
308 object[Symbol.unscopables] = {x: true};
310 for (var i = 0; i < 1000; i++) {
311 if (i === 500) delete object[Symbol.unscopables];
312 assertEquals(i < 500 ? 1 : 2, x);
316 TestChangeDuringWithWithPossibleOptimization2({});
319 function TestChangeDuringWithWithPossibleOptimization3(object) {
322 object[Symbol.unscopables] = {};
324 for (var i = 0; i < 1000; i++) {
325 if (i === 500) object[Symbol.unscopables].x = true;
326 assertEquals(i < 500 ? 2 : 1, x);
330 TestChangeDuringWithWithPossibleOptimization3({});
333 function TestChangeDuringWithWithPossibleOptimization4(object) {
336 object[Symbol.unscopables] = {x: true};
338 for (var i = 0; i < 1000; i++) {
339 if (i === 500) delete object[Symbol.unscopables].x;
340 assertEquals(i < 500 ? 1 : 2, x);
344 TestChangeDuringWithWithPossibleOptimization4({});
347 function TestAccessorReceiver(object, proto) {
350 Object.defineProperty(proto, 'x', {
352 assertEquals(object, this);
359 Object.setPrototypeOf(object, proto);
363 assertEquals('object', x);
366 runTest(TestAccessorReceiver);
369 function TestUnscopablesGetter(object) {
370 // This test gets really messy when object is the global since the assert
371 // functions are properties on the global object and the call count gets
372 // completely different.
373 if (object === global) return;
379 Object.defineProperty(object, Symbol.unscopables, {
387 assertEquals('object', x);
389 // Once for HasBinding
390 assertEquals(1, callCount);
393 Object.defineProperty(object, Symbol.unscopables, {
401 assertEquals('local', x);
403 // Once for HasBinding
404 assertEquals(1, callCount);
407 Object.defineProperty(object, Symbol.unscopables, {
410 return callCount == 1 ? {} : {x: true};
417 // Once for HasBinding
418 assertEquals(1, callCount);
419 assertEquals(1, object.x);
420 assertEquals('local', x);
424 // One more HasBinding.
425 assertEquals(2, callCount);
426 assertEquals(1, object.x);
429 runTest(TestUnscopablesGetter);
433 function TestUnscopablesGetter2() {
436 var globalProto = Object.getPrototypeOf(global);
437 var protos = [{}, [], function() {}, global];
438 var objects = [{}, [], function() {}];
440 protos.forEach(function(proto) {
441 objects.forEach(function(object) {
442 Object.defineProperty(proto, 'x', {
444 assertEquals(object, this);
450 object.__proto__ = proto;
451 Object.defineProperty(object, 'x', {
453 assertEquals(object, this);
460 assertEquals('object', x);
463 object[Symbol.unscopables] = {x: true};
465 assertEquals('local', x);
468 delete proto[Symbol.unscopables];
469 delete object[Symbol.unscopables];
474 Object.setPrototypeOf(global, globalProto);
476 TestUnscopablesGetter2();
479 function TestSetterOnBlacklisted(object, proto) {
481 Object.defineProperty(proto, 'x', {
490 Object.setPrototypeOf(object, proto);
491 Object.defineProperty(object, 'x', {
507 assertEquals(2, object.x);
509 object[Symbol.unscopables] = {x: true};
516 assertEquals(2, object.x);
518 runTest(TestSetterOnBlacklisted);
521 function TestObjectsAsUnscopables(object, unscopables) {
527 object[Symbol.unscopables] = unscopables;
531 runTest(TestObjectsAsUnscopables);
534 function TestAccessorOnUnscopables(object) {
546 object[Symbol.unscopables] = unscopables;
550 runTest(TestAccessorOnUnscopables);
553 function TestLengthUnscopables(object, proto) {
556 assertEquals(1, length);
557 object[Symbol.unscopables] = {length: true};
558 assertEquals(2, length);
559 delete object[Symbol.unscopables];
560 assertEquals(1, length);
563 TestLengthUnscopables([1], Array.prototype);
564 TestLengthUnscopables(function(x) {}, Function.prototype);
565 TestLengthUnscopables(new String('x'), String.prototype);
568 function TestFunctionNameUnscopables(object) {
571 assertEquals('f', name);
572 object[Symbol.unscopables] = {name: true};
573 assertEquals('local', name);
574 delete object[Symbol.unscopables];
575 assertEquals('f', name);
578 TestFunctionNameUnscopables(function f() {});
581 function TestFunctionPrototypeUnscopables() {
582 var prototype = 'local';
583 var f = function() {};
584 var g = function() {};
585 Object.setPrototypeOf(f, g);
586 var fp = f.prototype;
587 var gp = g.prototype;
589 assertEquals(fp, prototype);
590 f[Symbol.unscopables] = {prototype: true};
591 assertEquals('local', prototype);
592 delete f[Symbol.unscopables];
593 assertEquals(fp, prototype);
596 TestFunctionPrototypeUnscopables(function() {});
599 function TestFunctionArgumentsUnscopables() {
600 var func = function() {
601 var arguments = 'local';
602 var args = func.arguments;
604 assertEquals(args, arguments);
605 func[Symbol.unscopables] = {arguments: true};
606 assertEquals('local', arguments);
607 delete func[Symbol.unscopables];
608 assertEquals(args, arguments);
613 TestFunctionArgumentsUnscopables();
616 function TestArgumentsLengthUnscopables() {
617 var func = function() {
618 var length = 'local';
620 assertEquals(1, length);
621 arguments[Symbol.unscopables] = {length: true};
622 assertEquals('local', length);
627 TestArgumentsLengthUnscopables();
630 function TestFunctionCallerUnscopables() {
631 var func = function() {
632 var caller = 'local';
634 assertEquals(TestFunctionCallerUnscopables, caller);
635 func[Symbol.unscopables] = {caller: true};
636 assertEquals('local', caller);
637 delete func[Symbol.unscopables];
638 assertEquals(TestFunctionCallerUnscopables, caller);
643 TestFunctionCallerUnscopables();
646 function TestGetUnscopablesGetterThrows() {
652 function CustomError() {}
653 Object.defineProperty(object, Symbol.unscopables, {
655 throw new CustomError();
658 assertThrows(function() {
664 TestGetUnscopablesGetterThrows();