blob: 56c055cbd91b7a87f0bc0790cd4d88400bb1b62f [file] [log] [blame]
function shouldBe(actual, expected) {
if (!Object.is(actual, expected))
throw new Error(`Bad value: ${actual}!`);
}
function shouldThrow(func, expectedError) {
let errorThrown = false;
try {
func();
} catch (error) {
errorThrown = true;
if (error.toString() !== expectedError)
throw new Error(`Bad error: ${error}!`);
}
if (!errorThrown)
throw new Error("Didn't throw!");
}
(function toPrimitiveIsNull() {
Object.defineProperty(Symbol.prototype, Symbol.toPrimitive, { value: null });
for (let i = 0; i < 1e5; ++i) {
shouldBe(Object(Symbol()) == "Symbol()", false); // hint: default
shouldThrow(() => { +Object(Symbol()); }, "TypeError: Cannot convert a symbol to a number"); // hint: number
shouldBe(`${Object(Symbol())}`, "Symbol()"); // hint: string
}
})();
(function toPrimitiveIsUndefined() {
Object.defineProperty(Symbol.prototype, Symbol.toPrimitive, { value: undefined });
for (let i = 0; i < 1e5; ++i) {
shouldBe(Object(Symbol.iterator) != Symbol.iterator, false); // hint: default
shouldThrow(() => { Object(Symbol()) <= ""; }, "TypeError: Cannot convert a symbol to a number"); // hint: number
shouldBe({ "Symbol()": 1 }[Object(Symbol())], 1); // hint: string
}
})();
delete Symbol.prototype[Symbol.toPrimitive];
let valueOfGets = 0;
let valueOfCalls = 0;
let valueOfFunction = () => { ++valueOfCalls; return 123; };
Object.defineProperty(Symbol.prototype, "valueOf", {
get: () => { ++valueOfGets; return valueOfFunction; },
});
shouldBe(Object(Symbol()) == 123, true); // hint: default
shouldBe(Object(Symbol()) - 0, 123); // hint: number
shouldBe("".concat(Object(Symbol())), "Symbol()"); // hint: string
shouldBe(valueOfGets, 2);
shouldBe(valueOfCalls, 2);
let toStringGets = 0;
let toStringCalls = 0;
let toStringFunction = () => { ++toStringCalls; return "foo"; };
Object.defineProperty(Symbol.prototype, "toString", {
get: () => { ++toStringGets; return toStringFunction; },
});
shouldBe("" + Object(Symbol()), "123"); // hint: default
shouldBe(Object(Symbol()) * 1, 123); // hint: number
shouldBe({ "123": 1, "Symbol()": 2, "foo": 3 }[Object(Symbol())], 3); // hint: string
shouldBe(valueOfGets, 4);
shouldBe(valueOfCalls, 4);
shouldBe(toStringGets, 1);
shouldBe(toStringCalls, 1);
valueOfFunction = null;
shouldBe(new Date(Object(Symbol())).getTime(), NaN); // hint: default
shouldBe(+Object(Symbol()), NaN); // hint: number
shouldBe(`${Object(Symbol())}`, "foo"); // hint: string
shouldBe(valueOfGets, 6);
shouldBe(valueOfCalls, 4);
shouldBe(toStringGets, 4);
shouldBe(toStringCalls, 4);
toStringFunction = function() { throw new Error("toString()"); };
shouldThrow(() => { Object(Symbol()) != 123; }, "Error: toString()"); // hint: default
shouldThrow(() => { Object(Symbol()) / 0; }, "Error: toString()"); // hint: number
shouldThrow(() => { "".concat(Object(Symbol())); }, "Error: toString()"); // hint: string
shouldBe(valueOfGets, 8);
shouldBe(valueOfCalls, 4);
shouldBe(toStringGets, 7);
shouldBe(toStringCalls, 4);
toStringFunction = undefined;
shouldThrow(() => { 1 + Object(Symbol()); }, "TypeError: No default value"); // hint: default
shouldThrow(() => { Number(Object(Symbol())); }, "TypeError: No default value"); // hint: number
shouldThrow(() => { String(Object(Symbol())); }, "TypeError: No default value"); // hint: string
shouldBe(valueOfGets, 11);
shouldBe(valueOfCalls, 4);
shouldBe(toStringGets, 10);
shouldBe(toStringCalls, 4);