mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 13:57:32 +00:00
Bug 560650 - TM: json code should use JS_Enumerate. r=gal
This commit is contained in:
parent
9e4725da95
commit
7bf54364f0
@ -97,18 +97,6 @@ function getTestPairs() {
|
||||
return testPairs;
|
||||
}
|
||||
|
||||
function testIterator() {
|
||||
// custom iterator: JS 1.7+
|
||||
var x = {
|
||||
"a": "foo",
|
||||
b: "not included",
|
||||
c: "bar",
|
||||
"4": "qux",
|
||||
__iterator__: function() { return (function() { yield "a"; yield "c"; yield 4; })() }
|
||||
}
|
||||
do_check_eq('{"a":"foo","c":"bar","4":"qux"}', nativeJSON.encode(x));
|
||||
}
|
||||
|
||||
function testStringEncode() {
|
||||
// test empty arg
|
||||
do_check_eq(null, nativeJSON.encode());
|
||||
@ -185,61 +173,9 @@ function throwingToJSON() {
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
function throwingIterator() {
|
||||
var a = {
|
||||
"b": 1,
|
||||
"c": 2,
|
||||
__iterator__: function() { yield "b"; throw("uh oh"); }
|
||||
}
|
||||
try {
|
||||
var y = nativeJSON.encode(a);
|
||||
} catch (ex) {}
|
||||
}
|
||||
|
||||
function deletingIter(x) {
|
||||
return function() {
|
||||
yield "dd";
|
||||
print("after first yield");
|
||||
delete x["a"]["c"];
|
||||
gc();
|
||||
print("about to yield second");
|
||||
yield "ddddd";
|
||||
}
|
||||
}
|
||||
|
||||
function deleteDuringEncode() {
|
||||
var x = {};
|
||||
x.a = {
|
||||
b: 1,
|
||||
bb: 2,
|
||||
bbb: 3,
|
||||
c: {
|
||||
cc: 2,
|
||||
ccc: 3,
|
||||
d: {
|
||||
dd: 2,
|
||||
ddd: 3,
|
||||
__iterator__: deletingIter(x),
|
||||
dddd: 4,
|
||||
ddddd: 5
|
||||
},
|
||||
cccc: 4,
|
||||
ccccc: 5
|
||||
},
|
||||
bbbb: 4,
|
||||
bbbbb: 5,
|
||||
bbbbbb: 6
|
||||
};
|
||||
var z = nativeJSON.encode(x);
|
||||
print(z);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
testStringEncode();
|
||||
testIterator();
|
||||
throwingToJSON();
|
||||
throwingIterator();
|
||||
deleteDuringEncode();
|
||||
|
||||
// failing on windows -- bug 410005
|
||||
// testOutputStreams();
|
||||
|
@ -87,16 +87,6 @@ function getTestPairs() {
|
||||
var y = new X();
|
||||
testPairs.push(['{"a":"b"}', y]);
|
||||
|
||||
// custom iterator: JS 1.7+
|
||||
var x = {
|
||||
"a": "foo",
|
||||
b: "not included",
|
||||
c: "bar",
|
||||
"4": "qux",
|
||||
__iterator__: function() { return (function() { yield "a"; yield "c"; yield 4; })() }
|
||||
}
|
||||
do_check_eq('{"a":"foo","c":"bar","4":"qux"}', JSON.stringify(x));
|
||||
|
||||
return testPairs;
|
||||
}
|
||||
|
||||
|
@ -257,83 +257,61 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx)
|
||||
if (!scx->cb.append('{'))
|
||||
return JS_FALSE;
|
||||
|
||||
jsval vec[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
|
||||
jsval vec[4] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vec), vec);
|
||||
jsval& key = vec[0];
|
||||
jsval& outputValue = vec[1];
|
||||
jsval& outputValue = vec[0];
|
||||
jsval& whitelistElement = vec[1];
|
||||
jsid& id = vec[2];
|
||||
|
||||
JSObject *iterObj = NULL;
|
||||
jsval *keySource = vp;
|
||||
bool usingWhitelist = false;
|
||||
|
||||
// if the replacer is an array, we use the keys from it
|
||||
if (scx->replacer && JS_IsArrayObject(cx, scx->replacer)) {
|
||||
usingWhitelist = true;
|
||||
vec[2] = OBJECT_TO_JSVAL(scx->replacer);
|
||||
keySource = &vec[2];
|
||||
vec[3] = OBJECT_TO_JSVAL(scx->replacer);
|
||||
keySource = &vec[3];
|
||||
}
|
||||
|
||||
if (!js_ValueToIterator(cx, JSITER_ENUMERATE, keySource))
|
||||
return JS_FALSE;
|
||||
iterObj = JSVAL_TO_OBJECT(*keySource);
|
||||
|
||||
JSBool memberWritten = JS_FALSE;
|
||||
AutoIdArray ida(cx, JS_Enumerate(cx, JSVAL_TO_OBJECT(*keySource)));
|
||||
if (!ida)
|
||||
return JS_FALSE;
|
||||
|
||||
bool ok = false;
|
||||
while (true) {
|
||||
for (jsint i = 0, len = ida.length(); i < len; i++) {
|
||||
outputValue = JSVAL_VOID;
|
||||
if (!js_CallIteratorNext(cx, iterObj, &key))
|
||||
goto error_break;
|
||||
if (key == JSVAL_HOLE)
|
||||
break;
|
||||
|
||||
jsuint index = 0;
|
||||
if (usingWhitelist) {
|
||||
if (!usingWhitelist) {
|
||||
if (!js_ValueToStringId(cx, ida[i], &id))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
// skip non-index properties
|
||||
if (!js_IdIsIndex(key, &index))
|
||||
jsuint index = 0;
|
||||
if (!js_IdIsIndex(ID_TO_VALUE(ida[i]), &index))
|
||||
continue;
|
||||
|
||||
jsval newKey;
|
||||
if (!scx->replacer->getProperty(cx, key, &newKey))
|
||||
goto error_break;
|
||||
key = newKey;
|
||||
if (!scx->replacer->getProperty(cx, ID_TO_VALUE(ida[i]), &whitelistElement))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!js_ValueToStringId(cx, whitelistElement, &id))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSString *ks;
|
||||
if (JSVAL_IS_STRING(key)) {
|
||||
ks = JSVAL_TO_STRING(key);
|
||||
} else {
|
||||
ks = js_ValueToString(cx, key);
|
||||
if (!ks)
|
||||
goto error_break;
|
||||
}
|
||||
AutoValueRooter keyStringRoot(cx, ks);
|
||||
|
||||
// Don't include prototype properties, since this operation is
|
||||
// supposed to be implemented as if by ES3.1 Object.keys()
|
||||
jsid id;
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(ks), &id) ||
|
||||
!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &obj2, &prop)) {
|
||||
goto error_break;
|
||||
}
|
||||
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
obj2->dropProperty(cx, prop);
|
||||
// We should have a string id by this point. Either from
|
||||
// JS_Enumerate's id array, or by converting the values
|
||||
// in the whitelist.
|
||||
JS_ASSERT(JSVAL_IS_STRING(ID_TO_VALUE(id)));
|
||||
|
||||
if (!JS_GetPropertyById(cx, obj, id, &outputValue))
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
|
||||
if (JSVAL_IS_OBJECT(outputValue) && !js_TryJSON(cx, &outputValue))
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
|
||||
// call this here, so we don't write out keys if the replacer function
|
||||
// wants to elide the value.
|
||||
if (!CallReplacerFunction(cx, id, obj, scx, &outputValue))
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
|
||||
JSType type = JS_TypeOfValue(cx, outputValue);
|
||||
|
||||
@ -343,16 +321,16 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx)
|
||||
|
||||
// output a comma unless this is the first member to write
|
||||
if (memberWritten && !scx->cb.append(','))
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
memberWritten = JS_TRUE;
|
||||
|
||||
if (!WriteIndent(cx, scx, scx->depth))
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
|
||||
// Be careful below, this string is weakly rooted
|
||||
JSString *s = js_ValueToString(cx, key);
|
||||
JSString *s = js_ValueToString(cx, ID_TO_VALUE(id));
|
||||
if (!s)
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
|
||||
const jschar *chars;
|
||||
size_t length;
|
||||
@ -360,20 +338,9 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx)
|
||||
if (!write_string(cx, scx->cb, chars, length) ||
|
||||
!scx->cb.append(':') ||
|
||||
!Str(cx, id, obj, scx, &outputValue, false)) {
|
||||
goto error_break;
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
ok = true;
|
||||
|
||||
error_break:
|
||||
if (iterObj) {
|
||||
// Always close the iterator, but make sure not to stomp on OK
|
||||
JS_ASSERT(OBJECT_TO_JSVAL(iterObj) == *keySource);
|
||||
ok &= !!js_CloseIterator(cx, *keySource);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
if (memberWritten && !WriteIndent(cx, scx, scx->depth - 1))
|
||||
return JS_FALSE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user