Skip to content

Refactor: extract fallback/behavior-loss emitters into Diagnostics/FallbackEmitter (#242 slice 4)#249

Merged
chubes4 merged 1 commit into
trunkfrom
refactor/htmltransformer-fallback-emitters
Jun 28, 2026
Merged

Refactor: extract fallback/behavior-loss emitters into Diagnostics/FallbackEmitter (#242 slice 4)#249
chubes4 merged 1 commit into
trunkfrom
refactor/htmltransformer-fallback-emitters

Conversation

@chubes4

@chubes4 chubes4 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Refs #242 (slice 4: fallback / behavior-loss emitters).

Behavior-preserving extraction of the per-element fallback emission concern out of HtmlTransformer.php into a new Diagnostics/FallbackEmitter. Continues the decomposition after slice-1 deferred these (interwoven with shared helpers), slice-2 freed DomHelpersTrait, and slice-3 extracted the parity builders.

What moved

  • The 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, and script_static_metadata.
  • Runtime-island construction (recordRuntimeIslandpreserved_runtime_island) and the runtime required-scripts metadata (requiredScriptsForElement), plus isRuntimeCanvasTarget.
  • The fallback-only helper subtree: safe{Svg,Canvas,Script,Template}Attributes, scriptRole, staticScriptMetadataRole + the scriptBody* predicates, templateRole, templateRequiresRuntimePreservation.

How it stays a pure move

  • HtmlTransformer keeps thin delegating wrappers for the moved methods, so every call site is unchanged.
  • The accumulators (runtimeIslands, scriptMetadata) stay transformer-owned (they are read at output and by non-fallback code such as isPreservedRuntimeIslandElement) and are passed by reference — the module never reaches into transformer $this.
  • sourceContext enrichment 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 in HtmlTransformer.
  • Small shared leaves (eventMetadata, isSafeSvgContent, dedupeArrayRows, runtimeIslandSelector) are duplicated into the module (transformer keeps its copies for non-fallback callers), mirroring the slice-3 safeNavigationUrl duplication.
  • The module uses the existing DomHelpersTrait.

Deferred (too entangled — documented in the module)

  • interactive_control_behavior_lost emission (appendInteractiveControlBehaviorLossFallbacks): the head of the entire interactive-control / menu-toggle / commerce classification subsystem; not cleanly separable.
  • The inline html_form_fallback and html_iframe_embed_fallback build literals: woven into the form/embed conversion paths. Their recordRuntimeIsland calls already route through the emitter; only the FallbackDiagnostic::build literals 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).
  • Full composer test green (canonical + parity + packaging).
  • php -l clean on both files.

Line-count delta

HtmlTransformer.php: 5706 → 5351 (−355). New Diagnostics/FallbackEmitter.php: 594 lines.

DO NOT MERGE.

…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 chubes4 merged commit 9485b2c into trunk Jun 28, 2026
1 check passed
@chubes4 chubes4 deleted the refactor/htmltransformer-fallback-emitters branch June 28, 2026 00:17
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>
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