示例#1
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();
}
示例#2
0
文件: dbref.cpp 项目: i80and/mongo
void DBRefInfo::construct(JSContext* cx, JS::CallArgs args) {
    if (!(args.length() == 2 || args.length() == 3))
        uasserted(ErrorCodes::BadValue, "DBRef needs 2 or 3 arguments");

    if (!args.get(0).isString())
        uasserted(ErrorCodes::BadValue, "DBRef 1st parameter must be a string");

    JS::RootedObject thisv(cx, JS_NewPlainObject(cx));
    ObjectWrapper o(cx, thisv);

    o.setValue(InternedString::dollar_ref, args.get(0));
    o.setValue(InternedString::dollar_id, args.get(1));

    if (args.length() == 3) {
        if (!args.get(2).isString())
            uasserted(ErrorCodes::BadValue, "DBRef 3rd parameter must be a string");

        o.setValue(InternedString::dollar_db, args.get(2));
    }

    JS::RootedObject out(cx);
    DBRefInfo::make(cx, &out, o.toBSON(), nullptr, false);

    args.rval().setObjectOrNull(out);
}
示例#3
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();
}
示例#4
0
文件: status.cpp 项目: i80and/mongo
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);
}
示例#5
0
void TimestampInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);
    scope->getProto<TimestampInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    if (args.length() == 0) {
        o.setNumber(InternedString::t, 0);
        o.setNumber(InternedString::i, 0);
    } else if (args.length() == 2) {
        if (!args.get(0).isNumber())
            uasserted(ErrorCodes::BadValue, "Timestamp time must be a number");
        if (!args.get(1).isNumber())
            uasserted(ErrorCodes::BadValue, "Timestamp increment must be a number");

        int64_t t = ValueWriter(cx, args.get(0)).toInt64();
        int64_t largestVal = int64_t(Timestamp::max().getSecs());
        if (t > largestVal)
            uasserted(ErrorCodes::BadValue,
                      str::stream() << "The first argument must be in seconds; " << t
                                    << " is too large (max " << largestVal << ")");

        o.setValue(InternedString::t, args.get(0));
        o.setValue(InternedString::i, args.get(1));
    } else {
        uasserted(ErrorCodes::BadValue, "Timestamp needs 0 or 2 arguments");
    }

    args.rval().setObjectOrNull(thisv);
}
示例#6
0
void DBInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() != 2)
        uasserted(ErrorCodes::BadValue, "db constructor requires 2 arguments");

    for (unsigned i = 0; i < args.length(); ++i) {
        uassert(ErrorCodes::BadValue,
                "db initializer called with undefined argument",
                !args.get(i).isUndefined());
    }

    JS::RootedObject thisv(cx);
    scope->getProto<DBInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    o.setValue(InternedString::_mongo, args.get(0));
    o.setValue(InternedString::_name, args.get(1));

    std::string dbName = ValueWriter(cx, args.get(1)).toString();

    if (!NamespaceString::validDBName(dbName, NamespaceString::DollarInDbNameBehavior::Allow))
        uasserted(ErrorCodes::BadValue,
                  str::stream() << "[" << dbName << "] is not a valid database name");

    args.rval().setObjectOrNull(thisv);
}
示例#7
0
void CodeInfo::construct(JSContext* cx, JS::CallArgs args) {
    uassert(ErrorCodes::BadValue,
            "Code needs 0, 1 or 2 arguments",
            args.length() == 0 || args.length() == 1 || args.length() == 2);
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);

    scope->getProto<CodeInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    if (args.length() == 0) {
        o.setString(InternedString::code, "");
    } else if (args.length() == 1) {
        JS::HandleValue codeArg = args.get(0);
        if (!codeArg.isString())
            uasserted(ErrorCodes::BadValue, "code must be a string");

        o.setValue(InternedString::code, codeArg);
    } else {
        if (!args.get(0).isString())
            uasserted(ErrorCodes::BadValue, "code must be a string");
        if (!args.get(1).isObject())
            uasserted(ErrorCodes::BadValue, "scope must be an object");

        o.setValue(InternedString::code, args.get(0));
        o.setValue(InternedString::scope, args.get(1));
    }

    args.rval().setObjectOrNull(thisv);
}
示例#8
0
void DBCollectionInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() != 4)
        uasserted(ErrorCodes::BadValue, "collection constructor requires 4 arguments");

    for (unsigned i = 0; i < args.length(); ++i) {
        uassert(ErrorCodes::BadValue,
                "collection constructor called with undefined argument",
                !args.get(i).isUndefined());
    }

    JS::RootedObject thisv(cx);
    scope->getDbCollectionProto().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    o.setValue("_mongo", args.get(0));
    o.setValue("_db", args.get(1));
    o.setValue("_shortName", args.get(2));
    o.setValue("_fullName", args.get(3));

    std::string fullName = ValueWriter(cx, args.get(3)).toString();

    auto context = scope->getOpContext();
    if (context && haveLocalShardingInfo(context->getClient(), fullName))
        uasserted(ErrorCodes::BadValue, "can't use sharded collection from db.eval");

    args.rval().setObjectOrNull(thisv);
}
示例#9
0
文件: oid.cpp 项目: DINKIN/mongo
void OIDInfo::make(JSContext* cx, const OID& oid, JS::MutableHandleValue out) {
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);
    scope->getProto<OIDInfo>().newObject(&thisv);
    JS_SetPrivate(thisv, scope->trackedNew<OID>(oid));

    out.setObjectOrNull(thisv);
}
示例#10
0
static void *
callCountHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, bool before,
              bool *ok, void *closure)
{
    callCount[before]++;

    JS::RootedValue thisv(cx);
    frame.getThisValue(cx, &thisv); // assert if fp is incomplete

    return cx;  // any non-null value causes the hook to be called again after
}
示例#11
0
bool rs::jsapi::Object::CallFunction(JSContext* cx, unsigned argc, JS::Value* vp) {
    JSAutoRequest ar(cx);
    char nameBuffer[256];
    const char* name = nameBuffer;
    
    auto args = JS::CallArgsFromVp(argc, vp);
    auto func = JS_ValueToFunction(cx, args.calleev());
    if (func != nullptr) {
        auto funcName = JS_GetFunctionId(func);                
        if (funcName != nullptr) {
            auto nameLength = JS_EncodeStringToBuffer(cx, funcName, nameBuffer, sizeof(nameBuffer));
            if ((nameLength + 1) < sizeof(nameBuffer)) {
                nameBuffer[nameLength] = '\0';
            } else {
                std::vector<char> vBuffer(nameLength + 1);
                JS_EncodeStringToBuffer(cx, funcName, &vBuffer[0], nameLength);
                vBuffer[nameLength] = '\0';
                name = &vBuffer[0];
            }
        }
    }
    
    if (name == nullptr) {
        // TODO: test this case
        JS_ReportError(cx, "Unable to find function in libjsapi object");
        return false;        
    } else {
        auto that = args.thisv();
        auto state = that.isObjectOrNull() ? Object::GetState(cx, JS::RootedObject(cx, that.toObjectOrNull())) : nullptr;
        if (state == nullptr) {
            // TODO: test this case
            JS_ReportError(cx, "Unable to find function callback in libjsapi object");
            return false;
        } else {
            try {
                static thread_local std::vector<Value> vArgs;

                VectorUtils::ScopedVectorCleaner<Value> clean(vArgs);
                for (int i = 0; i < argc; ++i) {
                    vArgs.emplace_back(cx, args.get(i));
                }

                Value result(cx);
                state->functions[name](vArgs, result);
                args.rval().set(result);
                return true;
            } catch (const std::exception& ex) {
                JS_ReportError(cx, ex.what());
                return false;
            }
        }        
    }
}
示例#12
0
static void *
nonStrictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, bool before,
                  bool *ok, void *closure)
{
    if (before) {
        bool *allWrapped = (bool *) closure;
        JS::RootedValue thisv(cx);
        frame.getThisValue(cx, &thisv);
        *allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
    }
    return NULL;
}
static void *
strictThisHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before,
               JSBool *ok, void *closure)
{
    if (before) {
        bool *anyWrapped = (bool *) closure;
        js::RootedValue thisv(cx);
        frame.getThisValue(cx, thisv.address());
        *anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
    }
    return NULL;
}
示例#14
0
void TimestampInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);
    scope->getProto<TimestampInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    if (args.length() == 0) {
        o.setNumber(InternedString::t, 0);
        o.setNumber(InternedString::i, 0);
    } else if (args.length() == 2) {
        o.setNumber(InternedString::t, getTimestampArg(cx, args, 0, "Timestamp time (seconds)"));
        o.setNumber(InternedString::i, getTimestampArg(cx, args, 1, "Timestamp increment"));
    } else {
        uasserted(ErrorCodes::BadValue, "Timestamp needs 0 or 2 arguments");
    }

    args.rval().setObjectOrNull(thisv);
}
示例#15
0
void NumberIntInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);

    scope->getProto<NumberIntInfo>().newObject(&thisv);

    int32_t x = 0;

    if (args.length() == 0) {
        // Do nothing
    } else if (args.length() == 1) {
        x = ValueWriter(cx, args.get(0)).toInt32();
    } else {
        uasserted(ErrorCodes::BadValue, "NumberInt takes 0 or 1 arguments");
    }

    JS_SetPrivate(thisv, new int(x));

    args.rval().setObjectOrNull(thisv);
}
示例#16
0
void DBPointerInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() != 2)
        uasserted(ErrorCodes::BadValue, "DBPointer needs 2 arguments");

    if (!args.get(0).isString())
        uasserted(ErrorCodes::BadValue, "DBPointer 1st parameter must be a string");

    if (!scope->getProto<OIDInfo>().instanceOf(args.get(1)))
        uasserted(ErrorCodes::BadValue, "DBPointer 2nd parameter must be an ObjectId");

    JS::RootedObject thisv(cx);
    scope->getProto<DBPointerInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    o.setValue(InternedString::ns, args.get(0));
    o.setValue(InternedString::id, args.get(1));

    args.rval().setObjectOrNull(thisv);
}
示例#17
0
void NumberDecimalInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    JS::RootedObject thisv(cx);

    scope->getProto<NumberDecimalInfo>().newObject(&thisv);

    Decimal128 x(0);

    if (args.length() == 0) {
        // Do nothing
    } else if (args.length() == 1) {
        x = ValueWriter(cx, args.get(0)).toDecimal128();
    } else {
        uasserted(ErrorCodes::BadValue, "NumberDecimal takes 0 or 1 arguments");
    }

    JS_SetPrivate(thisv, scope->trackedNew<Decimal128>(x));

    args.rval().setObjectOrNull(thisv);
}
示例#18
0
文件: maxkey.cpp 项目: DINKIN/mongo
/**
 * The idea here is that MinKey and MaxKey are singleton callable objects that
 * return the singleton when called. This enables all instances to compare
 * == and === to MinKey even if created by "new MinKey()" in JS.
 */
void MaxKeyInfo::call(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    ObjectWrapper o(cx, scope->getProto<MaxKeyInfo>().getProto());

    JS::RootedValue val(cx);

    if (!o.hasField(InternedString::singleton)) {
        JS::RootedObject thisv(cx);
        scope->getProto<MaxKeyInfo>().newObject(&thisv);

        val.setObjectOrNull(thisv);
        o.setValue(InternedString::singleton, val);
    } else {
        o.getValue(InternedString::singleton, &val);

        if (!getScope(cx)->getProto<MaxKeyInfo>().instanceOf(val))
            uasserted(ErrorCodes::BadValue, "MaxKey singleton not of type MaxKey");
    }

    args.rval().set(val);
}
示例#19
0
void BinDataInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() != 2) {
        uasserted(ErrorCodes::BadValue, "BinData takes 2 arguments -- BinData(subtype,data)");
    }

    auto type = args.get(0);
    auto typeNumber = ValueWriter(cx, type).toInt32();
    if (!type.isNumber() || typeNumber < 0 || typeNumber > 255) {
        uasserted(ErrorCodes::BadValue,
                  "BinData subtype must be a Number between 0 and 255 inclusive");
    }

    auto utf = args.get(1);

    if (!utf.isString()) {
        uasserted(ErrorCodes::BadValue, "BinData data must be a String");
    }

    auto str = ValueWriter(cx, utf).toString();

    auto tmpBase64 = base64::decode(str);

    JS::RootedObject thisv(cx);
    scope->getProto<BinDataInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    JS::RootedValue len(cx);
    len.setInt32(tmpBase64.length());

    o.defineProperty(InternedString::len, len, JSPROP_READONLY);
    o.defineProperty(InternedString::type, type, JSPROP_READONLY);

    JS_SetPrivate(thisv, scope->trackedNew<std::string>(std::move(str)));

    args.rval().setObjectOrNull(thisv);
}
示例#20
0
void DBCollectionInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() != 4)
        uasserted(ErrorCodes::BadValue, "collection constructor requires 4 arguments");

    for (unsigned i = 0; i < args.length(); ++i) {
        uassert(ErrorCodes::BadValue,
                "collection constructor called with undefined argument",
                !args.get(i).isUndefined());
    }

    JS::RootedObject thisv(cx);
    scope->getProto<DBCollectionInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    o.setValue(InternedString::_mongo, args.get(0));
    o.setValue(InternedString::_db, args.get(1));
    o.setValue(InternedString::_shortName, args.get(2));
    o.setValue(InternedString::_fullName, args.get(3));

    args.rval().setObjectOrNull(thisv);
}
void DBQueryInfo::construct(JSContext* cx, JS::CallArgs args) {
    auto scope = getScope(cx);

    if (args.length() < 4)
        uasserted(ErrorCodes::BadValue, "dbQuery constructor requires at least 4 arguments");

    JS::RootedObject thisv(cx);
    scope->getProto<DBQueryInfo>().newObject(&thisv);
    ObjectWrapper o(cx, thisv);

    o.setValue(InternedString::_mongo, args.get(0));
    o.setValue(InternedString::_db, args.get(1));
    o.setValue(InternedString::_collection, args.get(2));
    o.setValue(InternedString::_ns, args.get(3));

    JS::RootedObject emptyObj(cx);
    JS::RootedValue emptyObjVal(cx);
    emptyObjVal.setObjectOrNull(emptyObj);

    JS::RootedValue nullVal(cx);
    nullVal.setNull();

    if (args.length() > 4 && args.get(4).isObject()) {
        o.setValue(InternedString::_query, args.get(4));
    } else {
        o.setValue(InternedString::_query, emptyObjVal);
    }

    if (args.length() > 5 && args.get(5).isObject()) {
        o.setValue(InternedString::_fields, args.get(5));
    } else {
        o.setValue(InternedString::_fields, nullVal);
    }

    if (args.length() > 6 && args.get(6).isNumber()) {
        o.setValue(InternedString::_limit, args.get(6));
    } else {
        o.setNumber(InternedString::_limit, 0);
    }

    if (args.length() > 7 && args.get(7).isNumber()) {
        o.setValue(InternedString::_skip, args.get(7));
    } else {
        o.setNumber(InternedString::_skip, 0);
    }

    if (args.length() > 8 && args.get(8).isNumber()) {
        o.setValue(InternedString::_batchSize, args.get(8));
    } else {
        o.setNumber(InternedString::_batchSize, 0);
    }

    if (args.length() > 9 && args.get(9).isNumber()) {
        o.setValue(InternedString::_options, args.get(9));
    } else {
        o.setNumber(InternedString::_options, 0);
    }

    o.setValue(InternedString::_cursor, nullVal);
    o.setNumber(InternedString::_numReturned, 0);
    o.setBoolean(InternedString::_special, false);

    args.rval().setObjectOrNull(thisv);
}