From e4a2bfccc07e65f9cfd1db9a943d93a84fb13ae4 Mon Sep 17 00:00:00 2001 From: Nicholas Rice <3213292+nicholasrice@users.noreply.github.com> Date: Wed, 9 Nov 2022 06:43:46 -0800 Subject: [PATCH] fix max call stack exceeded when setting token values from change handler (#6499) * fixing issue and adding regression tests * Change files Co-authored-by: nicholasrice Co-authored-by: Chris Holt Co-authored-by: Rob Eisenberg --- ...-70a0ba72-9ead-4a9b-ba30-447ff173c577.json | 7 ++++ .../core/design-token-node.pw.spec.ts | 34 +++++++++++++++++++ .../design-token/core/design-token-node.ts | 7 ++-- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 change/@microsoft-fast-foundation-70a0ba72-9ead-4a9b-ba30-447ff173c577.json diff --git a/change/@microsoft-fast-foundation-70a0ba72-9ead-4a9b-ba30-447ff173c577.json b/change/@microsoft-fast-foundation-70a0ba72-9ead-4a9b-ba30-447ff173c577.json new file mode 100644 index 00000000000..22afc7bdb69 --- /dev/null +++ b/change/@microsoft-fast-foundation-70a0ba72-9ead-4a9b-ba30-447ff173c577.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Fixing bug in DesignToken causing RangeError", + "packageName": "@microsoft/fast-foundation", + "email": "nicholasrice@users.noreply.github.com", + "dependentChangeType": "prerelease" +} diff --git a/packages/web-components/fast-foundation/src/design-token/core/design-token-node.pw.spec.ts b/packages/web-components/fast-foundation/src/design-token/core/design-token-node.pw.spec.ts index a1db1f8f26f..e0dfcf9c51b 100644 --- a/packages/web-components/fast-foundation/src/design-token/core/design-token-node.pw.spec.ts +++ b/packages/web-components/fast-foundation/src/design-token/core/design-token-node.pw.spec.ts @@ -160,6 +160,23 @@ test.describe("DesignTokenNode", () => { expect(target.getTokenValue(token)).toEqual(14); }); + + test("should not throw when setting a token value from within a change handler", () => { + const node = new DesignTokenNode(); + const tokenA = { $value: undefined }; + const tokenB = { $value: undefined }; + + node.setTokenValue(tokenA, 12); + Observable.getNotifier(tokenA).subscribe({ + handleChange(source, args) { + node.setTokenValue(tokenB, 14); + }, + }); + + expect(() => { + node.setTokenValue(tokenA, 13); + }).not.toThrow(); + }); }); test.describe("setting a token to a derived value", () => { test("should support getting and setting falsey values", () => { @@ -287,6 +304,23 @@ test.describe("DesignTokenNode", () => { }); }).toThrow(); }); + + test("should not throw when setting a token derived value from within a change handler", () => { + const node = new DesignTokenNode(); + const tokenA = { $value: undefined }; + const tokenB = { $value: undefined }; + + node.setTokenValue(tokenA, 12); + Observable.getNotifier(tokenA).subscribe({ + handleChange(source, args) { + node.setTokenValue(tokenB, () => 12); + }, + }); + + expect(() => { + node.setTokenValue(tokenA, 13); + }).not.toThrow(); + }); }); test.describe("getting a token value", () => { diff --git a/packages/web-components/fast-foundation/src/design-token/core/design-token-node.ts b/packages/web-components/fast-foundation/src/design-token/core/design-token-node.ts index 8520d1a2372..667236fb631 100644 --- a/packages/web-components/fast-foundation/src/design-token/core/design-token-node.ts +++ b/packages/web-components/fast-foundation/src/design-token/core/design-token-node.ts @@ -240,11 +240,12 @@ export class DesignTokenNode { * Emit all queued notifications */ private static notify() { - for (const record of this._notifications) { + const notifications = this._notifications; + this._notifications = []; + + for (const record of notifications) { record.notify(); } - - this._notifications = []; } private static queueNotification(...records: DesignTokenChangeRecordImpl[]) {