| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| |
| var echo = WScript.Echo; |
| |
| function guarded_call(func) { |
| try { |
| func(); |
| } catch (e) { |
| echo(e.name + " : " + e.message); |
| } |
| } |
| |
| var testCount = 0; |
| function scenario(title, func) { |
| if (testCount > 0) { |
| echo("\n"); |
| } |
| echo((testCount++) + ".", title); |
| guarded_call(func); |
| } |
| |
| function dumpProp(obj, name) { |
| var desc = Object.getOwnPropertyDescriptor(obj, name); |
| var s = " " + name + ": " + obj[name]; |
| if (desc) { |
| if (desc.enumerable) { s += " enumerable"; } |
| if (desc.configurable) { s += " configurable"; } |
| if (desc.writable) { s += " writable"; } |
| if (desc.getter) { s += " getter"; } |
| if (desc.setter) { s += " setter"; } |
| } |
| echo(s); |
| } |
| |
| scenario("[[Value]] absent, set enumerable: true", function () { |
| var o = []; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { enumerable: true }); |
| }); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] absent, set configurable: true", function () { |
| var o = []; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { configurable: true }); |
| }); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] absent, empty descriptor", function () { |
| var o = []; |
| Object.defineProperty(o, "length", {}); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] absent, no change", function () { |
| var o = []; |
| Object.defineProperty(o, "length", { enumerable: false, configurable: false }); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] absent, set writable: true", function () { |
| var o = []; |
| Object.defineProperty(o, "length", { writable: true }); |
| dumpProp(o, "length"); |
| o.length = 10; |
| echo(" length:", o.length); |
| }); |
| |
| scenario("[[Value]] absent, set writable: false", function () { |
| var o = []; |
| Object.defineProperty(o, "length", { writable: false }); |
| dumpProp(o, "length"); |
| o.length = 10; |
| echo(" length:", o.length); |
| }); |
| |
| scenario("[[Value]] absent, set multiple -- configurable: false, writable: false", function () { |
| var o = []; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { configurable: false, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] absent, set multiple -- enumerable: false, writable: false", function () { |
| var o = []; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { enumerable: false, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("[[Value]] invalid 1", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: Infinity }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("[[Value]] invalid 2", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: -3 }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set enumerable: true", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 5, enumerable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set enumerable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, enumerable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set configurable: true", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 5, configurable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set configurable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, configurable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set configurable: false, enumerable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, configurable: false, enumerable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set configurable: false, enumerable: true", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, configurable: false, enumerable: true }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set writable: true", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, writable: true }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| o.length = 10; |
| echo(" ", o); |
| }); |
| |
| scenario("newLen >= oldLen, set writable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 5, writable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| o.length = 10; |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, oldLen writable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { writable: false }); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, writable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| o.length = 10; |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set enumerable: true", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, enumerable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set configurable: true", function () { |
| var o = [0, 1, 2]; |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, configurable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set writable: true", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 2, writable: true }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| o.length = 10; |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set writable: false", function () { |
| var o = [0, 1, 2]; |
| Object.defineProperty(o, "length", { value: 2, writable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| o.length = 10; |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set writable: true, an element can't delete", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, 3, { configurable: false }); |
| dumpProp(o, 3); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, writable: true }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, set writable: false, an element can't delete", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, 3, { configurable: false }); |
| dumpProp(o, 3); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, an accessor can't delete", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, 3, { get: function(){ return "get 3"}, configurable: false }); |
| dumpProp(o, 3); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 2, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, an element can't delete, newLen == it", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, 3, { configurable: false }); |
| dumpProp(o, 3); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 3, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, an element can't delete, but newLen beyond it", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, 3, { configurable: false }); |
| dumpProp(o, 3); |
| |
| Object.defineProperty(o, "length", { value: 4, writable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, many attributes", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 2) { |
| Object.defineProperty(o, i, { value: i, configurable: true }); |
| } else { |
| var getValue = "get" + i; |
| Object.defineProperty(o, i, { get: function () { return getValue; }, configurable: true }); |
| } |
| dumpProp(o, i); |
| } |
| echo(" ", o); |
| |
| Object.defineProperty(o, "length", { value: 4, writable: false }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| for (var i = 0; i < 10; i++) { |
| dumpProp(o, i); |
| } |
| }); |
| |
| scenario("newLen < oldLen, many attributes, one cannot delete", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 2) { |
| var b = (i !== 5); |
| Object.defineProperty(o, i, { value: i, configurable: b }); |
| } else { |
| var getValue = "get" + i; |
| Object.defineProperty(o, i, { get: function () { return getValue; }, configurable: true }); |
| } |
| dumpProp(o, i); |
| } |
| echo(" ", o); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 4, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| for (var i = 0; i < 10; i++) { |
| dumpProp(o, i); |
| } |
| }); |
| |
| scenario("newLen < oldLen, many attributes, data item cannot delete", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 2) { |
| Object.defineProperty(o, i, { value: i, configurable: true }); |
| } else { |
| var getValue = "get" + i; |
| Object.defineProperty(o, i, { get: function () { return getValue; }, configurable: true }); |
| } |
| } |
| // append some data item not in attribute map |
| for (var i = 10; i < 15; i++) { |
| o[i] = i; |
| } |
| Object.seal(o); |
| echo(" ", o); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 4, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, a few attributes, one cannot delete", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 5) { |
| o[i] = i; |
| } else { |
| Object.defineProperty(o, i, { value: i, configurable: false }); |
| } |
| } |
| echo(" ", o); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 3, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("newLen < oldLen, no attributes, data item cannot delete", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| o[i] = i; |
| } |
| Object.seal(o); |
| echo(" ", o); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, "length", { value: 3, writable: false }); |
| }); |
| dumpProp(o, "length"); |
| echo(" ", o); |
| }); |
| |
| scenario("[[Put]] length: newLen < oldLen, many attributes", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 2) { |
| Object.defineProperty(o, i, { value: i, configurable: true }); |
| } else { |
| var getValue = "get" + i; |
| Object.defineProperty(o, i, { get: function () { return getValue; }, configurable: true }); |
| } |
| dumpProp(o, i); |
| } |
| echo(" ", o); |
| |
| o.length = 4; |
| dumpProp(o, "length"); |
| echo(" ", o); |
| for (var i = 0; i < 10; i++) { |
| dumpProp(o, i); |
| } |
| }); |
| |
| scenario("[[Put]] length: newLen < oldLen, many attributes, one cannot delete", function () { |
| var o = []; |
| for (var i = 0; i < 10; i++) { |
| if (i % 2) { |
| var b = (i !== 5); |
| Object.defineProperty(o, i, { value: i, configurable: b }); |
| } else { |
| var getValue = "get" + i; |
| Object.defineProperty(o, i, { get: function () { return getValue; }, configurable: true }); |
| } |
| dumpProp(o, i); |
| } |
| echo(" ", o); |
| |
| o.length = 4; // This would throw in strict mode |
| dumpProp(o, "length"); |
| echo(" ", o); |
| for (var i = 0; i < 10; i++) { |
| dumpProp(o, i); |
| } |
| }); |
| |
| scenario("Add item beyond non-writable length", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, "length", { writable: false }); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, 9, { value: 9, enumerable: true, configurable: true, writable: false }); |
| }); |
| echo(" ", o); |
| }); |
| |
| scenario("Add accessor beyond non-writable length", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, "length", { writable: false }); |
| |
| guarded_call(function () { |
| Object.defineProperty(o, 9, { get: function () { return "get9"; }, configurable: true }); |
| }); |
| echo(" ", o); |
| }); |
| |
| scenario("SetItem beyond non-writable length", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, "length", { writable: false }); |
| |
| o[9] = 9; // This would throw in strict mode |
| echo(" ", o); |
| }); |
| |
| scenario("SetItem with name beyond non-writable length", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.defineProperty(o, "length", { writable: false }); |
| |
| var name = "9"; |
| o[name] = 9; // This would throw in strict mode |
| echo(" ", o); |
| }); |
| |
| scenario("freeze should set length writable: false", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| Object.freeze(o); |
| dumpProp(o, "length"); |
| }); |
| |
| scenario("isFrozen should check length writable", function () { |
| var o = [0, 1, 2, 3, 4, 5]; |
| for (var i = 0; i < o.length; i++) { |
| Object.defineProperty(o, i, { writable: false, configurable: false }); |
| } |
| Object.preventExtensions(o); |
| echo("isFrozen:", Object.isFrozen(o)); // false, because length writable |
| |
| Object.defineProperty(o, "length", { writable: false }); |
| echo("isFrozen:", Object.isFrozen(o)); |
| }); |
| |