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