* Ingest an `ng-template` node from the AST into the given `ViewCompilation`.
(unit: ViewCompilationUnit, tmpl: t.Template)
| 446 | * Ingest an `ng-template` node from the AST into the given `ViewCompilation`. |
| 447 | */ |
| 448 | function ingestTemplate(unit: ViewCompilationUnit, tmpl: t.Template): void { |
| 449 | if ( |
| 450 | tmpl.i18n !== undefined && |
| 451 | !(tmpl.i18n instanceof i18n.Message || tmpl.i18n instanceof i18n.TagPlaceholder) |
| 452 | ) { |
| 453 | throw Error(`Unhandled i18n metadata type for template: ${tmpl.i18n.constructor.name}`); |
| 454 | } |
| 455 | |
| 456 | const childView = unit.job.allocateView(unit.xref); |
| 457 | |
| 458 | let tagNameWithoutNamespace = tmpl.tagName; |
| 459 | let namespacePrefix: string | null = ''; |
| 460 | if (tmpl.tagName) { |
| 461 | [namespacePrefix, tagNameWithoutNamespace] = splitNsName(tmpl.tagName); |
| 462 | } |
| 463 | |
| 464 | const i18nPlaceholder = tmpl.i18n instanceof i18n.TagPlaceholder ? tmpl.i18n : undefined; |
| 465 | const namespace = namespaceForKey(namespacePrefix); |
| 466 | const functionNameSuffix = |
| 467 | tagNameWithoutNamespace === null ? '' : prefixWithNamespace(tagNameWithoutNamespace, namespace); |
| 468 | const templateKind = isPlainTemplate(tmpl) |
| 469 | ? ir.TemplateKind.NgTemplate |
| 470 | : ir.TemplateKind.Structural; |
| 471 | const templateOp = ir.createTemplateOp( |
| 472 | childView.xref, |
| 473 | templateKind, |
| 474 | tagNameWithoutNamespace, |
| 475 | functionNameSuffix, |
| 476 | namespace, |
| 477 | i18nPlaceholder, |
| 478 | tmpl.startSourceSpan, |
| 479 | tmpl.sourceSpan, |
| 480 | ); |
| 481 | unit.create.push(templateOp); |
| 482 | |
| 483 | ingestTemplateBindings(unit, templateOp, tmpl, templateKind); |
| 484 | ingestReferences(templateOp, tmpl); |
| 485 | ingestNodes(childView, tmpl.children); |
| 486 | |
| 487 | for (const {name, value} of tmpl.variables) { |
| 488 | childView.contextVariables.set(name, value !== '' ? value : '$implicit'); |
| 489 | } |
| 490 | |
| 491 | // If this is a plain template and there is an i18n message associated with it, insert i18n start |
| 492 | // and end ops. For structural directive templates, the i18n ops will be added when ingesting the |
| 493 | // element/template the directive is placed on. |
| 494 | if (templateKind === ir.TemplateKind.NgTemplate && tmpl.i18n instanceof i18n.Message) { |
| 495 | const id = unit.job.allocateXrefId(); |
| 496 | ir.OpList.insertAfter( |
| 497 | ir.createI18nStartOp(id, tmpl.i18n, undefined, tmpl.startSourceSpan), |
| 498 | childView.create.head, |
| 499 | ); |
| 500 | ir.OpList.insertBefore( |
| 501 | ir.createI18nEndOp(id, tmpl.endSourceSpan ?? tmpl.startSourceSpan), |
| 502 | childView.create.tail, |
| 503 | ); |
| 504 | } |
| 505 | } |
no test coverage detected