diff --git a/dom/base/crashtests/601247.html b/dom/base/crashtests/601247.html
new file mode 100644
index 000000000000..6eb9f46574e5
--- /dev/null
+++ b/dom/base/crashtests/601247.html
@@ -0,0 +1,8 @@
+
+
diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list
index c28df66bd23d..f380031fbd6a 100644
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -22,3 +22,4 @@ load 499006-1.html
load 499006-2.html
load 502617.html
asserts(1) load 504224.html # bug 564098
+load 601247.html
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index 3590cec795f0..96f236299b0b 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -10174,55 +10174,47 @@ nsStorageSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 enum_op, jsval *statep,
jsid *idp, PRBool *_retval)
{
+ if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
+ nsCOMPtr storage(do_QueryWrappedNative(wrapper));
+
+ // XXXndeakin need to free the keys afterwards
+ nsTArray *keys = storage->GetKeys();
+ NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY);
+
+ *statep = PRIVATE_TO_JSVAL(keys);
+
+ if (idp) {
+ *idp = INT_TO_JSID(keys->Length());
+ }
+ return NS_OK;
+ }
+
nsTArray *keys =
(nsTArray *)JSVAL_TO_PRIVATE(*statep);
- switch (enum_op) {
- case JSENUMERATE_INIT:
- case JSENUMERATE_INIT_ALL:
- {
- nsCOMPtr storage(do_QueryWrappedNative(wrapper));
+ if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) {
+ nsString& key = keys->ElementAt(0);
+ JSString *str =
+ JS_NewUCStringCopyN(cx, reinterpret_cast
+ (key.get()),
+ key.Length());
+ NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
- // XXXndeakin need to free the keys afterwards
- keys = storage->GetKeys();
- NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY);
+ JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
- *statep = PRIVATE_TO_JSVAL(keys);
+ keys->RemoveElementAt(0);
- if (idp) {
- *idp = INT_TO_JSID(keys->Length());
- }
- break;
- }
- case JSENUMERATE_NEXT:
- if (keys->Length() != 0) {
- nsString& key = keys->ElementAt(0);
- JSString *str =
- JS_NewUCStringCopyN(cx, reinterpret_cast
- (key.get()),
- key.Length());
- NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
-
- JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
-
- keys->RemoveElementAt(0);
-
- break;
- }
-
- // Fall through
- case JSENUMERATE_DESTROY:
- delete keys;
-
- *statep = JSVAL_NULL;
-
- break;
- default:
- NS_NOTREACHED("Bad call from the JS engine");
-
- return NS_ERROR_FAILURE;
+ return NS_OK;
}
+ // destroy the keys array if we have no keys or if we're done
+ NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY ||
+ (enum_op == JSENUMERATE_NEXT && keys->Length() == 0),
+ "Bad call from the JS engine");
+ delete keys;
+
+ *statep = JSVAL_NULL;
+
return NS_OK;
}
@@ -10376,55 +10368,47 @@ nsStorage2SH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRUint32 enum_op, jsval *statep,
jsid *idp, PRBool *_retval)
{
+ if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) {
+ nsCOMPtr storage(do_QueryWrappedNative(wrapper));
+
+ // XXXndeakin need to free the keys afterwards
+ nsTArray *keys = storage->GetKeys();
+ NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY);
+
+ *statep = PRIVATE_TO_JSVAL(keys);
+
+ if (idp) {
+ *idp = INT_TO_JSID(keys->Length());
+ }
+ return NS_OK;
+ }
+
nsTArray *keys =
(nsTArray *)JSVAL_TO_PRIVATE(*statep);
- switch (enum_op) {
- case JSENUMERATE_INIT:
- case JSENUMERATE_INIT_ALL:
- {
- nsCOMPtr storage(do_QueryWrappedNative(wrapper));
+ if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) {
+ nsString& key = keys->ElementAt(0);
+ JSString *str =
+ JS_NewUCStringCopyN(cx, reinterpret_cast
+ (key.get()),
+ key.Length());
+ NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
- // XXXndeakin need to free the keys afterwards
- keys = storage->GetKeys();
- NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY);
+ JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
- *statep = PRIVATE_TO_JSVAL(keys);
+ keys->RemoveElementAt(0);
- if (idp) {
- *idp = INT_TO_JSID(keys->Length());
- }
- break;
- }
- case JSENUMERATE_NEXT:
- if (keys->Length() != 0) {
- nsString& key = keys->ElementAt(0);
- JSString *str =
- JS_NewUCStringCopyN(cx, reinterpret_cast
- (key.get()),
- key.Length());
- NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
-
- JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
-
- keys->RemoveElementAt(0);
-
- break;
- }
-
- // Fall through
- case JSENUMERATE_DESTROY:
- delete keys;
-
- *statep = JSVAL_NULL;
-
- break;
- default:
- NS_NOTREACHED("Bad call from the JS engine");
-
- return NS_ERROR_FAILURE;
+ return NS_OK;
}
+ // destroy the keys array if we have no keys or if we're done
+ NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY ||
+ (enum_op == JSENUMERATE_NEXT && keys->Length() == 0),
+ "Bad call from the JS engine");
+ delete keys;
+
+ *statep = JSVAL_NULL;
+
return NS_OK;
}