You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(gxt-backend): graduate __gxtInTriggerReRender to typed withInTriggerReRender + isInTriggerReRender bridge pair (Cluster B slice 18)
Promotes the `__gxtInTriggerReRender` save-restore writers (`compile.ts`'s
in-line toggle inside the canonical `triggerReRender` body, slice-15 fold of
core.ts's pre-slice-15 wrap; `metal/property_events.ts:96-101` caller-side
toggle around `gxtTrigger(obj, keyName)`) to a typed
`compilePipeline.withInTriggerReRender<T>(fn): T` helper on the gxt-bridge.
Adds the paired `compilePipeline.isInTriggerReRender(): boolean` read-side
predicate and routes the `metal/computed.ts:522` CP.get re-entrance guard
through it. The two writers used the same `wasInside`-save / set-true /
restore pattern; this helper folds that pattern into one documented bridge
surface.
Writer + reader audit (pre-slice-18):
Writers (set the flag, save+restore via try/finally):
- compile.ts:3130-3136 — wraps `_gxtTriggerReRenderBody` inside the
canonical `_gxtTriggerReRender` body. This is the slice-15 fold of
core.ts's pre-slice-15 `ensureTriggerReRenderWrapped` wrap.
- metal/property_events.ts:96-101 — wraps the `gxtTrigger(obj, keyName)`
call inside `notifyPropertyChange`. Mirrors the canonical-body wrap
so callers that invoke the trigger via globalThis (rather than through
the bridge) still observe `true` for the duration of the synchronous
notify cascade — including any nested `notifyPropertyChange` calls
produced by `__gxtTriggerReRender`'s cellFor cascades.
Readers (read the flag as `=== true`):
- metal/computed.ts:522 — `CP.get` short-circuits cache misses when
`__gxtInTriggerReRender === true && revision === undefined`. Preserves
classic Ember's "don't eagerly evaluate never-consumed CPs during a
change notification" semantic. MIGRATED to
`compilePipeline.isInTriggerReRender()` with globalThis fallback.
- @ember/object/core.ts:325 — DEBUG proxy trap's `_isInternalPath`
predicate. NOT migrated in this slice — `@ember/object/core.ts` has
no pre-existing `gxt-bridge` import edge, and the surrounding
predicate already reads other globalThis flags (`__gxtSyncing`,
`__gxtIsRendering`) raw. Migrating one flag while leaving the others
would not improve the edge count net. Slice 18 keeps this reader on
globalThis, matching slice-15/17's "RETAINED for cross-package
readers" precedent.
Bridge shape decision: save-restore wrapper (`withInTriggerReRender<T>(fn): T`)
+ read-only predicate (`isInTriggerReRender(): boolean`). The writers both
do the save-set-true-restore dance — a wrapper captures that exactly. The
readers want a fast boolean check — a predicate is the minimal surface.
The "three-method begin/end/is" alternative was rejected: the writers
ALWAYS save+restore in `try/finally`, so a method pair without enforced
pairing would invite drift. The wrapper enforces the pairing structurally.
Namespace decision: `compilePipeline`. The flag is semantically a scope-
modifier on the `triggerReRender` trigger — the compile.ts writer lives
inside the canonical `triggerReRender` body, the property_events.ts writer
wraps the call to `triggerReRender`, the computed.ts reader gates a CP.get
short-circuit specifically for the "are we inside a trigger" question.
Same namespace as slice 17's `withTriggerSuppressed` (the structural twin —
both are scope-modifiers on the trigger; one suppresses the function, the
other toggles the predicate).
Bridge interface evolution (slice 18 — thirteenth API change):
`GxtCompilePipelineCapabilities` extended with two new optional generic
methods:
- `withInTriggerReRender?<T>(fn: () => T): T`
- `isInTriggerReRender?(): boolean`
No new install API needed (reuses slice-6's `installCompilePipelinePart`).
The `withTriggerSuppressed` doc comment is preserved as-is.
Sites moved:
- packages/@ember/-internals/gxt-backend/compile.ts: add
`_gxtWithInTriggerReRender<T>` + `_gxtIsInTriggerReRender` definitions;
replace the in-line save-restore inside `_gxtTriggerReRender` with a
`_gxtWithInTriggerReRender(() => _gxtTriggerReRenderBody(...))` call;
contribute both helpers via `installCompilePipelinePart`.
- packages/@ember/-internals/gxt-backend/gxt-bridge.ts: add
`withInTriggerReRender?<T>(fn): T` + `isInTriggerReRender?(): boolean`
to `GxtCompilePipelineCapabilities` with slice-18 doc comments
covering the writer + reader audit and the unmigrated
`@ember/object/core.ts:325` reader.
- packages/@ember/-internals/metal/lib/property_events.ts: import
`getGxtRenderer` from `@ember/-internals/gxt-backend/gxt-bridge`
(new intra-metal-lib edge — joins property_set.ts and tracked.ts's
existing edges); route the `gxtTrigger(obj, keyName)` wrap through
`compilePipeline.withInTriggerReRender(fn)` with inline save-restore
fallback for the bridge-not-yet-installed window.
- packages/@ember/-internals/metal/lib/computed.ts: import
`getGxtRenderer` from `@ember/-internals/gxt-backend/gxt-bridge`
(new intra-metal-lib edge); read the `__gxtInTriggerReRender` flag
via `compilePipeline.isInTriggerReRender()` with raw-globalThis
fallback for the bridge-not-yet-installed window.
The `__gxtInTriggerReRender` globalThis writer is RETAINED post-slice-18
because of the unmigrated `@ember/object/core.ts:325` reader. Both bridge
writers continue to mirror to the globalThis slot so the unmigrated reader
observes the same value as the bridge-route readers.
Verification (all 6 baseline gates green):
- smoke: 333/333
- Errors thrown during render: 4/4
- Tracked Properties: 33/36 (matches baseline — 3 pre-existing Helper failures)
- computed: 147/148 (matches baseline — 1 pre-existing)
- Lifecycle: 40/42 (matches baseline — 2 pre-existing Component Context failures)
- render: 977/981 (matches baseline — 4 pre-existing)
Count delta: +2 bridge methods (`withInTriggerReRender` +
`isInTriggerReRender`); 0 globalThis writers removed (writer retained for
unmigrated core.ts reader); +2 new intra-metal-lib import edges to
`gxt-bridge` (property_events.ts, computed.ts). Cumulative across
Cluster B: 18 slices migrated, bridge API evolved 13 times. All 8
capabilities namespaces stable; the two new edges join the existing
metal-lib edges (property_set.ts, tracked.ts) — pattern is established.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments