// static nsresult Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd, JSContext* aCx, uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth) { NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR); if (*aPos - aTypeOffset >= eArray) { JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr)); if (!array) { NS_WARNING("Failed to make array!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } aTypeOffset += eMaxType; if (aTypeOffset == eMaxType * MaxArrayCollapse) { ++aPos; aTypeOffset = 0; } uint32_t index = 0; JS::Rooted<JS::Value> val(aCx); while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) { nsresult rv = DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, &val, aRecursionDepth + 1); NS_ENSURE_SUCCESS(rv, rv); aTypeOffset = 0; if (!JS_SetElement(aCx, array, index++, &val)) { NS_WARNING("Failed to set array element!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } NS_ASSERTION(aPos >= aEnd || (*aPos % eMaxType) == eTerminator, "Should have found end-of-array marker"); ++aPos; aVal.setObject(*array); } else if (*aPos - aTypeOffset == eString) { nsString key; DecodeString(aPos, aEnd, key); if (!xpc::StringToJsval(aCx, key, aVal)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } else if (*aPos - aTypeOffset == eDate) { double msec = static_cast<double>(DecodeNumber(aPos, aEnd)); JSObject* date = JS_NewDateObjectMsec(aCx, msec); if (!date) { NS_WARNING("Failed to make date!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } aVal.setObject(*date); } else if (*aPos - aTypeOffset == eFloat) { aVal.setDouble(DecodeNumber(aPos, aEnd)); } else { NS_NOTREACHED("Unknown key type!"); } return NS_OK; }