| // Any copyright is dedicated to the Public Domain. |
| // http://creativecommons.org/licenses/publicdomain/ |
| |
| //----------------------------------------------------------------------------- |
| 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"); |