Convert RuntimeIslandTrait into a RuntimeIslandAnalyzer collaborator (#242) - #1316
Merged
Merged
Conversation
…242) RuntimeIslandTrait's own docblock recorded that it had been "moved verbatim out of HtmlTransformer under #242". As a single-consumer trait that move changed nothing: every method still resolved against the transformer's $this, so none of the 404 lines had left the object scope. The logic now runs against an explicit RuntimeIslandContext. All 61 call sites across HtmlTransformer and the three dispatch traits were migrated to the collaborator, so no forwarding shims remain and the trait is deleted rather than hollowed out.
This was referenced Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 4 for #242, workstream 1. Follows #1310, #1312, #1315.
This one converts an actual trait, which is the argument the previous three slices were building toward.
Why this trait
RuntimeIslandTrait's own docblock said it best:It was one of the extractions this epic already performed. As a single-consumer trait, that move relocated 404 lines across a file boundary while every method still resolved against the transformer's
$this. Nothing left the object scope, nothing became testable, and two agents editing runtime-island logic and transformer logic still collided.Measured before this PR, 7 of the 8 traits mixed into
HtmlTransformerhave exactly one consumer, totalling 8,483 lines. OnlyDomHelpersTrait(4 consumers) is doing real reuse.What changed
RuntimeIslandAnalyzerruns the same logic against an explicitRuntimeIslandContextof 17 operations. Session-scoped collaborators (FallbackEmitter,RuntimeDomState,RuntimeSelectorState) are resolved through closures because they are per-transform — the analyzer is built once with the transformer but must see the state of the transform currently running.No forwarding shims. All 61 call sites were migrated to the collaborator:
HtmlTransformerFormDispatchTraitElementConversionTraitButtonLinkDispatchTraitThe trait file is deleted, not hollowed out.
RUNTIME_TAG_SELECTORSandRUNTIME_APP_ROOT_TOKENSmoved onto the analyzer with it.Behavior preservation
Corpus hash diff on clean
trunkbefore any edit, recaptured after —serializedBlocksSHA-256 plus block/diagnostic/fallback counts:Fallback and diagnostic counts matter here: this code records runtime islands and preservation fallbacks, so identical counts are what show the diagnostic path is unchanged.
composer testexit 0.Coverage
tests/unit/runtime-island-analyzer.php— 32 assertions, constructs no transformer. The distinction it pins down was previously unreachable without a full document plus script evidence plus a stylesheet:That is what keeps CSS-animated decoration out of runtime-island preservation, and it had no direct test. Also covered: the bounded selector grammar (accepted and rejected shapes), data-attribute preservation exclusions for
canvas/form/script/form controls, 160-char attribute truncation, app-shell detection needing both multiple targets and a root token, and native retention being limited to semantic wrappers with no interactive descendants.Impact
HtmlTransformer.phpHtmlTransformer.phpis 31 lines larger — the context factory costs more than theusestatement it replaced. The file size is not the metric. 404 lines of runtime-island decision logic left the transformer's object scope and gained 32 assertions.Cumulative across the four slices:
convertElement()441 → 301, 11 collaborator files, 132 isolation assertions, one trait eliminated.Scope
Six single-consumer traits remain:
StyleResolutionTrait(2,822),FormDispatchTrait(1,865),NavigationStyleProjectionTrait(1,319),SvgMaterializationTrait(983),NavigationToggleSuppressionTrait(781),ElementConversionTrait(594),ButtonLinkDispatchTrait(119).ButtonLinkDispatchTraitis the natural next one — smallest, and it already depends on the analyzer this PR introduces.AI assistance disclosure: implemented and drafted by Claude Sonnet 4.6 running in Claude Code, operated by @chubes4. The AI captured the pre-change corpus baseline, converted the trait, migrated all 61 call sites, verified byte-identical
serializedBlocksand fallback counts across 385 fixtures, and wrote the isolation test. Reviewed by a human before opening.