| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- if (typeof(WScript) != "undefined") {
- WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
- }
- var tests = {
- // Note: each test has name (string) and body (function) properties.
- // Success is when the body does not throw, failure -- when it throws.
- test01: {
- name: "formal arg: simple: verify connection: named vs indexed arg",
- body: function () {
- var passedValue = 1;
- function f(a) {
- var val1 = 2;
- a = val1;
- assert.areEqual(val1, a, "wrong value of named parameter (val1)");
- assert.areEqual(val1, arguments[0], "wrong value of indexed parameter (val1)");
- var val2 = 3;
- arguments[0] = val2;
- assert.areEqual(val2, arguments[0], "wrong value of indexed parameter (val2)");
- assert.areEqual(val2, a, "wrong value of named parameter (val2)");
- }
- f(passedValue);
- }
- },
- test02: {
- name: "formal arg: defineProperty, check property descriptor",
- body: function () {
- var passedValue = 1;
- function f(a) {
- var val = 2;
- Object.defineProperty(arguments, 0, { configurable: false, enumerable: false, value: val });
- // Note that we expect writable: true because this was omitted in defineProperty above
- // which is acually re-define property with all attributes == true.
- var expected = { configurable: false, enumerable: false, writable: true, value: val };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0), "wrong value of getOwnPropertyDescriptor");
- assert.areEqual(val, a, "wrong value of named parameter");
- }
- f(passedValue);
- }
- },
- test03: {
- name: "formal arg: defineProperty, set writable to false, verify writability and lost connection. WOOB 1128023",
- body: function () {
- var passedValue = 1;
- function f(a) {
- Object.defineProperty(arguments, 0, { writable: false });
- var expected = { configurable: true, enumerable: true, writable: false, value: passedValue };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0), "wrong value of getOwnPropertyDescriptor");
- // Attempt to change arguments[0] which is not writable now.
- var val1 = 2;
- arguments[0] = val1;
- assert.areEqual(passedValue, arguments[0], "non-writable changed");
- assert.areEqual(passedValue, a, "non-writable changed: named arg also changed");
- // Change named arg value, verify we are in connection named vs indexed arg.
- var val2 = 3;
- a = val2;
- assert.areEqual(val2, a, "Attemp to change named arg: didn't work");
- assert.areEqual(passedValue, arguments[0], "At this time we should not be connected, but we are");
- }
- f(passedValue);
- }
- },
- test04: {
- name: "formal arg: defineProperty, set writable to false AND set value, verify that value changed in both named and indexed arg and that the item was disconnected",
- body: function () {
- var passedValue = 1;
- function f(a) {
- var val1 = 2;
- var val2 = 3;
- Object.defineProperty(arguments, 0, { writable: false, value: val1 });
- var expected = { configurable: true, enumerable: true, writable: false, value: val1 };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0), "wrong value of getOwnPropertyDescriptor");
- assert.areEqual(val1, arguments[0], "value: arguments[0]");
- assert.areEqual(val1, a, "value: a");
- // Verify we are disconnected now.
- a = val2;
- assert.areEqual(val2, a, "new value: a");
- assert.areEqual(val1, arguments[0], "value: arguments[0] -- did not get disconnected!");
- }
- f(passedValue);
- }
- },
- test05: {
- name: "formal arg: defineProperty w/o cause of disconnect, verify still connected to named arg",
- body: function () {
- var passedValue = 1;
- var val1 = 2;
- var val2 = 3;
- function f(a) {
- Object.defineProperty(arguments, 0, { value: val1 });
- a = val1;
- assert.areEqual(val1, arguments[0], "arguments[0] got disconnected");
- arguments[0] = val2;
- assert.areEqual(val2, a, "a got disconnected");
- }
- f(passedValue);
- }
- },
- test06: {
- name: "formal arg: defineProperty, disconnect arg[0], verify that arg[1] is still connected",
- body: function () {
- function f(a, b) {
- Object.defineProperty(arguments, 0, { writable: false });
- var val1 = 3;
- var val2 = 4;
- arguments[1] = val1;
- assert.areEqual(val1, b, "arg[1] got disconnected");
- b = val2;
- assert.areEqual(val2, arguments[1], "arg[1] got disconnected");
- }
- f(1, 2);
- }
- },
- test07: {
- name: "formal arg: defineProperty: convert to accessor property",
- body: function () {
- function f(a) {
- var isGetterFired = false;
- var isSetterFired = false;
- Object.defineProperty(arguments, 0, {
- get: function() { isGetterFired = true; return this.value; },
- set: function(arg) { isSetterFired = true; this.value = arg; }
- });
- assert.areEqual(undefined, arguments[0], "unexpected arg[0] value right after conversion to accessor property");
- assert.areEqual(true, isGetterFired, "isGetterFired (1)");
- isGetterFired = false;
- var val1 = 2;
- arguments[0] = val1;
- assert.areEqual(true, isSetterFired, "isSetterFired");
- assert.areEqual(val1, arguments[0], "get value after set");
- assert.areEqual(true, isGetterFired, "isGetterFired (2)");
- }
- f(1);
- }
- },
- test08: {
- name: "formal arg: defineProperty: convert to accessor, then to data property, verify value and that connection is lost",
- body: function () {
- var passedValue = 1;
- var val1 = 2;
- var val2 = 3;
- function f(a) {
- Object.defineProperty(arguments, 0, {
- get: function() { return this.value; },
- set: function(arg) { this.value = arg; }
- });
- Object.defineProperty(arguments, 0, { value: val1 });
- a = val2;
- assert.areEqual(arguments[0], val1, "arguments[0]");
- assert.areNotEqual(arguments[0], a, "arguments[0] != a");
- }
- f(passedValue);
- }
- },
- test09: {
- name: "formal arg: defineProperty: force convert to ES5 version but keep connected, check enumeration",
- body: function () {
- var passedValue = 1;
- function f(a) {
- Object.defineProperty(arguments, 0, { enumerable: true });
- var accumulator = "";
- for (var i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual("0: " + passedValue + ";" , accumulator, "accumulator");
- }
- f(passedValue);
- }
- },
- test10: {
- name: "formal arg: defineProperty: set non-enumerable/non-writable/delete, check enumeration",
- body: function () {
- var passedValue1 = 2;
- var passedValue2 = 4;
- function f(a, b, c, d) {
- Object.defineProperty(arguments, 0, { enumerable: false }); // arguments[0].enumerable = false.
- Object.defineProperty(arguments, 1, { writable: false }); // arguments[1].writable = false -> disconnected.
- delete arguments[2]; // arguments[2] is deleted.
- var i, accumulator = "";
- for (i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- // Note that we expect [1].enumerable = true because this was omitted in defineProperty above
- // which is acually re-define property that previously already had enumerable = true.
- assert.areEqual("1: " + passedValue1 + ";" + "3: " + passedValue2 + ";", accumulator, "accumulator");
- }
- f(1, passedValue1, 3, passedValue2);
- }
- },
- test11: {
- name: "passed/undeclared arg: verify there is no correlation with Object.prototype indexed data properties. WOOB 1143896",
- body: function () {
- var passedValue = "passed";
- Object.defineProperty(Object.prototype, 0, { value: "from proto", configurable: true, writable: false });
- try {
- function f() { return arguments; }
- var argObj = f(passedValue);
- assert.areEqual(passedValue, argObj[0]);
- } finally {
- delete Object.prototype[0];
- }
- }
- },
- test12: {
- name: "formal arg: verify there is no correlation with Object.prototype indexed properties",
- body: function () {
- var passedValue = "passed";
- Object.defineProperty(Object.prototype, 0, { value: "from proto", configurable: true, writable: false });
- try {
- function f(a) { return arguments }
- var argObj = f(passedValue);
- assert.areEqual(passedValue, argObj[0]);
- } finally {
- delete Object.prototype[0];
- }
- }
- },
- test13: {
- name: "passed/undeclared arg: verify there is no correlation with Object.prototype indexed accessor properties. WOOB 1144602",
- body: function () {
- var initial = "initial";
- var passedValue = "passed";
- var data = initial;
- Object.defineProperty(Object.prototype, 0, {
- configurable: true,
- get: function() { return data; },
- set: function(arg) { data = arg; }
- });
- try {
- function f() { return arguments; }
- var argObj = f(passedValue);
- assert.areEqual(initial, data, "data: should not be changed as setter on prototype should not be fired");
- assert.areEqual(passedValue, argObj[0], "argObj[0]");
- } finally {
- delete Object.prototype[0];
- }
- }
- },
- test14: {
- name: "formal arg: verify there is no correlation with Object.prototype indexed accessor properties",
- body: function () {
- var initial = "initial";
- var passedValue = "passed";
- var data = initial;
- Object.defineProperty(Object.prototype, 0, {
- configurable: true,
- get: function() { return data; },
- set: function(arg) { data = arg; }
- });
- try {
- function f(a) { return arguments; }
- var argObj = f(passedValue);
- assert.areEqual(initial, data, "data: should not be changed as setter on prototype should not be fired");
- assert.areEqual(passedValue, argObj[0], "argObj[0]");
- } finally {
- delete Object.prototype[0];
- }
- }
- },
- test15: {
- name: "formal arg: delete, make sure it's deleted",
- body: function () {
- var passedValue = 1;
- function f(a) {
- Object.defineProperty(arguments, 0, { enumerable: false }); // Force convert to ES5 version.
- delete arguments[0];
- assert.areEqual(undefined, arguments[0], "was not deleted.");
- assert.areEqual(passedValue, a, "a is changed.");
- }
- f(passedValue);
- }
- },
- test16: {
- name: "formal arg: delete, add, check named arg is not changed",
- body: function () {
- var passedValue = 1;
- function f(a, b) {
- Object.defineProperty(arguments, 0, { enumerable: false }); // Force convert to ES5 version.
- delete arguments[0];
- arguments[0] = passedValue + 1;
- assert.areEqual(passedValue, a, "a is changed.");
- }
- f(passedValue, 2);
- }
- },
- test17: {
- name: "formal arg: delete, then defineProperty with attributes for data property, check the value",
- body: function () {
- var passedValue = 1;
- function f(a) {
- delete arguments[0];
- var val = 2;
- Object.defineProperty(arguments, 0, { enumerable: true, configurable: true, writable: true, value: val });
- assert.areEqual(val, arguments[0], "wrong value");
- }
- f(passedValue);
- }
- },
- test18: {
- name: "formal arg: delete, then defineProperty with attributes for accessor property, check the enumeration",
- body: function () {
- var passedValue = 1;
- var getter = function() {return this.value; };
- var setter = function(arg) { this.value = arg; };
- function f(a) {
- delete arguments[0];
- Object.defineProperty(arguments, 0, { enumerable: true, configurable: true, get: getter, set: setter });
- var expected = { configurable: true, enumerable: true, get: getter, set: setter };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0), "wrong descriptor");
- var accumulator = "";
- for (var i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual("0: " + undefined + ";", accumulator, "accumulator 2");
- }
- f(passedValue);
- }
- },
- test19: {
- name: "formal arg, es5 heap arguments: delete, add, check enumerable/order",
- body: function () {
- var passedValue1 = 1;
- var passedValue2 = 2;
- var newValue1 = 100;
- var newValue2 = 200;
- var i, accumulator;
- function f(a, b) {
- // Scenario 1: delete prior to converting to ES5 version.
- delete arguments[0]; // Delete [0] prior to conversion to ES5.
- Object.defineProperty(arguments, 0, { configurable: true, enumerable: true, value: newValue1 }); // Bring back [0] by defineProperty. Now args is ES5.
- accumulator = "";
- for (i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual("0: " + newValue1 + ";" + "1: " + passedValue2 + ";", accumulator, "accumulator 1");
- // Scenario 2: delete after converting to ES5 version.
- Object.defineProperty(arguments, 0, { configurable: true, enumerable: true, writable: true, value: newValue1 }); // Bring back [0] by defineProperty. Now args is ES5.
- delete arguments[0]; // Delete [0] prior after conversion to ES5.
- arguments[0] = newValue2; // Bring back [0] by setting value.
- accumulator = "";
- for (i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual("0: " + newValue2 + ";" + "1: " + passedValue2 + ";", accumulator, "accumulator 2");
- }
- f(passedValue1, passedValue2);
- }
- },
- test20: {
- name: "formal arg, es5 heap arguments: delete, add, keep another arg in objectArray and use one non-formal, check enumerable/order",
- body: function () {
- var passedValue1 = 1;
- var passedValue2 = 2;
- var passedValue3 = 3;
- var passedValue4 = 4;
- var newValue = 100;
- function f(a, b, c) {
- Object.defineProperty(arguments, 0, { enumerable: true }); // Add objectArray item
- Object.defineProperty(arguments, 2, { enumerable: true }); // Add objectArray item
- var accumulator = "";
- delete arguments[0];
- arguments[0] = newValue;
- for (var i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual(
- "0: " + newValue + ";" + "1: " + passedValue2 + ";" + "2: " + passedValue3 + ";" + "3: " + passedValue4 + ";",
- accumulator,
- "accumulator");
- }
- f(passedValue1, passedValue2, passedValue3, passedValue4);
- }
- },
- test21: {
- name: "formal arg: defineProperty, set enumerable to false, check getOwnPropertyNames",
- body: function (a, b) {
- function f(a) {
- Object.defineProperty(arguments, 0, { enumerable: false });
- // Note: Object.getOwnPropertyNames returns all properties, even non-enumerable.
- var actual = Object.getOwnPropertyNames(arguments);
- var expected = { 0: "0", 1: "1", 2: "length", 3: "callee" };
- assert.areEqual(expected, actual, "wrong property names");
- }
- f(101, 102);
- }
- },
- test22Helper: function test22Helper(isConvertNeeded, messagePrefix) {
- function mkerr(message) {
- return messagePrefix + ": " + message;
- }
- var passedValue = 1;
- var newPropertyName = "x";
- function f(a, b) {
- if (isConvertNeeded) {
- Object.defineProperty(arguments, 1, { enumerable: true }); // Force convert to ES5 version.
- }
- Object.preventExtensions(arguments); // No new properties can be added.
- assert.areEqual(false, Object.isExtensible(arguments), mkerr("isExtensible"));
- try {
- Object.defineProperty(arguments, newPropertyName, { enumerable: true, value: 100 }); // add new property
- assert.fail(mkerr("did not throw exception"));
- } catch (ex) {
- }
- arguments[newPropertyName] = 100;
- assert.areEqual(undefined, arguments[newPropertyName], mkerr("New property was added after preventExtensions was called"));
- }
- f(passedValue, passedValue + 1);
- },
- test22_1: {
- name: "arguments (non-ES5 version): call Object.preventExtensions, try add new property by defineProperty and direct set",
- body: function () {
- tests.test22Helper(false, "non-ES5 version");
- }
- },
- test22_2: {
- name: "arguments (ES5 version): call Object.preventExtensions, try add new property by defineProperty and direct set",
- body: function () {
- tests.test22Helper(true, "ES5 version");
- }
- },
- test23Helper: function test23Helper(isConvertNeeded, messagePrefix) {
- function mkerr(message) {
- return messagePrefix + ": " + message;
- }
- var passedValue = 1;
- function f(a, b) {
- if (isConvertNeeded) {
- Object.defineProperty(arguments, 1, { enumerable: true }); // Force convert to ES5 version.
- }
- Object.preventExtensions(arguments); // This causes configurable, writable = false for all properties + Object.preventExtensions.
- // Note: formals existed prior to calling Object.preventExtensions, thus they are still modifiable.
- assert.areEqual(false, Object.isExtensible(arguments), "isExtensible");
- var actual = Object.getOwnPropertyDescriptor(arguments, 0);
- var expected = { configurable: true, enumerable: true, writable: true, value: passedValue };
- assert.areEqual(expected, actual, mkerr("wrong descriptor - initial"));
- // Try to modify/re-configure
- // Note: do not change value here as it causes different code path than excersized by identified issue.
- Object.defineProperty(arguments, 0, { enumerable: false });
- Object.defineProperty(arguments, 0, { writable: false });
- Object.defineProperty(arguments, 0, { configurable: false });
- var expected = { configurable: false, enumerable: false, writable: false, value: passedValue };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0), mkerr("wrong descriptor - after redefine"));
- }
- f(passedValue, passedValue + 1);
- },
- // After Object.preventExtensions(arguments) we can't modify the attributes on formals.
- test23_1: {
- name: "arguments (non-ES5 version): call Object.preventExtensions, make sure we can still modify atttibutes on formals without changing the value",
- body: function () {
- tests.test23Helper(false, "non-ES5 version");
- }
- },
- // After Object.preventExtensions(arguments) we can't modify the attributes on formals.
- test23_2: {
- name: "arguments (ES5 version): call Object.preventExtensions, make sure we can still modify atttibutes on formals without changing the value",
- body: function () {
- tests.test23Helper(true, "ES5 version");
- }
- },
- test24Helper: function test24Helper(isConvertNeeded, messagePrefix) {
- function mkerr(message) {
- return messagePrefix + ": " + message;
- }
- var passedValue = 1;
- function f(a, b) {
- if (isConvertNeeded) {
- Object.defineProperty(arguments, 1, { enumerable: true }); // Force convert to ES5 version.
- }
- Object.seal(arguments); // This causes configurable = false for all properties + Object.preventExtensions.
- assert.areEqual(true, Object.isSealed(arguments), mkerr("isSealed"));
- assert.areEqual(false, Object.isExtensible(arguments), mkerr("isExtensible"));
- var actual = Object.getOwnPropertyDescriptor(arguments, 0);
- var expected = { configurable: false, enumerable: true, writable: true, value: passedValue };
- assert.areEqual(expected, actual, mkerr("wrong descriptor"));
- }
- f(passedValue, passedValue + 1);
- },
- // Object.freeze(arguments -- not ES5 version) does not set configurable to false on formals.
- test24_1: {
- name: "arguments (non-ES5 version): call Object.seal, verify desciptor on formal",
- body: function () {
- tests.test24Helper(false, "non-ES5 version");
- }
- },
- test24_2: {
- name: "arguments (ES5 version): call Object.seal, verify desciptor on formal",
- body: function () {
- tests.test24Helper(true, "ES5 version");
- }
- },
- test25Helper: function test25Helper(isConvertNeeded, messagePrefix) {
- function mkerr(message) {
- return messagePrefix + ": " + message;
- }
- var passedValue = 1;
- function f(a, b) {
- if (isConvertNeeded) {
- Object.defineProperty(arguments, 1, { enumerable: true }); // Force convert to ES5 version.
- }
- Object.freeze(arguments); // This causes configurable AND writable = false for all properties + Object.preventExtensions.
- assert.areEqual(true, Object.isFrozen(arguments), mkerr("isFrozen"));
- assert.areEqual(true, Object.isSealed(arguments), mkerr("isSealed"));
- assert.areEqual(false, Object.isExtensible(arguments), mkerr("isExtensible"));
- var actual = Object.getOwnPropertyDescriptor(arguments, 0);
- var expected = { configurable: false, enumerable: true, writable: false, value: passedValue };
- assert.areEqual(expected, actual, mkerr("wrong descriptor"));
- }
- f(passedValue, passedValue + 1);
- },
- // Object.freeze(arguments -- not ES5 version) does not set configurable and writable to false on formals.
- test25_1: {
- name: "arguments (non-ES5 version): call Object.freeze, verify descriptor on formal",
- body: function () {
- tests.test25Helper(false, "non-ES5 version");
- }
- },
- test25_2: {
- name: "arguments (ES5 version): call Object.freeze, verify descriptor on formal",
- body: function () {
- tests.test25Helper(true, "ES5 version");
- }
- },
- test26: {
- name: "formal arg: delete, preventExtensions, enumerate, make sure the item is deleted",
- body: function () {
- var passedValue1 = 1;
- var passedValue2 = 2;
- function f(a, b) {
- delete arguments[1];
- Object.preventExtensions(arguments);
- var accumulator = "";
- for (var i in arguments) {
- accumulator += i.toString() + ": " + arguments[i] + ";";
- }
- assert.areEqual("0: " + passedValue1 + ";", accumulator, "accumulator");
- assert.areEqual(undefined, arguments[1], "arguments[1]");
- }
- f(passedValue1, passedValue2);
- }
- },
- test27: {
- name: "formal arg: convert to ES5 version, change value and set writable to false",
- body: function () {
- var passedValue1 = 1;
- var val = 2;
- function f(a) {
- Object.defineProperty(arguments, 0, { enumerable: true });
- a = val;
- Object.defineProperty(arguments, 0, { writable: false });
- var expected = { configurable: true, enumerable: true, writable: false, value: val };
- assert.areEqual(expected, Object.getOwnPropertyDescriptor(arguments, 0));
- }
- f(passedValue1);
- }
- },
- test28: {
- name: "formal arg: convert to ES5 version, enumerate when number of actual params is less than number of formals",
- body: function () {
- var accumulator = "";
- function f(a, b) {
- Object.preventExtensions(arguments);
- for (var i in arguments) {
- if (accumulator.length != 0) accumulator += ",";
- accumulator += arguments[i];
- }
- }
- var value = 5;
- f(value);
- var expected = helpers.isVersion10OrLater ?
- value.toString() :
- value.toString() + ",undefined"; // IE9 compat mode -- Win8 558490.
- assert.areEqual(expected, accumulator, "Wrong accumulated value");
- }
- },
- } // tests.
- testRunner.runTests(tests);
|