Bug 1032208, part 1 - Fix JSON.stringify treatment of symbols. r=jandem.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 30 Jun 2014 14:22:44 -0500
changeset 192507 f81a509fc014e4c9ec4fbc200535ff94152d4cbc
parent 192506 0a63018c83a5cda09a8e9c8bd5c3e403d2496aac
child 192508 03f72dc8cbb1d430d370343e1ae1880f357f3c43
push id27088
push usercbook@mozilla.com
push dateMon, 07 Jul 2014 12:19:04 +0000
treeherdermozilla-central@699348fd356b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1032208
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1032208, part 1 - Fix JSON.stringify treatment of symbols. r=jandem.
js/src/json.cpp
js/src/tests/ecma_6/Symbol/json-stringify-keys.js
js/src/tests/ecma_6/Symbol/json-stringify-values.js
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -287,17 +287,17 @@ PreprocessValue(JSContext *cx, HandleObj
  * gauntlet will result in Str returning |undefined|.  This function is used to
  * properly omit properties resulting in such values when stringifying objects,
  * while properly stringifying such properties as null when they're encountered
  * in arrays.
  */
 static inline bool
 IsFilteredValue(const Value &v)
 {
-    return v.isUndefined() || IsCallable(v);
+    return v.isUndefined() || v.isSymbol() || IsCallable(v);
 }
 
 /* ES5 15.12.3 JO. */
 static bool
 JO(JSContext *cx, HandleObject obj, StringifyContext *scx)
 {
     /*
      * This method implements the JO algorithm in ES5 15.12.3, but:
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Symbol/json-stringify-keys.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// JSON.stringify ignores symbol-keyed properties, even enumerable ones.
+
+var obj = {a: 1};
+obj[Symbol.for("ponies")] = {toJSON: function () { throw "fit"; }};
+obj[Symbol.iterator] = {toJSON: function () { throw "fit"; }};
+assertEq(JSON.stringify(obj), '{"a":1}');
+
+var replacer = function (k, v) {
+    if (typeof k === "symbol")
+        throw "fit";
+    return v;
+};
+assertEq(JSON.stringify(obj, replacer), '{"a":1}');
+
+if (typeof reportCompare === 'function')
+    reportCompare(0, 0, 'ok');
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Symbol/json-stringify-values.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/ */
+
+// To JSON.stringify, symbols are the same as undefined.
+
+var symbols = [
+    Symbol(),
+    Symbol.for("ponies"),
+    Symbol.iterator
+];
+
+for (var sym of symbols) {
+    assertEq(JSON.stringify(sym), undefined);
+    assertEq(JSON.stringify([sym]), "[null]");
+
+    // JSON.stringify skips symbol-valued properties!
+    assertEq(JSON.stringify({x: sym}), '{}');
+
+    // However such properties are passed to the replacerFunction if any.
+    var replacer = function (key, val) {
+        assertEq(typeof this, "object");
+        if (typeof val === "symbol") {
+            assertEq(val, sym);
+            return "ding";
+        }
+        return val;
+    };
+    assertEq(JSON.stringify(sym, replacer), '"ding"');
+    assertEq(JSON.stringify({x: sym}, replacer), '{"x":"ding"}');
+}
+
+if (typeof reportCompare === 'function')
+    reportCompare(0, 0, 'ok');