Refactor: extract fallback/behavior-loss emitters into Diagnostics/FallbackEmitter (#242 slice 4)#249
Merged
Conversation
…dule (#242 slice 4) Behavior-preserving extraction of the per-element fallback emission concern out of HtmlTransformer into Diagnostics/FallbackEmitter: - capture*Fallback family (html_inline_svg_fallback / html_unsafe_inline_svg, html_canvas_runtime_fallback, html_script_fallback, html_template_runtime_fallback / html_template_metadata, script_static_metadata) - runtime-island construction (recordRuntimeIsland -> preserved_runtime_island) and required-scripts metadata - the fallback-only helper subtree (safe*Attributes, scriptRole, staticScriptMetadataRole + scriptBody* predicates, templateRole, templateRequiresRuntimePreservation) HtmlTransformer keeps thin delegating wrappers so all call sites are unchanged; accumulators (runtimeIslands/scriptMetadata) stay transformer-owned and are passed by reference. sourceContext enrichment is injected as a resolver closure (it spans the DOM-classification subsystem, not the fallback concern); small shared leaves (eventMetadata, isSafeSvgContent, dedupeArrayRows, runtimeIslandSelector) are duplicated per the slice-3 pattern. Deferred (too entangled, documented): interactive_control_behavior_lost emission and the inline html_form_fallback / html_iframe_embed_fallback build literals, which are woven into the interactive-control/form/embed conversion paths (their recordRuntimeIsland calls already route through the emitter). Pure move: canonical contracts green, parity 128->128 identical, full composer test green. HtmlTransformer 5706 -> 5351 lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chubes4
added a commit
that referenced
this pull request
Jun 28, 2026
Refactor slices 3 (#246, SemanticParityReporter) and 4 (#249, FallbackEmitter) were file-scoped, so they copied shared leaf helpers instead of promoting them. Each of the following was byte-identical across its copies; consolidate the single definition into Support/DomHelpersTrait (already used by all three classes) and remove the duplicates: - hasAncestorTag (HtmlTransformer + SemanticParityReporter) - hasSourceNavigationSignal (HtmlTransformer + SemanticParityReporter) - safeNavigationUrl (HtmlTransformer + SemanticParityReporter) - runtimeIslandSelector (HtmlTransformer + FallbackEmitter) - eventMetadata (HtmlTransformer + FallbackEmitter) - isSafeSvgContent (HtmlTransformer + FallbackEmitter) - dedupeArrayRows (HtmlTransformer + FallbackEmitter) Behavior-preserving pure dedupe: no logic or signature changes. Canonical and parity (144 fixtures) identical before and after; full composer test green. Refs #242 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
Refs #242 (slice 4: fallback / behavior-loss emitters).
Behavior-preserving extraction of the per-element fallback emission concern out of
HtmlTransformer.phpinto a newDiagnostics/FallbackEmitter. Continues the decomposition after slice-1 deferred these (interwoven with shared helpers), slice-2 freedDomHelpersTrait, and slice-3 extracted the parity builders.What moved
capture*Fallbackfamily:html_inline_svg_fallback/html_unsafe_inline_svg,html_canvas_runtime_fallback,html_script_fallback,html_template_runtime_fallback/html_template_metadata, andscript_static_metadata.recordRuntimeIsland→preserved_runtime_island) and the runtime required-scripts metadata (requiredScriptsForElement), plusisRuntimeCanvasTarget.safe{Svg,Canvas,Script,Template}Attributes,scriptRole,staticScriptMetadataRole+ thescriptBody*predicates,templateRole,templateRequiresRuntimePreservation.How it stays a pure move
HtmlTransformerkeeps thin delegating wrappers for the moved methods, so every call site is unchanged.runtimeIslands,scriptMetadata) stay transformer-owned (they are read at output and by non-fallback code such asisPreservedRuntimeIslandElement) and are passed by reference — the module never reaches into transformer$this.sourceContextenrichment is injected as a resolver closure: it spans the broader DOM-classification subsystem (structure signals, interactive attributes, commerce/card detection), which is not a fallback concern, so its canonical implementation stays inHtmlTransformer.eventMetadata,isSafeSvgContent,dedupeArrayRows,runtimeIslandSelector) are duplicated into the module (transformer keeps its copies for non-fallback callers), mirroring the slice-3safeNavigationUrlduplication.uses the existingDomHelpersTrait.Deferred (too entangled — documented in the module)
interactive_control_behavior_lostemission (appendInteractiveControlBehaviorLossFallbacks): the head of the entire interactive-control / menu-toggle / commerce classification subsystem; not cleanly separable.html_form_fallbackandhtml_iframe_embed_fallbackbuild literals: woven into the form/embed conversion paths. TheirrecordRuntimeIslandcalls already route through the emitter; only theFallbackDiagnostic::buildliterals remain inline.Verification — behavior-preserving, parity 128 → 128
Baseline (origin/trunk) and after are identical:
composer test:canonical: all contracts pass.composer parity: 128 → 128 fixtures pass (no fixture edits).composer testgreen (canonical + parity + packaging).php -lclean on both files.Line-count delta
HtmlTransformer.php: 5706 → 5351 (−355). NewDiagnostics/FallbackEmitter.php: 594 lines.DO NOT MERGE.