* Ingest an element AST from the template into the given `ViewCompilation`.
(unit: ViewCompilationUnit, element: t.Element)
| 274 | * Ingest an element AST from the template into the given `ViewCompilation`. |
| 275 | */ |
| 276 | function ingestElement(unit: ViewCompilationUnit, element: t.Element): void { |
| 277 | if ( |
| 278 | element.i18n !== undefined && |
| 279 | !(element.i18n instanceof i18n.Message || element.i18n instanceof i18n.TagPlaceholder) |
| 280 | ) { |
| 281 | throw Error(`Unhandled i18n metadata type for element: ${element.i18n.constructor.name}`); |
| 282 | } |
| 283 | |
| 284 | const id = unit.job.allocateXrefId(); |
| 285 | |
| 286 | const [namespaceKey, elementName] = splitNsName(element.name); |
| 287 | |
| 288 | const startOp = ir.createElementStartOp( |
| 289 | elementName, |
| 290 | id, |
| 291 | namespaceForKey(namespaceKey), |
| 292 | element.i18n instanceof i18n.TagPlaceholder ? element.i18n : undefined, |
| 293 | element.startSourceSpan, |
| 294 | element.sourceSpan, |
| 295 | ); |
| 296 | unit.create.push(startOp); |
| 297 | |
| 298 | ingestElementBindings(unit, startOp, element); |
| 299 | ingestReferences(startOp, element); |
| 300 | |
| 301 | // Start i18n, if needed, goes after the element create and bindings, but before the nodes |
| 302 | let i18nBlockId: ir.XrefId | null = null; |
| 303 | if (element.i18n instanceof i18n.Message) { |
| 304 | i18nBlockId = unit.job.allocateXrefId(); |
| 305 | unit.create.push( |
| 306 | ir.createI18nStartOp(i18nBlockId, element.i18n, undefined, element.startSourceSpan), |
| 307 | ); |
| 308 | } |
| 309 | |
| 310 | ingestNodes(unit, element.children); |
| 311 | |
| 312 | // The source span for the end op is typically the element closing tag. However, if no closing tag |
| 313 | // exists, such as in `<input>`, we use the start source span instead. Usually the start and end |
| 314 | // instructions will be collapsed into one `element` instruction, negating the purpose of this |
| 315 | // fallback, but in cases when it is not collapsed (such as an input with a binding), we still |
| 316 | // want to map the end instruction to the main element. |
| 317 | const endOp = ir.createElementEndOp(id, element.endSourceSpan ?? element.startSourceSpan); |
| 318 | unit.create.push(endOp); |
| 319 | |
| 320 | // If there is an i18n message associated with this element, insert i18n start and end ops. |
| 321 | if (i18nBlockId !== null) { |
| 322 | ir.OpList.insertBefore<ir.CreateOp>( |
| 323 | ir.createI18nEndOp(i18nBlockId, element.endSourceSpan ?? element.startSourceSpan), |
| 324 | endOp, |
| 325 | ); |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | /** |
| 330 | * Ingest an `ng-template` node from the AST into the given `ViewCompilation`. |
no test coverage detected
searching dependent graphs…