Skip to content

[BUGFIX] Re-render dynamic components in append position when the definition changes#21470

Merged
NullVoxPopuli merged 1 commit into
mainfrom
nvp/fix-21042
Jun 12, 2026
Merged

[BUGFIX] Re-render dynamic components in append position when the definition changes#21470
NullVoxPopuli merged 1 commit into
mainfrom
nvp/fix-21042

Conversation

…hanges

Previously, when a component definition rendered in append position
(e.g. `{{if @isok Ok Ko}}` or `{{@foo}}`) changed to a *different*
component definition, nothing invalidated the rendered component: the
content-type guard only re-renders when the content *type* changes
(component -> string, etc.), and the curried component was resolved
once on initial render.

Emit AssertSame before resolving the curried component in the dynamic
append paths (stdlib StdAppend and the dynamic call append in
statement compilation), mirroring the existing String/SafeString/
Fragment/Node branches and the Assert that InvokeDynamicComponent
already gets via Replayable. When the definition reference's value
changes, the enclosing Enter/Exit region is cleared and re-rendered
with the new component.

Fixes #21042

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📊 Size report

Tarball size1.2 MB1.2 MB

dist/dev   0%↑

File Before (Size / Brotli) After (Size / Brotli)
Total (Includes all files) 2.1 MB / 492.7 kB 0%↑2.1 MB / -0%↓492.6 kB

dist/prod   0%↑

File Before (Size / Brotli) After (Size / Brotli)
./packages/shared-chunks/api-{hash}.js 25.4 kB / 5.6 kB -67.2%↓8.3 kB / -68.7%↓1.8 kB
Total (Includes all files) 1.9 MB / 450.7 kB 0%↑1.9 MB / -0.01%↓450.7 kB

smoke-tests/v2-app-template/dist   0.01%↑

File Before (Size / Brotli) After (Size / Brotli)
Total (Includes all files) 348.1 kB / 94.7 kB 0.01%↑348.1 kB / -0.06%↓94.6 kB

smoke-tests/v2-app-hello-world-template/dist   0.01%↑

File Before (Size / Brotli) After (Size / Brotli)
Total (Includes all files) 159.4 kB / 43.9 kB 0.01%↑159.4 kB / 0.2%↑44 kB

🤖 This report was automatically generated by wyvox/pkg-size

@NullVoxPopuli NullVoxPopuli changed the title Re-render dynamic components in append position when the definition changes [BUGFIX] Re-render dynamic components in append position when the definition changes Jun 12, 2026
@NullVoxPopuli NullVoxPopuli marked this pull request as ready for review June 12, 2026 20:26
@NullVoxPopuli NullVoxPopuli merged commit d972eb6 into main Jun 12, 2026
48 checks passed
@NullVoxPopuli NullVoxPopuli deleted the nvp/fix-21042 branch June 12, 2026 20:41
lifeart added a commit to lifeart/ember.js that referenced this pull request Jun 12, 2026
…nentManager

The shim's setComponentManager writes COMPONENT_MANAGERS (custom managers)
while hasInternalComponentManager only walked INTERNAL_MANAGERS — so the
VM's dynamicContentType classified a custom-managed component class as a
HELPER (the shim treats any function as a default helper) and the helper
path CALLED the class: "Class constructor definition cannot be invoked
without 'new'". Never tripped before because the resolve path
(getInternalComponentManager) already consulted both maps; upstream emberjs#21470's
new AssertSame opcode re-enters the dynamic-append region on definition
change and re-runs DYNAMIC_CONTENT_TYPE on the swapped class, which is
exactly what its new test exercises. The has-predicate now mirrors the
getter's two-phase walk (and upstream @glimmer/manager's single-registry
semantics).

Found via CDP pause-on-exceptions (QUnit strips uncaught-in-render throw
stacks; see zzprobe-stack-dc.mjs).

Gates (with the emberjs#21470 merge, both modes): dev 9460/9443/17/0 exact in
fallback AND hook mode, prod 9310/9246/0, smokes 7/7; the three new
strict-mode dynamic-definition tests pass.

Co-Authored-By: Claude Fable 5 <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.

Bug: inline if helper doesn't work when condition is an arg

2 participants