import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { getReloadVersion } from '../../../src/core/reload-version.js'; import { MainThreadRef, clearMainThreadRefLastIdForTesting } from '../../../src/core/main-thread-ref.js'; import { takeMainThreadRefInitValuePatch } from '../../../src/core/main-thread-ref-init-value.js'; import { clearMtsConfigCacheForTesting } from '../../../src/core/mts-capability.js'; import { globalCommitContext, markRemovedSubtreeForPostDispatchTeardown, } from '../../../src/element-template/background/commit-context.js'; import { resetElementTemplateCommitState } from '../../../src/element-template/background/commit-hook.js'; import { installElementTemplateHydrationListener, resetElementTemplateHydrationListener, } from '../../../src/element-template/background/hydration-listener.js'; import { BackgroundElementTemplateInstance } from '../../../src/element-template/background/instance.js'; import { backgroundElementTemplateInstanceManager } from '../../../src/element-template/background/manager.js'; import { ElementTemplateLifecycleConstant } from '../../../src/element-template/protocol/lifecycle-constant.js'; import { ElementTemplateUpdateOps } from '../../../src/element-template/protocol/opcodes.js'; import type { SerializedCompiledNode } from '../../../src/element-template/protocol/types.js'; import { callDestroyLifetimeFun } from '../../../src/element-template/native/callDestroyLifetimeFun.js'; import { __root } from '../../../src/element-template/runtime/page/root-instance.js'; import { ElementTemplateEnvManager } from '../test-utils/debug/envManager.js'; describe('callDestroyLifetimeFun', () => { const envManager = new ElementTemplateEnvManager(); beforeEach(() => { vi.clearAllMocks(); resetElementTemplateHydrationListener(); resetElementTemplateCommitState(); clearMainThreadRefLastIdForTesting(); clearMtsConfigCacheForTesting(); takeMainThreadRefInitValuePatch(); envManager.resetEnv('background'); }); afterEach(() => { resetElementTemplateHydrationListener(); resetElementTemplateCommitState(); takeMainThreadRefInitValuePatch(); }); it('destroys background runtime state', () => { const root = new BackgroundElementTemplateInstance('_et_test'); const child = new BackgroundElementTemplateInstance('_et_child'); root.appendChild(child); markRemovedSubtreeForPostDispatchTeardown(root); globalCommitContext.ops = [ ElementTemplateUpdateOps.createTemplate, child.instanceId, '_et_child', null, [], [], ]; callDestroyLifetimeFun(); expect([...globalCommitContext.nonPayload.removedSubtreesAwaitingTeardown]).toEqual([]); expect(globalCommitContext.ops).toEqual([]); expect(backgroundElementTemplateInstanceManager.values.size).toBe(0); }); it('discards pending MainThreadRef init values on full-lifetime destroy', () => { new MainThreadRef('stale'); callDestroyLifetimeFun(); expect(takeMainThreadRefInitValuePatch()).toEqual([]); }); it('removes the hydration listener without processing later hydrate payloads', () => { installElementTemplateHydrationListener(); const backgroundRoot = __root as BackgroundElementTemplateInstance; const after = new BackgroundElementTemplateInstance('_et_test'); backgroundRoot.appendChild(after); callDestroyLifetimeFun(); envManager.switchToMainThread(); lynx.getJSContext().dispatchEvent({ type: ElementTemplateLifecycleConstant.hydrate, data: { page: { tag: 'page', attributes: null, childSlots: [[ { templateKey: '_et_test', attributeSlots: [], childSlots: [], uid: -1, } satisfies SerializedCompiledNode, ]], uid: 0, }, reloadVersion: getReloadVersion(), }, }); envManager.switchToBackground(); expect(backgroundElementTemplateInstanceManager.get(-1)).toBeUndefined(); expect(backgroundElementTemplateInstanceManager.values.size).toBe(0); }); });