コード例 #1
0
        public void prototype()
        {
            // Prototype
            if (TestUtils.Engine != JSEngine.JScript)
            {
                // prototype of built-in object.
                Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("Function", "prototype"));

                // prototype of new function.
                Assert.AreEqual(PropertyAttributes.Writable, TestUtils.EvaluateAccessibility("new Function()", "prototype"));

                // prototype of empty function.
                Assert.AreEqual(true, TestUtils.Evaluate("Object.getPrototypeOf(Function).prototype === undefined"));

                // [[Prototype]]
                Assert.AreEqual(true, TestUtils.Evaluate("Object.getPrototypeOf(new Function()) === Function.prototype"));
                Assert.AreEqual(true, TestUtils.Evaluate("Object.getPrototypeOf(Function.prototype) === Object.prototype"));
                Assert.AreEqual(true, TestUtils.Evaluate("Object.getPrototypeOf(new Function().prototype) === Object.prototype"));
                Assert.AreEqual(true, TestUtils.Evaluate("Object.getPrototypeOf((function() {}).prototype) === Object.prototype"));
            }

            // prototype of built-in functions should be undefined.
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Math.sin.prototype"));

            // prototype of new functions should be a new object.
            Assert.AreEqual(true, TestUtils.Evaluate("Function('a+b').prototype !== Object.prototype"));
            Assert.AreEqual("object", TestUtils.Evaluate("typeof(Function('a+b').prototype)"));

            // The prototype property becomes the prototype of new objects (as long as the prototype property is an object).
            Assert.AreEqual(true, TestUtils.Evaluate("f = function() { }; x = {}; f.prototype = x; Object.getPrototypeOf(new f()) === x"));
            Assert.AreEqual(true, TestUtils.Evaluate("f = function() { }; x = 5; f.prototype = x; Object.getPrototypeOf(new f()) === Object.prototype"));
        }
コード例 #2
0
        public void constructor()
        {
            Assert.AreEqual(true, TestUtils.Evaluate("new Function().constructor === Function"));
            Assert.AreEqual(true, TestUtils.Evaluate("f = Function('a+b'); f.prototype.constructor === f"));

            // constructor is non-enumerable, writable and configurable.
            if (TestUtils.Engine != JSEngine.JScript)
            {
                Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("Function.prototype", "constructor"));
            }
        }
コード例 #3
0
        public void length()
        {
            Assert.AreEqual(0, TestUtils.Evaluate("Function.prototype.length"));
            Assert.AreEqual(1, TestUtils.Evaluate("new Function('a', 'return this / a').length"));
            Assert.AreEqual(2, TestUtils.Evaluate("new Function('a,b', 'return a / b').length"));
            Assert.AreEqual(2, TestUtils.Evaluate("(function(a, b) {}).length"));

            // length is non-enumerable, non-writable and non-configurable.
            if (TestUtils.Engine != JSEngine.JScript)
            {
                Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("Function", "length"));
                Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("new Function", "length"));
            }
        }
コード例 #4
0
        public void GlobalProperties()
        {
            // Global constants: Infinity, NaN and undefined.
            Assert.AreEqual(double.PositiveInfinity, TestUtils.Evaluate("Infinity"));
            Assert.AreEqual(double.NaN, TestUtils.Evaluate("NaN"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("undefined"));

            // In ECMAScript 5 these properties are not enumerable, not configurable and not writable.
            Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("this", "Infinity"));
            Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("this", "NaN"));
            Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("this", "undefined"));

            // In ECMAScript 5 these properties are not enumerable, not configurable and writable.
            TestUtils.CompatibilityMode = CompatibilityMode.ECMAScript3;
            try
            {
                Assert.AreEqual(PropertyAttributes.Writable, TestUtils.EvaluateAccessibility("this", "Infinity"));
                Assert.AreEqual(PropertyAttributes.Writable, TestUtils.EvaluateAccessibility("this", "NaN"));
                Assert.AreEqual(PropertyAttributes.Writable, TestUtils.EvaluateAccessibility("this", "undefined"));
            }
            finally
            {
                TestUtils.CompatibilityMode = CompatibilityMode.Latest;
            }

            // Built-in objects should be writable and configurable but not enumerable.
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Array"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Boolean"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Date"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Error"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "EvalError"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Function"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "JSON"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Math"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Number"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "Object"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "RangeError"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "ReferenceError"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "RegExp"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "String"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "SyntaxError"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "TypeError"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "URIError"));

            // Functions are writable and configurable.
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("this", "decodeURI"));

            // length is sealed.
            Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("this.decodeURI", "length"));
        }
コード例 #5
0
        public void preventExtensions()
        {
            // Simple object
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {a: 1, c: 2}; Object.preventExtensions(x) === x"));
            Assert.AreEqual(2, TestUtils.Evaluate("x.a = 2; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.b = 6; x.b"));
            Assert.AreEqual(PropertyAttributes.FullAccess, TestUtils.EvaluateAccessibility("x", "c"));

            // length
            Assert.AreEqual(1, TestUtils.Evaluate("Object.preventExtensions.length"));

            // Argument must be an object.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions()"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions(undefined)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions(null)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions(true)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions(5)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.preventExtensions('test')"));
        }
コード例 #6
0
        public void freeze()
        {
            // Simple object
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {a: 1}; Object.freeze(x) === x"));
            Assert.AreEqual(false, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(1, TestUtils.Evaluate("x.a = 2; x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.b = 6; x.b"));
            Assert.AreEqual(PropertyAttributes.Enumerable, TestUtils.EvaluateAccessibility("x", "a"));

            // length
            Assert.AreEqual(1, TestUtils.Evaluate("Object.freeze.length"));

            // Argument must be an object.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze()"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze(undefined)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze(null)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze(true)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze(5)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.freeze('test')"));
        }
コード例 #7
0
        public void Constructor()
        {
            // Construct
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("new Object().toString()"));
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("new Object(undefined).toString()"));
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("new Object(null).toString()"));
            Assert.AreEqual("hi", TestUtils.Evaluate("new Object('hi').valueOf()"));
            Assert.AreEqual(5501, TestUtils.Evaluate("new Object(5501).valueOf()"));
            Assert.AreEqual(true, TestUtils.Evaluate("x = new String('test'); new Object(x) === x"));
            Assert.AreEqual(true, TestUtils.Evaluate("x = new Number(55); new Object(x) === x"));

            // Call
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("Object().toString()"));
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("Object(undefined).toString()"));
            Assert.AreEqual("[object Object]", TestUtils.Evaluate("Object(null).toString()"));
            Assert.AreEqual("hi", TestUtils.Evaluate("Object('hi').valueOf()"));
            Assert.AreEqual(5501, TestUtils.Evaluate("Object(5501).valueOf()"));
            Assert.AreEqual(true, TestUtils.Evaluate("x = new String('test'); Object(x) === x"));
            Assert.AreEqual(true, TestUtils.Evaluate("x = new Number(55); Object(x) === x"));

            // length
            Assert.AreEqual(1, TestUtils.Evaluate("Object.length"));

            // toString
            Assert.AreEqual("function Object() { [native code] }", TestUtils.Evaluate("Object.toString()"));

            // valueOf
            Assert.AreEqual(true, TestUtils.Evaluate("Object.valueOf() === Object"));

            // prototype
            Assert.AreEqual(true, TestUtils.Evaluate("Object.prototype === Object.getPrototypeOf(new Object())"));
            Assert.AreEqual(PropertyAttributes.Sealed, TestUtils.EvaluateAccessibility("Object", "prototype"));

            // constructor
            Assert.AreEqual(true, TestUtils.Evaluate("Object.prototype.constructor === Object"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("Object.prototype", "constructor"));

            // Functions are writable and configurable.
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("Object", "keys"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("Object.prototype", "hasOwnProperty"));
        }
コード例 #8
0
        public void defineProperty()
        {
            // Add simple property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: true, configurable: true}) === x"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(PropertyAttributes.FullAccess, TestUtils.EvaluateAccessibility("x", "a"));
            Assert.AreEqual("a", TestUtils.Evaluate("var p = ''; for (var y in x) { p += y } p"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Add non-writable property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: false, configurable: true}) === x"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(PropertyAttributes.Enumerable | PropertyAttributes.Configurable, TestUtils.EvaluateAccessibility("x", "a"));
            Assert.AreEqual("a", TestUtils.Evaluate("var p = ''; for (var y in x) { p += y } p"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Non-writable properties can have the value changed (as long as configurable = true).
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: false, configurable: true}) === x"));
            Assert.AreEqual(8, TestUtils.Evaluate("Object.defineProperty(x, 'a', {value: 8, enumerable: true, writable: false, configurable: true}); x.a"));
            Assert.AreEqual(9, TestUtils.Evaluate("Object.defineProperty(x, 'a', {value: 9, enumerable: true, writable: false, configurable: false}); x.a"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {value: 10, enumerable: true, writable: false, configurable: false}); x.a"));

            // Non-writable properties can be switched to accessor properties (as long as configurable = true).
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: false, configurable: true}) === x"));
            Assert.AreEqual(1, TestUtils.Evaluate("Object.defineProperty(x, 'a', {get: function() { return 1 }, enumerable: true, configurable: true}); x.a"));

            // Non-writable properties can go back to writable.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: false, configurable: true}) === x"));
            Assert.AreEqual(8, TestUtils.Evaluate("Object.defineProperty(x, 'a', {value: 8, enumerable: true, writable: true, configurable: true}); x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));

            // Add non-enumerable property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: false, writable: true, configurable: true}) === x"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(PropertyAttributes.NonEnumerable, TestUtils.EvaluateAccessibility("x", "a"));
            Assert.AreEqual("", TestUtils.Evaluate("var p = ''; for (var y in x) { p += y } p"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Add non-configurable property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: true, configurable: false}) === x"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(PropertyAttributes.Enumerable | PropertyAttributes.Writable, TestUtils.EvaluateAccessibility("x", "a"));
            Assert.AreEqual("a", TestUtils.Evaluate("var p = ''; for (var y in x) { p += y } p"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(false, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a"));

            // Add read-only accessor property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 7 }, enumerable: true, configurable: true}) === x"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual("function", TestUtils.Evaluate("typeof(Object.getOwnPropertyDescriptor(x, 'a').get)"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').set"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));
            Assert.AreEqual(7, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Add read-write accessor property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {a2: 10}; Object.defineProperty(x, 'a', {get: function() { return this.a2 }, set: function(value) { this.a2 = value }, enumerable: true, configurable: true}) === x"));
            Assert.AreEqual(10, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual("function", TestUtils.Evaluate("typeof(Object.getOwnPropertyDescriptor(x, 'a').get)"));
            Assert.AreEqual("function", TestUtils.Evaluate("typeof(Object.getOwnPropertyDescriptor(x, 'a').set)"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Add write-only accessor property.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {set: function(value) { this.a2 = value }, enumerable: true, configurable: true}) === x"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').get"));
            Assert.AreEqual("function", TestUtils.Evaluate("typeof(Object.getOwnPropertyDescriptor(x, 'a').set)"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a = 5; x.a"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a = 5; x.a2"));
            Assert.AreEqual(true, TestUtils.Evaluate("delete x.a"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // An empty property descriptor defines a default property (if the property doesn't already exist).
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {}) === x"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("x.hasOwnProperty('a')"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').get"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').set"));
            Assert.AreEqual(false, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(false, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(false, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));

            // An empty property descriptor does nothing if the property already exists.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {a: 5}; Object.defineProperty(x, 'a', {}) === x"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("x.hasOwnProperty('a')"));
            Assert.AreEqual(5, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').get"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').set"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));

            // A property descriptor without a value does not change the existing value.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {a: 5}; Object.defineProperty(x, 'a', {writable: false}) === x"));
            Assert.AreEqual(5, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("x.hasOwnProperty('a')"));
            Assert.AreEqual(5, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').value"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').get"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').set"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').enumerable"));
            Assert.AreEqual(false, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').writable"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.getOwnPropertyDescriptor(x, 'a').configurable"));

            // get and set can be undefined.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 1; }, set: undefined, configurable: true}) === x"));
            Assert.AreEqual(1, TestUtils.Evaluate("x.a"));
            Assert.AreEqual(true, TestUtils.Evaluate("Object.defineProperty(x, 'a', {get: undefined, set: undefined}) === x"));
            Assert.AreEqual(Undefined.Value, TestUtils.Evaluate("x.a"));

            // Non-extensible objects cannot have properties added.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.preventExtensions(x) === x"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: true, configurable: true})"));

            // Non-configurable properties can only have the value changed.
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {value: 7, enumerable: true, writable: true, configurable: false}) === x"));
            Assert.AreEqual(10, TestUtils.Evaluate("Object.defineProperty(x, 'a', {value: 10, enumerable: true, writable: true, configurable: false}); x.a"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {get: function() { return 7; }, enumerable: true, writable: true, configurable: false}); x.a"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {value: 10, enumerable: false, writable: true, configurable: false})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {value: 10, enumerable: true, writable: false, configurable: false})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(x, 'a', {value: 10, enumerable: true, writable: true, configurable: true})"));
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; var f = function() { return 1; }; Object.defineProperty(x, 'a', {get: f}); Object.defineProperty(x, 'a', {get: f}) === x"));
            Assert.AreEqual(true, TestUtils.Evaluate("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 1; }}); Object.defineProperty(x, 'a', {set: undefined}) === x"));

            // Value is not allowed when specifying an accessor property.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 7 }, enumerable: true, configurable: true, value: 5})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 7 }, set: function() { }, enumerable: true, configurable: true, value: 5})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {set: function() { }, enumerable: true, configurable: true, value: 5})"));

            // Writable is not allowed when specifying an accessor property.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 7 }, enumerable: true, writable: false, configurable: true})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: function() { return 7 }, set: function() { }, enumerable: true, writable: true, configurable: true})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {set: function() { }, enumerable: true, writable: true, configurable: true})"));

            // Get and set must be a function.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: 5, enumerable: true, configurable: true})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {get: 5, set: 5, enumerable: true, configurable: true})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("var x = {}; Object.defineProperty(x, 'a', {set: 5, enumerable: true, configurable: true})"));

            // length
            Assert.AreEqual(3, TestUtils.Evaluate("Object.defineProperty.length"));

            // Argument must be an object.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty()"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty({})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(undefined, {})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(null, {})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(true, {})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty(5, {})"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty('test', {})"));

            // Property descriptors must be objects.
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty({}, 'a', 5)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty({}, 'a', undefined)"));
            Assert.AreEqual("TypeError", TestUtils.EvaluateExceptionType("Object.defineProperty({}, 'a', null)"));
        }