Add HostEntityPropSource so content-entity-reference props can resolve to the rendering host entity
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3587374. -->
Reported by: [penyaskito](https://www.drupal.org/user/959536)
Related to !1060
>>>
<h3 id="overview">Overview</h3>
<p>When a Canvas <code>JavaScriptComponent</code> is placed on an entity-render page (a node, page, etc.), an editor configuring an entity-reference prop on that component has only two ways to populate it after <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3586613" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3586613</a></span> (merged 2026-05-12):</p>
<ul>
<li>Statically pick a specific entity via autocomplete (<code>StaticPropSource</code>).</li>
<li>Link to an entity-reference field on the host entity (<code>EntityFieldPropSource</code>, established in <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-13"><a href="https://www.drupal.org/project/drupal/issues/3031367" title="Status: Needs work">#3031367: Generate JSON schema for content entity types</a></span>).</li>
</ul>
<p>The very common intent "use this page's entity itself" — i.e. pass the host node/page directly into the prop — has no representation: <code>HostEntityUrlPropSource</code> exists for the host entity's URL, but no sibling exists for the host entity object.</p>
<p>This is the back-end follow-up to the entity-reference prop-shape work in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3586613" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3586613</a></span>. The shape itself is usable without a host-entity source, so it has been lifted into this dedicated child of the META <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3573831" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3573831</a></span>.</p>
<h3 id="proposed-resolution">Proposed resolution</h3>
<p>Add a new <code>HostEntityPropSource</code> as the third valid source for entity-reference-shaped props, alongside <code>StaticPropSource</code> and <code>EntityFieldPropSource</code>. The change is purely additive.</p>
<h4>New PropSource class and enum case</h4>
<ul>
<li>New <code>final</code> class <code>Drupal\canvas\PropSource\HostEntityPropSource</code> implementing the standard <code>PropSource</code> contract.</li>
<li><code>evaluate(NULL, …)</code> always throws <code>MissingHostEntityException</code>; <code>evaluate($entity, …)</code> returns <code>new EvaluationResult($entity)</code>. The throw-from-evaluate contract is intentional — the generic <code>PropSource::parse()</code> + <code>$source->evaluate()</code> loop in <code>GeneratedFieldExplicitInputUxComponentSourceBase::getExplicitInput()</code> already wraps <code>evaluate()</code> in a try/catch that silently skips on this exception, which is what protects host-less render contexts (e.g. pattern previews). <code>JsComponent::getExplicitInput()</code> inherits the protection by calling <code>parent::getExplicitInput()</code> first.</li>
<li>New enum case <code>PropSource::HostEntity = 'host-entity'</code>, plus the <code>getTypePrefix()</code> / <code>parse()</code> dispatch entries that route to the new class.</li>
</ul>
<h3 id="remaining-tasks">Remaining tasks</h3>
<ul>
<li>Add the <code>HostEntityPropSource</code> class and wire it into the <code>PropSource</code> enum. (Done — see <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-2"><a href="https://www.drupal.org/project/canvas/issues/3587374" title="Status: Fixed">#3587374: Add HostEntityPropSource so content-entity-reference props can resolve to the rendering host entity</a></span> MR !1060 draft scope.)</li>
<li>Widen <code>LinkedPropSource</code> and <code>GeneratedFieldExplicitInputUxComponentSourceBase</code> to recognize the new class.</li>
<li>Add a new <code>HostEntityPropSourceMatcher</code> class and inject it into <code>PropSourceSuggester</code> with a new <code>PropSource::HostEntity->value</code> bucket.</li>
<li>Tests (all using programmatic <code>JavaScriptComponent::create([...])</code> fixtures — never SDC fixtures, since SDC content-entity-reference end-to-end support is not supported): focused <code>HostEntityPropSourceTest</code> (parse round-trip, evaluate semantics, label, dependencies); new <code>HostEntityPropSourceMatcherTest</code> covering the matcher's positive/negative bundle-gate logic; extend <code>PropSourceSuggesterTest</code> with integration coverage of the new bucket; extend <code>JavascriptComponentStorageTest</code> with one render against a real host and one host-less skip case.</li>
<li>Update <code>docs/shape-matching.md</code> with a "Sources" subsection enumerating the three valid sources</li>
</ul>
> Related issue: [Issue #3586613](https://www.drupal.org/node/3586613)
> Related issue: [Issue #3588438](https://www.drupal.org/node/3588438)
> Related issue: [Issue #3573831](https://www.drupal.org/node/3573831)
issue