Skip to content

🐛 Bug: Diff reporter fails on cyclic object with custom [Symbol.toStringTag] #5641

@balagge

Description

@balagge

Bug Report Checklist

  • I have read and agree to Mocha's Code of Conduct and Contributing Guidelines
  • I have searched for related issues and issues with the faq label, but none matched my issue.
  • I have 'smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, my usage of Mocha, or Mocha itself.
  • I want to provide a PR to resolve this

Expected

Reporting object diff successfully.

Actual

TypeError: Converting circular structure to JSON being printed

Minimal, Complete and Verifiable Example

'use strict';

const chai = require('chai');
const assert = chai.assert;

describe('Test circular', function() {

    it ('Reporting diff successfully on circular object with no custom [Symbol.toStringTag]', function() {

        const obj1 = {x:1};
        obj1.self = obj1;
        const obj2 = {x:2};
        obj2.self = obj2;
        assert.deepEqual(obj1, obj2);
    });

    it ('Report fail on circular object with custom [Symbol.toStringTag]', function() {

        const obj1 = {x:1, [Symbol.toStringTag]:"CustomTag"};
        obj1.self = obj1;
        const obj2 = {x:2, [Symbol.toStringTag]:"CustomTag"};
        obj2.self = obj2;
        assert.deepEqual(obj1, obj2);
    });

});

Output:

1) Test circular
       Reporting diff successfully on circular object with no custom [Symbol.toStringTag]:

      AssertionError: expected { x: 1, self: [Circular] } to deeply equal { x: 2, self: [Circular] }
      + expected - actual

       {
         "self": [Circular]
      -  "x": 1
      +  "x": 2
       }
      
      at Context.<anonymous> (test/unitTests/runtime/set/circular.js:14:16)
      at process.processImmediate (node:internal/timers:505:21)

  2) Test circular
       Report fail on circular object with custom [Symbol.toStringTag]:
     TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'CustomTag'
    --- property 'self' closes the circle
      at JSON.stringify (<anonymous>)
      at Runner.emit (node:events:520:35)
      at process.processImmediate (node:internal/timers:505:21)

Fun fact: V8 JSON.stringify also mistakes the custom tag for a constructor name in the TypeError text.

Versions

npx mocha --version
11.7.5

node_modules/.bin/mocha --version
11.7.5

node --version
v24.10.0

Additional Info

Did some testing and debugging. Seems to be caused by

  • function canonicalType(value) in lib/utils treating custom [Symbol.toStringTag] as a type,
  • which is not handled by function jsonStringify(object, spaces, depth) , so it calls JSON.stringify() directly on the object.

Metadata

Metadata

Assignees

Labels

status: in triagea maintainer should (re-)triage (review) this issuetype: buga defect, confirmed by a maintainer

Type

No type

Projects

Status

No status

Relationships

None yet

Development

No branches or pull requests

Issue actions