Bug 645416, part 17 - Implement ToPrimitive on Symbol wrapper objects. r=sfink.

The spec defines this by way of a @@toPrimitive method. We fake it using a
JSClass::convert hook. (Once @@toPrimitive is implemented, convert hooks
can be removed entirely, but we need symbols first.)

--HG--
extra : rebase_source : c8c7ed3eead8bd79bb38b70f448ebb98c5b3d780
This commit is contained in:
Jason Orendorff 2014-06-23 10:56:51 -05:00
parent 0ff275fd1e
commit 893e2556d3
5 changed files with 32 additions and 2 deletions

View File

@ -24,7 +24,7 @@ const Class SymbolObject::class_ = {
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
convert
};
SymbolObject *
@ -121,6 +121,14 @@ SymbolObject::construct(JSContext *cx, unsigned argc, Value *vp)
return true;
}
// Stand-in for Symbol.prototype[@@toPrimitive], ES6 rev 25 (2014 May 22) 19.4.3.4
bool
SymbolObject::convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SYMBOL_TO_PRIMITIVE);
return false;
}
// ES6 rev 24 (2014 Apr 27) 19.4.2.2
bool
SymbolObject::for_(JSContext *cx, unsigned argc, Value *vp)

View File

@ -42,6 +42,8 @@ class SymbolObject : public JSObject
static bool construct(JSContext *cx, unsigned argc, Value *vp);
static bool convert(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp);
// Static methods.
static bool for_(JSContext *cx, unsigned argc, Value *vp);

View File

@ -239,7 +239,7 @@ MSG_DEF(JSMSG_CANT_REPORT_AS_NON_EXTENSIBLE, 185, 0, JSEXN_TYPEERR, "proxy can't
MSG_DEF(JSMSG_SYMBOL_TO_STRING, 186, 0, JSEXN_TYPEERR, "can't convert symbol to string")
MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
MSG_DEF(JSMSG_UNUSED189, 189, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_SYMBOL_TO_PRIMITIVE, 189, 0, JSEXN_TYPEERR, "can't convert symbol object to primitive")
MSG_DEF(JSMSG_UNUSED190, 190, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_INDEX, 191, 0, JSEXN_RANGEERR, "invalid or out-of-range index")
MSG_DEF(JSMSG_UNUSED192, 192, 0, JSEXN_NONE, "")

View File

@ -13,6 +13,8 @@ assertEq(Symbol(7).toString(), "Symbol(7)");
assertEq(Symbol(true).toString(), "Symbol(true)");
assertEq(Symbol(null).toString(), "Symbol(null)");
assertEq(Symbol([1, 2]).toString(), "Symbol(1,2)");
var symobj = Object(sym);
assertThrowsInstanceOf(() => Symbol(symobj), TypeError);
var hits = 0;
var obj = {

View File

@ -7,7 +7,25 @@ var symbols = [
Symbol.iterator
];
if (Symbol.toPrimitive in Symbol.prototype) {
// We should test that deleting Symbol.prototype[@@toPrimitive] changes the
// behavior of ToPrimitive on Symbol objects, but @@toPrimitive is not
// implemented yet.
throw new Error("Congratulations on implementing @@toPrimitive! Please update this test.");
}
for (var sym of symbols) {
// 7.1.1 ToPrimitive
var symobj = Object(sym);
assertThrowsInstanceOf(() => Number(symobj), TypeError);
assertThrowsInstanceOf(() => String(symobj), TypeError);
assertThrowsInstanceOf(() => symobj < 0, TypeError);
assertThrowsInstanceOf(() => 0 < symobj, TypeError);
assertThrowsInstanceOf(() => symobj == 0, TypeError);
assertThrowsInstanceOf(() => 0 != symobj, TypeError);
assertThrowsInstanceOf(() => symobj + 1, TypeError);
assertThrowsInstanceOf(() => "" + symobj, TypeError);
// 7.1.2 ToBoolean
assertEq(Boolean(sym), true);
assertEq(!sym, false);