From 132453a655c12fc3f1e95a56d1535004d7fc942f Mon Sep 17 00:00:00 2001 From: Mariusz Nowak Date: Wed, 13 Jan 2021 13:51:40 +0100 Subject: [PATCH] feat(Mocha): Patch circular references parallel invocation bug --- setup/patch.js | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/setup/patch.js b/setup/patch.js index 89ab74f..dde8c9f 100644 --- a/setup/patch.js +++ b/setup/patch.js @@ -10,11 +10,39 @@ const EventEmitter = require('events'); const runnerEmitter = new EventEmitter(); +const isObject = require('type/object/is'); const Mocha = require('mocha/lib/mocha'); +const { serialize } = require('mocha/lib/nodejs/serializer'); + +const removeCyclicReferences = (object, handled = new Set()) => { + handled.add(object); + const entries = Array.isArray(object) ? object.entries() : Object.entries(object); + for (const [key, value] of entries) { + if (!isObject(value)) continue; + if (handled.has(value)) delete object[key]; + else removeCyclicReferences(value, new Set(handled)); + } +}; const mochaRun = Mocha.prototype.run; Mocha.prototype.run = function (fn, ...args) { - const runner = mochaRun.call(this, fn, ...args); + const runner = mochaRun.call( + this, + (result) => { + // Workaround https://github.com/mochajs/mocha/issues/4552 + const serialized = serialize(result); + const stringifiedResult = (() => { + try { + return JSON.stringify(serialized); + } catch (error) { + removeCyclicReferences(serialized); + return JSON.stringify(serialized); + } + })(); + return fn.call(this, JSON.parse(stringifiedResult)); + }, + ...args + ); if (runner.constructor.name === 'Runner') runnerEmitter.emit('runner', runner); runner.constructor.immediately = process.nextTick; return runner;