Source code
Revision control
Copy as Markdown
Other Tools
// Any copyright is dedicated to the Public Domain.
//-----------------------------------------------------------------------------
var BUGNUMBER = 1061853;
var summary =
"__proto__ in object literals in non-__proto__:v contexts doesn't modify " +
"[[Prototype]]";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function hasOwn(obj, prop)
{
return Object.getOwnPropertyDescriptor(obj, prop) !== undefined;
}
var objectStart = "{ ";
var objectEnd = " }";
var members =
{
nullProto: "__proto__: null",
functionProtoProto: "__proto__: Function.prototype",
computedNull: "['__proto__']: null",
method: "__proto__() {}",
computedMethod: "['__proto__']() {}",
generatorMethod: "*__proto__() {}",
computedGenerator: "*['__proto__']() {}",
shorthand: "__proto__",
getter: "get __proto__() { return 42; }",
getterComputed: "get ['__proto__']() { return 42; }",
setter: "set __proto__(v) { }",
setterComputed: "set ['__proto__'](v) { }",
};
function isProtoMutation(key)
{
return key === "nullProto" || key === "functionProtoProto";
}
function isGetter(key)
{
return key === "getter" || key === "getterComputed";
}
function isSetter(key)
{
return key === "setter" || key === "setterComputed";
}
function isData(key)
{
return !isProtoMutation(key) && !isGetter(key) && !isSetter(key);
}
var __proto__ = "string value";
function typeOfProto(key)
{
if (key === "computedNull")
return "object";
if (key === "method" || key === "computedMethod" ||
key === "computedGenerator" || key === "generatorMethod")
{
return "function";
}
if (key === "getter" || key === "getterComputed")
return "number";
assertEq(key, "shorthand", "bug in test!");
return "string";
}
for (var first in members)
{
var fcode = "return " + objectStart + members[first] + objectEnd;
var f = Function(fcode);
var oneProp = f();
if (first === "nullProto")
{
assertEq(Object.getPrototypeOf(oneProp), null);
assertEq(hasOwn(oneProp, "__proto__"), false);
}
else if (first === "functionProtoProto")
{
assertEq(Object.getPrototypeOf(oneProp), Function.prototype);
assertEq(hasOwn(oneProp, "__proto__"), false);
}
else if (isSetter(first))
{
assertEq(Object.getPrototypeOf(oneProp), Object.prototype);
assertEq(hasOwn(oneProp, "__proto__"), true);
assertEq(typeof Object.getOwnPropertyDescriptor(oneProp, "__proto__").set,
"function");
}
else
{
assertEq(Object.getPrototypeOf(oneProp), Object.prototype);
assertEq(hasOwn(oneProp, "__proto__"), true);
assertEq(typeof oneProp.__proto__, typeOfProto(first));
}
for (var second in members)
{
try
{
var gcode = "return " + objectStart + members[first] + ", " +
members[second] + objectEnd;
var g = Function(gcode);
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"__proto__ member conflicts should be syntax errors, got " + e);
assertEq(+(first === "nullProto" || first === "functionProtoProto") +
+(second === "nullProto" || second === "functionProtoProto") > 1,
true,
"unexpected conflict between members: " + first + ", " + second);
continue;
}
var twoProps = g();
if (first === "nullProto" || second === "nullProto")
assertEq(Object.getPrototypeOf(twoProps), null);
else if (first === "functionProtoProto" || second === "functionProtoProto")
assertEq(Object.getPrototypeOf(twoProps), Function.prototype);
else
assertEq(Object.getPrototypeOf(twoProps), Object.prototype);
if (isSetter(second))
{
assertEq(hasOwn(twoProps, "__proto__"), true);
assertEq(typeof Object.getOwnPropertyDescriptor(twoProps, "__proto__").get,
isGetter(first) ? "function" : "undefined");
}
else if (!isProtoMutation(second))
{
assertEq(hasOwn(twoProps, "__proto__"), true);
assertEq(typeof twoProps.__proto__, typeOfProto(second));
if (isGetter(second))
{
assertEq(typeof Object.getOwnPropertyDescriptor(twoProps, "__proto__").get,
"function");
assertEq(typeof Object.getOwnPropertyDescriptor(twoProps, "__proto__").set,
isSetter(first) ? "function" : "undefined");
}
}
else if (isSetter(first))
{
assertEq(hasOwn(twoProps, "__proto__"), true);
assertEq(typeof Object.getOwnPropertyDescriptor(twoProps, "__proto__").set,
"function");
assertEq(typeof Object.getOwnPropertyDescriptor(twoProps, "__proto__").get,
"undefined");
}
else if (!isProtoMutation(first))
{
assertEq(hasOwn(twoProps, "__proto__"), true);
assertEq(typeof twoProps.__proto__, typeOfProto(first));
}
else
{
assertEq(true, false, "should be unreachable: " + first + ", " + second);
}
for (var third in members)
{
try
{
var hcode = "return " + objectStart + members[first] + ", " +
members[second] + ", " +
members[third] + objectEnd;
var h = Function(hcode);
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"__proto__ member conflicts should be syntax errors, got " + e);
assertEq(+(first === "nullProto" || first === "functionProtoProto") +
+(second === "nullProto" || second === "functionProtoProto") +
+(third === "nullProto" || third === "functionProtoProto") > 1,
true,
"unexpected conflict among members: " +
first + ", " + second + ", " + third);
continue;
}
var threeProps = h();
if (first === "nullProto" || second === "nullProto" ||
third === "nullProto")
{
assertEq(Object.getPrototypeOf(threeProps), null);
}
else if (first === "functionProtoProto" ||
second === "functionProtoProto" ||
third === "functionProtoProto")
{
assertEq(Object.getPrototypeOf(threeProps), Function.prototype);
}
else
{
assertEq(Object.getPrototypeOf(threeProps), Object.prototype);
}
if (isSetter(third))
{
assertEq(hasOwn(threeProps, "__proto__"), true);
assertEq(typeof Object.getOwnPropertyDescriptor(threeProps, "__proto__").get,
isGetter(second) || (!isData(second) && isGetter(first))
? "function"
: "undefined",
"\n" + hcode);
}
else if (!isProtoMutation(third))
{
assertEq(hasOwn(threeProps, "__proto__"), true);
assertEq(typeof threeProps.__proto__, typeOfProto(third), first + ", " + second + ", " + third);
if (isGetter(third))
{
var desc = Object.getOwnPropertyDescriptor(threeProps, "__proto__");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set,
isSetter(second) || (!isData(second) && isSetter(first))
? "function"
: "undefined");
}
}
else if (isSetter(second))
{
assertEq(hasOwn(threeProps, "__proto__"), true);
assertEq(typeof Object.getOwnPropertyDescriptor(threeProps, "__proto__").get,
isGetter(first) ? "function" : "undefined");
}
else if (!isProtoMutation(second))
{
assertEq(hasOwn(threeProps, "__proto__"), true);
assertEq(typeof threeProps.__proto__, typeOfProto(second));
if (isGetter(second))
{
var desc = Object.getOwnPropertyDescriptor(threeProps, "__proto__");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set,
isSetter(first) ? "function" : "undefined");
}
}
else
{
assertEq(true, false,
"should be unreachable: " +
first + ", " + second + ", " + third);
}
}
}
}
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");