From 9d88d8837a26bf1e4f54dcadedbc0aee523aefd7 Mon Sep 17 00:00:00 2001 From: Marko Mlakar Date: Wed, 1 Oct 2025 19:12:04 +0200 Subject: [PATCH] refactor: simplify evaluation context updates for hooks - Remove redundant loop for updating the hook contexts - Add simple test case to make sure the same object reference is being updated Signed-off-by: Marko Mlakar --- .../client/internal/open-feature-client.ts | 10 ++--- packages/server/test/hooks.spec.ts | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/server/src/client/internal/open-feature-client.ts b/packages/server/src/client/internal/open-feature-client.ts index 01120f693..e16695c76 100644 --- a/packages/server/src/client/internal/open-feature-client.ts +++ b/packages/server/src/client/internal/open-feature-client.ts @@ -338,20 +338,16 @@ export class OpenFeatureClient implements Client { const hookContextIndex = hooks.length - 1 - index; // reverse index for before hooks const hookContext = hookContexts[hookContextIndex]; - // Update the context on the stable hook context object - Object.assign(hookContext.context, accumulatedContext); - const hookResult = await hook?.before?.(hookContext, Object.freeze(options.hookHints)); if (hookResult) { accumulatedContext = { ...accumulatedContext, ...hookResult, }; - - for (let i = 0; i < hooks.length; i++) { - Object.assign(hookContexts[hookContextIndex].context, accumulatedContext); - } } + + // Update the context on the stable hook context object + Object.assign(hookContext.context, accumulatedContext); } // after before hooks, freeze the EvaluationContext. diff --git a/packages/server/test/hooks.spec.ts b/packages/server/test/hooks.spec.ts index 542a042ba..4972883e2 100644 --- a/packages/server/test/hooks.spec.ts +++ b/packages/server/test/hooks.spec.ts @@ -321,6 +321,45 @@ describe('Hooks', () => { expect.anything(), ); }); + it('Should share the same context object reference across all hooks', (done) => { + let hook1Context: EvaluationContext; + let hook2Context: EvaluationContext; + let hook3Context: EvaluationContext; + + client.getBooleanValue(FLAG_KEY, false, undefined, { + hooks: [ + { + before: (hookContext) => { + hook1Context = hookContext.context; + return { fromHook1: 'value1' }; + }, + }, + { + before: (hookContext) => { + hook2Context = hookContext.context; + return { fromHook2: 'value2' }; + }, + }, + { + before: (hookContext) => { + hook3Context = hookContext.context; + return { fromHook3: 'value3' }; + }, + + after: (hookContext) => { + try { + expect(hookContext.context).toBe(hook1Context); + expect(hookContext.context).toBe(hook2Context); + expect(hookContext.context).toBe(hook3Context); + done(); + } catch (err) { + done(err); + } + }, + }, + ], + }); + }); }); describe('Requirement 4.3.5', () => {