michael@0: // |reftest| skip-if(!xulRuntime.shell) -- needs evaluate() michael@0: /* michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/licenses/publicdomain/ michael@0: */ michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: var BUGNUMBER = 577325; michael@0: var summary = 'Implement the ES5 algorithm for processing function statements'; michael@0: michael@0: print(BUGNUMBER + ": " + summary); michael@0: michael@0: /************** michael@0: * BEGIN TEST * michael@0: **************/ michael@0: michael@0: var outer, desc; michael@0: michael@0: /////////////////////////////////////////////////// michael@0: // Function definitions over accessor properties // michael@0: /////////////////////////////////////////////////// michael@0: michael@0: var getCalled, setCalled; michael@0: michael@0: // configurable properties get blown away michael@0: michael@0: getCalled = false, setCalled = false; michael@0: Object.defineProperty(this, "acc1", michael@0: { michael@0: get: function() { getCalled = true; throw "FAIL get 1"; }, michael@0: set: function(v) { setCalled = true; throw "FAIL set 1 " + v; }, michael@0: configurable: true, michael@0: enumerable: false michael@0: }); michael@0: michael@0: // does not throw michael@0: outer = undefined; michael@0: evaluate("function acc1() { throw 'FAIL redefined 1'; } outer = acc1;"); michael@0: assertEq(getCalled, false); michael@0: assertEq(setCalled, false); michael@0: assertEq(typeof acc1, "function"); michael@0: assertEq(acc1, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "acc1"); michael@0: assertEq(desc.value, acc1); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.configurable, false); michael@0: michael@0: michael@0: getCalled = false, setCalled = false; michael@0: Object.defineProperty(this, "acc2", michael@0: { michael@0: get: function() { getCalled = true; throw "FAIL get 2"; }, michael@0: set: function(v) { setCalled = true; throw "FAIL set 2 " + v; }, michael@0: configurable: true, michael@0: enumerable: true michael@0: }); michael@0: michael@0: // does not throw michael@0: outer = undefined; michael@0: evaluate("function acc2() { throw 'FAIL redefined 2'; } outer = acc2;"); michael@0: assertEq(getCalled, false); michael@0: assertEq(setCalled, false); michael@0: assertEq(typeof acc2, "function"); michael@0: assertEq(acc2, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "acc2"); michael@0: assertEq(desc.value, acc2); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.configurable, false); michael@0: michael@0: michael@0: // non-configurable properties produce a TypeError michael@0: michael@0: getCalled = false, setCalled = false; michael@0: Object.defineProperty(this, "acc3", michael@0: { michael@0: get: function() { getCalled = true; throw "FAIL get 3"; }, michael@0: set: function(v) { setCalled = true; throw "FAIL set 3 " + v; }, michael@0: configurable: false, michael@0: enumerable: true michael@0: }); michael@0: michael@0: outer = undefined; michael@0: try michael@0: { michael@0: evaluate("function acc3() { throw 'FAIL redefined 3'; }; outer = acc3"); michael@0: throw new Error("should have thrown trying to redefine global function " + michael@0: "over a non-configurable, enumerable accessor"); michael@0: } michael@0: catch (e) michael@0: { michael@0: assertEq(e instanceof TypeError, true, michael@0: "global function definition, when that function would overwrite " + michael@0: "a non-configurable, enumerable accessor, must throw a TypeError " + michael@0: "per ES5+errata: " + e); michael@0: desc = Object.getOwnPropertyDescriptor(this, "acc3"); michael@0: assertEq(typeof desc.get, "function"); michael@0: assertEq(typeof desc.set, "function"); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(outer, undefined); michael@0: assertEq(getCalled, false); michael@0: assertEq(setCalled, false); michael@0: } michael@0: michael@0: michael@0: getCalled = false, setCalled = false; michael@0: Object.defineProperty(this, "acc4", michael@0: { michael@0: get: function() { getCalled = true; throw "FAIL get 4"; }, michael@0: set: function(v) { setCalled = true; throw "FAIL set 4 " + v; }, michael@0: configurable: false, michael@0: enumerable: false michael@0: }); michael@0: michael@0: outer = undefined; michael@0: try michael@0: { michael@0: evaluate("function acc4() { throw 'FAIL redefined 4'; }; outer = acc4"); michael@0: throw new Error("should have thrown trying to redefine global function " + michael@0: "over a non-configurable, non-enumerable accessor"); michael@0: } michael@0: catch (e) michael@0: { michael@0: assertEq(e instanceof TypeError, true, michael@0: "global function definition, when that function would overwrite " + michael@0: "a non-configurable, non-enumerable accessor, must throw a " + michael@0: "TypeError per ES5+errata: " + e); michael@0: desc = Object.getOwnPropertyDescriptor(this, "acc4"); michael@0: assertEq(typeof desc.get, "function"); michael@0: assertEq(typeof desc.set, "function"); michael@0: assertEq(desc.enumerable, false); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(outer, undefined); michael@0: assertEq(getCalled, false); michael@0: assertEq(setCalled, false); michael@0: } michael@0: michael@0: michael@0: /////////////////////////////////////////////// michael@0: // Function definitions over data properties // michael@0: /////////////////////////////////////////////// michael@0: michael@0: michael@0: // configurable properties, regardless of other attributes, get blown away michael@0: michael@0: Object.defineProperty(this, "data1", michael@0: { michael@0: configurable: true, michael@0: enumerable: true, michael@0: writable: true, michael@0: value: "data1" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: evaluate("function data1() { return 'data1 function'; } outer = data1;"); michael@0: assertEq(typeof data1, "function"); michael@0: assertEq(data1, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data1"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.value, data1); michael@0: michael@0: michael@0: Object.defineProperty(this, "data2", michael@0: { michael@0: configurable: true, michael@0: enumerable: true, michael@0: writable: false, michael@0: value: "data2" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: evaluate("function data2() { return 'data2 function'; } outer = data2;"); michael@0: assertEq(typeof data2, "function"); michael@0: assertEq(data2, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data2"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.value, data2); michael@0: michael@0: michael@0: Object.defineProperty(this, "data3", michael@0: { michael@0: configurable: true, michael@0: enumerable: false, michael@0: writable: true, michael@0: value: "data3" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: evaluate("function data3() { return 'data3 function'; } outer = data3;"); michael@0: assertEq(typeof data3, "function"); michael@0: assertEq(data3, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data3"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.value, data3); michael@0: michael@0: michael@0: Object.defineProperty(this, "data4", michael@0: { michael@0: configurable: true, michael@0: enumerable: false, michael@0: writable: false, michael@0: value: "data4" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: evaluate("function data4() { return 'data4 function'; } outer = data4;"); michael@0: assertEq(typeof data4, "function"); michael@0: assertEq(data4, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data4"); michael@0: assertEq(desc.value, data4); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.configurable, false); michael@0: michael@0: michael@0: // non-configurable data properties are trickier michael@0: michael@0: Object.defineProperty(this, "data5", michael@0: { michael@0: configurable: false, michael@0: enumerable: true, michael@0: writable: true, michael@0: value: "data5" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: evaluate("function data5() { return 'data5 function'; } outer = data5;"); michael@0: assertEq(typeof data5, "function"); michael@0: assertEq(data5, outer); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data5"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.value, data5); michael@0: michael@0: michael@0: Object.defineProperty(this, "data6", michael@0: { michael@0: configurable: false, michael@0: enumerable: true, michael@0: writable: false, michael@0: value: "data6" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: try michael@0: { michael@0: evaluate("function data6() { return 'data6 function'; } outer = data6;"); michael@0: throw new Error("should have thrown trying to redefine global function " + michael@0: "over a non-configurable, enumerable, non-writable accessor"); michael@0: } michael@0: catch (e) michael@0: { michael@0: assertEq(e instanceof TypeError, true, michael@0: "global function definition, when that function would overwrite " + michael@0: "a non-configurable, enumerable, non-writable data property, must " + michael@0: "throw a TypeError per ES5+errata: " + e); michael@0: assertEq(data6, "data6"); michael@0: assertEq(outer, undefined); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data6"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, true); michael@0: assertEq(desc.writable, false); michael@0: assertEq(desc.value, "data6"); michael@0: } michael@0: michael@0: michael@0: Object.defineProperty(this, "data7", michael@0: { michael@0: configurable: false, michael@0: enumerable: false, michael@0: writable: true, michael@0: value: "data7" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: try michael@0: { michael@0: evaluate("function data7() { return 'data7 function'; } outer = data7;"); michael@0: throw new Error("should have thrown trying to redefine global function " + michael@0: "over a non-configurable, non-enumerable, writable data" + michael@0: "property"); michael@0: } michael@0: catch (e) michael@0: { michael@0: assertEq(e instanceof TypeError, true, michael@0: "global function definition, when that function would overwrite " + michael@0: "a non-configurable, non-enumerable, writable data property, must " + michael@0: "throw a TypeError per ES5+errata: " + e); michael@0: assertEq(data7, "data7"); michael@0: assertEq(outer, undefined); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data7"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, false); michael@0: assertEq(desc.writable, true); michael@0: assertEq(desc.value, "data7"); michael@0: } michael@0: michael@0: michael@0: Object.defineProperty(this, "data8", michael@0: { michael@0: configurable: false, michael@0: enumerable: false, michael@0: writable: false, michael@0: value: "data8" michael@0: }); michael@0: michael@0: outer = undefined; michael@0: try michael@0: { michael@0: evaluate("function data8() { return 'data8 function'; } outer = data8;"); michael@0: throw new Error("should have thrown trying to redefine global function " + michael@0: "over a non-configurable, non-enumerable, non-writable data" + michael@0: "property"); michael@0: } michael@0: catch (e) michael@0: { michael@0: assertEq(e instanceof TypeError, true, michael@0: "global function definition, when that function would overwrite " + michael@0: "a non-configurable, non-enumerable, non-writable data property, " + michael@0: "must throw a TypeError per ES5+errata: " + e); michael@0: assertEq(data8, "data8"); michael@0: assertEq(outer, undefined); michael@0: desc = Object.getOwnPropertyDescriptor(this, "data8"); michael@0: assertEq(desc.configurable, false); michael@0: assertEq(desc.enumerable, false); michael@0: assertEq(desc.writable, false); michael@0: assertEq(desc.value, "data8"); michael@0: } michael@0: michael@0: /******************************************************************************/ michael@0: michael@0: if (typeof reportCompare === "function") michael@0: reportCompare(true, true); michael@0: michael@0: print("All tests passed!");