Skip to content

Autoresearch/apr3#2

Draft
devagrawal09 wants to merge 46 commits intomainfrom
autoresearch/apr3
Draft

Autoresearch/apr3#2
devagrawal09 wants to merge 46 commits intomainfrom
autoresearch/apr3

Conversation

@devagrawal09
Copy link
Copy Markdown
Owner

No description provided.

Reuse the subscriber local through the loop and collapse the optimistic branch so the dirty flag is set in one place without changing queue behavior.
Remove the single-use reassignPendingTransition() helper function and inline
its 4-line loop at both call sites (scheduler.ts:275, 299). The function
adds unnecessary indirection without providing clarity or reusability.

This reduces cognitive overhead and makes the transition reassignment logic
directly visible where it's used, improving code simplicity.
Replace do-while with break pattern with a clearer while loop that uses
early returns. This eliminates the confusing break-on-depsTail pattern,
making the early-exit strategy immediately obvious. The logic is identical—
both implementations iterate the dep chain and return true on match or false
when reaching depsTail—but the while-with-returns is more direct and easier
to reason about.

No behavior change; all tests pass, benchmarks stable.
Simplify the reactive core by eliminating duplicate code in insertSubs and
queueStashedOptimisticEffects. Both functions had identical tracked effect
handling logic that checked for EFFECT_TRACKED and enqueued them directly
to the effect queue.

Extract this logic into a dedicated helper function enqueueTrackedEffect()
that returns a boolean indicating whether the effect was tracked. This removes
the duplication, makes the intent clearer, and reduces overall complexity
in the scheduler without changing behavior or affecting performance.
Return early from transitionComplete instead of threading a mutable done flag through both pending-node scans. This keeps the completion conditions identical while making the control flow easier to read.
Keep dependency-link validation as a single linear scan so the stop condition lives in the loop structure instead of an extra branch in the loop body.
Use early returns in unlinkSubs so the common removal path stays linear and the last-subscriber cleanup path no longer sits inside nested else blocks.
Use a direct max-based length assignment so heap growth no longer needs a separate guard while preserving the same no-shrink behavior.
Keep the dependency unlink traversal in the for-loop header so unobserved no longer needs a separate mutable loop variable.
Return the memo accessor directly from computed() so the wrapper no longer needs a temporary node variable.
Remove the one-use dep temporary in adjustHeight so the firewall fallback stays on a single line with the height check.
Skip empty lane effect queues with an early continue so runLaneEffects keeps the work path linear without changing scheduling behavior.
Keep createTrackedEffect as a single forwarding expression so the wrapper stays as direct as the primitive it delegates to.
Let the createReaction cleanup slot rely on its optional type instead of an explicit undefined initializer to keep the wrapper state smaller.
Use const for read-only heap flag snapshots and simplify scheduler queue helpers so the hot-path control flow stays more direct without changing reactive behavior.
Use direct iteration in small scheduler helpers so the code carries fewer mutable loop locals while preserving queue and transition behavior.
Replace manual index loops in transition bookkeeping with direct iteration so the scheduler carries less mutable state while preserving queue and transition order.
Let markNode's child traversal loop handle the null case directly so the recursion path needs one less branch and one less nesting level.
Use an early return in Queue.removeChild so the actual unlink path stays flat without changing parent-child queue semantics.
Use an early return in enqueueTrackedEffect so the tracked-effect path stays linear without changing queueing behavior.
devagrawal09 and others added 16 commits April 4, 2026 00:34
The ternary `completingTransition ? lane._transition === completingTransition : !lane._transition`
always reduces to `lane._transition === completingTransition`.

When completingTransition is null, `lane._transition === null` is identical to `!lane._transition`
because _transition is typed as `Transition | null` and can only hold an object reference or null.
The two branches of the ternary compute the same comparison in both cases, so the ternary is redundant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The condition `dep._height >= newHeight` before assigning `dep._height + 1`
is equivalent to using Math.max directly. Both produce the same result for
all inputs, but Math.max expresses the "keep the maximum" intent more
directly and removes the explicit comparison operator.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…irectly

The `let newHeight` local was used to accumulate the max dep height and then
assigned back to `el._height` at the end. Since Math.max is monotonically
non-decreasing, updating `el._height` in-place produces identical results.
This removes the intermediate mutable variable and the trailing assignment,
making the intent (update the node's height if any dep is taller) more direct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The indexed for loop maintained a separate `let i` counter and two
local consts just to access the same positions in two arrays and guard
against missing children. Using stub._children.entries() with
destructuring gives both index and value in one declaration (removing
the mutable `let i`) and optional chaining replaces the explicit
`if (child)` null guard, eliminating two lines with no behavior change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The pattern `if (queue._min > sub._height) queue._min = sub._height`
appeared twice in scheduler.ts (insertSubs and queueStashedOptimisticEffects).
Both sites just clamp _min down to the new subscriber height, which is exactly
what Math.min expresses without an explicit branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The loop body needed both the index and the child element. Using
entries() replaces the manual `let i` counter and the explicit
`const child = this._children[i]` lookup with a single destructured
binding, matching the pattern already in use in restoreQueues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
`runQueue([])` iterates nothing, so the `if (!effects.length) continue`
guard before swapping and running the effect queue is a no-op. Removing
it makes the drain path unconditional and removes one branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The if-guard already asserts !(computed._flags & REACTIVE_ZOMBIE), so
the inner ternary `computed._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue`
always resolved to dirtyQueue. Replace with dirtyQueue directly and drop
the now-unused zombieQueue import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CHECK branch cleared both CHECK and DIRTY then immediately OR-ed
DIRTY back in. Clearing a bit you set in the same expression is a no-op,
so drop REACTIVE_DIRTY from the clear mask for clarity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both computed() and createOwner() checked whether _firstChild was null
before prepending a new node. Both branches assigned _firstChild = self;
the only difference was the else also set _nextSibling. Since _nextSibling
is already initialized to null, assigning null is a no-op, so we can
unconditionally set both fields and drop the branch + temporary variable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e + assertion

The do…while + toRemove! pattern required a mutable local, a non-null
assertion, and (in dispose) a redundant || null coercion.  Replace both
sites with the for-loop idiom already used inside unlinkSubs itself.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant