Ejemplo n.º 1
0
static bool
PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, MutableHandleValue vp, StringifyContext *scx)
{
    JSString *keyStr = NULL;

    /* Step 2. */
    if (vp.get().isObject()) {
        Value toJSON;
        RootedId id(cx, NameToId(cx->runtime->atomState.toJSONAtom));
        Rooted<JSObject*> obj(cx, &vp.get().toObject());
        if (!GetMethod(cx, obj, 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.set(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.set(args.rval());
    }

    /* Step 4. */
    if (vp.get().isObject()) {
        JSObject &obj = vp.get().toObject();
        if (ObjectClassIs(obj, ESClass_Number, cx)) {
            double d;
            if (!ToNumber(cx, vp, &d))
                return false;
            vp.set(NumberValue(d));
        } else if (ObjectClassIs(obj, ESClass_String, cx)) {
            JSString *str = ToStringSlow(cx, vp);
            if (!str)
                return false;
            vp.set(StringValue(str));
        } else if (ObjectClassIs(obj, ESClass_Boolean, cx)) {
            if (!BooleanGetPrimitiveValue(cx, obj, vp.address()))
                return false;
            JS_ASSERT(vp.get().isBoolean());
        }
    }

    return true;
}
Ejemplo n.º 2
0
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 = 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 = 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;
}
Ejemplo n.º 3
0
static bool
PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleValue vp, StringifyContext *scx)
{
    RootedString keyStr(cx);

    /* Step 2. */
    if (vp.isObject()) {
        RootedValue toJSON(cx);
        RootedObject obj(cx, &vp.toObject());
        if (!JSObject::getProperty(cx, obj, obj, cx->names().toJSON, &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.setCallee(toJSON);
            args.setThis(vp);
            args[0] = StringValue(keyStr);

            if (!Invoke(cx, args))
                return false;
            vp.set(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.setCallee(ObjectValue(*scx->replacer));
        args.setThis(ObjectValue(*holder));
        args[0] = StringValue(keyStr);
        args[1] = vp;

        if (!Invoke(cx, args))
            return false;
        vp.set(args.rval());
    }

    /* Step 4. */
    if (vp.get().isObject()) {
        RootedObject obj(cx, &vp.get().toObject());
        if (ObjectClassIs(obj, ESClass_Number, cx)) {
            double d;
            if (!ToNumber(cx, vp, &d))
                return false;
            vp.set(NumberValue(d));
        } else if (ObjectClassIs(obj, ESClass_String, cx)) {
            JSString *str = ToStringSlow<CanGC>(cx, vp);
            if (!str)
                return false;
            vp.set(StringValue(str));
        } else if (ObjectClassIs(obj, ESClass_Boolean, cx)) {
            if (!BooleanGetPrimitiveValue(cx, obj, vp.address()))
                return false;
            JS_ASSERT(vp.get().isBoolean());
        }
    }

    return true;
}
Ejemplo n.º 4
0
bool
js::GetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, uint32_t index,
               unsigned resolveFlags, Value *vp)
{
    NEW_OBJECT_REPRESENTATION_ONLY();

    Rooted<ObjectImpl*> current(cx, obj);

    RootedValue getter(cx);
    do {
        MOZ_ASSERT(current);

        if (Downcast(current)->isProxy()) {
            MOZ_NOT_REACHED("NYI: proxy [[GetP]]");
            return false;
        }

        PropDesc desc;
        if (!GetOwnElement(cx, current, index, resolveFlags, &desc))
            return false;

        /* No property?  Recur or bottom out. */
        if (desc.isUndefined()) {
            current = current->getProto();
            if (current)
                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()) {
            getter = desc.getterValue();
            if (getter.isUndefined()) {
                vp->setUndefined();
                return true;
            }

            InvokeArgsGuard args;
            if (!cx->stack.pushInvokeArgs(cx, 0, &args))
                return false;

            /* Push getter, receiver, and no args. */
            args.setCallee(getter);
            args.setThis(ObjectValue(*current));

            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;
}
Ejemplo n.º 5
0
bool
js::GetProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver,
                Handle<PropertyId> pid, unsigned resolveFlags, MutableHandle<Value> vp)
{
    NEW_OBJECT_REPRESENTATION_ONLY();

    MOZ_ASSERT(receiver);

    Rooted<ObjectImpl*> current(cx, obj);

    do {
        MOZ_ASSERT(obj);

        if (Downcast(current)->isProxy()) {
            MOZ_NOT_REACHED("NYI: proxy [[GetP]]");
            return false;
        }

        PropDesc desc;
        PropDesc::AutoRooter rootDesc(cx, &desc);
        if (!GetOwnProperty(cx, current, pid, resolveFlags, &desc))
            return false;

        /* No property?  Recur or bottom out. */
        if (desc.isUndefined()) {
            current = current->getProto();
            if (current)
                continue;

            vp.setUndefined();
            return true;
        }

        /* If it's a data property, return the value. */
        if (desc.isDataDescriptor()) {
            vp.set(desc.value());
            return true;
        }

        /* If it's an accessor property, call its [[Get]] with the receiver. */
        if (desc.isAccessorDescriptor()) {
            Rooted<Value> get(cx, desc.getterValue());
            if (get.isUndefined()) {
                vp.setUndefined();
                return true;
            }

            InvokeArgsGuard args;
            if (!cx->stack.pushInvokeArgs(cx, 0, &args))
                return false;

            args.setCallee(get);
            args.setThis(ObjectValue(*receiver));

            bool ok = Invoke(cx, args);
            vp.set(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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/*
 * 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;
}