diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 04bda668151d..0bc856b47e3f 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2756,18 +2756,6 @@ js::GetPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id, return true; } -bool -js::ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp) -{ - bool ok; - if (JSConvertOp op = obj->getClass()->convert) - ok = op(cx, obj, hint, vp); - else - ok = JS::OrdinaryToPrimitive(cx, obj, hint, vp); - MOZ_ASSERT_IF(ok, vp.isPrimitive()); - return ok; -} - bool js::WatchGuts(JSContext* cx, JS::HandleObject origObj, JS::HandleId id, JS::HandleObject callable) { @@ -2975,6 +2963,47 @@ JS::OrdinaryToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHan return false; } +bool +js::ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp) +{ + bool ok; + if (JSConvertOp op = obj->getClass()->convert) + ok = op(cx, obj, hint, vp); + else + ok = JS::OrdinaryToPrimitive(cx, obj, hint, vp); + MOZ_ASSERT_IF(ok, vp.isPrimitive()); + return ok; +} + +bool +js::ToPrimitiveSlow(JSContext* cx, MutableHandleValue vp) +{ + JSObject* obj = &vp.toObject(); + + /* Optimize new String(...).valueOf(). */ + if (obj->is()) { + jsid id = NameToId(cx->names().valueOf); + StringObject* nobj = &obj->as(); + if (ClassMethodIsNative(cx, nobj, &StringObject::class_, id, str_toString)) { + vp.setString(nobj->unbox()); + return true; + } + } + + /* Optimize new Number(...).valueOf(). */ + if (obj->is()) { + jsid id = NameToId(cx->names().valueOf); + NumberObject* nobj = &obj->as(); + if (ClassMethodIsNative(cx, nobj, &NumberObject::class_, id, num_valueOf)) { + vp.setNumber(nobj->unbox()); + return true; + } + } + + RootedObject objRoot(cx, obj); + return ToPrimitive(cx, objRoot, JSTYPE_VOID, vp); +} + bool js::IsDelegate(JSContext* cx, HandleObject obj, const js::Value& v, bool* result) { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 59988b2ebbae..b195a15649c6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1008,18 +1008,30 @@ WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject callabl extern bool UnwatchProperty(JSContext* cx, HandleObject obj, HandleId id); -/* - * ToPrimitive support, currently implemented like an internal method (JSClass::convert). - * In ES6 this is just a method, @@toPrimitive. See bug 1054756. - */ +/* ES6 draft rev 36 (2015 March 17) 7.1.1 ToPrimitive(vp, preferredType) */ +extern bool +ToPrimitiveSlow(JSContext* cx, MutableHandleValue vp); + +inline bool +ToPrimitive(JSContext* cx, MutableHandleValue vp) +{ + if (vp.isPrimitive()) + return true; + return ToPrimitiveSlow(cx, vp); +} + extern bool ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp); -MOZ_ALWAYS_INLINE bool -ToPrimitive(JSContext* cx, MutableHandleValue vp); - -MOZ_ALWAYS_INLINE bool -ToPrimitive(JSContext* cx, JSType preferredType, MutableHandleValue vp); +inline bool +ToPrimitive(JSContext* cx, JSType preferredType, MutableHandleValue vp) +{ + MOZ_ASSERT(preferredType != JSTYPE_VOID); // Use the other ToPrimitive! + if (vp.isPrimitive()) + return true; + RootedObject obj(cx, &vp.toObject()); + return ToPrimitive(cx, obj, preferredType, vp); +} /* * toString support. (This isn't called GetClassName because there's a macro in diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 3dfadaf2cdd0..a197a9484a7c 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -567,50 +567,6 @@ HasObjectValueOf(JSObject* obj, JSContext* cx) return IsNativeFunction(v, obj_valueOf); } -/* ES5 9.1 ToPrimitive(input). */ -MOZ_ALWAYS_INLINE bool -ToPrimitive(JSContext* cx, MutableHandleValue vp) -{ - if (vp.isPrimitive()) - return true; - - JSObject* obj = &vp.toObject(); - - /* Optimize new String(...).valueOf(). */ - if (obj->is()) { - jsid id = NameToId(cx->names().valueOf); - StringObject* nobj = &obj->as(); - if (ClassMethodIsNative(cx, nobj, &StringObject::class_, id, str_toString)) { - vp.setString(nobj->unbox()); - return true; - } - } - - /* Optimize new Number(...).valueOf(). */ - if (obj->is()) { - jsid id = NameToId(cx->names().valueOf); - NumberObject* nobj = &obj->as(); - if (ClassMethodIsNative(cx, nobj, &NumberObject::class_, id, num_valueOf)) { - vp.setNumber(nobj->unbox()); - return true; - } - } - - RootedObject objRoot(cx, obj); - return ToPrimitive(cx, objRoot, JSTYPE_VOID, vp); -} - -/* ES5 9.1 ToPrimitive(input, PreferredType). */ -MOZ_ALWAYS_INLINE bool -ToPrimitive(JSContext* cx, JSType preferredType, MutableHandleValue vp) -{ - MOZ_ASSERT(preferredType != JSTYPE_VOID); /* Use the other ToPrimitive! */ - if (vp.isPrimitive()) - return true; - RootedObject obj(cx, &vp.toObject()); - return ToPrimitive(cx, obj, preferredType, vp); -} - /* ES6 draft rev 28 (2014 Oct 14) 7.1.14 */ inline bool ToPropertyKey(JSContext* cx, Value argument, MutableHandleId result)