| Index: test/mjsunit/harmony/unscopables.js
|
| diff --git a/test/mjsunit/harmony/unscopables.js b/test/mjsunit/harmony/unscopables.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..da24601b7b5f9d852ea5637baadc58c585716c82
|
| --- /dev/null
|
| +++ b/test/mjsunit/harmony/unscopables.js
|
| @@ -0,0 +1,614 @@
|
| +// Copyright 2014 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// Flags: --harmony-unscopables
|
| +// Flags: --harmony-collections
|
| +
|
| +var global = this;
|
| +var globalProto = Object.getPrototypeOf(global);
|
| +
|
| +// Number of objects being tested. There is an assert ensuring this is correct.
|
| +var objectCount = 21;
|
| +
|
| +
|
| +function runTest(f) {
|
| + function restore(object, oldProto) {
|
| + Object.setPrototypeOf(object, oldProto);
|
| + delete object[Symbol.unscopables];
|
| + delete object.x;
|
| + delete object.x_;
|
| + delete object.y;
|
| + delete object.z;
|
| + }
|
| +
|
| + function getObject(i) {
|
| + var objects = [
|
| + {},
|
| + [],
|
| + function() {},
|
| + function() {
|
| + return arguments;
|
| + }(),
|
| + function() {
|
| + 'use strict';
|
| + return arguments;
|
| + }(),
|
| + Object(1),
|
| + Object(true),
|
| + Object('bla'),
|
| + new Date,
|
| + new RegExp,
|
| + new Set,
|
| + new Map,
|
| + new WeakMap,
|
| + new WeakSet,
|
| + new ArrayBuffer(10),
|
| + new Int32Array(5),
|
| + Object,
|
| + Function,
|
| + Date,
|
| + RegExp,
|
| + global
|
| + ];
|
| +
|
| + assertEquals(objectCount, objects.length);
|
| + return objects[i];
|
| + }
|
| +
|
| + if (f.length === 1) {
|
| + for (var i = 0; i < objectCount; i++) {
|
| + var object = getObject(i);
|
| + var oldObjectProto = Object.getPrototypeOf(object);
|
| + f(object);
|
| + restore(object, oldObjectProto);
|
| + }
|
| + } else {
|
| + for (var i = 0; i < objectCount; i++) {
|
| + for (var j = 0; j < objectCount; j++) {
|
| + var object = getObject(i);
|
| + var proto = getObject(j);
|
| + if (object === proto) {
|
| + continue;
|
| + }
|
| + var oldObjectProto = Object.getPrototypeOf(object);
|
| + var oldProtoProto = Object.getPrototypeOf(proto);
|
| + f(object, proto);
|
| + restore(object, oldObjectProto);
|
| + restore(proto, oldProtoProto);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +function TestBasics(object) {
|
| + var x = 1;
|
| + var y = 2;
|
| + var z = 3;
|
| + object.x = 4;
|
| + object.y = 5;
|
| +
|
| + with (object) {
|
| + assertEquals(4, x);
|
| + assertEquals(5, y);
|
| + assertEquals(3, z);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + assertEquals(1, x);
|
| + assertEquals(5, y);
|
| + assertEquals(3, z);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = {x: 0, y: true};
|
| + with (object) {
|
| + assertEquals(1, x);
|
| + assertEquals(2, y);
|
| + assertEquals(3, z);
|
| + }
|
| +}
|
| +runTest(TestBasics);
|
| +
|
| +
|
| +function TestBasicsSet(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| +
|
| + with (object) {
|
| + assertEquals(2, x);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + assertEquals(1, x);
|
| + x = 3;
|
| + assertEquals(3, x);
|
| + }
|
| +
|
| + assertEquals(3, x);
|
| + assertEquals(2, object.x);
|
| +}
|
| +runTest(TestBasicsSet);
|
| +
|
| +
|
| +function TestOnProto(object, proto) {
|
| + var x = 1;
|
| + var y = 2;
|
| + var z = 3;
|
| + proto.x = 4;
|
| +
|
| + Object.setPrototypeOf(object, proto);
|
| + object.y = 5;
|
| +
|
| + with (object) {
|
| + assertEquals(4, x);
|
| + assertEquals(5, y);
|
| + assertEquals(3, z);
|
| + }
|
| +
|
| + proto[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + assertEquals(1, x);
|
| + assertEquals(5, y);
|
| + assertEquals(3, z);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = {y: true};
|
| + with (object) {
|
| + assertEquals(1, x);
|
| + assertEquals(2, y);
|
| + assertEquals(3, z);
|
| + }
|
| +
|
| + proto[Symbol.unscopables] = {y: true};
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + assertEquals(4, x);
|
| + assertEquals(5, y);
|
| + assertEquals(3, z);
|
| + }
|
| +}
|
| +runTest(TestOnProto);
|
| +
|
| +
|
| +function TestNonObject(object) {
|
| + var x = 1;
|
| + var y = 2;
|
| + object.x = 3;
|
| + object.y = 4;
|
| +
|
| + object[Symbol.unscopables] = 'xy';
|
| + with (object) {
|
| + assertEquals(3, x);
|
| + assertEquals(4, y);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = null;
|
| + with (object) {
|
| + assertEquals(3, x);
|
| + assertEquals(4, y);
|
| + }
|
| +}
|
| +runTest(TestNonObject);
|
| +
|
| +
|
| +function TestChangeDuringWith(object) {
|
| + var x = 1;
|
| + var y = 2;
|
| + object.x = 3;
|
| + object.y = 4;
|
| +
|
| + with (object) {
|
| + assertEquals(3, x);
|
| + assertEquals(4, y);
|
| + object[Symbol.unscopables] = {x: true};
|
| + assertEquals(1, x);
|
| + assertEquals(4, y);
|
| + }
|
| +}
|
| +runTest(TestChangeDuringWith);
|
| +
|
| +
|
| +function TestChangeDuringWithWithPossibleOptimization(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| + with (object) {
|
| + for (var i = 0; i < 1000; i++) {
|
| + if (i === 500) object[Symbol.unscopables] = {x: true};
|
| + assertEquals(i < 500 ? 2: 1, x);
|
| + }
|
| + }
|
| +}
|
| +TestChangeDuringWithWithPossibleOptimization({});
|
| +
|
| +
|
| +function TestChangeDuringWithWithPossibleOptimization2(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + for (var i = 0; i < 1000; i++) {
|
| + if (i === 500) delete object[Symbol.unscopables];
|
| + assertEquals(i < 500 ? 1 : 2, x);
|
| + }
|
| + }
|
| +}
|
| +TestChangeDuringWithWithPossibleOptimization2({});
|
| +
|
| +
|
| +function TestChangeDuringWithWithPossibleOptimization3(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| + object[Symbol.unscopables] = {};
|
| + with (object) {
|
| + for (var i = 0; i < 1000; i++) {
|
| + if (i === 500) object[Symbol.unscopables].x = true;
|
| + assertEquals(i < 500 ? 2 : 1, x);
|
| + }
|
| + }
|
| +}
|
| +TestChangeDuringWithWithPossibleOptimization3({});
|
| +
|
| +
|
| +function TestChangeDuringWithWithPossibleOptimization4(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + for (var i = 0; i < 1000; i++) {
|
| + if (i === 500) delete object[Symbol.unscopables].x;
|
| + assertEquals(i < 500 ? 1 : 2, x);
|
| + }
|
| + }
|
| +}
|
| +TestChangeDuringWithWithPossibleOptimization4({});
|
| +
|
| +
|
| +(function TestGlobal() {
|
| + global.values = 'global.values';
|
| + Array.prototype.values = 'Array.prototype.values';
|
| + Array.prototype[Symbol.unscopables] = {values: true};
|
| + Array.prototype.__proto__ = {values: 42};
|
| + var array = [];
|
| + with (array) {
|
| + assertEquals(42, values);
|
| + }
|
| +})();
|
| +
|
| +
|
| +function TestAccessorReceiver(object, proto) {
|
| + var x = 'local';
|
| +
|
| + Object.defineProperty(proto, 'x', {
|
| + get: function() {
|
| + assertEquals(object, this);
|
| + return this.x_;
|
| + },
|
| + configurable: true
|
| + });
|
| + proto.x_ = 'proto';
|
| +
|
| + Object.setPrototypeOf(object, proto);
|
| + proto.x_ = 'object';
|
| +
|
| + with (object) {
|
| + assertEquals('object', x);
|
| + }
|
| +}
|
| +runTest(TestAccessorReceiver);
|
| +
|
| +
|
| +function TestUnscopablesGetter(object) {
|
| + // This test gets really messy when object is the global since the assert
|
| + // functions are properties on the global object and the call count gets
|
| + // completely different.
|
| + if (object === global) return;
|
| +
|
| + var x = 'local';
|
| + object.x = 'object';
|
| +
|
| + var callCount = 0;
|
| + Object.defineProperty(object, Symbol.unscopables, {
|
| + get: function() {
|
| + callCount++;
|
| + return {};
|
| + },
|
| + configurable: true
|
| + });
|
| + with (object) {
|
| + assertEquals('object', x);
|
| + }
|
| + // Once for HasBinding and once for GetBindingValue
|
| + assertEquals(2, callCount);
|
| +
|
| + callCount = 0;
|
| + Object.defineProperty(object, Symbol.unscopables, {
|
| + get: function() {
|
| + callCount++;
|
| + return {x: true};
|
| + },
|
| + configurable: true
|
| + });
|
| + with (object) {
|
| + assertEquals('local', x);
|
| + }
|
| + // Once for HasBinding
|
| + assertEquals(1, callCount);
|
| +
|
| + callCount = 0;
|
| + Object.defineProperty(object, Symbol.unscopables, {
|
| + get: function() {
|
| + callCount++;
|
| + return callCount === 1 ? {} : {x: true};
|
| + },
|
| + configurable: true
|
| + });
|
| + with (object) {
|
| + assertEquals(void 0, x);
|
| + }
|
| + // Once for HasBinding, once for GetBindingValue.
|
| + assertEquals(2, callCount);
|
| +
|
| + callCount = 0;
|
| + Object.defineProperty(object, Symbol.unscopables, {
|
| + get: function() {
|
| + callCount++;
|
| + return callCount === 1 ? {} : {x: true};
|
| + },
|
| + configurable: true
|
| + });
|
| + with (object) {
|
| + x = 1;
|
| + }
|
| + // Once for HasBinding
|
| + assertEquals(1, callCount);
|
| + assertEquals(1, object.x);
|
| + assertEquals('local', x);
|
| + with (object) {
|
| + x = 2;
|
| + }
|
| + // One more HasBinding.
|
| + assertEquals(2, callCount);
|
| + assertEquals(1, object.x);
|
| + assertEquals(2, x);
|
| +}
|
| +runTest(TestUnscopablesGetter);
|
| +
|
| +
|
| +var global = this;
|
| +(function TestUnscopablesGetter2() {
|
| + var x = 'local';
|
| +
|
| + var protos = [{}, [], function() {}, global];
|
| + var objects = [{}, [], function() {}];
|
| +
|
| + protos.forEach(function(proto) {
|
| + objects.forEach(function(object) {
|
| + Object.defineProperty(proto, 'x', {
|
| + get: function() {
|
| + assertEquals(object, this);
|
| + return 'proto';
|
| + },
|
| + configurable: true
|
| + });
|
| +
|
| + object.__proto__ = proto;
|
| + Object.defineProperty(object, 'x', {
|
| + get: function() {
|
| + assertEquals(object, this);
|
| + return 'object';
|
| + },
|
| + configurable: true
|
| + });
|
| +
|
| + with (object) {
|
| + assertEquals('object', x);
|
| + }
|
| +
|
| + object[Symbol.unscopables] = {x: true};
|
| + with (object) {
|
| + assertEquals('proto', x);
|
| + }
|
| +
|
| + delete proto[Symbol.unscopables];
|
| + delete object[Symbol.unscopables];
|
| + });
|
| + });
|
| +})();
|
| +
|
| +
|
| +function TestSetterOnBlacklisted(object, proto) {
|
| + Object.defineProperty(proto, 'x', {
|
| + set: function(x) {
|
| + assertUnreachable();
|
| + },
|
| + get: function() {
|
| + return 'proto';
|
| + },
|
| + configurable: true
|
| + });
|
| + Object.setPrototypeOf(object, proto);
|
| + Object.defineProperty(object, 'x', {
|
| + get: function() {
|
| + return this.x_;
|
| + },
|
| + set: function(x) {
|
| + this.x_ = x;
|
| + },
|
| + configurable: true
|
| + });
|
| + object.x_ = 1;
|
| +
|
| + with (object) {
|
| + x = 2;
|
| + assertEquals(2, x);
|
| + }
|
| +
|
| + assertEquals(2, object.x);
|
| +
|
| + object[Symbol.unscopables] = {x: true};
|
| +
|
| + with (object) {
|
| + x = 3;
|
| + assertEquals('proto', x);
|
| + }
|
| +
|
| + assertEquals(3, object.x);
|
| +}
|
| +runTest(TestSetterOnBlacklisted);
|
| +
|
| +
|
| +function TestObjectsAsUnscopables(object, unscopables) {
|
| + var x = 1;
|
| + object.x = 2;
|
| +
|
| + with (object) {
|
| + assertEquals(2, x);
|
| + object[Symbol.unscopables] = unscopables;
|
| + assertEquals(2, x);
|
| + }
|
| +}
|
| +runTest(TestAccessorOnUnscopables);
|
| +
|
| +
|
| +function TestAccessorOnUnscopables(object) {
|
| + var x = 1;
|
| + object.x = 2;
|
| +
|
| + var unscopables = {
|
| + get x() {
|
| + assertUnreachable();
|
| + }
|
| + };
|
| +
|
| + with (object) {
|
| + assertEquals(2, x);
|
| + object[Symbol.unscopables] = unscopables;
|
| + assertEquals(1, x);
|
| + }
|
| +}
|
| +runTest(TestAccessorOnUnscopables);
|
| +
|
| +
|
| +function TestLengthUnscopables(object, proto) {
|
| + var length = 2;
|
| + with (object) {
|
| + assertEquals(1, length);
|
| + object[Symbol.unscopables] = {length: true};
|
| + assertEquals(0, length); // From prototype
|
| + proto[Symbol.unscopables] = {length: true};
|
| + assertEquals(2, length);
|
| + delete proto[Symbol.unscopables];
|
| + assertEquals(0, length); // From prototype
|
| + }
|
| +}
|
| +TestLengthUnscopables([1], Array.prototype);
|
| +TestLengthUnscopables(function(x) {}, Function.prototype);
|
| +TestLengthUnscopables(new String('x'), String.prototype);
|
| +
|
| +
|
| +function TestFunctionNameUnscopables(object) {
|
| + var name = 'local';
|
| + with (object) {
|
| + assertEquals('f', name);
|
| + object[Symbol.unscopables] = {name: true};
|
| + assertEquals('Empty', name); // From prototype
|
| + Object.getPrototypeOf(object)[Symbol.unscopables] = {name: true};
|
| + assertEquals('local', name);
|
| + delete Object.getPrototypeOf(object)[Symbol.unscopables];
|
| + assertEquals('Empty', name); // From prototype
|
| + }
|
| +}
|
| +TestFunctionNameUnscopables(function f() {});
|
| +
|
| +
|
| +function TestFunctionPrototypeUnscopables() {
|
| + var prototype = 'local';
|
| + var f = function() {};
|
| + var g = function() {};
|
| + Object.setPrototypeOf(f, g);
|
| + var fp = f.prototype;
|
| + var gp = g.prototype;
|
| + with (f) {
|
| + assertEquals(fp, prototype);
|
| + f[Symbol.unscopables] = {prototype: true};
|
| + assertEquals(gp, prototype);
|
| + g[Symbol.unscopables] = {prototype: true};
|
| + assertEquals('local', prototype);
|
| + }
|
| +}
|
| +TestFunctionPrototypeUnscopables(function() {});
|
| +
|
| +
|
| +function TestFunctionArgumentsUnscopables() {
|
| + var func = function() {
|
| + var arguments = 'local';
|
| + var args = func.arguments;
|
| + with (func) {
|
| + assertEquals(args, arguments);
|
| + func[Symbol.unscopables] = {arguments: true};
|
| + assertEquals(null, arguments); // From prototype
|
| + Function.prototype[Symbol.unscopables] = {arguments: true};
|
| + assertEquals('local', arguments);
|
| + delete Function.prototype[Symbol.unscopables];
|
| + assertEquals(null, arguments); // From prototype
|
| + }
|
| + }
|
| + func(1);
|
| +}
|
| +TestFunctionArgumentsUnscopables();
|
| +
|
| +
|
| +function TestArgumentsLengthUnscopables() {
|
| + var func = function() {
|
| + var length = 'local';
|
| + with (arguments) {
|
| + assertEquals(1, length);
|
| + arguments[Symbol.unscopables] = {length: true};
|
| + assertEquals('local', length);
|
| + }
|
| + }
|
| + func(1);
|
| +}
|
| +TestArgumentsLengthUnscopables();
|
| +
|
| +
|
| +function TestFunctionCallerUnscopables() {
|
| + var func = function() {
|
| + var caller = 'local';
|
| + with (func) {
|
| + assertEquals(TestFunctionCallerUnscopables, caller);
|
| + func[Symbol.unscopables] = {caller: true};
|
| + assertEquals(null, caller); // From prototype
|
| + Function.prototype[Symbol.unscopables] = {caller: true};
|
| + assertEquals('local', caller);
|
| + delete Function.prototype[Symbol.unscopables];
|
| + assertEquals(null, caller); // From prototype
|
| + }
|
| + }
|
| + func(1);
|
| +}
|
| +TestFunctionCallerUnscopables();
|
| +
|
| +
|
| +function TestGetUnscopablesGetterThrows() {
|
| + var object = {
|
| + get x() {
|
| + assertUnreachable();
|
| + }
|
| + };
|
| + function CustomError() {}
|
| + Object.defineProperty(object, Symbol.unscopables, {
|
| + get: function() {
|
| + throw new CustomError();
|
| + }
|
| + });
|
| + assertThrows(function() {
|
| + with (object) {
|
| + x;
|
| + }
|
| + }, CustomError);
|
| +}
|
| +TestGetUnscopablesGetterThrows();
|
|
|