mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 15:17:29 +09:00
Fix a crash in IndexedDB.
This commit is contained in:
parent
f40a82f098
commit
cfc50f18c4
10 changed files with 102 additions and 39 deletions
|
|
@ -430,7 +430,7 @@ IDBCursor::Continue(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
aRv = key.SetFromJSVal(aCx, aKey);
|
aRv = key.SetFromJSVal(aCx, aKey, /* aCallGetters */ true);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -536,7 +536,7 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
aRv = key.SetFromJSVal(aCx, aKey);
|
aRv = key.SetFromJSVal(aCx, aKey, /* aCallGetters */ true);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -558,7 +558,7 @@ IDBCursor::ContinuePrimaryKey(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
Key primaryKey;
|
Key primaryKey;
|
||||||
aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey);
|
aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey, /* aCallGetters */ true);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -718,7 +718,7 @@ IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||||
const KeyPath& keyPath = objectStore->GetKeyPath();
|
const KeyPath& keyPath = objectStore->GetKeyPath();
|
||||||
Key key;
|
Key key;
|
||||||
|
|
||||||
aRv = keyPath.ExtractKey(aCx, aValue, key);
|
aRv = keyPath.ExtractKey(aCx, aValue, key, /* aCallGetters */ false);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -482,13 +482,13 @@ IDBFactory::Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
|
||||||
JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
|
JS::Handle<JS::Value> aSecond, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
Key first, second;
|
Key first, second;
|
||||||
nsresult rv = first.SetFromJSVal(aCx, aFirst);
|
nsresult rv = first.SetFromJSVal(aCx, aFirst, /* aCallGetters */ true);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
aRv.Throw(rv);
|
aRv.Throw(rv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = second.SetFromJSVal(aCx, aSecond);
|
rv = second.SetFromJSVal(aCx, aSecond, /* aCallGetters */ true);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
aRv.Throw(rv);
|
aRv.Throw(rv);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ GetKeyFromJSVal(JSContext* aCx,
|
||||||
JS::Handle<JS::Value> aVal,
|
JS::Handle<JS::Value> aVal,
|
||||||
Key& aKey)
|
Key& aKey)
|
||||||
{
|
{
|
||||||
nsresult rv = aKey.SetFromJSVal(aCx, aVal);
|
nsresult rv = aKey.SetFromJSVal(aCx, aVal, /* aCallGetters */ true);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
MOZ_ASSERT(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
MOZ_ASSERT(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
||||||
|
|
@ -1084,7 +1084,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
|
||||||
|
|
||||||
if (!aMultiEntry) {
|
if (!aMultiEntry) {
|
||||||
Key key;
|
Key key;
|
||||||
rv = aKeyPath.ExtractKey(aCx, aVal, key);
|
rv = aKeyPath.ExtractKey(aCx, aVal, key, /* aCallGetters */ false);
|
||||||
|
|
||||||
// If an index's keyPath doesn't match an object, we ignore that object.
|
// If an index's keyPath doesn't match an object, we ignore that object.
|
||||||
if (rv == NS_ERROR_DOM_INDEXEDDB_DATA_ERR || key.IsUnset()) {
|
if (rv == NS_ERROR_DOM_INDEXEDDB_DATA_ERR || key.IsUnset()) {
|
||||||
|
|
@ -1128,13 +1128,13 @@ IDBObjectStore::AppendIndexUpdateInfo(
|
||||||
|
|
||||||
for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
|
for (uint32_t arrayIndex = 0; arrayIndex < arrayLength; arrayIndex++) {
|
||||||
JS::Rooted<JS::Value> arrayItem(aCx);
|
JS::Rooted<JS::Value> arrayItem(aCx);
|
||||||
if (NS_WARN_IF(!JS_GetElement(aCx, array, arrayIndex, &arrayItem))) {
|
if (NS_WARN_IF(!JS_GetOwnElement(aCx, array, arrayIndex, &arrayItem))) {
|
||||||
IDB_REPORT_INTERNAL_ERR();
|
IDB_REPORT_INTERNAL_ERR();
|
||||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key value;
|
Key value;
|
||||||
if (NS_FAILED(value.SetFromJSVal(aCx, arrayItem)) ||
|
if (NS_FAILED(value.SetFromJSVal(aCx, arrayItem, /* aCallGetters */ false)) ||
|
||||||
value.IsUnset()) {
|
value.IsUnset()) {
|
||||||
// Not a value we can do anything with, ignore it.
|
// Not a value we can do anything with, ignore it.
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1153,7 +1153,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Key value;
|
Key value;
|
||||||
if (NS_FAILED(value.SetFromJSVal(aCx, val)) ||
|
if (NS_FAILED(value.SetFromJSVal(aCx, val, /* aCallGetters */ false)) ||
|
||||||
value.IsUnset()) {
|
value.IsUnset()) {
|
||||||
// Not a value we can do anything with, ignore it.
|
// Not a value we can do anything with, ignore it.
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
@ -1324,12 +1324,12 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
||||||
|
|
||||||
if (!HasValidKeyPath()) {
|
if (!HasValidKeyPath()) {
|
||||||
// Out-of-line keys must be passed in.
|
// Out-of-line keys must be passed in.
|
||||||
rv = aKey.SetFromJSVal(aCx, aKeyVal);
|
rv = aKey.SetFromJSVal(aCx, aKeyVal, /* aCallGetters */ true);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
} else if (!isAutoIncrement) {
|
} else if (!isAutoIncrement) {
|
||||||
rv = GetKeyPath().ExtractKey(aCx, aValue, aKey);
|
rv = GetKeyPath().ExtractKey(aCx, aValue, aKey, /* aCallGetters */ false);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
@ -1368,7 +1368,8 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
||||||
aValue,
|
aValue,
|
||||||
aKey,
|
aKey,
|
||||||
&GetAddInfoCallback,
|
&GetAddInfoCallback,
|
||||||
&data);
|
&data,
|
||||||
|
/* aCallGetters */ false);
|
||||||
} else {
|
} else {
|
||||||
rv = GetAddInfoCallback(aCx, &data);
|
rv = GetAddInfoCallback(aCx, &data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,11 @@ Key::ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
Key::EncodeJSValInternal(JSContext* aCx,
|
||||||
uint8_t aTypeOffset, uint16_t aRecursionDepth)
|
JS::Handle<JS::Value> aVal,
|
||||||
|
uint8_t aTypeOffset,
|
||||||
|
uint16_t aRecursionDepth,
|
||||||
|
bool aCallGetters)
|
||||||
{
|
{
|
||||||
static_assert(eMaxType * kMaxArrayCollapse < 256,
|
static_assert(eMaxType * kMaxArrayCollapse < 256,
|
||||||
"Unable to encode jsvals.");
|
"Unable to encode jsvals.");
|
||||||
|
|
@ -257,13 +260,18 @@ Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
||||||
|
|
||||||
for (uint32_t index = 0; index < length; index++) {
|
for (uint32_t index = 0; index < length; index++) {
|
||||||
JS::Rooted<JS::Value> val(aCx);
|
JS::Rooted<JS::Value> val(aCx);
|
||||||
if (!JS_GetElement(aCx, obj, index, &val)) {
|
bool ok = aCallGetters ? JS_GetElement(aCx, obj, index, &val)
|
||||||
|
: JS_GetOwnElement(aCx, obj, index, &val);
|
||||||
|
if (!ok) {
|
||||||
IDB_REPORT_INTERNAL_ERR();
|
IDB_REPORT_INTERNAL_ERR();
|
||||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = EncodeJSValInternal(aCx, val, aTypeOffset,
|
nsresult rv = EncodeJSValInternal(aCx,
|
||||||
aRecursionDepth + 1);
|
val,
|
||||||
|
aTypeOffset,
|
||||||
|
aRecursionDepth + 1,
|
||||||
|
aCallGetters);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
@ -406,9 +414,10 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||||
nsresult
|
nsresult
|
||||||
Key::EncodeJSVal(JSContext* aCx,
|
Key::EncodeJSVal(JSContext* aCx,
|
||||||
JS::Handle<JS::Value> aVal,
|
JS::Handle<JS::Value> aVal,
|
||||||
uint8_t aTypeOffset)
|
uint8_t aTypeOffset,
|
||||||
|
bool aCallGetters)
|
||||||
{
|
{
|
||||||
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
|
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0, aCallGetters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -741,7 +750,8 @@ Key::SetFromValueArray(mozIStorageValueArray* aValues,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Key::SetFromJSVal(JSContext* aCx,
|
Key::SetFromJSVal(JSContext* aCx,
|
||||||
JS::Handle<JS::Value> aVal)
|
JS::Handle<JS::Value> aVal,
|
||||||
|
bool aCallGetters)
|
||||||
{
|
{
|
||||||
mBuffer.Truncate();
|
mBuffer.Truncate();
|
||||||
|
|
||||||
|
|
@ -750,7 +760,7 @@ Key::SetFromJSVal(JSContext* aCx,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = EncodeJSVal(aCx, aVal, 0);
|
nsresult rv = EncodeJSVal(aCx, aVal, 0, aCallGetters);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
Unset();
|
Unset();
|
||||||
return rv;
|
return rv;
|
||||||
|
|
@ -793,9 +803,15 @@ Key::ToJSVal(JSContext* aCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Key::AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal)
|
Key::AppendItem(JSContext* aCx,
|
||||||
|
bool aFirstOfArray,
|
||||||
|
JS::Handle<JS::Value> aVal,
|
||||||
|
bool aCallGetters)
|
||||||
{
|
{
|
||||||
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
|
nsresult rv = EncodeJSVal(aCx,
|
||||||
|
aVal,
|
||||||
|
aFirstOfArray ? eMaxType : 0,
|
||||||
|
aCallGetters);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
Unset();
|
Unset();
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal);
|
SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, bool aCallGetters);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
|
ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
|
||||||
|
|
@ -212,7 +212,10 @@ public:
|
||||||
ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
|
ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
|
AppendItem(JSContext* aCx,
|
||||||
|
bool aFirstOfArray,
|
||||||
|
JS::Handle<JS::Value> aVal,
|
||||||
|
bool aCallGetters);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
|
ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
|
||||||
|
|
@ -283,7 +286,10 @@ private:
|
||||||
|
|
||||||
// Encoding functions. These append the encoded value to the end of mBuffer
|
// Encoding functions. These append the encoded value to the end of mBuffer
|
||||||
nsresult
|
nsresult
|
||||||
EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
|
EncodeJSVal(JSContext* aCx,
|
||||||
|
JS::Handle<JS::Value> aVal,
|
||||||
|
uint8_t aTypeOffset,
|
||||||
|
bool aCallGetters);
|
||||||
|
|
||||||
void
|
void
|
||||||
EncodeString(const nsAString& aString, uint8_t aTypeOffset);
|
EncodeString(const nsAString& aString, uint8_t aTypeOffset);
|
||||||
|
|
@ -331,7 +337,8 @@ private:
|
||||||
EncodeJSValInternal(JSContext* aCx,
|
EncodeJSValInternal(JSContext* aCx,
|
||||||
JS::Handle<JS::Value> aVal,
|
JS::Handle<JS::Value> aVal,
|
||||||
uint8_t aTypeOffset,
|
uint8_t aTypeOffset,
|
||||||
uint16_t aRecursionDepth);
|
uint16_t aRecursionDepth,
|
||||||
|
bool aCallGetters);
|
||||||
|
|
||||||
static nsresult
|
static nsresult
|
||||||
DecodeJSValInternal(const unsigned char*& aPos,
|
DecodeJSValInternal(const unsigned char*& aPos,
|
||||||
|
|
|
||||||
|
|
@ -372,11 +372,13 @@ KeyPath::AppendStringWithValidation(const nsAString& aString)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
KeyPath::ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const
|
KeyPath::ExtractKey(JSContext* aCx,
|
||||||
|
const JS::Value& aValue,
|
||||||
|
Key& aKey,
|
||||||
|
bool aCallGetters) const
|
||||||
{
|
{
|
||||||
uint32_t len = mStrings.Length();
|
uint32_t len = mStrings.Length();
|
||||||
JS::Rooted<JS::Value> value(aCx);
|
JS::Rooted<JS::Value> value(aCx);
|
||||||
|
|
||||||
aKey.Unset();
|
aKey.Unset();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < len; ++i) {
|
for (uint32_t i = 0; i < len; ++i) {
|
||||||
|
|
@ -388,7 +390,10 @@ KeyPath::ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(aKey.AppendItem(aCx, IsArray() && i == 0, value))) {
|
if (NS_FAILED(aKey.AppendItem(aCx,
|
||||||
|
IsArray() && i == 0,
|
||||||
|
value,
|
||||||
|
aCallGetters))) {
|
||||||
NS_ASSERTION(aKey.IsUnset(), "Encoding error should unset");
|
NS_ASSERTION(aKey.IsUnset(), "Encoding error should unset");
|
||||||
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
}
|
}
|
||||||
|
|
@ -437,9 +442,12 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
|
KeyPath::ExtractOrCreateKey(JSContext* aCx,
|
||||||
Key& aKey, ExtractOrCreateKeyCallback aCallback,
|
const JS::Value& aValue,
|
||||||
void* aClosure) const
|
Key& aKey,
|
||||||
|
ExtractOrCreateKeyCallback aCallback,
|
||||||
|
void* aClosure,
|
||||||
|
bool aCallGetters) const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IsString(), "This doesn't make sense!");
|
NS_ASSERTION(IsString(), "This doesn't make sense!");
|
||||||
|
|
||||||
|
|
@ -455,7 +463,7 @@ KeyPath::ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(aKey.AppendItem(aCx, false, value))) {
|
if (NS_FAILED(aKey.AppendItem(aCx, false, value, aCallGetters))) {
|
||||||
NS_ASSERTION(aKey.IsUnset(), "Should be unset");
|
NS_ASSERTION(aKey.IsUnset(), "Should be unset");
|
||||||
return value.isUndefined() ? NS_OK : NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
return value.isUndefined() ? NS_OK : NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,10 @@ public:
|
||||||
Parse(const Nullable<OwningStringOrStringSequence>& aValue, KeyPath* aKeyPath);
|
Parse(const Nullable<OwningStringOrStringSequence>& aValue, KeyPath* aKeyPath);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ExtractKey(JSContext* aCx, const JS::Value& aValue, Key& aKey) const;
|
ExtractKey(JSContext* aCx,
|
||||||
|
const JS::Value& aValue,
|
||||||
|
Key& aKey,
|
||||||
|
bool aCallGetters) const;
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
|
ExtractKeyAsJSVal(JSContext* aCx, const JS::Value& aValue,
|
||||||
|
|
@ -82,9 +85,12 @@ public:
|
||||||
(*ExtractOrCreateKeyCallback)(JSContext* aCx, void* aClosure);
|
(*ExtractOrCreateKeyCallback)(JSContext* aCx, void* aClosure);
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ExtractOrCreateKey(JSContext* aCx, const JS::Value& aValue, Key& aKey,
|
ExtractOrCreateKey(JSContext* aCx,
|
||||||
|
const JS::Value& aValue,
|
||||||
|
Key& aKey,
|
||||||
ExtractOrCreateKeyCallback aCallback,
|
ExtractOrCreateKeyCallback aCallback,
|
||||||
void* aClosure) const;
|
void* aClosure,
|
||||||
|
bool aCallGetters) const;
|
||||||
|
|
||||||
inline bool IsValid() const {
|
inline bool IsValid() const {
|
||||||
return mType != NONEXISTENT;
|
return mType != NONEXISTENT;
|
||||||
|
|
|
||||||
|
|
@ -2010,6 +2010,28 @@ JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* n
|
||||||
return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
|
return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
JS_GetOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
RootedId id(cx);
|
||||||
|
if (!IndexToId(cx, index, &id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rooted<PropertyDescriptor> desc(cx);
|
||||||
|
if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.object() && desc.isDataDescriptor()) {
|
||||||
|
vp.set(desc.value());
|
||||||
|
} else {
|
||||||
|
vp.setUndefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
JS_GetPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
|
JS_GetPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
|
||||||
MutableHandle<PropertyDescriptor> desc)
|
MutableHandle<PropertyDescriptor> desc)
|
||||||
|
|
|
||||||
|
|
@ -2922,6 +2922,9 @@ extern JS_PUBLIC_API(bool)
|
||||||
JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
|
JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
|
||||||
JS::MutableHandle<JS::PropertyDescriptor> desc);
|
JS::MutableHandle<JS::PropertyDescriptor> desc);
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(bool)
|
||||||
|
JS_GetOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
|
* Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain
|
||||||
* if no own property is found directly on obj. The object on which the
|
* if no own property is found directly on obj. The object on which the
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue