From a914a6b1ce5eceda5c383466cc33314e46aef9b7 Mon Sep 17 00:00:00 2001 From: Dylan Hunn Date: Wed, 1 Nov 2023 17:06:43 -0700 Subject: [PATCH] refactor(compiler): Fix two-way binding source maps Now that two-way bindings work correctly with implicit receivers, we can fix the corresponing source map tests. The main issue was that we were not properly mapping `elementEnd` for elements with no closing tag (self-closing elements). --- .../source_mapping/inline_templates/TEST_CASES.json | 6 ++---- packages/compiler/src/template/pipeline/src/ingest.ts | 9 +++++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/TEST_CASES.json b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/TEST_CASES.json index 9c298c30fcd3e7..c60b1fc7cafd47 100644 --- a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/TEST_CASES.json +++ b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/TEST_CASES.json @@ -419,8 +419,7 @@ ], "compilerOptions": { "sourceMap": true - }, - "skipForTemplatePipeline": true + } }, { "description": "should map a two-way binding expression (partial compile)", @@ -454,8 +453,7 @@ ], "compilerOptions": { "sourceMap": true - }, - "skipForTemplatePipeline": true + } }, { "description": "should map a longhand two-way binding expression (partial compile)", diff --git a/packages/compiler/src/template/pipeline/src/ingest.ts b/packages/compiler/src/template/pipeline/src/ingest.ts index 155b067eab88e3..dbe2b4f9c51a0c 100644 --- a/packages/compiler/src/template/pipeline/src/ingest.ts +++ b/packages/compiler/src/template/pipeline/src/ingest.ts @@ -166,7 +166,12 @@ function ingestElement(unit: ViewCompilationUnit, element: t.Element): void { ingestReferences(startOp, element); ingestNodes(unit, element.children); - const endOp = ir.createElementEndOp(id, element.endSourceSpan); + // The source span for the end op is typically the element closing tag. However, if no closing tag + // exists, such as in ``, we use the start source span instead. Usually the start and end + // instructions will be collapsed into one `element` instruction, negating the purpose of this + // fallback, but in cases when it is not collapsed (such as an input with a binding), we still + // want to map the end instruction to the main element. + const endOp = ir.createElementEndOp(id, element.endSourceSpan ?? element.startSourceSpan); unit.create.push(endOp); // If there is an i18n message associated with this element, insert i18n start and end ops. @@ -563,7 +568,7 @@ function convertAst( return new o.WritePropExpr( // TODO: Is it correct to always use the root context in place of the implicit receiver? new ir.ContextExpr(job.root.xref), ast.name, convertAst(ast.value, job, baseSourceSpan), - null, convertSourceSpan(ast.span, baseSourceSpan)) + null, convertSourceSpan(ast.span, baseSourceSpan)); } return new o.WritePropExpr( convertAst(ast.receiver, job, baseSourceSpan), ast.name,