From 359c96038c9c4ecc3abda10e90af6b57a16ea37b Mon Sep 17 00:00:00 2001 From: Avraham Essoudry Date: Tue, 23 Jan 2024 09:03:26 +0200 Subject: [PATCH] fix(compose): properly handle replace strategy --- src/compose.ts | 13 ++++++++++--- test/compose.integration.spec.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/compose.ts b/src/compose.ts index 33ce764..7f66c8b 100644 --- a/src/compose.ts +++ b/src/compose.ts @@ -253,11 +253,15 @@ function processChanges(composer: Compose) { const changes = composer.changes; composer.changes = Object.create(null); - if (needsReInitialization(composer, changes)) { + const activationStrategy = determineActivationStrategy(composer); + if (needsReInitialization(activationStrategy, changes)) { + //when using `replace` activation strategy - we cant force the creation of a new VM + const currentViewModel = activationStrategy === ActivationStrategy.Replace ? null : composer.currentViewModel; + // init context let instruction = { view: composer.view, - viewModel: composer.currentViewModel || composer.viewModel, + viewModel: currentViewModel || composer.viewModel, model: composer.model } as CompositionContext; @@ -302,13 +306,16 @@ function requestUpdate(composer: Compose) { }); } -function needsReInitialization(composer: Compose, changes: any) { +function determineActivationStrategy(composer: Compose): ActivationStrategy { let activationStrategy = composer.activationStrategy; const vm = composer.currentViewModel; if (vm && typeof vm.determineActivationStrategy === 'function') { activationStrategy = vm.determineActivationStrategy(); } + return activationStrategy; +} +function needsReInitialization(activationStrategy: ActivationStrategy, changes: any): boolean { return 'view' in changes || 'viewModel' in changes || activationStrategy === ActivationStrategy.Replace; diff --git a/test/compose.integration.spec.ts b/test/compose.integration.spec.ts index 4a0abc1..c3581e9 100644 --- a/test/compose.integration.spec.ts +++ b/test/compose.integration.spec.ts @@ -82,10 +82,14 @@ describe('compose.integration.spec.ts', () => { }); it('works with determineActivationStrategy() - replace', async () => { + let constructorCount = 0; const { component, compose } = await bootstrapCompose( ``, { viewModel: class { + constructor() { + constructorCount++; + } // w/o the get view strategy, the initial composition fails, which results to undefined currentViewModel getViewStrategy() { return new InlineViewStrategy(''); @@ -104,6 +108,7 @@ describe('compose.integration.spec.ts', () => { compose.modelChanged({ a: 1 }, oldModel); taskQueue.queueMicroTask(() => { + expect(constructorCount).toBe(2, 'constructor count === 2'); expect(compose.compositionEngine.compose).toHaveBeenCalledTimes(1); component.dispose(); }); @@ -111,11 +116,15 @@ describe('compose.integration.spec.ts', () => { }); it('works with determineActivationStrategy() - invoke-lifecycle', async () => { + let constructorCount = 0; let activationCount = 0; const { component, compose } = await bootstrapCompose( ``, { viewModel: class { + constructor() { + constructorCount++; + } activate() { activationCount++; } @@ -138,6 +147,7 @@ describe('compose.integration.spec.ts', () => { compose.modelChanged({}, oldModel); taskQueue.queueMicroTask(() => { + expect(constructorCount).toBe(1, 'constructor count === 1'); expect(activationCount).toBe(2, 'activation count === 2'); component.dispose(); });