From 739d8cf91d949c6648079de873cb33946b0614fd Mon Sep 17 00:00:00 2001 From: benizz0 Date: Tue, 23 Jan 2024 20:09:48 +0100 Subject: [PATCH 1/2] Add circular structure detection --- index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 42e1ddc..0ddfd68 100644 --- a/index.js +++ b/index.js @@ -17,8 +17,9 @@ export function flatten (target, opts) { const transformKey = opts.transformKey || keyIdentity const output = {} - function step (object, prev, currentDepth) { + function step (object, prev, currentDepth, referenceMap = new Map) { currentDepth = currentDepth || 1 + referenceMap.set(object, prev || "object-root"); Object.keys(object).forEach(function (key) { const value = object[key] const isarray = opts.safe && Array.isArray(value) @@ -35,11 +36,16 @@ export function flatten (target, opts) { if (!isarray && !isbuffer && isobject && Object.keys(value).length && (!opts.maxDepth || currentDepth < maxDepth)) { - return step(value, newKey, currentDepth + 1) + + if(referenceMap.has(value)) + throw new Error("Circular structure on key '" + key + "' (to '" + referenceMap.get(value) + "')"); + + return step(value, newKey, currentDepth + 1, referenceMap) } output[newKey] = value - }) + }); + referenceMap.delete(object); } step(target) From ffdb5b429b594b45e529173e35b18412740f1453 Mon Sep 17 00:00:00 2001 From: benizz0 Date: Tue, 23 Jan 2024 20:10:11 +0100 Subject: [PATCH 2/2] add test --- test/test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/test.js b/test/test.js index ef01c9b..2093df5 100644 --- a/test/test.js +++ b/test/test.js @@ -206,6 +206,39 @@ describe('Flatten', function () { 'hello.0500': 'darkness my old friend' }) }) + + test('Cyclic object - With depth cycle reference', function() { + let objA = { h:"hello" } + objA.propA = { A_h:"hello" } + objA.propA._propA = { _A_h:"hello" } + objA.propA._propA.cycle = objA.propA; + + try { + flatten(objA); + } catch(e) { + if(e instanceof RangeError) + throw e; + } + + }) + + test('Cyclic object - Inner reference without cycle', function() { + let objA = { h:"hello1" } + objA.propA = { A_h:"hello2" } + objA.propB = { B_h:"hello3" } + objA.propA._propA = { _A_h:"hello4" } + objA.propA._propA.no_cycle = objA.propB; + + assert.deepStrictEqual(flatten(objA),{ + "h":"hello1", + "propA.A_h":"hello2", + "propA._propA._A_h":"hello4", + "propA._propA.no_cycle.B_h":"hello3", + "propB.B_h":"hello3", + }) + }) + + }) describe('Unflatten', function () {