Пример #1
0
JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _isSet(true) {
    if (!str)
        throwCurrentJSException(cx, ErrorCodes::InternalError, "Cannot encode null JSString");

    // We have to do this flatstring thing because no public api tells us
    // how long the utf8 strings we get out are.
    //
    // Well, at least js/CharacterEncoding's GetDeflatedUTF8StringLength
    // and JS_flattenString are all in the public headers...
    JSFlatString* flat = JS_FlattenString(cx, str);
    if (!flat)
        throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to flatten JSString");

    _length = JS::GetDeflatedUTF8StringLength(flat);

    char* out;
    if (_length < sizeof(_buf)) {
        out = _buf;
    } else {
        _str.reset(new char[_length + 1]);
        out = _str.get();
    }

    JS::DeflateStringToUTF8Buffer(flat, mozilla::RangedPtr<char>(out, _length));
    out[_length] = '\0';
}
Пример #2
0
int32_t ValueWriter::toInt32() {
    int32_t out;
    if (JS::ToInt32(_context, _value, &out))
        return out;

    throwCurrentJSException(_context, ErrorCodes::BadValue, "Failure to convert value to number");
}
Пример #3
0
double ValueWriter::toNumber() {
    double out;
    if (JS::ToNumber(_context, _value, &out))
        return out;

    throwCurrentJSException(_context, ErrorCodes::BadValue, "Failure to convert value to number");
}
Пример #4
0
void ObjectWrapper::Key::set(JSContext* cx, JS::HandleObject o, JS::HandleValue value) {
    switch (_type) {
        case Type::Field:
            if (JS_SetProperty(cx, o, _field, value))
                return;
            break;
        case Type::Index:
            if (JS_SetElement(cx, o, _idx, value))
                return;
            break;
        case Type::Id: {
            JS::RootedId id(cx, _id);

            if (JS_SetPropertyById(cx, o, id, value))
                return;
            break;
        }
        case Type::InternedString: {
            InternedStringId id(cx, _internedString);

            if (JS_SetPropertyById(cx, o, id, value))
                return;
            break;
        }
    }

    throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to set value on a JSObject");
}
Пример #5
0
void ObjectWrapper::Key::del(JSContext* cx, JS::HandleObject o) {
    switch (_type) {
        case Type::Field:
            if (JS_DeleteProperty(cx, o, _field))
                return;
            break;
        case Type::Index:
            if (JS_DeleteElement(cx, o, _idx))
                return;
            break;
        case Type::Id: {
            JS::RootedId id(cx, _id);

            // For some reason JS_DeletePropertyById doesn't link
            if (JS_DeleteProperty(cx, o, IdWrapper(cx, id).toString().c_str()))
                return;
            break;
        }
        case Type::InternedString: {
            InternedStringId id(cx, _internedString);

            if (JS_DeleteProperty(cx, o, IdWrapper(cx, id).toString().c_str()))
                break;
        }
    }

    throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to delete value on a JSObject");
}
Пример #6
0
bool ObjectWrapper::Key::hasOwn(JSContext* cx, JS::HandleObject o) {
    bool has;

    switch (_type) {
        case Type::Field:
            if (JS_AlreadyHasOwnProperty(cx, o, _field, &has))
                return has;
            break;
        case Type::Index:
            if (JS_AlreadyHasOwnElement(cx, o, _idx, &has))
                return has;
            break;
        case Type::Id: {
            JS::RootedId id(cx, _id);

            if (JS_AlreadyHasOwnPropertyById(cx, o, id, &has))
                return has;
            break;
        }
        case Type::InternedString: {
            InternedStringId id(cx, _internedString);

            if (JS_AlreadyHasOwnPropertyById(cx, o, id, &has))
                return has;
            break;
        }
    }

    throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to hasOwn value on a JSObject");
}
Пример #7
0
void ObjectWrapper::callMethod(JS::HandleValue fun,
                               const JS::HandleValueArray& args,
                               JS::MutableHandleValue out) {
    if (JS::Call(_context, _object, fun, args, out))
        return;

    throwCurrentJSException(_context, ErrorCodes::InternalError, "Failed to call method");
}
Пример #8
0
int64_t ValueWriter::toInt64() {
    int64_t out;
    if (getScope(_context)->getProto<NumberLongInfo>().instanceOf(_value))
        return NumberLongInfo::ToNumberLong(_context, _value);

    if (JS::ToInt64(_context, _value, &out))
        return out;

    throwCurrentJSException(_context, ErrorCodes::BadValue, "Failure to convert value to number");
}
Пример #9
0
ObjectWrapper::WriteFieldRecursionFrame::WriteFieldRecursionFrame(JSContext* cx,
                                                                  JSObject* obj,
                                                                  BSONObjBuilder* parent,
                                                                  StringData sd)
    : thisv(cx, obj), ids(cx, JS::IdVector(cx)) {
    bool isArray = false;
    if (parent) {
        if (!JS_IsArrayObject(cx, thisv, &isArray)) {
            throwCurrentJSException(
                cx, ErrorCodes::JSInterpreterFailure, "Failure to check object is an array");
        }

        subbob.emplace(isArray ? parent->subarrayStart(sd) : parent->subobjStart(sd));
    }

    if (isArray) {
        uint32_t length;
        if (!JS_GetArrayLength(cx, thisv, &length)) {
            throwCurrentJSException(
                cx, ErrorCodes::JSInterpreterFailure, "Failure to get array length");
        }

        if (!ids.reserve(length)) {
            throwCurrentJSException(
                cx, ErrorCodes::JSInterpreterFailure, "Failure to reserve array");
        }

        JS::RootedId rid(cx);
        for (uint32_t i = 0; i < length; i++) {
            rid.set(INT_TO_JSID(i));
            ids.infallibleAppend(rid);
        }
    } else {
        if (!JS_Enumerate(cx, thisv, &ids)) {
            throwCurrentJSException(
                cx, ErrorCodes::JSInterpreterFailure, "Failure to enumerate object");
        }
    }

    if (getScope(cx)->getProto<BSONInfo>().instanceOf(thisv)) {
        std::tie(originalBSON, altered) = BSONInfo::originalBSON(cx, thisv);
    }
}
Пример #10
0
StringData IdWrapper::toStringData(JSStringWrapper* jsstr) const {
    if (JSID_IS_STRING(_value)) {
        *jsstr = JSStringWrapper(_context, JSID_TO_STRING(_value));
    } else if (JSID_IS_INT(_value)) {
        *jsstr = JSStringWrapper(JSID_TO_INT(_value));
    } else {
        throwCurrentJSException(_context,
                                ErrorCodes::TypeMismatch,
                                "Cannot toString() non-string and non-integer jsid");
    }

    return jsstr->toStringData();
}
Пример #11
0
void JSThreadInfo::Functions::_threadInject::call(JSContext* cx, JS::CallArgs args) {
    uassert(ErrorCodes::JSInterpreterFailure,
            "threadInject takes exactly 1 argument",
            args.length() == 1);
    uassert(ErrorCodes::JSInterpreterFailure,
            "threadInject needs to be passed a prototype",
            args.get(0).isObject());

    JS::RootedObject o(cx, args.get(0).toObjectOrNull());

    if (!JS_DefineFunctions(cx, o, JSThreadInfo::threadMethods))
        throwCurrentJSException(cx, ErrorCodes::JSInterpreterFailure, "Failed to define functions");

    args.rval().setUndefined();
}