// Check all the algorithms that call ToPrimitive. Confirm that they're passing
// the correct hint, per spec.

var STRING = "xyzzy";
var NUMBER = 42;

function assertCallsToPrimitive(f, expectedHint, expectedResult) {
    var hint = undefined;
    var testObj = {
        [Symbol.toPrimitive](h) {
            assertEq(hint, undefined);
            hint = h;
            return h === "number" ? NUMBER : STRING;
        }
    };
    var result = f(testObj);
    assertEq(hint, expectedHint, String(f));
    assertEq(result, expectedResult, String(f));
}

// ToNumber
assertCallsToPrimitive(Number, "number", NUMBER);

// ToString
assertCallsToPrimitive(String, "string", STRING);

// ToPropertyKey
var obj = {[STRING]: "pass"};
assertCallsToPrimitive(key => obj[key], "string", "pass");

// Abstract Relational Comparison
assertCallsToPrimitive(x => x >= 42, "number", true);
assertCallsToPrimitive(x => x > "42", "number", false);

// Abstract Equality Comparison
assertCallsToPrimitive(x => x != STRING, "default", false);
assertCallsToPrimitive(x => STRING == x, "default", true);
assertCallsToPrimitive(x => x == NUMBER, "default", false);
assertCallsToPrimitive(x => NUMBER != x, "default", true);

// Addition
assertCallsToPrimitive(x => 1 + x, "default", "1" + STRING);
assertCallsToPrimitive(x => "" + x, "default", STRING);

// Date constructor
assertCallsToPrimitive(x => (new Date(x)).valueOf(), "default", Number(STRING));

// Date.prototype.toJSON
var expected = "a suffusion of yellow";
function testJSON(x) {
    x.toJSON = Date.prototype.toJSON;
    x.toISOString = function () { return expected; };
    return JSON.stringify(x);
}
assertCallsToPrimitive(testJSON, "number", JSON.stringify(expected));

reportCompare(0, 0);
