From 2ae44cf8354ddb65baf6a3538a804fff92cc1716 Mon Sep 17 00:00:00 2001 From: Joel Mut Date: Thu, 25 Jan 2024 15:14:41 +0100 Subject: [PATCH 1/3] Update BotState cache hash string --- libraries/botbuilder-core/src/storage.ts | 28 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libraries/botbuilder-core/src/storage.ts b/libraries/botbuilder-core/src/storage.ts index 8eff47da55..cd3673749e 100644 --- a/libraries/botbuilder-core/src/storage.ts +++ b/libraries/botbuilder-core/src/storage.ts @@ -7,6 +7,7 @@ */ import { TurnContext } from './turnContext'; import { Assertion, assert } from 'botbuilder-stdlib'; +import { createHash } from 'crypto'; /** * Callback to calculate a storage key. @@ -115,10 +116,29 @@ export const assertStoreItems: Assertion = (val, path) => { * @param item Item to calculate the change hash for. */ export function calculateChangeHash(item: StoreItem): string { - const cpy: any = { ...item }; - if (cpy.eTag) { - delete cpy.eTag; + if (!item) { + return ''; } - return JSON.stringify(cpy); + const { eTag, ...rest } = item; + + const seen = new WeakMap(); + const result = JSON.stringify(rest, function circularReplacer(key, value) { + if (value === null || value === undefined || typeof value !== 'object') { + return value; + } + + const path = seen.get(value); + if (path) { + return `[Circular *${path.join('.')}]`; + } + + const parent = seen.get(this) ?? []; + seen.set(value, [...parent, key]); + return value; + }); + + const hash = createHash('sha256', { encoding: 'utf-8' }); + const hashed = hash.update(result).digest('hex'); + return hashed; } From 1014296fe7d0d9b1aa8a337160389438e1c8c677 Mon Sep 17 00:00:00 2001 From: Joel Mut Date: Thu, 25 Jan 2024 17:57:45 +0100 Subject: [PATCH 2/3] Execute the circularReplacer only on circular structure detection --- libraries/botbuilder-core/src/storage.ts | 35 +++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/libraries/botbuilder-core/src/storage.ts b/libraries/botbuilder-core/src/storage.ts index cd3673749e..7a0e75efe9 100644 --- a/libraries/botbuilder-core/src/storage.ts +++ b/libraries/botbuilder-core/src/storage.ts @@ -116,27 +116,36 @@ export const assertStoreItems: Assertion = (val, path) => { * @param item Item to calculate the change hash for. */ export function calculateChangeHash(item: StoreItem): string { + let result = ''; if (!item) { - return ''; + return result; } const { eTag, ...rest } = item; - const seen = new WeakMap(); - const result = JSON.stringify(rest, function circularReplacer(key, value) { - if (value === null || value === undefined || typeof value !== 'object') { - return value; + try { + result = JSON.stringify(rest); + } catch (error) { + if (!error?.message.includes('circular structure')) { + throw error; } - const path = seen.get(value); - if (path) { - return `[Circular *${path.join('.')}]`; - } + const seen = new WeakMap(); + result = JSON.stringify(rest, function circularReplacer(key, value) { + if (value === null || value === undefined || typeof value !== 'object') { + return value; + } + + const path = seen.get(value); + if (path) { + return `[Circular *${path.join('.')}]`; + } - const parent = seen.get(this) ?? []; - seen.set(value, [...parent, key]); - return value; - }); + const parent = seen.get(this) ?? []; + seen.set(value, [...parent, key]); + return value; + }); + } const hash = createHash('sha256', { encoding: 'utf-8' }); const hashed = hash.update(result).digest('hex'); From 07b531cd1388b3b4f494f72187febf00e2519b2c Mon Sep 17 00:00:00 2001 From: Joel Mut Date: Thu, 25 Jan 2024 20:05:14 +0100 Subject: [PATCH 3/3] Fix lint issue --- libraries/botbuilder-core/src/storage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/botbuilder-core/src/storage.ts b/libraries/botbuilder-core/src/storage.ts index 7a0e75efe9..6bb135d71a 100644 --- a/libraries/botbuilder-core/src/storage.ts +++ b/libraries/botbuilder-core/src/storage.ts @@ -121,6 +121,7 @@ export function calculateChangeHash(item: StoreItem): string { return result; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { eTag, ...rest } = item; try {