Use Microtasks for activation#57
Conversation
Run `pnpm install` and `pnpm run build` to update the package before running tests.
Remove unused experiments dependencies and prune redundant entries. After applying these changes, run `pnpm install` and `pnpm run test` to ensure the project is correctly rebuilt and verified.
Rebuild packages with `pnpm build` before running `pnpm run test` to verify the microtask timing.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
retend | f9f193e | Commit Preview URL Branch Preview URL |
Jun 26 2026, 07:33 AM |
PR Summary by QodoUse microtasks for setup-effect activation and stabilize @adbl/cells Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1. Reentrant activation duplicates setup
|
| async activate() { | ||
| if (!this.#enabled || this.#active) return; | ||
| await new Promise((resolve) => setTimeout(resolve)); | ||
| await new Promise((resolve) => { | ||
| queueMicrotask(() => resolve(undefined)); | ||
| }); | ||
| await this.#runActivateFns(); | ||
| this.renderer?.host.dispatchEvent(new Event('retend:activate')); |
There was a problem hiding this comment.
1. Reentrant activation duplicates setup 🐞 Bug ≡ Correctness
EffectNode.activate() now defers via queueMicrotask before running #runActivateFns(), but #runActivateFns() awaits each SetupFn and only sets #active after the loop, so a second activate() call can enter while the first is mid-await and run the same setup effects again. This is reachable because multiple call sites invoke node.activate() without awaiting it (e.g., If/For updates), so repeated activations in the same tick can overlap and duplicate side effects like event listeners/timers.
Agent Prompt
## Issue description
`EffectNode.activate()` can be invoked multiple times before the node becomes active. After this PR, activation is microtask-based, which allows concurrent/overlapping activations while `#runActivateFns()` is mid-`await`, causing setup effects to execute more than once.
## Issue Context
- `#runActivateFns()` awaits each `SetupFn` and only sets `#active` after all setup functions complete.
- Several call sites call `node.activate()` without `await`, so repeated updates in the same tick can trigger multiple activations.
## Fix Focus Areas
- packages/retend/source/library/scope.js[120-146]
- packages/retend/source/library/if.js[149-158]
- packages/retend/source/library/for.js[237-242]
## Implementation direction
- Add a single-flight guard in `EffectNode` (e.g., `#activationPromise` or `#activating` flag).
- In `activate()`, if an activation is already in progress, return/await the same promise.
- Ensure `retend:activate` is dispatched once per activation and only after setup execution.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Ensure packages are rebuilt with `pnpm build` before running `pnpm run test`.
- Standardize `If()` usage by migrating away from object bags for true-only branches. - Add `retend/no-if-three-args` to enforce cleaner `If()` syntax. - Run `pnpm build` after making these changes to ensure the lint plugin is updated before testing.
retend
retend-oxlint-plugin
retend-server
retend-start
retend-utils
retend-web
retend-web-devtools
commit: |
Ensure nodes are detached from their previous parents before being moved. Also, update router replacement to correctly trigger navigation logic. Run `pnpm install` and `pnpm run test` after these changes.
Run `pnpm install` and `pnpm run build` to update the package dependencies before testing.
Rebuild packages after updating dependencies and run tests using `pnpm run test`.
No description provided.