/* ES5 15.12.3 JA. */ static JSBool JA(JSContext *cx, HandleObject obj, StringifyContext *scx) { /* * This method implements the JA algorithm in ES5 15.12.3, but: * * * The algorithm is somewhat reformulated to allow the final string to * be streamed into a single buffer, rather than be created and copied * into place incrementally as the ES5 algorithm specifies it. This * requires moving portions of the Str call in 8a into this algorithm * (and in JO as well). */ /* Steps 1-2, 11. */ CycleDetector detect(cx, scx, obj); if (!detect.init(cx)) return JS_FALSE; if (!scx->sb.append('[')) return JS_FALSE; /* Step 6. */ uint32_t length; if (!js_GetLengthProperty(cx, obj, &length)) return JS_FALSE; /* Steps 7-10. */ if (length != 0) { /* Steps 4, 10b(i). */ if (!WriteIndent(cx, scx, scx->depth)) return JS_FALSE; /* Steps 7-10. */ Value outputValue; for (uint32_t i = 0; i < length; i++) { /* * Steps 8a-8c. Again note how the call to the spec's Str method * is broken up into getting the property, running it past toJSON * and the replacer and maybe unboxing, and interpreting some * values as |null| in separate steps. */ if (!obj->getElement(cx, i, &outputValue)) return JS_FALSE; if (!PreprocessValue(cx, obj, i, &outputValue, scx)) return JS_FALSE; if (IsFilteredValue(outputValue)) { if (!scx->sb.append("null")) return JS_FALSE; } else { if (!Str(cx, outputValue, scx)) return JS_FALSE; } /* Steps 3, 4, 10b(i). */ if (i < length - 1) { if (!scx->sb.append(',')) return JS_FALSE; if (!WriteIndent(cx, scx, scx->depth)) return JS_FALSE; } } /* Step 10(b)(iii). */ if (!WriteIndent(cx, scx, scx->depth - 1)) return JS_FALSE; } return scx->sb.append(']'); }