mirror of https://github.com/tc39/test262.git
326 lines
11 KiB
JavaScript
326 lines
11 KiB
JavaScript
/// Copyright (c) 2009 Microsoft Corporation
|
|
///
|
|
/// Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
|
/// that the following conditions are met:
|
|
/// * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
|
/// the following disclaimer.
|
|
/// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
|
/// the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
/// * Neither the name of Microsoft nor the names of its contributors may be used to
|
|
/// endorse or promote products derived from this software without specific prior written permission.
|
|
///
|
|
/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
/// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
/// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
/// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
/// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
/// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
/// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
function compareArray(aExpected, aActual) {
|
|
if (aActual.length != aExpected.length) {
|
|
return false;
|
|
}
|
|
|
|
aExpected.sort();
|
|
aActual.sort();
|
|
|
|
var s;
|
|
for (var i = 0; i < aExpected.length; i++) {
|
|
if (aActual[i] !== aExpected[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
function arrayContains(arr, expected) {
|
|
var found;
|
|
for (var i = 0; i < expected.length; i++) {
|
|
found = false;
|
|
for (var j = 0; j < arr.length; j++) {
|
|
if (expected[i] === arr[j]) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
var supportsArrayIndexGettersOnArrays = undefined;
|
|
function fnSupportsArrayIndexGettersOnArrays() {
|
|
if (typeof supportsArrayIndexGettersOnArrays !== "undefined") {
|
|
return supportsArrayIndexGettersOnArrays;
|
|
}
|
|
|
|
supportsArrayIndexGettersOnArrays = false;
|
|
|
|
if (fnExists(Object.defineProperty)) {
|
|
var arr = [];
|
|
Object.defineProperty(arr, "0", {
|
|
get: function() {
|
|
supportsArrayIndexGettersOnArrays = true;
|
|
return 0;
|
|
}
|
|
});
|
|
var res = arr[0];
|
|
}
|
|
|
|
return supportsArrayIndexGettersOnArrays;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
var supportsArrayIndexGettersOnObjects = undefined;
|
|
function fnSupportsArrayIndexGettersOnObjects() {
|
|
if (typeof supportsArrayIndexGettersOnObjects !== "undefined")
|
|
return supportsArrayIndexGettersOnObjects;
|
|
|
|
supportsArrayIndexGettersOnObjects = false;
|
|
|
|
if (fnExists(Object.defineProperty)) {
|
|
var obj = {};
|
|
Object.defineProperty(obj, "0", {
|
|
get: function() {
|
|
supportsArrayIndexGettersOnObjects = true;
|
|
return 0;
|
|
}
|
|
});
|
|
var res = obj[0];
|
|
}
|
|
|
|
return supportsArrayIndexGettersOnObjects;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
function ConvertToFileUrl(pathStr) {
|
|
return "file:" + pathStr.replace(/\\/g, "/");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
function fnExists(/*arguments*/) {
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
if (typeof (arguments[i]) !== "function") return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
var __globalObject = Function("return this;")();
|
|
function fnGlobalObject() {
|
|
return __globalObject;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
function fnSupportsStrict() {
|
|
"use strict";
|
|
try {
|
|
eval('with ({}) {}');
|
|
return false;
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//Verify all attributes specified data property of given object:
|
|
//value, writable, enumerable, configurable
|
|
//If all attribute values are expected, return true, otherwise, return false
|
|
function dataPropertyAttributesAreCorrect(obj,
|
|
name,
|
|
value,
|
|
writable,
|
|
enumerable,
|
|
configurable) {
|
|
var attributesCorrect = true;
|
|
|
|
if (obj[name] !== value) {
|
|
if (typeof obj[name] === "number" &&
|
|
isNaN(obj[name]) &&
|
|
typeof value === "number" &&
|
|
isNaN(value)) {
|
|
// keep empty
|
|
} else {
|
|
attributesCorrect = false;
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (obj[name] === "oldValue") {
|
|
obj[name] = "newValue";
|
|
} else {
|
|
obj[name] = "OldValue";
|
|
}
|
|
} catch (we) {
|
|
}
|
|
|
|
var overwrited = false;
|
|
if (obj[name] !== value) {
|
|
if (typeof obj[name] === "number" &&
|
|
isNaN(obj[name]) &&
|
|
typeof value === "number" &&
|
|
isNaN(value)) {
|
|
// keep empty
|
|
} else {
|
|
overwrited = true;
|
|
}
|
|
}
|
|
if (overwrited !== writable) {
|
|
attributesCorrect = false;
|
|
}
|
|
|
|
var enumerated = false;
|
|
for (var prop in obj) {
|
|
if (obj.hasOwnProperty(prop) && prop === name) {
|
|
enumerated = true;
|
|
}
|
|
}
|
|
|
|
if (enumerated !== enumerable) {
|
|
attributesCorrect = false;
|
|
}
|
|
|
|
|
|
var deleted = false;
|
|
|
|
try {
|
|
delete obj[name];
|
|
} catch (de) {
|
|
}
|
|
if (!obj.hasOwnProperty(name)) {
|
|
deleted = true;
|
|
}
|
|
if (deleted !== configurable) {
|
|
attributesCorrect = false;
|
|
}
|
|
|
|
return attributesCorrect;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//Verify all attributes specified accessor property of given object:
|
|
//get, set, enumerable, configurable
|
|
//If all attribute values are expected, return true, otherwise, return false
|
|
function accessorPropertyAttributesAreCorrect(obj,
|
|
name,
|
|
get,
|
|
set,
|
|
setVerifyHelpProp,
|
|
enumerable,
|
|
configurable) {
|
|
var attributesCorrect = true;
|
|
|
|
if (get !== undefined) {
|
|
if (obj[name] !== get()) {
|
|
if (typeof obj[name] === "number" &&
|
|
isNaN(obj[name]) &&
|
|
typeof get() === "number" &&
|
|
isNaN(get())) {
|
|
// keep empty
|
|
} else {
|
|
attributesCorrect = false;
|
|
}
|
|
}
|
|
} else {
|
|
if (obj[name] !== undefined) {
|
|
attributesCorrect = false;
|
|
}
|
|
}
|
|
|
|
try {
|
|
var desc = Object.getOwnPropertyDescriptor(obj, name);
|
|
if (typeof desc.set === "undefined") {
|
|
if (typeof set !== "undefined") {
|
|
attributesCorrect = false;
|
|
}
|
|
} else {
|
|
obj[name] = "toBeSetValue";
|
|
if (obj[setVerifyHelpProp] !== "toBeSetValue") {
|
|
attributesCorrect = false;
|
|
}
|
|
}
|
|
} catch (se) {
|
|
throw se;
|
|
}
|
|
|
|
|
|
var enumerated = false;
|
|
for (var prop in obj) {
|
|
if (obj.hasOwnProperty(prop) && prop === name) {
|
|
enumerated = true;
|
|
}
|
|
}
|
|
|
|
if (enumerated !== enumerable) {
|
|
attributesCorrect = false;
|
|
}
|
|
|
|
|
|
var deleted = false;
|
|
try {
|
|
delete obj[name];
|
|
} catch (de) {
|
|
throw de;
|
|
}
|
|
if (!obj.hasOwnProperty(name)) {
|
|
deleted = true;
|
|
}
|
|
if (deleted !== configurable) {
|
|
attributesCorrect = false;
|
|
}
|
|
|
|
return attributesCorrect;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
var NotEarlyErrorString = "NotEarlyError";
|
|
var EarlyErrorRePat = "^((?!" + NotEarlyErrorString + ").)*$";
|
|
var NotEarlyError = new Error(NotEarlyErrorString);
|
|
|
|
//--Test case registration-----------------------------------------------------
|
|
var ES5Harness = {};
|
|
ES5Harness.registerTest = function (test) {
|
|
var error;
|
|
//Has a test precondition set, but the precondition fails
|
|
if (test.precondition && !test.precondition()) {
|
|
testRun(test.id, test.path, test.description, test.test.toString(),
|
|
typeof test.precondition !== 'undefined' ? test.precondition.toString() : '',
|
|
'fail', Error('Precondition Failed'));
|
|
}
|
|
//We're good to actually run the test case
|
|
else {
|
|
try {
|
|
if (test.strict!==undefined) {
|
|
var res = test.test();
|
|
} else {
|
|
var res = test.test.call(window);
|
|
}
|
|
|
|
} catch (e) {
|
|
res = 'fail';
|
|
error = e;
|
|
if (!(e instanceof Error)) {
|
|
try {
|
|
error = Error(e.toString());
|
|
} catch (e2) {
|
|
error = Error("test262: unknown error in test case or ECMAScript implementation");
|
|
}
|
|
}
|
|
}
|
|
//Sputnik and IE Test Center tests are a bit different in terms of return values.
|
|
//That is, IE Test Center will always return 'true' IFF the test passed. Sputnik
|
|
//test cases will return either 'true' or 'undefined' if they pass.
|
|
var retVal = /^s/i.test(test.id) ? (res === true || typeof res === 'undefined' ? 'pass' : 'fail') : (res === true ? 'pass' : 'fail');
|
|
testRun(test.id, test.path, test.description, test.test.toString(),
|
|
typeof test.precondition !== 'undefined' ? test.precondition.toString() : '',
|
|
retVal, error);
|
|
}
|
|
}
|