bool BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp) { InvokeArgsGuard ag; if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) return false; ag.calleev() = cx->compartment->maybeGlobal()->booleanValueOf(); ag.thisv().setObject(obj); if (!Invoke(cx, ag)) return false; *vp = ag.rval(); return true; }
bool BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp) { JS_ASSERT(ObjectClassIs(obj, ESClass_Boolean, cx)); JS_ASSERT(obj.isProxy()); /* * To respect the proxy abstraction, we can't simply unwrap and call * getPrimitiveThis on the wrapped object. All we know is that obj says * its [[Class]] is "Boolean". Boolean.prototype.valueOf is specified to * return the [[PrimitiveValue]] internal property, so call that instead. */ InvokeArgsGuard ag; if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) return false; ag.calleev().setUndefined(); ag.thisv().setObject(obj); if (!GetProxyHandler(&obj)->nativeCall(cx, &obj, &BooleanClass, bool_valueOf, ag)) return false; *vp = ag.rval(); return true; }
static bool PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, Value *vp, StringifyContext *scx) { JSString *keyStr = NULL; /* Step 2. */ if (vp->isObject()) { Value toJSON; jsid id = NameToId(cx->runtime->atomState.toJSONAtom); if (!js_GetMethod(cx, RootedVarObject(cx, &vp->toObject()), id, 0, &toJSON)) return false; if (js_IsCallable(toJSON)) { keyStr = KeyStringifier<KeyType>::toString(cx, key); if (!keyStr) return false; InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 1, &args)) return false; args.calleev() = toJSON; args.thisv() = *vp; args[0] = StringValue(keyStr); if (!Invoke(cx, args)) return false; *vp = args.rval(); } } /* Step 3. */ if (scx->replacer && scx->replacer->isCallable()) { if (!keyStr) { keyStr = KeyStringifier<KeyType>::toString(cx, key); if (!keyStr) return false; } InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 2, &args)) return false; args.calleev() = ObjectValue(*scx->replacer); args.thisv() = ObjectValue(*holder); args[0] = StringValue(keyStr); args[1] = *vp; if (!Invoke(cx, args)) return false; *vp = args.rval(); } /* Step 4. */ if (vp->isObject()) { JSObject &obj = vp->toObject(); if (ObjectClassIs(obj, ESClass_Number, cx)) { double d; if (!ToNumber(cx, *vp, &d)) return false; vp->setNumber(d); } else if (ObjectClassIs(obj, ESClass_String, cx)) { JSString *str = ToStringSlow(cx, *vp); if (!str) return false; vp->setString(str); } else if (ObjectClassIs(obj, ESClass_Boolean, cx)) { if (!BooleanGetPrimitiveValue(cx, obj, vp)) return false; JS_ASSERT(vp->isBoolean()); } } return true; }
bool js::SetElement(JSContext *cx, ObjectImpl *obj, ObjectImpl *receiver, uint32_t index, const Value &v, bool *succeeded) { NEW_OBJECT_REPRESENTATION_ONLY(); do { MOZ_ASSERT(obj); if (static_cast<JSObject *>(obj)->isProxy()) { // XXX MOZ_NOT_REACHED("NYI: proxy [[SetP]]"); return false; } PropDesc ownDesc; if (!GetOwnElement(cx, obj, index, &ownDesc)) return false; if (!ownDesc.isUndefined()) { if (ownDesc.isDataDescriptor()) { if (!ownDesc.writable()) { *succeeded = false; return true; } if (receiver == obj) { PropDesc updateDesc = PropDesc::valueOnly(v); return DefineElement(cx, receiver, index, updateDesc, false, succeeded); } PropDesc newDesc; return DefineElement(cx, receiver, index, newDesc, false, succeeded); } if (ownDesc.isAccessorDescriptor()) { Value setter = ownDesc.setterValue(); if (setter.isUndefined()) { *succeeded = false; return true; } InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 1, &args)) return false; /* Push set, receiver, and v as the sole argument. */ args.calleev() = setter; args.thisv() = ObjectValue(*receiver); args[0] = v; *succeeded = true; return Invoke(cx, args); } MOZ_NOT_REACHED("NYI: setting PropertyOp-based property"); return false; } obj = obj->getProto(); if (obj) continue; PropDesc newDesc(v, PropDesc::Writable, PropDesc::Enumerable, PropDesc::Configurable); return DefineElement(cx, receiver, index, newDesc, false, succeeded); } while (false); MOZ_NOT_REACHED("buggy control flow"); return false; }
bool js::GetElement(JSContext *cx, ObjectImpl *obj, ObjectImpl *receiver, uint32_t index, Value *vp) { NEW_OBJECT_REPRESENTATION_ONLY(); do { MOZ_ASSERT(obj); if (static_cast<JSObject *>(obj)->isProxy()) { // XXX MOZ_NOT_REACHED("NYI: proxy [[GetP]]"); return false; } PropDesc desc; if (!GetOwnElement(cx, obj, index, &desc)) return false; /* No property? Recur or bottom out. */ if (desc.isUndefined()) { obj = obj->getProto(); if (obj) continue; vp->setUndefined(); return true; } /* If it's a data property, return the value. */ if (desc.isDataDescriptor()) { *vp = desc.value(); return true; } /* If it's an accessor property, call its [[Get]] with the receiver. */ if (desc.isAccessorDescriptor()) { Value get = desc.getterValue(); if (get.isUndefined()) { vp->setUndefined(); return true; } InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 0, &args)) return false; /* Push get, receiver, and no args. */ args.calleev() = get; args.thisv() = ObjectValue(*receiver); bool ok = Invoke(cx, args); *vp = args.rval(); return ok; } /* Otherwise it's a PropertyOp-based property. XXX handle this! */ MOZ_NOT_REACHED("NYI: handle PropertyOp'd properties here"); return false; } while (false); MOZ_NOT_REACHED("buggy control flow"); return false; }
/* * ES5 15.12.3 Str, steps 2-4, extracted to enable preprocessing of property * values when stringifying objects in JO. */ static bool PreprocessValue(JSContext *cx, JSObject *holder, jsid key, Value *vp, StringifyContext *scx) { JSString *keyStr = NULL; /* Step 2. */ if (vp->isObject()) { Value toJSON; jsid id = ATOM_TO_JSID(cx->runtime->atomState.toJSONAtom); if (!js_GetMethod(cx, &vp->toObject(), id, JSGET_NO_METHOD_BARRIER, &toJSON)) return false; if (js_IsCallable(toJSON)) { keyStr = IdToString(cx, key); if (!keyStr) return false; LeaveTrace(cx); InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 1, &args)) return false; args.calleev() = toJSON; args.thisv() = *vp; args[0] = StringValue(keyStr); if (!Invoke(cx, args)) return false; *vp = args.rval(); } } /* Step 3. */ if (scx->replacer && scx->replacer->isCallable()) { if (!keyStr) { keyStr = IdToString(cx, key); if (!keyStr) return false; } LeaveTrace(cx); InvokeArgsGuard args; if (!cx->stack.pushInvokeArgs(cx, 2, &args)) return false; args.calleev() = ObjectValue(*scx->replacer); args.thisv() = ObjectValue(*holder); args[0] = StringValue(keyStr); args[1] = *vp; if (!Invoke(cx, args)) return false; *vp = args.rval(); } /* Step 4. */ if (vp->isObject()) { JSObject *obj = &vp->toObject(); Class *clasp = obj->getClass(); if (clasp == &js_NumberClass) { double d; if (!ValueToNumber(cx, *vp, &d)) return false; vp->setNumber(d); } else if (clasp == &js_StringClass) { JSString *str = js_ValueToString(cx, *vp); if (!str) return false; vp->setString(str); } else if (clasp == &js_BooleanClass) { *vp = obj->getPrimitiveThis(); JS_ASSERT(vp->isBoolean()); } } return true; }