1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/supporting/testBuiltInObject.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,124 @@ 1.4 +// Copyright 2012 Mozilla Corporation. All rights reserved. 1.5 +// This code is governed by the BSD license found in the LICENSE file. 1.6 + 1.7 +/** 1.8 + * @description Tests that obj meets the requirements for built-in objects 1.9 + * defined by the introduction of chapter 15 of the ECMAScript Language Specification. 1.10 + * @param {Object} obj the object to be tested. 1.11 + * @param {boolean} isFunction whether the specification describes obj as a function. 1.12 + * @param {boolean} isConstructor whether the specification describes obj as a constructor. 1.13 + * @param {String[]} properties an array with the names of the built-in properties of obj, 1.14 + * excluding length, prototype, or properties with non-default attributes. 1.15 + * @param {number} length for functions only: the length specified for the function 1.16 + * or derived from the argument list. 1.17 + * @author Norbert Lindenberg 1.18 + */ 1.19 + 1.20 +function testBuiltInObject(obj, isFunction, isConstructor, properties, length) { 1.21 + 1.22 + if (obj === undefined) { 1.23 + $ERROR("Object being tested is undefined."); 1.24 + } 1.25 + 1.26 + var objString = Object.prototype.toString.call(obj); 1.27 + if (isFunction) { 1.28 + if (objString !== "[object Function]") { 1.29 + $ERROR("The [[Class]] internal property of a built-in function must be " + 1.30 + "\"Function\", but toString() returns " + objString); 1.31 + } 1.32 + } else { 1.33 + if (objString !== "[object Object]") { 1.34 + $ERROR("The [[Class]] internal property of a built-in non-function object must be " + 1.35 + "\"Object\", but toString() returns " + objString); 1.36 + } 1.37 + } 1.38 + 1.39 + if (!Object.isExtensible(obj)) { 1.40 + $ERROR("Built-in objects must be extensible."); 1.41 + } 1.42 + 1.43 + if (isFunction && Object.getPrototypeOf(obj) !== Function.prototype) { 1.44 + $ERROR("Built-in functions must have Function.prototype as their prototype."); 1.45 + } 1.46 + 1.47 + if (isConstructor && Object.getPrototypeOf(obj.prototype) !== Object.prototype) { 1.48 + $ERROR("Built-in prototype objects must have Object.prototype as their prototype."); 1.49 + } 1.50 + 1.51 + // verification of the absence of the [[Construct]] internal property has 1.52 + // been moved to the end of the test 1.53 + 1.54 + // verification of the absence of the prototype property has 1.55 + // been moved to the end of the test 1.56 + 1.57 + if (isFunction) { 1.58 + 1.59 + if (typeof obj.length !== "number" || obj.length !== Math.floor(obj.length)) { 1.60 + $ERROR("Built-in functions must have a length property with an integer value."); 1.61 + } 1.62 + 1.63 + if (obj.length !== length) { 1.64 + $ERROR("Function's length property doesn't have specified value; expected " + 1.65 + length + ", got " + obj.length + "."); 1.66 + } 1.67 + 1.68 + var desc = Object.getOwnPropertyDescriptor(obj, "length"); 1.69 + if (desc.writable) { 1.70 + $ERROR("The length property of a built-in function must not be writable."); 1.71 + } 1.72 + if (desc.enumerable) { 1.73 + $ERROR("The length property of a built-in function must not be enumerable."); 1.74 + } 1.75 + if (desc.configurable) { 1.76 + $ERROR("The length property of a built-in function must not be configurable."); 1.77 + } 1.78 + } 1.79 + 1.80 + properties.forEach(function(prop) { 1.81 + var desc = Object.getOwnPropertyDescriptor(obj, prop); 1.82 + if (desc === undefined) { 1.83 + $ERROR("Missing property " + prop + "."); 1.84 + } 1.85 + // accessor properties don't have writable attribute 1.86 + if (desc.hasOwnProperty("writable") && !desc.writable) { 1.87 + $ERROR("The " + prop + " property of this built-in function must be writable."); 1.88 + } 1.89 + if (desc.enumerable) { 1.90 + $ERROR("The " + prop + " property of this built-in function must not be enumerable."); 1.91 + } 1.92 + if (!desc.configurable) { 1.93 + $ERROR("The " + prop + " property of this built-in function must be configurable."); 1.94 + } 1.95 + }); 1.96 + 1.97 + // The remaining sections have been moved to the end of the test because 1.98 + // unbound non-constructor functions written in JavaScript cannot possibly 1.99 + // pass them, and we still want to test JavaScript implementations as much 1.100 + // as possible. 1.101 + 1.102 + var exception; 1.103 + if (isFunction && !isConstructor) { 1.104 + // this is not a complete test for the presence of [[Construct]]: 1.105 + // if it's absent, the exception must be thrown, but it may also 1.106 + // be thrown if it's present and just has preconditions related to 1.107 + // arguments or the this value that this statement doesn't meet. 1.108 + try { 1.109 + /*jshint newcap:false*/ 1.110 + var instance = new obj(); 1.111 + } catch (e) { 1.112 + exception = e; 1.113 + } 1.114 + if (exception === undefined || exception.name !== "TypeError") { 1.115 + $ERROR("Built-in functions that aren't constructors must throw TypeError when " + 1.116 + "used in a \"new\" statement."); 1.117 + } 1.118 + } 1.119 + 1.120 + if (isFunction && !isConstructor && obj.hasOwnProperty("prototype")) { 1.121 + $ERROR("Built-in functions that aren't constructors must not have a prototype property."); 1.122 + } 1.123 + 1.124 + // passed the complete test! 1.125 + return true; 1.126 +} 1.127 +