mirror of
https://github.com/tc39/test262.git
synced 2025-07-22 21:45:04 +02:00
use informative stack traces instead of loops
This commit is contained in:
parent
29938e9525
commit
0f3f22f6ab
@ -6,249 +6,219 @@ description: |
|
|||||||
operations like ToNumber.
|
operations like ToNumber.
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
function getValuesCoercibleToIntegerZero() {
|
function testCoercibleToIntegerZero(test) {
|
||||||
var result = [];
|
function testPrimitiveValue(value) {
|
||||||
|
test(value);
|
||||||
|
// ToPrimitive
|
||||||
|
testPrimitiveWrappers(value, "number", test);
|
||||||
|
}
|
||||||
|
|
||||||
var primitiveValues = [
|
// ToNumber
|
||||||
// ToNumber
|
testPrimitiveValue(null);
|
||||||
null,
|
testPrimitiveValue(false);
|
||||||
false,
|
testPrimitiveValue(0);
|
||||||
0,
|
testPrimitiveValue("0");
|
||||||
"0",
|
|
||||||
|
|
||||||
// ToInteger: NaN -> +0
|
// ToInteger: NaN -> +0
|
||||||
undefined,
|
testPrimitiveValue(undefined);
|
||||||
NaN,
|
testPrimitiveValue(NaN);
|
||||||
"",
|
testPrimitiveValue("");
|
||||||
"foo",
|
testPrimitiveValue("foo");
|
||||||
"true",
|
testPrimitiveValue("true");
|
||||||
|
|
||||||
// ToInteger: floor(abs(number))
|
// ToInteger: floor(abs(number))
|
||||||
0.9,
|
testPrimitiveValue(0.9);
|
||||||
-0,
|
testPrimitiveValue(-0);
|
||||||
-0.9,
|
testPrimitiveValue(-0.9);
|
||||||
"0.9",
|
testPrimitiveValue("0.9");
|
||||||
"-0",
|
testPrimitiveValue("-0");
|
||||||
"-0.9",
|
testPrimitiveValue("-0.9");
|
||||||
];
|
|
||||||
|
|
||||||
// ToPrimitive
|
|
||||||
primitiveValues.forEach(function(zero) {
|
|
||||||
result.push(zero);
|
|
||||||
result = result.concat(getPrimitiveWrappers(zero, "number"));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Non-primitive values that coerce to 0:
|
// Non-primitive values that coerce to 0:
|
||||||
// toString() returns a string that parses to NaN.
|
// toString() returns a string that parses to NaN.
|
||||||
result = result.concat([
|
test({});
|
||||||
{},
|
test([]);
|
||||||
[],
|
|
||||||
]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValuesCoercibleToIntegerOne() {
|
function testCoercibleToIntegerOne(test) {
|
||||||
var result = [];
|
function testPrimitiveValue(value) {
|
||||||
|
test(value);
|
||||||
|
// ToPrimitive
|
||||||
|
testPrimitiveWrappers(value, "number", test);
|
||||||
|
}
|
||||||
|
|
||||||
var primitiveValues = [
|
// ToNumber
|
||||||
// ToNumber
|
testPrimitiveValue(true);
|
||||||
true,
|
testPrimitiveValue(1);
|
||||||
1,
|
testPrimitiveValue("1");
|
||||||
"1",
|
|
||||||
|
|
||||||
// ToInteger: floor(abs(number))
|
// ToInteger: floor(abs(number))
|
||||||
1.9,
|
testPrimitiveValue(1.9);
|
||||||
"1.9",
|
testPrimitiveValue("1.9");
|
||||||
];
|
|
||||||
|
|
||||||
// ToPrimitive
|
|
||||||
primitiveValues.forEach(function(value) {
|
|
||||||
result.push(value);
|
|
||||||
result = result.concat(getPrimitiveWrappers(value, "number"));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Non-primitive values that coerce to 1:
|
// Non-primitive values that coerce to 1:
|
||||||
// toString() returns a string that parses to 1.
|
// toString() returns a string that parses to 1.
|
||||||
result = result.concat([
|
test([1]);
|
||||||
[1],
|
test(["1"]);
|
||||||
["1"],
|
|
||||||
]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValuesCoercibleToIntegerFromInteger(nominalInteger) {
|
function testCoercibleToIntegerFromInteger(nominalInteger, test) {
|
||||||
assert(Number.isInteger(nominalInteger));
|
assert(Number.isInteger(nominalInteger));
|
||||||
var result = [];
|
|
||||||
|
|
||||||
var primitiveValues = [ nominalInteger ];
|
function testPrimitiveValue(value) {
|
||||||
|
test(value);
|
||||||
|
// ToPrimitive
|
||||||
|
testPrimitiveWrappers(value, "number", test);
|
||||||
|
|
||||||
|
// Non-primitive values that coerce to the nominal integer:
|
||||||
|
// toString() returns a string that parsers to a primitive value.
|
||||||
|
test([value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPrimitiveNumber(number) {
|
||||||
|
testPrimitiveValue(number);
|
||||||
|
// ToNumber: String -> Number
|
||||||
|
testPrimitiveValue(number.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
testPrimitiveNumber(nominalInteger);
|
||||||
|
|
||||||
// ToInteger: floor(abs(number))
|
// ToInteger: floor(abs(number))
|
||||||
if (nominalInteger >= 0) {
|
if (nominalInteger >= 0) {
|
||||||
primitiveValues.push(nominalInteger + 0.9);
|
testPrimitiveNumber(nominalInteger + 0.9);
|
||||||
}
|
}
|
||||||
if (nominalInteger <= 0) {
|
if (nominalInteger <= 0) {
|
||||||
primitiveValues.push(nominalInteger - 0.9);
|
testPrimitiveNumber(nominalInteger - 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToNumber: String -> Number
|
|
||||||
primitiveValues = primitiveValues.concat(primitiveValues.map(function(number) { return number.toString(); }));
|
|
||||||
|
|
||||||
// ToPrimitive
|
|
||||||
primitiveValues.forEach(function(value) {
|
|
||||||
result.push(value);
|
|
||||||
result = result.concat(getPrimitiveWrappers(value, "number"));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Non-primitive values that coerce to the nominal integer:
|
|
||||||
// toString() returns a string that parsers to a primitive value.
|
|
||||||
result = result.concat(primitiveValues.map(function(number) { return [number]; }));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrimitiveWrappers(primitiveValue, hint) {
|
function testPrimitiveWrappers(primitiveValue, hint, test) {
|
||||||
assert(hint === "number" || hint === "string");
|
|
||||||
var result = [];
|
|
||||||
|
|
||||||
if (primitiveValue != null) {
|
if (primitiveValue != null) {
|
||||||
// null and undefined result in {} rather than a proper wrapper,
|
// null and undefined result in {} rather than a proper wrapper,
|
||||||
// so skip this case for those values.
|
// so skip this case for those values.
|
||||||
result.push(Object(primitiveValue));
|
test(Object(primitiveValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.concat(getValuesCoercibleToPrimitiveWithMethod(hint, function() {
|
testCoercibleToPrimitiveWithMethod(hint, function() {
|
||||||
return primitiveValue;
|
return primitiveValue;
|
||||||
}));
|
}, test);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValuesCoercibleToPrimitiveWithMethod(hint, method) {
|
function testCoercibleToPrimitiveWithMethod(hint, method, test) {
|
||||||
var methodNames;
|
var methodNames;
|
||||||
if (hint === "number") {
|
if (hint === "number") {
|
||||||
methodNames = ["valueOf", "toString"];
|
methodNames = ["valueOf", "toString"];
|
||||||
} else {
|
} else if (hint === "string") {
|
||||||
methodNames = ["toString", "valueOf"];
|
methodNames = ["toString", "valueOf"];
|
||||||
|
} else {
|
||||||
|
throw new Test262Error();
|
||||||
}
|
}
|
||||||
return [
|
// precedence order
|
||||||
// precedence order
|
test({
|
||||||
{
|
[Symbol.toPrimitive]: method,
|
||||||
[Symbol.toPrimitive]: method,
|
[methodNames[0]]: function() { throw new Test262Error(); },
|
||||||
[methodNames[0]]: function() { throw new Test262Error(); },
|
[methodNames[1]]: function() { throw new Test262Error(); },
|
||||||
[methodNames[1]]: function() { throw new Test262Error(); },
|
});
|
||||||
}, {
|
test({
|
||||||
[methodNames[0]]: method,
|
[methodNames[0]]: method,
|
||||||
[methodNames[1]]: function() { throw new Test262Error(); },
|
[methodNames[1]]: function() { throw new Test262Error(); },
|
||||||
}, {
|
});
|
||||||
[methodNames[1]]: method,
|
test({
|
||||||
},
|
[methodNames[1]]: method,
|
||||||
|
});
|
||||||
|
|
||||||
// GetMethod: if func is undefined or null, return undefined.
|
// GetMethod: if func is undefined or null, return undefined.
|
||||||
{
|
test({
|
||||||
[Symbol.toPrimitive]: undefined,
|
[Symbol.toPrimitive]: undefined,
|
||||||
[methodNames[0]]: method,
|
[methodNames[0]]: method,
|
||||||
[methodNames[1]]: method,
|
[methodNames[1]]: method,
|
||||||
}, {
|
});
|
||||||
[Symbol.toPrimitive]: null,
|
test({
|
||||||
[methodNames[0]]: method,
|
[Symbol.toPrimitive]: null,
|
||||||
[methodNames[1]]: method,
|
[methodNames[0]]: method,
|
||||||
},
|
[methodNames[1]]: method,
|
||||||
|
});
|
||||||
|
|
||||||
// if methodNames[0] is not callable, fallback to methodNames[1]
|
// if methodNames[0] is not callable, fallback to methodNames[1]
|
||||||
{
|
test({
|
||||||
[methodNames[0]]: null,
|
[methodNames[0]]: null,
|
||||||
[methodNames[1]]: method,
|
[methodNames[1]]: method,
|
||||||
}, {
|
});
|
||||||
[methodNames[0]]: 1,
|
test({
|
||||||
[methodNames[1]]: method,
|
[methodNames[0]]: 1,
|
||||||
}, {
|
[methodNames[1]]: method,
|
||||||
[methodNames[0]]: {},
|
});
|
||||||
[methodNames[1]]: method,
|
test({
|
||||||
},
|
[methodNames[0]]: {},
|
||||||
|
[methodNames[1]]: method,
|
||||||
|
});
|
||||||
|
|
||||||
// if methodNames[0] returns an object, fallback to methodNames[1]
|
// if methodNames[0] returns an object, fallback to methodNames[1]
|
||||||
{
|
test({
|
||||||
[methodNames[0]]: function() { return {}; },
|
[methodNames[0]]: function() { return {}; },
|
||||||
[methodNames[1]]: method,
|
[methodNames[1]]: method,
|
||||||
}, {
|
});
|
||||||
[methodNames[0]]: function() { return Object(1); },
|
test({
|
||||||
[methodNames[1]]: method,
|
[methodNames[0]]: function() { return Object(1); },
|
||||||
},
|
[methodNames[1]]: method,
|
||||||
];
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValuesNotCoercibleToInteger() {
|
function testNotCoercibleToInteger(test) {
|
||||||
// ToInteger only throws from ToNumber.
|
// ToInteger only throws from ToNumber.
|
||||||
return getValuesNotCoercibleToNumber();
|
return testNotCoercibleToNumber(test);
|
||||||
}
|
}
|
||||||
function getValuesNotCoercibleToNumber() {
|
function testNotCoercibleToNumber(test) {
|
||||||
var result = [];
|
function testPrimitiveValue(value) {
|
||||||
|
test(TypeError, value);
|
||||||
|
// ToPrimitive
|
||||||
|
testPrimitiveWrappers(value, "number", function(value) {
|
||||||
|
test(TypeError, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ToNumber: Symbol -> TypeError
|
// ToNumber: Symbol -> TypeError
|
||||||
var primitiveValues = [
|
testPrimitiveValue(Symbol("1"));
|
||||||
Symbol("1"),
|
|
||||||
];
|
|
||||||
if (typeof BigInt !== "undefined") {
|
if (typeof BigInt !== "undefined") {
|
||||||
// ToNumber: BigInt -> TypeError
|
// ToNumber: BigInt -> TypeError
|
||||||
primitiveValues.push(BigInt(0));
|
testPrimitiveValue(BigInt(0));
|
||||||
}
|
}
|
||||||
primitiveValues.forEach(function(value) {
|
|
||||||
result.push({error:TypeError, value:value});
|
|
||||||
getPrimitiveWrappers(value, "number").forEach(function(value) {
|
|
||||||
result.push({error:TypeError, value:value});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ToPrimitive
|
// ToPrimitive
|
||||||
result = result.concat(getValuesNotCoercibleToPrimitive("number"));
|
testNotCoercibleToPrimitive("number", test);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValuesNotCoercibleToPrimitive(hint) {
|
function testNotCoercibleToPrimitive(hint, test) {
|
||||||
function MyError() {}
|
function MyError() {}
|
||||||
|
|
||||||
var result = [];
|
|
||||||
|
|
||||||
var methodNames;
|
|
||||||
if (hint === "number") {
|
|
||||||
methodNames = ["valueOf", "toString"];
|
|
||||||
} else {
|
|
||||||
methodNames = ["toString", "valueOf"];
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToPrimitive: input[@@toPrimitive] is not callable (and non-null)
|
// ToPrimitive: input[@@toPrimitive] is not callable (and non-null)
|
||||||
result.push({error:TypeError, value:{[Symbol.toPrimitive]: 1}});
|
test(TypeError, {[Symbol.toPrimitive]: 1});
|
||||||
result.push({error:TypeError, value:{[Symbol.toPrimitive]: {}}});
|
test(TypeError, {[Symbol.toPrimitive]: {}});
|
||||||
|
|
||||||
// ToPrimitive: input[@@toPrimitive] returns object
|
// ToPrimitive: input[@@toPrimitive] returns object
|
||||||
result.push({error:TypeError, value:{[Symbol.toPrimitive]: function() { return Object(1); }}});
|
test(TypeError, {[Symbol.toPrimitive]: function() { return Object(1); }});
|
||||||
result.push({error:TypeError, value:{[Symbol.toPrimitive]: function() { return {}; }}});
|
test(TypeError, {[Symbol.toPrimitive]: function() { return {}; }});
|
||||||
|
|
||||||
// ToPrimitive: input[@@toPrimitive] throws
|
// ToPrimitive: input[@@toPrimitive] throws
|
||||||
result.push({error:MyError, value:{[Symbol.toPrimitive]: function() { throw new MyError(); }}});
|
test(MyError, {[Symbol.toPrimitive]: function() { throw new MyError(); }});
|
||||||
|
|
||||||
// OrdinaryToPrimitive: method throws
|
// OrdinaryToPrimitive: method throws
|
||||||
result = result.concat(getValuesCoercibleToPrimitiveWithMethod(hint, function() {
|
testCoercibleToPrimitiveWithMethod(hint, function() {
|
||||||
throw new MyError();
|
throw new MyError();
|
||||||
}).map(function(value) {
|
}, function(value) {
|
||||||
return {error:MyError, value:value};
|
test(MyError, value);
|
||||||
}));
|
|
||||||
|
|
||||||
// OrdinaryToPrimitive: both methods are unsuitable
|
|
||||||
var unsuitableMethods = [
|
|
||||||
// not callable:
|
|
||||||
null,
|
|
||||||
1,
|
|
||||||
{},
|
|
||||||
// returns object:
|
|
||||||
function() { return Object(1); },
|
|
||||||
function() { return {}; },
|
|
||||||
];
|
|
||||||
unsuitableMethods.forEach(function(method) {
|
|
||||||
result.push({error:TypeError, value:{valueOf:method, toString:method}});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
// OrdinaryToPrimitive: both methods are unsuitable
|
||||||
|
function testUnsuitableMethod(method) {
|
||||||
|
test(TypeError, {valueOf:method, toString:method});
|
||||||
|
}
|
||||||
|
// not callable:
|
||||||
|
testUnsuitableMethod(null);
|
||||||
|
testUnsuitableMethod(1);
|
||||||
|
testUnsuitableMethod({});
|
||||||
|
// returns object:
|
||||||
|
testUnsuitableMethod(function() { return Object(1); });
|
||||||
|
testUnsuitableMethod(function() { return {}; });
|
||||||
}
|
}
|
||||||
|
@ -11,20 +11,18 @@ info: >
|
|||||||
includes: [typeCoercion.js]
|
includes: [typeCoercion.js]
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
getValuesCoercibleToIntegerZero().forEach(function(zero) {
|
testCoercibleToIntegerZero(function(zero) {
|
||||||
assert.sameValue("aaaa".indexOf("aa", zero), 0, "with value " + zero);
|
assert.sameValue("aaaa".indexOf("aa", zero), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
getValuesCoercibleToIntegerOne().forEach(function(one) {
|
testCoercibleToIntegerOne(function(one) {
|
||||||
assert.sameValue("aaaa".indexOf("aa", one), 1, "with value " + one);
|
assert.sameValue("aaaa".indexOf("aa", one), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
getValuesCoercibleToIntegerFromInteger(2).forEach(function(two) {
|
testCoercibleToIntegerFromInteger(2, function(two) {
|
||||||
assert.sameValue("aaaa".indexOf("aa", two), 2, "with value " + two);
|
assert.sameValue("aaaa".indexOf("aa", two), 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
getValuesNotCoercibleToInteger().forEach(function(pair) {
|
testNotCoercibleToInteger(function(error, value) {
|
||||||
var error = pair.error;
|
|
||||||
var value = pair.value;
|
|
||||||
assert.throws(error, function() { "".indexOf("", value); });
|
assert.throws(error, function() { "".indexOf("", value); });
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user