refactor(compiler): Support defer triggers with no arguments in template pipeline (#52479)

Some defer triggers, such as `hover`, expect a local reference as an argument. For example, `@defer (on hover(target))` waits until the user hovers over the target.

However, these defer conditions also have a nullary form, in which the trigger is implicitly the first element in the placeholder block. We now support that case in template pipeline.

PR Close #52479
This commit is contained in:
Dylan Hunn
2023-10-31 17:30:24 -07:00
committed by Andrew Scott
parent 8400533555
commit dab522f011
2 changed files with 22 additions and 3 deletions
@@ -226,8 +226,7 @@
],
"failureMessage": "Incorrect template"
}
],
"skipForTemplatePipeline": true
]
}
]
}
@@ -7,7 +7,7 @@
*/
import * as ir from '../../ir';
import type {ViewCompilationUnit, ComponentCompilationJob} from '../compilation';
import type {ComponentCompilationJob, ViewCompilationUnit} from '../compilation';
/**
* Some `defer` conditions can reference other elements in the template, using their local reference
@@ -58,6 +58,26 @@ export function resolveDeferTargetNames(job: ComponentCompilationJob): void {
case ir.DeferTriggerKind.Interaction:
case ir.DeferTriggerKind.Viewport:
if (op.trigger.targetName === null) {
// A `null` target name indicates we should default to the first element in the
// placeholder block.
if (placeholderView === null) {
throw new Error('defer on trigger with no target name must have a placeholder block');
}
const placeholder = job.views.get(placeholderView);
if (placeholder == undefined) {
throw new Error('AssertionError: could not find placeholder view for defer on trigger');
}
for (const placeholderOp of placeholder.create) {
if (ir.hasConsumesSlotTrait(placeholderOp) &&
(ir.isElementOrContainerOp(placeholderOp) ||
placeholderOp.kind === ir.OpKind.Projection)) {
op.trigger.targetXref = placeholderOp.xref;
op.trigger.targetView = placeholderView;
op.trigger.targetSlotViewSteps = -1;
op.trigger.targetSlot = placeholderOp.handle;
return;
}
}
return;
}
let view: ViewCompilationUnit|null =