bool
JavaScriptShared::toDescriptor(JSContext* cx, const PPropertyDescriptor& in,
                               MutableHandle<JSPropertyDescriptor> out)
{
    out.setAttributes(in.attrs());
    if (!fromVariant(cx, in.value(), out.value()))
        return false;
    out.object().set(fromObjectOrNullVariant(cx, in.obj()));

    if (in.getter().type() == GetterSetter::Tuint64_t && !in.getter().get_uint64_t()) {
        out.setGetter(nullptr);
    } else if (in.attrs() & JSPROP_GETTER) {
        Rooted<JSObject*> getter(cx);
        getter = fromObjectVariant(cx, in.getter().get_ObjectVariant());
        if (!getter)
            return false;
        out.setGetter(JS_DATA_TO_FUNC_PTR(JSGetterOp, getter.get()));
    } else {
        out.setGetter(UnknownPropertyStub);
    }

    if (in.setter().type() == GetterSetter::Tuint64_t && !in.setter().get_uint64_t()) {
        out.setSetter(nullptr);
    } else if (in.attrs() & JSPROP_SETTER) {
        Rooted<JSObject*> setter(cx);
        setter = fromObjectVariant(cx, in.setter().get_ObjectVariant());
        if (!setter)
            return false;
        out.setSetter(JS_DATA_TO_FUNC_PTR(JSSetterOp, setter.get()));
    } else {
        out.setSetter(UnknownStrictPropertyStub);
    }

    return true;
}
bool
JavaScriptShared::toDescriptor(JSContext *cx, const PPropertyDescriptor &in,
                               MutableHandle<JSPropertyDescriptor> out)
{
    out.setAttributes(in.attrs());
    if (!toValue(cx, in.value(), out.value()))
        return false;
    Rooted<JSObject*> obj(cx);
    if (!unwrap(cx, in.objId(), &obj))
        return false;
    out.object().set(obj);

    if (!in.getter()) {
        out.setGetter(nullptr);
    } else if (in.attrs() & JSPROP_GETTER) {
        Rooted<JSObject*> getter(cx);
        if (!unwrap(cx, in.getter(), &getter))
            return false;
        out.setGetter(JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get()));
    } else {
        if (in.getter() == DefaultPropertyOp)
            out.setGetter(JS_PropertyStub);
        else
            out.setGetter(UnknownPropertyStub);
    }

    if (!in.setter()) {
        out.setSetter(nullptr);
    } else if (in.attrs() & JSPROP_SETTER) {
        Rooted<JSObject*> setter(cx);
        if (!unwrap(cx, in.setter(), &setter))
            return false;
        out.setSetter(JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get()));
    } else {
        if (in.setter() == DefaultPropertyOp)
            out.setSetter(JS_StrictPropertyStub);
        else if (in.setter() == GetterOnlyPropertyStub)
            out.setSetter(js_GetterOnlyPropertyStub);
        else
            out.setSetter(UnknownStrictPropertyStub);
    }

    return true;
}