blob: bcba84700e42e94ecc1fd6253fe5bf66b302f0ad [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// 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));
});