Ejemplo n.º 1
0
BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) {
    MozJSEntry entry(this);

    JS::RootedValue function(_context);
    ValueReader(_context, &function).fromBSONElement(args.firstElement(), true);

    int argc = args.nFields() - 1;

    JS::AutoValueVector argv(_context);
    BSONObjIterator it(args);
    it.next();
    JS::RootedValue value(_context);

    for (int i = 0; i < argc; ++i) {
        ValueReader(_context, &value).fromBSONElement(*it, true);
        argv.append(value);
        it.next();
    }

    JS::RootedValue out(_context);
    JS::RootedObject thisv(_context);

    _checkErrorState(JS::Call(_context, thisv, function, argv, &out), false, true);

    BSONObjBuilder b;
    ValueWriter(_context, out).writeThis(&b, "ret");

    return b.obj();
}
Ejemplo n.º 2
0
BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) {
    MozJSEntry entry(this);

    JS::RootedValue function(_context);
    ValueReader(_context, &function).fromBSONElement(args.firstElement(), args, true);

    int argc = args.nFields() - 1;

    JS::AutoValueVector argv(_context);
    BSONObjIterator it(args);
    it.next();
    JS::RootedValue value(_context);

    for (int i = 0; i < argc; ++i) {
        ValueReader(_context, &value).fromBSONElement(*it, args, true);
        argv.append(value);
        it.next();
    }

    JS::RootedValue out(_context);
    JS::RootedObject thisv(_context);

    _checkErrorState(JS::Call(_context, thisv, function, argv, &out), false, true);

    JS::RootedObject rout(_context, JS_NewPlainObject(_context));
    ObjectWrapper wout(_context, rout);
    wout.setValue("ret", out);

    return wout.toBSON();
}
Ejemplo n.º 3
0
void SessionInfo::Functions::getTxnNumber::call(JSContext* cx, JS::CallArgs args) {
    auto holder = getHolder(args);
    invariant(holder);
    uassert(ErrorCodes::BadValue, "getTxnNumber takes no arguments", args.length() == 0);

    ValueReader(cx, args.rval()).fromInt64(holder->txnNumber);
}
Ejemplo n.º 4
0
void SessionInfo::Functions::getTxnState::call(JSContext* cx, JS::CallArgs args) {
    auto holder = getHolder(args);
    invariant(holder);
    uassert(ErrorCodes::BadValue, "getTxnState takes no arguments", args.length() == 0);

    ValueReader(cx, args.rval()).fromStringData(transactionStateName(holder->txnState));
}
Ejemplo n.º 5
0
void BSONInfo::enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties) {
    auto holder = getHolder(obj);

    if (!holder)
        return;

    BSONObjIterator i(holder->_obj);

    ObjectWrapper o(cx, obj);
    JS::RootedValue val(cx);
    JS::RootedId id(cx);

    while (i.more()) {
        BSONElement e = i.next();

        // TODO: when we get heterogenous set lookup, switch to StringData
        // rather than involving the temporary string
        if (holder->_removed.count(e.fieldName()))
            continue;

        ValueReader(cx, &val).fromStringData(e.fieldNameStringData());

        if (!JS_ValueToId(cx, val, &id))
            uasserted(ErrorCodes::JSInterpreterFailure, "Failed to invoke JS_ValueToId");

        properties.append(id);
    }
}
Ejemplo n.º 6
0
void BinDataInfo::Functions::UUID::call(JSContext* cx, JS::CallArgs args) {
    boost::optional<mongo::UUID> uuid;

    if (args.length() == 0) {
        uuid = mongo::UUID::gen();
    } else {
        uassert(ErrorCodes::BadValue, "UUID needs 0 or 1 arguments", args.length() == 1);
        auto arg = args.get(0);
        std::string str = ValueWriter(cx, arg).toString();

        // For backward compatibility quietly accept and convert 32-character hex strings to
        // BinData(3, ...) as used for the deprecated UUID v3 BSON type.
        if (str.length() == 32) {
            hexToBinData(cx, bdtUUID, arg, args.rval());
            return;
        }
        uuid = uassertStatusOK(mongo::UUID::parse(str));
    };
    ConstDataRange cdr = uuid->toCDR();
    std::string encoded = mongo::base64::encode(cdr.data(), cdr.length());

    JS::AutoValueArray<2> newArgs(cx);
    newArgs[0].setInt32(newUUID);
    ValueReader(cx, newArgs[1]).fromStringData(encoded);
    getScope(cx)->getProto<BinDataInfo>().newInstance(newArgs, args.rval());
}
Ejemplo n.º 7
0
Archivo: oid.cpp Proyecto: DINKIN/mongo
void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull()));

    std::string str = str::stream() << "ObjectId(\"" << oid->toString() << "\")";

    ValueReader(cx, args.rval()).fromStringData(str);
}
Ejemplo n.º 8
0
void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandleValue value) {
    auto scope = getScope(cx);

    JS::RootedValue undef(cx);
    undef.setUndefined();

    JS::AutoValueArray<1> args(cx);
    ValueReader(cx, args[0]).fromStringData(status.reason());
    JS::RootedObject error(cx);
    scope->getProto<ErrorInfo>().newInstance(args, &error);

    JS::RootedObject thisv(cx);
    scope->getProto<MongoStatusInfo>().newObjectWithProto(&thisv, error);
    ObjectWrapper thisvObj(cx, thisv);
    thisvObj.defineProperty(
        InternedString::code,
        undef,
        JSPROP_ENUMERATE | JSPROP_SHARED,
        smUtils::wrapConstrainedMethod<Functions::code, false, MongoStatusInfo>);

    thisvObj.defineProperty(
        InternedString::reason,
        undef,
        JSPROP_ENUMERATE | JSPROP_SHARED,
        smUtils::wrapConstrainedMethod<Functions::reason, false, MongoStatusInfo>);

    JS_SetPrivate(thisv, scope->trackedNew<Status>(std::move(status)));

    value.setObjectOrNull(thisv);
}
Ejemplo n.º 9
0
void NativeFunctionInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    ObjectWrapper o(cx, args.thisv());

    str::stream ss;
    ss << "[native code]";

    ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
Ejemplo n.º 10
0
void NumberDecimalInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    Decimal128 val = NumberDecimalInfo::ToNumberDecimal(cx, args.thisv());

    str::stream ss;
    ss << "NumberDecimal(\"" << val.toString() << "\")";

    ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
Ejemplo n.º 11
0
void NumberIntInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    int val = NumberIntInfo::ToNumberInt(cx, args.thisv());

    str::stream ss;
    ss << "NumberInt(" << val << ")";

    ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
Ejemplo n.º 12
0
void TimestampInfo::Functions::toJSON::call(JSContext* cx, JS::CallArgs args) {
    ObjectWrapper o(cx, args.thisv());

    ValueReader(cx, args.rval())
        .fromBSON(BSON("$timestamp" << BSON("t" << o.getNumber(InternedString::t) << "i"
                                                << o.getNumber(InternedString::i))),
                  nullptr,
                  false);
}
Ejemplo n.º 13
0
void CodeInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    ObjectWrapper o(cx, args.thisv());

    std::string str = str::stream() << "Code({\"code\":\"" << o.getString(InternedString::code)
                                    << "\","
                                    << "\"scope\":" << o.getObject(InternedString::scope) << "\"})";

    ValueReader(cx, args.rval()).fromStringData(str);
}
Ejemplo n.º 14
0
void ObjectWrapper::setBSONElement(Key key,
                                   const BSONElement& elem,
                                   const BSONObj& parent,
                                   bool readOnly) {
    JS::RootedValue value(_context);
    ValueReader(_context, &value).fromBSONElement(elem, parent, readOnly);

    setValue(key, value);
}
void ValueReader::fromBSONArray(const BSONObj& obj, const BSONObj* parent, bool readOnly) {
    JS::AutoValueVector avv(_context);

    BSONForEach(elem, obj) {
        JS::RootedValue member(_context);

        ValueReader(_context, &member).fromBSONElement(elem, parent ? *parent : obj, readOnly);
        if (!avv.append(member)) {
            uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append to JS array");
        }
    }
std::string parseJSFunctionOrExpression(JSContext* cx, const StringData input) {
    JS::RootedValue jsStrOut(cx);
    JS::RootedValue jsStrIn(cx);

    ValueReader(cx, &jsStrIn).fromStringData(input);
    ObjectWrapper helpersWrapper(cx, getScope(cx)->getProto<MongoHelpersInfo>().getProto());

    helpersWrapper.callMethod("functionExpressionParser", JS::HandleValueArray(jsStrIn), &jsStrOut);

    return ValueWriter(cx, jsStrOut).toString();
}
Ejemplo n.º 17
0
void BinDataInfo::Functions::toJSON::call(JSContext* cx, JS::CallArgs args) {
    ObjectWrapper o(cx, args.thisv());

    auto data_str = getEncoded(args.thisv());

    std::stringstream ss;
    ss << std::hex;
    ss.width(2);
    ss.fill('0');
    ss << o.getNumber(InternedString::type);

    ValueReader(cx, args.rval())
        .fromBSON(BSON("$binary" << *data_str << "$type" << ss.str()), nullptr, false);
}
Ejemplo n.º 18
0
void BinDataInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
    ObjectWrapper o(cx, args.thisv());

    auto str = getEncoded(args.thisv());

    str::stream ss;
    auto binType = o.getNumber(InternedString::type);

    if (binType == newUUID) {
        auto decoded = mongo::base64::decode(*str);

        // If this is in fact a UUID, use a more friendly string representation.
        if (decoded.length() == mongo::UUID::kNumBytes) {
            mongo::UUID uuid = mongo::UUID::fromCDR({decoded.data(), decoded.length()});
            ss << "UUID(\"" << uuid.toString() << "\")";
            ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
            return;
        }
    }

    ss << "BinData(" << binType << ",\"" << *str << "\")";
    ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
Ejemplo n.º 19
0
void BinDataInfo::Functions::hex::call(JSContext* cx, JS::CallArgs args) {
    auto str = getEncoded(args.thisv());

    std::string data = mongo::base64::decode(*str);
    std::stringstream ss;
    ss.setf(std::ios_base::hex, std::ios_base::basefield);
    ss.fill('0');
    ss.setf(std::ios_base::right, std::ios_base::adjustfield);
    for (auto it = data.begin(); it != data.end(); ++it) {
        unsigned v = (unsigned char)*it;
        ss << std::setw(2) << v;
    }

    ValueReader(cx, args.rval()).fromStringData(ss.str());
}
Ejemplo n.º 20
0
void CursorInfo::Functions::next::call(JSContext* cx, JS::CallArgs args) {
    auto cursor = getCursor(args);

    if (!cursor) {
        args.rval().setUndefined();
        return;
    }

    ObjectWrapper o(cx, args.thisv());

    BSONObj bson = cursor->next();
    bool ro = o.hasField(InternedString::_ro) ? o.getBoolean(InternedString::_ro) : false;

    // getOwned because cursor->next() gives us unowned bson from an internal
    // buffer and we need to make a copy
    ValueReader(cx, args.rval()).fromBSON(bson.getOwned(), nullptr, ro);
}
Ejemplo n.º 21
0
void NativeFunctionInfo::call(JSContext* cx, JS::CallArgs args) {
    auto holder = getHolder(args);

    if (!holder) {
        // Calling the prototype
        args.rval().setUndefined();
        return;
    }

    JS::RootedObject robj(cx, JS_NewArrayObject(cx, args));
    if (!robj) {
        uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject");
    }

    BSONObj out = holder->_func(ObjectWrapper(cx, robj).toBSON(), holder->_ctx);

    ValueReader(cx, args.rval()).fromBSONElement(out.firstElement(), out, false);
}
Ejemplo n.º 22
0
void BSONInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) {
    auto holder = getHolder(obj);

    *resolvedp = false;

    if (!holder) {
        return;
    }

    IdWrapper idw(cx, id);

    if (!holder->_readOnly && holder->_removed.count(idw.toString())) {
        return;
    }

    ObjectWrapper o(cx, obj);

    std::string sname = IdWrapper(cx, id).toString();

    if (holder->_obj.hasField(sname)) {
        auto elem = holder->_obj[sname];

        JS::RootedValue vp(cx);

        ValueReader(cx, &vp).fromBSONElement(elem, holder->_readOnly);

        o.defineProperty(id, vp, JSPROP_ENUMERATE);

        if (!holder->_readOnly && (elem.type() == mongo::Object || elem.type() == mongo::Array)) {
            // if accessing a subobject, we have no way to know if
            // modifications are being made on writable objects

            holder->_altered = true;
        }

        *resolvedp = true;
    }
}
Ejemplo n.º 23
0
void ObjectInfo::Functions::invalidForStorage::call(JSContext* cx, JS::CallArgs args) {
    if (args.length() != 1)
        uasserted(ErrorCodes::BadValue, "invalidForStorage needs 1 argument");

    if (args.get(0).isNull()) {
        args.rval().setNull();
        return;
    }

    if (!args.get(0).isObject())
        uasserted(ErrorCodes::BadValue, "argument to invalidForStorage has to be an object");

    Status validForStorage = ValueWriter(cx, args.get(0)).toBSON().storageValid(true);
    if (validForStorage.isOK()) {
        args.rval().setNull();
        return;
    }

    std::string errmsg = str::stream() << validForStorage.codeString() << ": "
                                       << validForStorage.reason();

    ValueReader(cx, args.rval()).fromStringData(errmsg);
}
Ejemplo n.º 24
0
int MozJSImplScope::invoke(ScriptingFunction func,
                           const BSONObj* argsObject,
                           const BSONObj* recv,
                           int timeoutMs,
                           bool ignoreReturn,
                           bool readOnlyArgs,
                           bool readOnlyRecv) {
    MozJSEntry entry(this);

    auto funcValue = _funcs[func - 1];
    JS::RootedValue result(_context);

    const int nargs = argsObject ? argsObject->nFields() : 0;

    JS::AutoValueVector args(_context);

    if (nargs) {
        BSONObjIterator it(*argsObject);
        for (int i = 0; i < nargs; i++) {
            BSONElement next = it.next();

            JS::RootedValue value(_context);
            ValueReader(_context, &value).fromBSONElement(next, *argsObject, readOnlyArgs);

            args.append(value);
        }
    }

    JS::RootedValue smrecv(_context);
    if (recv)
        ValueReader(_context, &smrecv).fromBSON(*recv, nullptr, readOnlyRecv);
    else
        smrecv.setObjectOrNull(_global);

    if (timeoutMs)
        _engine->getDeadlineMonitor().startDeadline(this, timeoutMs);

    JS::RootedValue out(_context);
    JS::RootedObject obj(_context, smrecv.toObjectOrNull());

    bool success = JS::Call(_context, obj, funcValue, args, &out);

    if (timeoutMs)
        _engine->getDeadlineMonitor().stopDeadline(this);

    _checkErrorState(success);

    if (!ignoreReturn) {
        // must validate the handle because TerminateExecution may have
        // been thrown after the above checks
        if (out.isObject() && _nativeFunctionProto.instanceOf(out)) {
            warning() << "storing native function as return value";
            _lastRetIsNativeCode = true;
        } else {
            _lastRetIsNativeCode = false;
        }

        ObjectWrapper(_context, _global).setValue(kInvokeResult, out);
    }

    return 0;
}
Ejemplo n.º 25
0
Archivo: oid.cpp Proyecto: DINKIN/mongo
void OIDInfo::Functions::getter::call(JSContext* cx, JS::CallArgs args) {
    auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull()));

    ValueReader(cx, args.rval()).fromStringData(oid->toString());
}
Ejemplo n.º 26
0
Archivo: oid.cpp Proyecto: DINKIN/mongo
void OIDInfo::Functions::toJSON::call(JSContext* cx, JS::CallArgs args) {
    auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull()));

    ValueReader(cx, args.rval()).fromBSON(BSON("$oid" << oid->toString()), nullptr, false);
}
Ejemplo n.º 27
0
void JSThreadInfo::Functions::returnData::call(JSContext* cx, JS::CallArgs args) {
    ValueReader(cx, args.rval())
        .fromBSONElement(getConfig(cx, args)->returnData().firstElement(), true);
}
Ejemplo n.º 28
0
void BinDataInfo::Functions::base64::call(JSContext* cx, JS::CallArgs args) {
    auto str = getEncoded(args.thisv());

    ValueReader(cx, args.rval()).fromStringData(*str);
}
Ejemplo n.º 29
0
void MaxKeyInfo::Functions::toJSON::call(JSContext* cx, JS::CallArgs args) {
    ValueReader(cx, args.rval()).fromBSON(BSON("$maxKey" << 1), nullptr, false);
}
Ejemplo n.º 30
0
void MaxKeyInfo::Functions::tojson::call(JSContext* cx, JS::CallArgs args) {
    ValueReader(cx, args.rval()).fromStringData("{ \"$maxKey\" : 1 }");
}