Skip to content

Commit

Permalink
SNOW-959721 TypeError: Converting circular structure to JSON in isVal…
Browse files Browse the repository at this point in the history
…idAsync exception handling (#688)
  • Loading branch information
sfc-gh-dszmolka authored Nov 8, 2023
1 parent 611fa33 commit 645faeb
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/connection/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ function Connection(context)
}
catch (e)
{
Logger.getInstance().trace('Connection heartbeat failed: %s', JSON.stringify(e));
Logger.getInstance().trace('Connection heartbeat failed: %s', JSON.stringify(e, Util.getCircularReplacer()));
return false;
}
};
Expand Down
25 changes: 25 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,3 +603,28 @@ exports.convertSmkIdToString = function (body)
{
return body.replace(/"smkId" : ([0-9]*)/g, '"smkId" : "$1"');
};

/**
* Under some circumstances the object passed to JSON.stringify in exception handling
* can contain circular reference, on which JSON.stringify bails out
* MDN way of handling such error
* @returns string
*/
exports.getCircularReplacer = function() {
const ancestors = [];
return function (key, value) {
if (typeof value !== "object" || value === null) {
return value;
}
// `this` is the object that value is contained in,
// i.e., its direct parent.
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {
ancestors.pop();
}
if (ancestors.includes(value)) {
return "[Circular]";
}
ancestors.push(value);
return value;
};
};
18 changes: 18 additions & 0 deletions test/unit/util_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -804,4 +804,22 @@ describe('Util', function ()
});
});
});

describe("Util Test - handling circular reference in isValidAsync exception handling", () => {
let shouldMatchNonCircular = '{"one":1,"two":2}';
let shouldMatchCircular = '{"one":1,"two":2,"myself":"[Circular]"}';

it("non-circular reference is handled correctly by JSON.stringify replacer", () => {
const a = {"one": 1, "two": 2};
const replacedA = JSON.stringify(a, Util.getCircularReplacer());
assert.deepEqual(replacedA, shouldMatchNonCircular);
});

it("circular reference is handled correctly by JSON.stringify replacer", () => {
const b = {"one": 1, "two": 2};
b.myself = b;
const replacedB = JSON.stringify(b, Util.getCircularReplacer());
assert.deepEqual(replacedB, shouldMatchCircular);
});
});
});

0 comments on commit 645faeb

Please sign in to comment.