Bug 1107443 part 6. Make attempts to define a non-configurable property via WindowProxy throw. r=peterv,jorendorff

This commit is contained in:
Boris Zbarsky 2015-01-23 09:54:15 -05:00
Родитель 57de0e8c3f
Коммит 7f78049fc1
5 изменённых файлов: 220 добавлений и 163 удалений

Просмотреть файл

@ -787,6 +787,14 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
return true;
}
// For now, allow chrome code to define non-configurable properties
// on windows, until we sort out what exactly the addon SDK is
// doing. In the meantime, this still allows us to test web compat
// behavior.
if (desc.isPermanent() && !nsContentUtils::IsCallerChrome()) {
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
}
return js::Wrapper::defineProperty(cx, proxy, id, desc);
}

Просмотреть файл

@ -767,3 +767,4 @@ support-files = file_bug1011748_redirect.sjs file_bug1011748_OK.sjs
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
[test_bug1081686.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
[test_window_define_nonconfigurable.html]

Просмотреть файл

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1107443</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1107443 **/
try {
Object.defineProperty(window, "nosuchprop", { value: 5 });
throw "didn't throw";
} catch (e) {
ise(e instanceof TypeError, true,
"defineProperty(window) with a non-configurable property should " +
"throw a TypeError, instead got: " + e);
ise(Object.getOwnPropertyDescriptor(window, "nosuchprop"), undefined,
'Window should not have property after an attempt to define it failed');
}
Object.defineProperty(window, "nosuchprop", { value: 7, configurable: true });
var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
ise(typeof(desc), "object", "Should have a property now");
ise(desc.configurable, true, "Property should be configurable");
ise(desc.writable, false, "Property should be readonly");
ise(desc.value, 7, "Property should have the right value");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107443">Mozilla Bug 1107443</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -63,3 +63,4 @@ MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, "Missing required {0}.")
MSG_DEF(MSG_INVALID_REQUEST_METHOD, 1, "Invalid request method {0}.")
MSG_DEF(MSG_REQUEST_BODY_CONSUMED_ERROR, 0, "Request body has already been consumed.")
MSG_DEF(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR, 0, "Response statusText may not contain newline or carriage return.")
MSG_DEF(MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW, 0, "Not allowed to define a non-configurable property on the WindowProxy object")

Просмотреть файл

@ -14,6 +14,7 @@ print(BUGNUMBER + ": " + summary);
**************/
var outer, desc;
var isInShell = !("Window" in this);
///////////////////////////////////////////////////
// Function definitions over accessor properties //
@ -69,71 +70,73 @@ assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
// non-configurable properties produce a TypeError
// 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
});
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);
}
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
});
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);
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);
}
}
@ -220,119 +223,121 @@ assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
// non-configurable data properties are trickier
// non-configurable data properties are trickier. Again, we test these only in shell.
Object.defineProperty(this, "data5",
{
configurable: false,
enumerable: true,
writable: true,
value: "data5"
});
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);
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"
});
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");
}
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"
});
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");
}
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"
});
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");
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");
}
}
/******************************************************************************/