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; 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); 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' skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
[test_bug1081686.html] [test_bug1081686.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s 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_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_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_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 outer, desc;
var isInShell = !("Window" in this);
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// Function definitions over accessor properties // // Function definitions over accessor properties //
@ -69,71 +70,73 @@ assertEq(desc.enumerable, true);
assertEq(desc.configurable, 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; outer = undefined;
Object.defineProperty(this, "acc3", try
{ {
get: function() { getCalled = true; throw "FAIL get 3"; }, eval("function acc3() { throw 'FAIL redefined 3'; }; outer = acc3");
set: function(v) { setCalled = true; throw "FAIL set 3 " + v; }, throw new Error("should have thrown trying to redefine global function " +
configurable: false, "over a non-configurable, enumerable accessor");
enumerable: true }
}); catch (e)
{
outer = undefined; assertEq(e instanceof TypeError, true,
try "global function definition, when that function would overwrite " +
{ "a non-configurable, enumerable accessor, must throw a TypeError " +
eval("function acc3() { throw 'FAIL redefined 3'; }; outer = acc3"); "per ES5+errata: " + e);
throw new Error("should have thrown trying to redefine global function " + desc = Object.getOwnPropertyDescriptor(this, "acc3");
"over a non-configurable, enumerable accessor"); assertEq(typeof desc.get, "function");
} assertEq(typeof desc.set, "function");
catch (e) assertEq(desc.enumerable, true);
{ assertEq(desc.configurable, false);
assertEq(e instanceof TypeError, true, assertEq(outer, undefined);
"global function definition, when that function would overwrite " + assertEq(getCalled, false);
"a non-configurable, enumerable accessor, must throw a TypeError " + assertEq(setCalled, false);
"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; getCalled = false, setCalled = false;
Object.defineProperty(this, "acc4", Object.defineProperty(this, "acc4",
{ {
get: function() { getCalled = true; throw "FAIL get 4"; }, get: function() { getCalled = true; throw "FAIL get 4"; },
set: function(v) { setCalled = true; throw "FAIL set 4 " + v; }, set: function(v) { setCalled = true; throw "FAIL set 4 " + v; },
configurable: false, configurable: false,
enumerable: false enumerable: false
}); });
outer = undefined; outer = undefined;
try try
{ {
eval("function acc4() { throw 'FAIL redefined 4'; }; outer = acc4"); eval("function acc4() { throw 'FAIL redefined 4'; }; outer = acc4");
throw new Error("should have thrown trying to redefine global function " + throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable accessor"); "over a non-configurable, non-enumerable accessor");
} }
catch (e) catch (e)
{ {
assertEq(e instanceof TypeError, true, assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " + "global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable accessor, must throw a " + "a non-configurable, non-enumerable accessor, must throw a " +
"TypeError per ES5+errata: " + e); "TypeError per ES5+errata: " + e);
desc = Object.getOwnPropertyDescriptor(this, "acc4"); desc = Object.getOwnPropertyDescriptor(this, "acc4");
assertEq(typeof desc.get, "function"); assertEq(typeof desc.get, "function");
assertEq(typeof desc.set, "function"); assertEq(typeof desc.set, "function");
assertEq(desc.enumerable, false); assertEq(desc.enumerable, false);
assertEq(desc.configurable, false); assertEq(desc.configurable, false);
assertEq(outer, undefined); assertEq(outer, undefined);
assertEq(getCalled, false); assertEq(getCalled, false);
assertEq(setCalled, false); assertEq(setCalled, false);
}
} }
@ -220,119 +223,121 @@ assertEq(desc.enumerable, true);
assertEq(desc.configurable, 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", if (isInShell) {
{ Object.defineProperty(this, "data5",
configurable: false, {
enumerable: true, configurable: false,
writable: true, enumerable: true,
value: "data5" writable: true,
}); value: "data5"
});
outer = undefined; outer = undefined;
eval("function data5() { return 'data5 function'; } outer = data5;"); eval("function data5() { return 'data5 function'; } outer = data5;");
assertEq(typeof data5, "function"); assertEq(typeof data5, "function");
assertEq(data5, outer); assertEq(data5, outer);
desc = Object.getOwnPropertyDescriptor(this, "data5"); desc = Object.getOwnPropertyDescriptor(this, "data5");
assertEq(desc.configurable, false); assertEq(desc.configurable, false);
assertEq(desc.enumerable, true); assertEq(desc.enumerable, true);
assertEq(desc.writable, true); assertEq(desc.writable, true);
assertEq(desc.value, data5); assertEq(desc.value, data5);
Object.defineProperty(this, "data6", Object.defineProperty(this, "data6",
{ {
configurable: false, configurable: false,
enumerable: true, enumerable: true,
writable: false, writable: false,
value: "data6" value: "data6"
}); });
outer = undefined; outer = undefined;
try try
{ {
eval("function data6() { return 'data6 function'; } outer = data6;"); eval("function data6() { return 'data6 function'; } outer = data6;");
throw new Error("should have thrown trying to redefine global function " + throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, enumerable, non-writable accessor"); "over a non-configurable, enumerable, non-writable accessor");
} }
catch (e) catch (e)
{ {
assertEq(e instanceof TypeError, true, assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " + "global function definition, when that function would overwrite " +
"a non-configurable, enumerable, non-writable data property, must " + "a non-configurable, enumerable, non-writable data property, must " +
"throw a TypeError per ES5+errata: " + e); "throw a TypeError per ES5+errata: " + e);
assertEq(data6, "data6"); assertEq(data6, "data6");
assertEq(outer, undefined); assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data6"); desc = Object.getOwnPropertyDescriptor(this, "data6");
assertEq(desc.configurable, false); assertEq(desc.configurable, false);
assertEq(desc.enumerable, true); assertEq(desc.enumerable, true);
assertEq(desc.writable, false); assertEq(desc.writable, false);
assertEq(desc.value, "data6"); assertEq(desc.value, "data6");
} }
Object.defineProperty(this, "data7", Object.defineProperty(this, "data7",
{ {
configurable: false, configurable: false,
enumerable: false, enumerable: false,
writable: true, writable: true,
value: "data7" value: "data7"
}); });
outer = undefined; outer = undefined;
try try
{ {
eval("function data7() { return 'data7 function'; } outer = data7;"); eval("function data7() { return 'data7 function'; } outer = data7;");
throw new Error("should have thrown trying to redefine global function " + throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, writable data" + "over a non-configurable, non-enumerable, writable data" +
"property"); "property");
} }
catch (e) catch (e)
{ {
assertEq(e instanceof TypeError, true, assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " + "global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, writable data property, must " + "a non-configurable, non-enumerable, writable data property, must " +
"throw a TypeError per ES5+errata: " + e); "throw a TypeError per ES5+errata: " + e);
assertEq(data7, "data7"); assertEq(data7, "data7");
assertEq(outer, undefined); assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data7"); desc = Object.getOwnPropertyDescriptor(this, "data7");
assertEq(desc.configurable, false); assertEq(desc.configurable, false);
assertEq(desc.enumerable, false); assertEq(desc.enumerable, false);
assertEq(desc.writable, true); assertEq(desc.writable, true);
assertEq(desc.value, "data7"); assertEq(desc.value, "data7");
} }
Object.defineProperty(this, "data8", Object.defineProperty(this, "data8",
{ {
configurable: false, configurable: false,
enumerable: false, enumerable: false,
writable: false, writable: false,
value: "data8" value: "data8"
}); });
outer = undefined; outer = undefined;
try try
{ {
eval("function data8() { return 'data8 function'; } outer = data8;"); eval("function data8() { return 'data8 function'; } outer = data8;");
throw new Error("should have thrown trying to redefine global function " + throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, non-writable data" + "over a non-configurable, non-enumerable, non-writable data" +
"property"); "property");
} }
catch (e) catch (e)
{ {
assertEq(e instanceof TypeError, true, assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " + "global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, non-writable data property, " + "a non-configurable, non-enumerable, non-writable data property, " +
"must throw a TypeError per ES5+errata: " + e); "must throw a TypeError per ES5+errata: " + e);
assertEq(data8, "data8"); assertEq(data8, "data8");
assertEq(outer, undefined); assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data8"); desc = Object.getOwnPropertyDescriptor(this, "data8");
assertEq(desc.configurable, false); assertEq(desc.configurable, false);
assertEq(desc.enumerable, false); assertEq(desc.enumerable, false);
assertEq(desc.writable, false); assertEq(desc.writable, false);
assertEq(desc.value, "data8"); assertEq(desc.value, "data8");
}
} }
/******************************************************************************/ /******************************************************************************/