| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| |
| /// <reference path="../UnitTestFramework/UnitTestFramework.js" /> |
| if (this.WScript && this.WScript.LoadScriptFile) { |
| WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); |
| } |
| |
| function make_engine(/*default=samethread*/thread) { |
| return WScript.LoadScriptFile("protolib.js", thread || "samethread"); |
| } |
| |
| // Run a function expression in this engine |
| function run(f) { |
| return eval("(" + f + ")()"); |
| } |
| |
| |
| // Save __proto__ descriptor at startup |
| var __saved__proto__desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); |
| |
| // assert __proto__ throws "this" not object. "method" default to Object.prototype.__proto__ |
| assert.throws__proto__ThisNotObject = function (f, method) { |
| assert.throws(f, TypeError, undefined, (method || "Object.prototype.__proto__") + ": 'this' is not an Object"); |
| }; |
| |
| // assert __proto__ throws arg not object. "method" default to Object.setPrototypeOf |
| assert.throws__proto__ArgNotObject = function (f, method) { |
| assert.throws(f, TypeError, undefined, (method || "Object.setPrototypeOf") + ": argument is not an Object"); |
| }; |
| |
| // assert __proto__ throws arg not object or null. "method" default to Object.prototype.__proto__ |
| assert.throws__proto__ArgNotObjectOrNull = function (f, method) { |
| assert.throws(f, TypeError, undefined, (method || "Object.prototype.__proto__") + ": argument is not an Object and is not null"); |
| }; |
| |
| // assert __proto__ throws cyclic error |
| assert.throws__proto__Cyclic = function (f, method) { |
| assert.throws(f, TypeError, undefined, "Cyclic __proto__ value"); |
| }; |
| |
| function disable__proto__() { |
| delete Object.prototype.__proto__; |
| } |
| |
| function verify__proto__enabled() { |
| assert.isTrue(Object.prototype.hasOwnProperty("__proto__"), "__proto__ enabled, Object.prototype must have own property __proto__"); |
| |
| var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); |
| assert.isTrue(__saved__proto__desc.get === desc.get, "must have original getter"); |
| assert.isTrue(__saved__proto__desc.set === desc.set, "must have original setter"); |
| // Ignore enumerable/configurable. They can be changed and __proto__ still takes effect. |
| |
| var p = { a: 0 }; |
| var o = { b: 1 }; |
| |
| assert.isTrue(o.__proto__ === Object.getPrototypeOf(o)); |
| assert.areEqual(Object.prototype, o.__proto__, "__proto__ enabled, __proto__ value should be [[prototype]]"); |
| |
| o.__proto__ = p; |
| assert.isTrue(o.__proto__ === Object.getPrototypeOf(o)); |
| assert.areEqual(p, o.__proto__, "__proto__ enabled, [[prototype]] should be changed"); |
| |
| Object.setPrototypeOf(o, Object.prototype); |
| assert.isTrue(o.__proto__ === Object.getPrototypeOf(o)); |
| assert.areEqual(Object.prototype, o.__proto__); |
| } |
| |
| function verify__proto__disabled(label) { |
| var p = { a: 0 }; |
| var o = { b: 1 }; |
| |
| assert.areEqual(Object.prototype, Object.getPrototypeOf(o)); |
| o.__proto__ = p; |
| assert.areEqual(Object.prototype, Object.getPrototypeOf(o), "__proto__ disabled, [[prototype]] should not be changed " + (label || "")); |
| |
| Object.setPrototypeOf(o, p); // always works |
| assert.areEqual(p, Object.getPrototypeOf(o)); |
| } |
| |
| // verify (in a new engine) if an expression disables __proto__. |
| function verify_disable(expr, keepEnabled) { |
| make_engine().__verify_disable(expr, keepEnabled); |
| } |
| var KEEP_ENABLED = {}; |
| function __verify_disable(expr, keepEnabled) { |
| verify__proto__enabled(); |
| helpers.writeln(expr); |
| eval(expr); |
| |
| if (keepEnabled) { |
| verify__proto__enabled(); |
| } else { |
| verify__proto__disabled(); |
| } |
| } |