Ejemplo n.º 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();
}
Ejemplo n.º 2
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.º 3
0
void MozJSImplScope::newFunction(StringData raw, JS::MutableHandleValue out) {
    MozJSEntry entry(this);

    std::string code = str::stream() << "____MongoToSM_newFunction_temp = " << raw;

    JS::CompileOptions co(_context);
    setCompileOptions(&co);
    _checkErrorState(JS::Evaluate(_context, _global, co, code.c_str(), code.length(), out));
}
Ejemplo n.º 4
0
bool MozJSImplScope::exec(StringData code,
                          const std::string& name,
                          bool printResult,
                          bool reportError,
                          bool assertOnError,
                          int timeoutMs) {
    MozJSEntry entry(this);

    JS::CompileOptions co(_context);
    setCompileOptions(&co);
    co.setFile(name.c_str());
    JS::RootedScript script(_context);

    bool success = JS::Compile(_context, _global, co, code.rawData(), code.size(), &script);

    if (_checkErrorState(success, reportError, assertOnError))
        return false;

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

    JS::RootedValue out(_context);

    success = JS_ExecuteScript(_context, _global, script, &out);

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

    if (_checkErrorState(success, reportError, assertOnError))
        return false;

    ObjectWrapper(_context, _global).setValue(kExecResult, out);

    if (printResult && !out.isUndefined()) {
        // appears to only be used by shell
        std::cout << ValueWriter(_context, out).toString() << std::endl;
    }

    return true;
}
Ejemplo n.º 5
0
void MozJSImplScope::_MozJSCreateFunction(const char* raw,
                                          ScriptingFunction functionNumber,
                                          JS::MutableHandleValue fun) {
    std::string code = str::stream() << "_funcs" << functionNumber << " = "
                                     << parseJSFunctionOrExpression(_context, StringData(raw));

    JS::CompileOptions co(_context);
    setCompileOptions(&co);

    _checkErrorState(JS::Evaluate(_context, _global, co, code.c_str(), code.length(), fun));
    uassert(10232,
            "not a function",
            fun.isObject() && JS_ObjectIsFunction(_context, fun.toObjectOrNull()));
}
Ejemplo n.º 6
0
// TODO: This function identification code is broken.  Fix it up to be more robust
//
// See: SERVER-16703 for more info
void MozJSImplScope::_MozJSCreateFunction(const char* raw,
                                          ScriptingFunction functionNumber,
                                          JS::MutableHandleValue fun) {
    std::string code = jsSkipWhiteSpace(raw);
    if (!hasFunctionIdentifier(code)) {
        if (code.find('\n') == std::string::npos && !hasJSReturn(code) &&
            (code.find(';') == std::string::npos || code.find(';') == code.size() - 1)) {
            code = "return " + code;
        }
        code = "function(){ " + code + "}";
    }

    code = str::stream() << "_funcs" << functionNumber << " = " << code;

    JS::CompileOptions co(_context);
    setCompileOptions(&co);

    _checkErrorState(JS::Evaluate(_context, _global, co, code.c_str(), code.length(), fun));
    uassert(10232,
            "not a function",
            fun.isObject() && JS_ObjectIsFunction(_context, fun.toObjectOrNull()));
}
Ejemplo n.º 7
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.º 8
0
MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine)
    : _engine(engine),
      _mr(),
      _runtime(_mr._runtime),
      _context(_mr._context),
      _globalProto(_context),
      _global(_globalProto.getProto()),
      _funcs(),
      _internedStrings(_context),
      _pendingKill(false),
      _opId(0),
      _opCtx(nullptr),
      _pendingGC(false),
      _connectState(ConnectState::Not),
      _status(Status::OK()),
      _quickExit(false),
      _generation(0),
      _binDataProto(_context),
      _bsonProto(_context),
      _countDownLatchProto(_context),
      _cursorProto(_context),
      _cursorHandleProto(_context),
      _dbCollectionProto(_context),
      _dbPointerProto(_context),
      _dbQueryProto(_context),
      _dbProto(_context),
      _dbRefProto(_context),
      _errorProto(_context),
      _jsThreadProto(_context),
      _maxKeyProto(_context),
      _minKeyProto(_context),
      _mongoExternalProto(_context),
      _mongoHelpersProto(_context),
      _mongoLocalProto(_context),
      _nativeFunctionProto(_context),
      _numberIntProto(_context),
      _numberLongProto(_context),
      _numberDecimalProto(_context),
      _objectProto(_context),
      _oidProto(_context),
      _regExpProto(_context),
      _timestampProto(_context) {
    kCurrentScope = this;

    // The default is quite low and doesn't seem to directly correlate with
    // malloc'd bytes.  Set it to MAX_INT here and catching things in the
    // jscustomallocator.cpp
    JS_SetGCParameter(_runtime, JSGC_MAX_BYTES, 0xffffffff);

    JS_SetInterruptCallback(_runtime, _interruptCallback);
    JS_SetGCCallback(_runtime, _gcCallback, this);
    JS_SetContextPrivate(_context, this);
    JSAutoRequest ar(_context);

    JS_SetErrorReporter(_runtime, _reportError);

    JSAutoCompartment ac(_context, _global);

    _checkErrorState(JS_InitStandardClasses(_context, _global));

    installBSONTypes();

    JS_FireOnNewGlobalObject(_context, _global);

    execSetup(JSFiles::assert);
    execSetup(JSFiles::types);

    // install process-specific utilities in the global scope (dependancy: types.js, assert.js)
    if (_engine->getScopeInitCallback())
        _engine->getScopeInitCallback()(*this);

    // install global utility functions
    installGlobalUtils(*this);
    _mongoHelpersProto.install(_global);
}