JSON.stringify.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. describe("correct behavior", () => {
  2. test("length", () => {
  3. expect(JSON.stringify).toHaveLength(3);
  4. });
  5. test("basic functionality", () => {
  6. [
  7. [5, "5"],
  8. [undefined, undefined],
  9. [null, "null"],
  10. [NaN, "null"],
  11. [-NaN, "null"],
  12. [Infinity, "null"],
  13. [-Infinity, "null"],
  14. [true, "true"],
  15. [false, "false"],
  16. ["test", '"test"'],
  17. [new Number(5), "5"],
  18. [new Boolean(false), "false"],
  19. [new String("test"), '"test"'],
  20. [() => {}, undefined],
  21. [[1, 2, "foo"], '[1,2,"foo"]'],
  22. [{ foo: 1, bar: "baz", qux() {} }, '{"foo":1,"bar":"baz"}'],
  23. [
  24. {
  25. var1: 1,
  26. var2: 2,
  27. toJSON(key) {
  28. let o = this;
  29. o.var2 = 10;
  30. return o;
  31. },
  32. },
  33. '{"var1":1,"var2":10}',
  34. ],
  35. ].forEach(testCase => {
  36. expect(JSON.stringify(testCase[0])).toEqual(testCase[1]);
  37. });
  38. });
  39. test("serialize BigInt with a toJSON property", () => {
  40. Object.defineProperty(BigInt.prototype, "toJSON", {
  41. configurable: true, // Allows deleting this property at the end of this test case.
  42. get() {
  43. "use strict";
  44. return () => typeof this;
  45. },
  46. });
  47. expect(JSON.stringify(1n)).toBe('"bigint"');
  48. delete BigInt.prototype.toJSON;
  49. });
  50. test("ignores non-enumerable properties", () => {
  51. let o = { foo: "bar" };
  52. Object.defineProperty(o, "baz", { value: "qux", enumerable: false });
  53. expect(JSON.stringify(o)).toBe('{"foo":"bar"}');
  54. });
  55. test("ignores symbol properties", () => {
  56. let o = { foo: "bar" };
  57. let sym = Symbol("baz");
  58. o[sym] = "qux";
  59. expect(JSON.stringify(o)).toBe('{"foo":"bar"}');
  60. });
  61. test("escape surrogate codepoints in strings", () => {
  62. expect(JSON.stringify("\ud83d\ude04")).toBe('"😄"');
  63. expect(JSON.stringify("\ud83d")).toBe('"\\ud83d"');
  64. expect(JSON.stringify("\ude04")).toBe('"\\ude04"');
  65. expect(JSON.stringify("\ud83d\ud83d\ude04\ud83d\ude04\ude04")).toBe('"\\ud83d😄😄\\ude04"');
  66. expect(JSON.stringify("\ude04\ud83d\ude04\ud83d\ude04\ud83d")).toBe('"\\ude04😄😄\\ud83d"');
  67. });
  68. });
  69. describe("errors", () => {
  70. test("cannot serialize BigInt", () => {
  71. expect(() => {
  72. JSON.stringify(5n);
  73. }).toThrow(TypeError, "Cannot serialize BigInt value to JSON");
  74. });
  75. test("cannot serialize circular structures", () => {
  76. let bad1 = {};
  77. bad1.foo = bad1;
  78. let bad2 = [];
  79. bad2[5] = [[[bad2]]];
  80. let bad3a = { foo: "bar" };
  81. let bad3b = [1, 2, bad3a];
  82. bad3a.bad = bad3b;
  83. [bad1, bad2, bad3a].forEach(bad => {
  84. expect(() => {
  85. JSON.stringify(bad);
  86. }).toThrow(TypeError, "Cannot stringify circular object");
  87. });
  88. });
  89. });