Bug 1293995 - Remove proxy OwnPropertyKeys error with duplicate keys. r=Waldo

This commit is contained in:
Tom Schuster 2016-08-11 14:16:38 +02:00
parent 9d47e7f519
commit e9bed0b38f
2 changed files with 12 additions and 19 deletions

View File

@ -765,25 +765,17 @@ ScriptedProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy, AutoIdV
return props.appendAll(trapResult);
// Step 16.
// The algorithm below always removes all occurences of the same key
// at once, so we can use a set here.
Rooted<GCHashSet<jsid>> uncheckedResultKeys(cx, GCHashSet<jsid>(cx));
if (!uncheckedResultKeys.init(trapResult.length()))
return false;
bool foundDuplicate = false;
for (size_t i = 0, len = trapResult.length(); i < len; i++) {
MOZ_ASSERT(!JSID_IS_VOID(trapResult[i]));
// This dup-checking (and complaining only if we reach the end of the
// overall algorithm, but not if we exit early without erroring) is
// dumb, but it's ECMA state of the art right now. This should be
// fixed in <https://github.com/tc39/ecma262/issues/461>.
auto ptr = uncheckedResultKeys.lookupForAdd(trapResult[i]);
if (!ptr) {
if (!uncheckedResultKeys.add(ptr, trapResult[i]))
return false;
} else {
foundDuplicate = true;
}
if (!uncheckedResultKeys.put(trapResult[i]))
return false;
}
// Step 17.
@ -823,7 +815,7 @@ ScriptedProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy, AutoIdV
}
// Step 20.
if (!uncheckedResultKeys.empty() || foundDuplicate) {
if (!uncheckedResultKeys.empty()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_NEW);
return false;
}

View File

@ -4,9 +4,9 @@
*/
var gTestfile = 'ownkeys-trap-duplicates.js';
var BUGNUMBER = 1257779;
var BUGNUMBER = 1293995;
var summary =
"Scripted proxies' [[OwnPropertyKeys]] should throw if the trap " +
"Scripted proxies' [[OwnPropertyKeys]] should not throw if the trap " +
"implementation returns duplicate properties and the object is " +
"non-extensible or has non-configurable properties";
@ -17,11 +17,12 @@ print(BUGNUMBER + ": " + summary);
**************/
var target = Object.preventExtensions({ a: 1 });
var proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } });
assertDeepEq(Object.getOwnPropertyNames(proxy), ["a", "a"]);
var proxy = new Proxy(target, { ownKeys(t) { return ['a', 'a']; } });
assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy),
TypeError);
target = Object.freeze({ a: 1 });
proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } });
assertDeepEq(Object.getOwnPropertyNames(proxy), ["a", "a"]);
/******************************************************************************/