static PyObject *to_python_object(JSContext *context, jsval value) { if (JSVAL_IS_PRIMITIVE(value)) { if (JSVAL_IS_STRING(value)) { return PyUnicode_FromString(JS_EncodeString(context, JSVAL_TO_STRING(value))); } else if (JSVAL_IS_BOOLEAN(value)) { return PyBool_FromLong(JSVAL_TO_BOOLEAN(value)); } else if (JSVAL_IS_INT(value)) { return PyLong_FromLong(JSVAL_TO_INT(value)); } else if (JSVAL_IS_DOUBLE(value)) { return PyFloat_FromDouble(JSVAL_TO_DOUBLE(value)); } else { Py_INCREF(Py_None); return Py_None; } } else { JSObject *obj = JSVAL_TO_OBJECT(value); if (JS_ObjectIsDate(context, obj)) { return to_python_datetime(context, obj); } else if (JS_IsArrayObject(context, obj)) { return to_python_list(context, obj); } else { return to_python_dict(context, obj); } } }
std::string ValueWriter::typeAsString() { if (_value.isNull()) return "null"; if (_value.isUndefined()) return "undefined"; if (_value.isString()) return "string"; if (JS_IsArrayObject(_context, _value)) return "array"; if (_value.isBoolean()) return "boolean"; if (_value.isNumber()) return "number"; if (_value.isObject()) { JS::RootedObject obj(_context, _value.toObjectOrNull()); if (JS_IsArrayObject(_context, obj)) return "array"; if (JS_ObjectIsDate(_context, obj)) return "date"; if (JS_ObjectIsFunction(_context, obj)) return "function"; return ObjectWrapper(_context, _value).getClassName(); } uasserted(ErrorCodes::BadValue, "unable to get type"); }
int ValueWriter::type() { if (_value.isNull()) return jstNULL; if (_value.isUndefined()) return Undefined; if (_value.isString()) return String; if (JS_IsArrayObject(_context, _value)) return Array; if (_value.isBoolean()) return Bool; // We could do something more sophisticated here by checking to see if we // round trip through int32_t, int64_t and double and picking a type that // way, for now just always come back as double for numbers though (it's // what we did for v8) if (_value.isNumber()) return NumberDouble; if (_value.isObject()) { JS::RootedObject obj(_context, _value.toObjectOrNull()); if (JS_ObjectIsDate(_context, obj)) return Date; if (JS_ObjectIsFunction(_context, obj)) return Code; return Object; } uasserted(ErrorCodes::BadValue, "unable to get type"); }
NS_IMETHODIMP calDateTime::SetJsDate(JSContext* aCx, JS::HandleValue aDate) { if (!aDate.isObject()) { mIsValid = false; return NS_OK; } JS::Rooted<JSObject*> dobj(aCx, &aDate.toObject()); dobj = js::CheckedUnwrap(dobj); if (!dobj) { mIsValid = false; return NS_OK; } JSAutoCompartment ac(aCx, dobj); if (!JS_ObjectIsDate(aCx, dobj) || !js_DateIsValid(dobj)) { mIsValid = false; return NS_OK; } PRTime utcTime = PRTime(js_DateGetMsecSinceEpoch(dobj)) * 1000; mIsValid = NS_SUCCEEDED(SetNativeTime(utcTime)); return NS_OK; }
// static nsresult IDBKeyRange::FromJSVal(JSContext* aCx, const jsval& aVal, IDBKeyRange** aKeyRange) { nsresult rv; nsRefPtr<IDBKeyRange> keyRange; if (JSVAL_IS_VOID(aVal) || JSVAL_IS_NULL(aVal)) { // undefined and null returns no IDBKeyRange. } else if (JSVAL_IS_PRIMITIVE(aVal) || JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(aVal)) || JS_ObjectIsDate(aCx, JSVAL_TO_OBJECT(aVal))) { // A valid key returns an 'only' IDBKeyRange. keyRange = new IDBKeyRange(false, false, true); rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower()); if (NS_FAILED(rv)) { return rv; } } else { // An object is not permitted unless it's another IDBKeyRange. nsIXPConnect* xpc = nsContentUtils::XPConnect(); NS_ASSERTION(xpc, "This should never be null!"); nsCOMPtr<nsIXPConnectWrappedNative> wrapper; rv = xpc->GetWrappedNativeOfJSObject(aCx, JSVAL_TO_OBJECT(aVal), getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsCOMPtr<nsIIDBKeyRange> iface; if (!wrapper || !(iface = do_QueryInterface(wrapper->Native()))) { // Some random JS object? return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } keyRange = static_cast<IDBKeyRange*>(iface.get()); } keyRange.forget(aKeyRange); return NS_OK; }
NS_IMETHODIMP calDateTime::SetJsDate(JSContext* aCx, const JS::Value& aDate) { if (!aDate.isObject()) { mIsValid = false; return NS_OK; } JSObject* dobj = js::CheckedUnwrap(JSVAL_TO_OBJECT(aDate)); JSAutoCompartment ac(aCx, dobj); if (!JS_ObjectIsDate(aCx, dobj) || !js_DateIsValid(dobj)) { mIsValid = false; return NS_OK; } PRTime utcTime = PRTime(js_DateGetMsecSinceEpoch(dobj)) * 1000; mIsValid = NS_SUCCEEDED(SetNativeTime(utcTime)); return NS_OK; }
nsresult Key::EncodeJSVal(JSContext* aCx, const jsval aVal, PRUint8 aTypeOffset) { PR_STATIC_ASSERT(eMaxType * MaxArrayCollapse < 256); if (JSVAL_IS_STRING(aVal)) { nsDependentJSString str; if (!str.init(aCx, aVal)) { return NS_ERROR_OUT_OF_MEMORY; } EncodeString(str, aTypeOffset); return NS_OK; } if (JSVAL_IS_INT(aVal)) { EncodeNumber((double)JSVAL_TO_INT(aVal), eFloat + aTypeOffset); return NS_OK; } if (JSVAL_IS_DOUBLE(aVal)) { double d = JSVAL_TO_DOUBLE(aVal); if (DOUBLE_IS_NaN(d)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } EncodeNumber(d, eFloat + aTypeOffset); return NS_OK; } if (!JSVAL_IS_PRIMITIVE(aVal)) { JSObject* obj = JSVAL_TO_OBJECT(aVal); if (JS_IsArrayObject(aCx, obj)) { aTypeOffset += eMaxType; if (aTypeOffset == eMaxType * MaxArrayCollapse) { mBuffer.Append(aTypeOffset); aTypeOffset = 0; } NS_ASSERTION((aTypeOffset % eMaxType) == 0 && aTypeOffset < (eMaxType * MaxArrayCollapse), "Wrong typeoffset"); jsuint length; if (!JS_GetArrayLength(aCx, obj, &length)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } for (jsuint index = 0; index < length; index++) { jsval val; if (!JS_GetElement(aCx, obj, index, &val)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsresult rv = EncodeJSVal(aCx, val, aTypeOffset); NS_ENSURE_SUCCESS(rv, rv); aTypeOffset = 0; } mBuffer.Append(eTerminator + aTypeOffset); return NS_OK; } if (JS_ObjectIsDate(aCx, obj)) { EncodeNumber(js_DateGetMsecSinceEpoch(aCx, obj), eDate + aTypeOffset); return NS_OK; } } return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; }
nsresult Key::EncodeJSValInternal(JSContext* aCx, const jsval aVal, uint8_t aTypeOffset, uint16_t aRecursionDepth) { NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR); MOZ_STATIC_ASSERT(eMaxType * MaxArrayCollapse < 256, "Unable to encode jsvals."); if (JSVAL_IS_STRING(aVal)) { nsDependentJSString str; if (!str.init(aCx, aVal)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } EncodeString(str, aTypeOffset); return NS_OK; } if (JSVAL_IS_INT(aVal)) { EncodeNumber((double)JSVAL_TO_INT(aVal), eFloat + aTypeOffset); return NS_OK; } if (JSVAL_IS_DOUBLE(aVal)) { double d = JSVAL_TO_DOUBLE(aVal); if (MOZ_DOUBLE_IS_NaN(d)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } EncodeNumber(d, eFloat + aTypeOffset); return NS_OK; } if (!JSVAL_IS_PRIMITIVE(aVal)) { JSObject* obj = JSVAL_TO_OBJECT(aVal); if (JS_IsArrayObject(aCx, obj)) { aTypeOffset += eMaxType; if (aTypeOffset == eMaxType * MaxArrayCollapse) { mBuffer.Append(aTypeOffset); aTypeOffset = 0; } NS_ASSERTION((aTypeOffset % eMaxType) == 0 && aTypeOffset < (eMaxType * MaxArrayCollapse), "Wrong typeoffset"); uint32_t length; if (!JS_GetArrayLength(aCx, obj, &length)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } for (uint32_t index = 0; index < length; index++) { jsval val; if (!JS_GetElement(aCx, obj, index, &val)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsresult rv = EncodeJSValInternal(aCx, val, aTypeOffset, aRecursionDepth + 1); if (NS_FAILED(rv)) { return rv; } aTypeOffset = 0; } mBuffer.Append(eTerminator + aTypeOffset); return NS_OK; } if (JS_ObjectIsDate(aCx, obj)) { if (!js_DateIsValid(obj)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } EncodeNumber(js_DateGetMsecSinceEpoch(obj), eDate + aTypeOffset); return NS_OK; } } return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; }