Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions php-transformer/src/HtmlToBlocks/Elements/RuntimeIslandContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Elements;

use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Diagnostics\FallbackEmitter;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\HtmlTransformerSession;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\RuntimeDomState;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\RuntimeSelectorState;
use Closure;
Expand All @@ -12,17 +13,12 @@
/**
* Explicit collaborator surface for {@see RuntimeIslandAnalyzer}.
*
* The session state objects and the fallback emitter are resolved lazily
* through closures because they are per-transform: the analyzer is constructed
* once with the transformer, but must see the state belonging to the transform
* currently running.
* Per-transform state is read from the compilation's typed session. Closures
* remain only for transformer-owned operations.
*/
final class RuntimeIslandContext
{
/**
* @param Closure(): FallbackEmitter $fallbackEmitter
* @param Closure(): RuntimeDomState $runtimeDom
* @param Closure(): RuntimeSelectorState $runtimeSelectors
* @param Closure(DOMElement): iterable<DOMElement> $descendantElements
* @param Closure(DOMElement): array<int, array<string, mixed>> $requiredScriptsForElement
* @param Closure(string): ?DOMElement $preservedHtmlRootElement
Expand All @@ -31,9 +27,7 @@ final class RuntimeIslandContext
* @param Closure(string): bool $isPresentationalAnimationSelector
*/
public function __construct(
private readonly Closure $fallbackEmitter,
private readonly Closure $runtimeDom,
private readonly Closure $runtimeSelectors,
private readonly HtmlTransformerSession $session,
private readonly Closure $descendantElements,
private readonly Closure $requiredScriptsForElement,
private readonly Closure $preservedHtmlRootElement,
Expand All @@ -45,17 +39,17 @@ public function __construct(

public function fallbackEmitter(): FallbackEmitter
{
return ($this->fallbackEmitter)();
return $this->session->fallbackEmitter();
}

public function runtimeDom(): RuntimeDomState
{
return ($this->runtimeDom)();
return $this->session->runtimeDomState();
}

public function runtimeSelectors(): RuntimeSelectorState
{
return ($this->runtimeSelectors)();
return $this->session->runtimeSelectorState();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Elements;

use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\HtmlTransformerSession;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Support\SourceDom;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Classification\FormControlClassifier;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Style\GeneratedSupportStylesheetState;
Expand All @@ -17,16 +18,15 @@ final class SearchBlockConversionContext
* @param Closure(DOMElement): array<string, string> $presentationDeclarations
* @param Closure(string, array<string, mixed>, array<int, array<string, mixed>>, ?DOMElement): array<string, mixed> $createBlock
* @param Closure(string): string $restoreSvgCasing
* @param Closure(): GeneratedSupportStylesheetState $generatedSupportStyles
* @param Closure(DOMElement): bool $isRuntimeDomTarget
* @param Closure(DOMElement): array<string, mixed> $htmlPreservationBlock
*/
public function __construct(
private readonly HtmlTransformerSession $session,
private readonly Closure $presentationAttributes,
private readonly Closure $presentationDeclarations,
private readonly Closure $createBlock,
private readonly Closure $restoreSvgCasing,
private readonly Closure $generatedSupportStyles,
private readonly Closure $isRuntimeDomTarget,
private readonly Closure $htmlPreservationBlock
) {
Expand Down Expand Up @@ -82,7 +82,7 @@ public function restoreSvgCasing(string $html): string

public function generatedSupportStyles(): GeneratedSupportStylesheetState
{
return ($this->generatedSupportStyles)();
return $this->session->generatedSupportStylesheetState();
}

public function isRuntimeDomTarget(DOMElement $element): bool
Expand Down
65 changes: 15 additions & 50 deletions php-transformer/src/HtmlToBlocks/HtmlCompilation.php
Original file line number Diff line number Diff line change
Expand Up @@ -845,18 +845,11 @@ private function onSourceMarkupMutated(): void
$this->sourceStyles()->invalidateSelectorMatches();
}

/**
* Collaborator surface for {@see StyleResolver}. Per-transform state is
* resolved lazily so the resolver always sees the running transform.
*/
/** Collaborator surface for {@see StyleResolver}. */
private function createStyleResolutionContext(): StyleResolutionContext
{
return new StyleResolutionContext(
fn (): AuthorStyleAnalysis => $this->authorStyles(),
fn (): SourceStyleResolutionState => $this->sourceStyles(),
fn (): LayoutGeometryState => $this->layoutGeometry(),
fn (): PresentationResolutionCache => $this->presentationResolutionCache(),
fn (): TransformationEvidenceState => $this->transformationEvidence(),
$this->session,
fn (DOMElement $element): int => $this->cardLikeChildCount($element),
fn (string $value): string => $this->cssComparableValue($value),
fn (string $selector): array => $this->parsedCssSelector($selector),
Expand Down Expand Up @@ -906,71 +899,51 @@ private function materializeStylesheetAsset(array $cssParts, string $source, str
));
}

/**
* Collaborator surface for {@see NavigationToggleSuppressor}. Per-transform
* state is resolved lazily so the suppressor always sees the running
* transform.
*/
/** Collaborator surface for {@see NavigationToggleSuppressor}. */
private function createNavigationToggleSuppressionContext(): NavigationToggleSuppressionContext
{
return new NavigationToggleSuppressionContext(
$this->session,
fn (DOMElement $element): bool => $this->sourceElementStartsHidden($element),
fn (): RuntimeSelectorState => $this->runtimeSelectors(),
fn (): NavigationProjectionState => $this->navigationProjection(),
fn (): PatternRecognizerRegistry => $this->patternRecognizers,
fn (): PatternContext => $this->probePatternContext()
);
}

/**
* Collaborator surface for {@see SvgMaterializer}. Per-transform state is
* resolved lazily so the materializer always sees the running transform.
*/
/** Collaborator surface for {@see SvgMaterializer}. */
private function createSvgMaterializationContext(): SvgMaterializationContext
{
return new SvgMaterializationContext(
$this->session,
fn (string $name, array $attrs = array(), array $innerBlocks = array(), ?DOMElement $sourceElement = null, ?DOMElement $logicalSourceElement = null): array
=> $this->createBlock($name, $attrs, $innerBlocks, $sourceElement, $logicalSourceElement),
fn (string $tagName): bool => $this->sourceElementClassifier->isInlineContentElement($tagName),
fn (DOMElement $element): bool => $this->sourceElementClassifier->isVisualLayerElement($element),
fn (): LayoutGeometryState => $this->layoutGeometry(),
fn (): AssetMaterializationState => $this->materializedAssets(),
fn (DOMElement $element): ?string => $this->reusableComponentFingerprintFor($element),
fn (DOMElement $element): string => $this->safeFallbackHtml($element),
fn (DOMElement $element): string => $this->sanitizeInlineSvgMarkup($element),
fn (): TransformationEvidenceState => $this->transformationEvidence(),
fn (): TransformationProvenanceState => $this->transformationProvenance()
fn (DOMElement $element): string => $this->sanitizeInlineSvgMarkup($element)
);
}

/** Collaborator surface for {@see SearchBlockConverter}. */
private function createSearchBlockConversionContext(): SearchBlockConversionContext
{
return new SearchBlockConversionContext(
$this->session,
fn (DOMElement $element): array => $this->styleResolver->presentationAttributes($element),
fn (DOMElement $element): array => $this->styleResolver->presentationDeclarations($element),
fn (string $name, array $attributes, array $innerBlocks, ?DOMElement $sourceElement): array => $this->createBlock($name, $attributes, $innerBlocks, $sourceElement),
fn (string $html): string => $this->svgMaterializer->restoreSvgCasing($html),
fn (): GeneratedSupportStylesheetState => $this->generatedSupportStyles(),
fn (DOMElement $element): bool => $this->runtimeIslands->isRuntimeDomTarget($element),
fn (DOMElement $element): array => $this->htmlPreservationBlock($element)
);
}

/**
* Collaborator surface for {@see NavigationStyleProjector}. Per-transform
* state is resolved lazily so the projector always sees the running
* transform.
*/
/** Collaborator surface for {@see NavigationStyleProjector}. */
private function createNavigationStyleProjectionContext(): NavigationStyleProjectionContext
{
return new NavigationStyleProjectionContext(
fn (): AuthorStyleAnalysis => $this->authorStyles(),
fn (): SourceStyleResolutionState => $this->sourceStyles(),
fn (): AuthorSelectorProjectionState => $this->session->authorSelectorProjectionState(),
fn (): GeneratedSupportStylesheetState => $this->generatedSupportStyles(),
fn (): RuntimeBehaviorState => $this->runtimeBehavior(),
fn (): TransformationEvidenceState => $this->transformationEvidence(),
$this->session,
fn (string $selector): array => $this->parsedCssSelector($selector),
function (array $cssParts, string $source, string $placement, string $pathPrefix, string $target = 'both'): void {
$this->materializeStylesheetAsset($cssParts, $source, $placement, $pathPrefix, $target);
Expand Down Expand Up @@ -1007,16 +980,11 @@ function (DOMElement $element, array &$fallbacks): ?array {
);
}

/**
* Collaborator surface for {@see RuntimeIslandAnalyzer}. Session-scoped
* state is resolved lazily so the analyzer always sees the running transform.
*/
/** Collaborator surface for {@see RuntimeIslandAnalyzer}. */
private function createRuntimeIslandContext(): RuntimeIslandContext
{
return new RuntimeIslandContext(
fn (): FallbackEmitter => $this->fallbackEmitter(),
fn (): RuntimeDomState => $this->runtimeDom(),
fn (): RuntimeSelectorState => $this->runtimeSelectors(),
$this->session,
fn (DOMElement $element): iterable => $this->descendantElements($element),
fn (DOMElement $element): array => $this->requiredScriptsForElement($element),
fn (string $html): ?DOMElement => $this->preservedHtmlRootElement($html),
Expand Down Expand Up @@ -1111,14 +1079,12 @@ function (DOMElement $element, array &$fallbacks, bool $captureUnsupported): arr

private function authorStyles(): AuthorStyleAnalysis
{
return $this->session->authorStyleAnalysis()
?? throw new \LogicException('Author styles have not been prepared for this transform.');
return $this->session->authorStyleAnalysis();
}

private function layoutGeometry(): LayoutGeometryState
{
return $this->session->layoutGeometryState()
?? throw new \LogicException('Layout geometry state has not been prepared for this transform.');
return $this->session->layoutGeometryState();
}

private function transformationProvenance(): TransformationProvenanceState
Expand Down Expand Up @@ -1154,8 +1120,7 @@ private function generatedBlocks(): GeneratedBlockRegistry

private function materializedAssets(): AssetMaterializationState
{
return $this->session->assetMaterializationState()
?? throw new \LogicException('Asset materialization state has not been prepared for this transform.');
return $this->session->assetMaterializationState();
}

private function runtimeDom(): RuntimeDomState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,21 @@ public function installAuthorStyleAnalysis(AuthorStyleAnalysis $analysis): void
$this->authorSelectorProjectionState->installAuthorStyles($analysis);
}

public function authorStyleAnalysis(): ?AuthorStyleAnalysis
public function authorStyleAnalysis(): AuthorStyleAnalysis
{
return $this->authorStyleAnalysis;
return $this->authorStyleAnalysis
?? throw new \LogicException('Author styles have not been prepared for this transform.');
}

public function installLayoutGeometryState(LayoutGeometryState $state): void
{
$this->layoutGeometryState = $state;
}

public function layoutGeometryState(): ?LayoutGeometryState
public function layoutGeometryState(): LayoutGeometryState
{
return $this->layoutGeometryState;
return $this->layoutGeometryState
?? throw new \LogicException('Layout geometry state has not been prepared for this transform.');
}

public function installGeneratedBlockRegistry(GeneratedBlockRegistry $registry): void
Expand All @@ -95,9 +97,10 @@ public function installAssetMaterializationState(AssetMaterializationState $stat
$this->assetMaterializationState = $state;
}

public function assetMaterializationState(): ?AssetMaterializationState
public function assetMaterializationState(): AssetMaterializationState
{
return $this->assetMaterializationState;
return $this->assetMaterializationState
?? throw new \LogicException('Asset materialization state has not been prepared for this transform.');
}

public function runtimeDomState(): RuntimeDomState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Style;

use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\HtmlTransformerSession;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\RuntimeBehaviorState;
use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\Session\TransformationEvidenceState;
use Closure;
Expand All @@ -11,11 +12,8 @@
/**
* Explicit collaborator surface for {@see NavigationStyleProjector}.
*
* Per-transform state (author styles, source styles, generated support styles,
* materialized assets, runtime behavior, transformation evidence) is resolved
* through closures because the projector is constructed once with the
* transformer but must see the state belonging to the transform currently
* running.
* Per-transform state is read from the compilation's typed session. Closures
* remain only for transformer-owned operations.
*
* `materializeStylesheetAsset` is a transformer-owned operation rather than a
* navigation concern — the transformer uses it for engine-support and author
Expand All @@ -25,55 +23,44 @@
final class NavigationStyleProjectionContext
{
/**
* @param Closure(): AuthorStyleAnalysis $authorStyles
* @param Closure(): SourceStyleResolutionState $sourceStyles
* @param Closure(): AuthorSelectorProjectionState $selectorProjections
* @param Closure(): GeneratedSupportStylesheetState $generatedSupportStyles
* @param Closure(): RuntimeBehaviorState $runtimeBehavior
* @param Closure(): TransformationEvidenceState $transformationEvidence
* @param Closure(string): array<string, mixed> $parsedCssSelector
* @param Closure(array<int, string>, string, string, string, string): void $materializeStylesheetAsset
*/
public function __construct(
private readonly Closure $authorStyles,
private readonly Closure $sourceStyles,
private readonly Closure $selectorProjections,
private readonly Closure $generatedSupportStyles,
private readonly Closure $runtimeBehavior,
private readonly Closure $transformationEvidence,
private readonly HtmlTransformerSession $session,
private readonly Closure $parsedCssSelector,
private readonly Closure $materializeStylesheetAsset
) {
}

public function authorStyles(): AuthorStyleAnalysis
{
return ($this->authorStyles)();
return $this->session->authorStyleAnalysis();
}

public function sourceStyles(): SourceStyleResolutionState
{
return ($this->sourceStyles)();
return $this->session->sourceStyleResolutionState();
}

public function selectorProjections(): AuthorSelectorProjectionState
{
return ($this->selectorProjections)();
return $this->session->authorSelectorProjectionState();
}

public function generatedSupportStyles(): GeneratedSupportStylesheetState
{
return ($this->generatedSupportStyles)();
return $this->session->generatedSupportStylesheetState();
}

public function runtimeBehavior(): RuntimeBehaviorState
{
return ($this->runtimeBehavior)();
return $this->session->runtimeBehaviorState();
}

public function transformationEvidence(): TransformationEvidenceState
{
return ($this->transformationEvidence)();
return $this->session->transformationEvidenceState();
}

/**
Expand Down
Loading
Loading