Skip to content

Commit

Permalink
Fix "TypeError: Converting circular structure to JSON" when passing `…
Browse files Browse the repository at this point in the history
…hyperformulaInstance` to `hotSettings` (#10186)
  • Loading branch information
tonextone committed Dec 13, 2023
1 parent b96fb9f commit e2b07e5
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 2 deletions.
8 changes: 8 additions & 0 deletions .changelogs/8728.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"issuesOrigin": "private",
"title": "Fixed \"TypeError: Converting circular structure to JSON\" when passing `hyperformulaInstance` to `hotSettings`",
"type": "fixed",
"issueOrPR": 8728,
"breaking": false,
"framework": "vue"
}
15 changes: 14 additions & 1 deletion wrappers/vue/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,18 @@ export function createVueComponent(vNode: VNode, parent: Vue, props: object, dat
* @returns {boolean} `true` if they're the same, `false` otherwise.
*/
function simpleEqual(objectA, objectB) {
return JSON.stringify(objectA) === JSON.stringify(objectB);
const circularReplacer = (function() {
const seen = new WeakSet();

return function(key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return;
seen.add(value);
}

return value;
};
}());

return JSON.stringify(objectA, circularReplacer) === JSON.stringify(objectB, circularReplacer);
}
17 changes: 17 additions & 0 deletions wrappers/vue/test/hotTableHelpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,21 @@ describe('prepareSettings', () => {
expect(preparedSettings.settings).toBe(void 0);
expect(preparedSettings.wrapperRendererCacheSize).toBe(void 0);
});

it('should handle settings with circular structure', () => {
const circularStructure = { foo: 'bar', myself: {} };

circularStructure.myself = circularStructure;

const propsMockCircular = {
readOnly: true,
whatever: circularStructure
};

const preparedSettings = prepareSettings(propsMockCircular, {});

expect(preparedSettings.readOnly).toBe(true);
expect(preparedSettings.whatever.foo).toBe('bar');
expect(preparedSettings.whatever.myself.foo).toBe('bar');
});
});
15 changes: 14 additions & 1 deletion wrappers/vue3/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,18 @@ export function prepareSettings(props: HotTableProps, currentSettings?: Handsont
* @returns {boolean} `true` if they're the same, `false` otherwise.
*/
function simpleEqual(objectA, objectB) {
return JSON.stringify(objectA) === JSON.stringify(objectB);
const circularReplacer = (function() {
const seen = new WeakSet();

return function(key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return;
seen.add(value);
}

return value;
};
}());

return JSON.stringify(objectA, circularReplacer) === JSON.stringify(objectB, circularReplacer);
}
17 changes: 17 additions & 0 deletions wrappers/vue3/test/hotTableHelpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,21 @@ describe('prepareSettings', () => {
expect(preparedSettings.id).toBe(void 0);
expect(preparedSettings.settings).toBe(void 0);
});

it('should handle settings with circular structure', () => {
const circularStructure = { foo: 'bar', myself: {} };

circularStructure.myself = circularStructure;

const propsMockCircular = {
readOnly: true,
whatever: circularStructure
};

const preparedSettings = prepareSettings(propsMockCircular, {});

expect(preparedSettings.readOnly).toBe(true);
expect(preparedSettings.whatever.foo).toBe('bar');
expect(preparedSettings.whatever.myself.foo).toBe('bar');
});
});

0 comments on commit e2b07e5

Please sign in to comment.