From 753241e284f5cee5129d3df204781cc8825c1876 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Fri, 6 Jun 2008 22:30:38 -0700 Subject: [PATCH] Fix encoder to iterate over array indices from 0 to length, instead of over enumerable property ids (437724, r=sayrer). --- dom/src/json/nsJSON.cpp | 66 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/dom/src/json/nsJSON.cpp b/dom/src/json/nsJSON.cpp index 83e3aebbf4f3..be751f7f3ce7 100644 --- a/dom/src/json/nsJSON.cpp +++ b/dom/src/json/nsJSON.cpp @@ -269,12 +269,21 @@ nsJSON::EncodeObject(JSContext *cx, jsval *vp, nsJSONWriter *writer, NS_ENSURE_SUCCESS(rv, rv); JSBool ok = JS_TRUE; + JSObject *iterObj = nsnull; + jsint i = 0; + jsuint length = 0; - ok = js_ValueToIterator(cx, JSITER_ENUMERATE, vp); - if (!ok) - return NS_ERROR_FAILURE; + if (isArray) { + ok = JS_GetArrayLength(cx, obj, &length); + if (!ok) + return NS_ERROR_FAILURE; + } else { + ok = js_ValueToIterator(cx, JSITER_ENUMERATE, vp); + if (!ok) + return NS_ERROR_FAILURE; - JSObject *iterObj = JSVAL_TO_OBJECT(*vp); + iterObj = JSVAL_TO_OBJECT(*vp); + } jsval outputValue = JSVAL_VOID; JSAutoTempValueRooter tvr(cx, 1, &outputValue); @@ -283,27 +292,34 @@ nsJSON::EncodeObject(JSContext *cx, jsval *vp, nsJSONWriter *writer, PRBool memberWritten = PR_FALSE; do { outputValue = JSVAL_VOID; - ok = js_CallIteratorNext(cx, iterObj, &key); - if (!ok) - break; - - if (key == JSVAL_HOLE) - break; - - JSString *ks; - if (JSVAL_IS_STRING(key)) { - ks = JSVAL_TO_STRING(key); - } else { - ks = JS_ValueToString(cx, key); - if (!ks) { - ok = JS_FALSE; + if (isArray) { + if ((jsuint)i >= length) break; + + ok = JS_GetElement(cx, obj, i++, &outputValue); + } else { + ok = js_CallIteratorNext(cx, iterObj, &key); + if (!ok) + break; + if (key == JSVAL_HOLE) + break; + + JSString *ks; + if (JSVAL_IS_STRING(key)) { + ks = JSVAL_TO_STRING(key); + } else { + ks = JS_ValueToString(cx, key); + if (!ks) { + ok = JS_FALSE; + break; + } } + + ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks), + JS_GetStringLength(ks), &outputValue); } - ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks), - JS_GetStringLength(ks), &outputValue); if (!ok) break; @@ -398,11 +414,13 @@ nsJSON::EncodeObject(JSContext *cx, jsval *vp, nsJSONWriter *writer, } while (NS_SUCCEEDED(rv)); - // Always close the iterator, but make sure not to stomp on OK - ok &= js_CloseIterator(cx, *vp); + if (iterObj) { + // Always close the iterator, but make sure not to stomp on OK + ok &= js_CloseIterator(cx, *vp); + if (!ok) + rv = NS_ERROR_FAILURE; // encoding error or propagate? FIXME: Bug 408838. + } - if (!ok) - rv = NS_ERROR_FAILURE; // encoding error or propagate? FIXME: Bug 408838. NS_ENSURE_SUCCESS(rv, rv); output = PRUnichar(isArray ? ']' : '}');