description("Test to ensure correct behaviour of Object.getOwnPropertyDescriptor"); function descriptorShouldBe(object, property, expected) { var test = 'Object.getOwnPropertyDescriptor('+object+", "+property+')'; if ("writable" in expected) { // shouldBe(test+'.writable', '' + expected.writable); shouldBe(test+'.value', '' + expected.value); shouldBeFalse(test+".hasOwnProperty('get')"); shouldBeFalse(test+".hasOwnProperty('set')"); } else { shouldBe(test+'.get', '' + expected.get); shouldBe(test+'.set', '' + expected.set); shouldBeFalse(test+".hasOwnProperty('value')"); shouldBeFalse(test+".hasOwnProperty('writable')"); } shouldBe(test+'.enumerable', '' + expected.enumerable); shouldBe(test+'.configurable', '' + expected.configurable); } shouldBeUndefined("Object.getOwnPropertyDescriptor({}, 'undefinedProperty')"); descriptorShouldBe("{definedProperty:'defined'}", "'definedProperty'", {writable: true, enumerable: true, configurable: true, value:'"defined"'}); descriptorShouldBe("Array.prototype", "'concat'", {writable: true, enumerable: false, configurable: true, value:"Array.prototype.concat"}); descriptorShouldBe("Date.prototype", "'toISOString'", {writable: true, enumerable: false, configurable: true, value: "Date.prototype.toISOString"}); descriptorShouldBe("String.prototype", "'concat'", {writable: true, enumerable: false, configurable: true, value:"String.prototype.concat"}); descriptorShouldBe("RegExp.prototype", "'exec'", {writable: true, enumerable: false, configurable: true, value:"RegExp.prototype.exec"}); descriptorShouldBe("document.__proto__.__proto__", "'createElement'", {writable: true, enumerable: true, configurable: false, value:"document.createElement"}); descriptorShouldBe("Number", "'NEGATIVE_INFINITY'", {writable: false, enumerable: false, configurable: false, value:"Number.NEGATIVE_INFINITY"}); descriptorShouldBe("RegExp", "'$_'", {writable: true, enumerable: false, configurable: true, value:"RegExp.$_"}); descriptorShouldBe("/a/g", "'global'", {writable: true, enumerable: false, configurable: false, value:true}); descriptorShouldBe("Node", "'DOCUMENT_POSITION_DISCONNECTED'", {writable: false, enumerable: true, configurable: false, value:"Node.DOCUMENT_POSITION_DISCONNECTED"}); descriptorShouldBe("Math", "'sin'", {writable: true, enumerable: false, configurable: true, value:"Math.sin"}); descriptorShouldBe("[1,2,3]", "0", {writable: true, enumerable: true, configurable: true, value:"1"}); descriptorShouldBe("[1,2,3]", "'length'", {writable: true, enumerable: false, configurable: false, value:"3"}); descriptorShouldBe("[1,2,3]", "'length'", {writable: true, enumerable: false, configurable: false, value:"3"}); descriptorShouldBe("/(a)*/g.exec('a')", "0", {writable: true, enumerable: true, configurable: true, value:"'a'"}); descriptorShouldBe("/(a)*/g.exec('a')", "'length'", {writable: true, enumerable: false, configurable: false, value:2}); descriptorShouldBe("function(){}", "'length'", {writable: false, enumerable: false, configurable: false, value:0}); descriptorShouldBe("Math.sin", "'length'", {writable: false, enumerable: false, configurable: false, value:1}); descriptorShouldBe("Math.sin", "'name'", {writable: false, enumerable: false, configurable: false, value:"'sin'"}); var global = this; descriptorShouldBe("global", "'global'", {writable: true, enumerable: true, configurable: false, value:"global"}); descriptorShouldBe("global", "'undefined'", {writable: false, enumerable: false, configurable: false, value:"undefined"}); descriptorShouldBe("global", "'NaN'", {writable: false, enumerable: false, configurable: false, value:"NaN"}); descriptorShouldBe("global", "'Infinity'", {writable: false, enumerable: false, configurable: false, value:"Infinity"}); descriptorShouldBe("global", "'window'", {writable: false, enumerable: true, configurable: false, value:"global"}); descriptorShouldBe("global", "'XMLHttpRequest'", {writable: true, enumerable: true, configurable: false, value:"XMLHttpRequest"}); descriptorShouldBe("global", "'length'", {writable: true, enumerable: true, configurable: false, value:"global.length"}); descriptorShouldBe("global", "0", {writable: true, enumerable: false, configurable: false, value:"global[0]"}); descriptorShouldBe("document.getElementsByTagName('div')", "'length'", {writable: false, enumerable: true, configurable: false, value:"1"}); descriptorShouldBe("document.getElementsByTagName('div')", "0", {writable: false, enumerable: true, configurable: false, value:"document.getElementsByTagName('div')[0]"}); descriptorShouldBe("document.getElementsByClassName('pass')", "0", {writable: false, enumerable: true, configurable: false, value:"document.getElementsByClassName('pass')[0]"}); descriptorShouldBe("document.getElementsByClassName('pass')", "'length'", {writable: false, enumerable: true, configurable: false, value:"document.getElementsByClassName('pass').length"}); var canvas = document.createElement("canvas"); var canvasPixelArray = canvas.getContext("2d").createImageData(10,10).data; descriptorShouldBe("canvasPixelArray", "'length'", {writable: false, enumerable: true, configurable: false, value:"canvasPixelArray.length"}); descriptorShouldBe("canvasPixelArray", "0", {writable: true, enumerable: true, configurable: false, value:"canvasPixelArray[0]"}); var select = document.createElement("select"); select.innerHTML = ""; descriptorShouldBe("select", "'length'", {writable: false, enumerable: true, configurable: false, value:"select.length"}); descriptorShouldBe("select", "0", {writable: true, enumerable: true, configurable: false, value:"select[0]"}); var objectWithGetter = {}; function getterFunc(){}; objectWithGetter.__defineGetter__("getter", getterFunc); descriptorShouldBe("objectWithGetter", "'getter'", {"get": "getterFunc", "set": undefined, enumerable: true, configurable: true}); var objectWithSetter = {}; function setterFunc(){}; objectWithSetter.__defineSetter__("setter", setterFunc); descriptorShouldBe("objectWithSetter", "'setter'", {"set": "setterFunc", "get": undefined, enumerable: true, configurable: true}); var objectWithAccessor = {}; objectWithAccessor.__defineSetter__("accessor", setterFunc); objectWithAccessor.__defineGetter__("accessor", getterFunc); descriptorShouldBe("objectWithAccessor", "'accessor'", {"set": "setterFunc", "get": "getterFunc", enumerable: true, configurable: true}); shouldThrow("Object.getOwnPropertyDescriptor(null)"); shouldThrow("Object.getOwnPropertyDescriptor(undefined)"); shouldThrow("Object.getOwnPropertyDescriptor(1)"); shouldThrow("Object.getOwnPropertyDescriptor('')"); shouldThrow("Object.getOwnPropertyDescriptor(true)"); shouldThrow("Object.getOwnPropertyDescriptor(false)"); debug("Checking property ordering"); var normalOrder = ["'value'", "'writable'", "'enumerable'", "'configurable'"]; var accessorOrder = ["'get'", "'set'", "'enumerable'", "'configurable'"]; var i = 0; for (var property in Object.getOwnPropertyDescriptor(Math, "sin")) shouldBe('property', normalOrder[i++]); i = 0; for (var property in Object.getOwnPropertyDescriptor(objectWithGetter, "getter")) shouldBe('property', accessorOrder[i++]); i = 0; for (var property in Object.getOwnPropertyDescriptor(objectWithSetter, "setter")) shouldBe('property', accessorOrder[i++]); i = 0; for (var property in Object.getOwnPropertyDescriptor(objectWithAccessor, "accessor")) shouldBe('property', accessorOrder[i++]); successfullyParsed = true;