From cb75e827e86df8f9332c9836178b52d8d45f9152 Mon Sep 17 00:00:00 2001 From: Andrew Jakubowicz Date: Thu, 27 Jul 2023 06:40:06 -0700 Subject: [PATCH 1/2] add logic to only compile the valid html tag function imported from lit --- .../compiler/src/lib/template-transform.ts | 34 ++++++++++++++++--- .../do_not_compile_aliased_html.golden.js | 5 +++ .../test_files/do_not_compile_aliased_html.ts | 5 +++ .../do_not_compile_lit_static.golden.js | 3 ++ .../test_files/do_not_compile_lit_static.ts | 3 ++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 packages/labs/compiler/test_files/do_not_compile_aliased_html.golden.js create mode 100644 packages/labs/compiler/test_files/do_not_compile_aliased_html.ts create mode 100644 packages/labs/compiler/test_files/do_not_compile_lit_static.golden.js create mode 100644 packages/labs/compiler/test_files/do_not_compile_lit_static.ts diff --git a/packages/labs/compiler/src/lib/template-transform.ts b/packages/labs/compiler/src/lib/template-transform.ts index f30c5926d3..24ed88d881 100644 --- a/packages/labs/compiler/src/lib/template-transform.ts +++ b/packages/labs/compiler/src/lib/template-transform.ts @@ -67,6 +67,9 @@ class CompiledTemplatePass { return (sourceFile: ts.SourceFile): ts.SourceFile => { const pass = new CompiledTemplatePass(context); pass.findTemplates(sourceFile); + if (!pass.shouldCompileFile) { + return sourceFile; + } const transformedSourceFile = pass.rewriteTemplates(sourceFile); if (!ts.isSourceFile(transformedSourceFile)) { throw new Error( @@ -89,6 +92,10 @@ class CompiledTemplatePass { ts.TaggedTemplateExpression, TemplateInfo >(); + /** + * Only compile the file if an `html` tag was imported from lit or lit-html. + */ + private shouldCompileFile = false; /** * Track the added security brand AST node so we only add one. */ @@ -117,6 +124,7 @@ class CompiledTemplatePass { const findTemplates = (node: T) => { return ts.visitNode(node, (node: ts.Node): ts.Node => { nodeStack.push(node); + this.shouldCompileFile ||= this.shouldMarkFileForCompilation(node); if (isLitTemplate(node)) { const topStatement = nodeStack[1] as ts.Statement; const templateInfo = { @@ -139,6 +147,28 @@ class CompiledTemplatePass { return findTemplates(sourceFile); } + /** + * Returns true if passed a node that marks the file for compilation. + * Currently files are marked for compilation if an importClause is detected + * that contains an `html` import from `lit` or `lit-html`. + */ + private shouldMarkFileForCompilation(node: T): boolean { + if ( + ts.isImportDeclaration(node) && + ts.isStringLiteral(node.moduleSpecifier) && + (node.moduleSpecifier.text === 'lit' || + node.moduleSpecifier.text === 'lit-html') && + node.importClause?.namedBindings != null && + ts.isNamedImports(node.importClause.namedBindings) + ) { + const namedBindings = node.importClause.namedBindings; + return namedBindings.elements.some( + (imp) => ts.isIdentifier(imp.name) && imp.name.text === 'html' + ); + } + return false; + } + /** * Perform an inorder traversal starting at the passed in `node`, calling * `this.rewriteTemplates` on each node traversed. @@ -356,10 +386,6 @@ export const compileLitTemplates = (): ts.TransformerFactory => /** * E.g. html`foo` or html`foo${bar}` - * - * TODO(ajakubowicz): Figure out how to handle detecting templates to compile - * correctly and robustly. We want to avoid situations where `html` imported - * from 'lit/static.js' is compiled. */ const isLitTemplate = (node: ts.Node): node is ts.TaggedTemplateExpression => ts.isTaggedTemplateExpression(node) && diff --git a/packages/labs/compiler/test_files/do_not_compile_aliased_html.golden.js b/packages/labs/compiler/test_files/do_not_compile_aliased_html.golden.js new file mode 100644 index 0000000000..eebe1cd910 --- /dev/null +++ b/packages/labs/compiler/test_files/do_not_compile_aliased_html.golden.js @@ -0,0 +1,5 @@ +// TODO(ajakubowicz): Should we add support for aliased imports from 'lit' and +// 'lit-html'? +import { html as h } from 'lit-html'; +import { render } from 'lit'; +render(h `

Hello

`, document.body); diff --git a/packages/labs/compiler/test_files/do_not_compile_aliased_html.ts b/packages/labs/compiler/test_files/do_not_compile_aliased_html.ts new file mode 100644 index 0000000000..2fc4caa2bf --- /dev/null +++ b/packages/labs/compiler/test_files/do_not_compile_aliased_html.ts @@ -0,0 +1,5 @@ +// TODO(ajakubowicz): Should we add support for aliased imports from 'lit' and +// 'lit-html'? +import {html as h} from 'lit-html'; +import {render} from 'lit'; +render(h`

Hello

`, document.body); diff --git a/packages/labs/compiler/test_files/do_not_compile_lit_static.golden.js b/packages/labs/compiler/test_files/do_not_compile_lit_static.golden.js new file mode 100644 index 0000000000..0de16e910d --- /dev/null +++ b/packages/labs/compiler/test_files/do_not_compile_lit_static.golden.js @@ -0,0 +1,3 @@ +import { html, literal } from 'lit-html/static.js'; +import { render } from 'lit'; +render(html `${literal `

Hello

`}`, document.body); diff --git a/packages/labs/compiler/test_files/do_not_compile_lit_static.ts b/packages/labs/compiler/test_files/do_not_compile_lit_static.ts new file mode 100644 index 0000000000..079d389973 --- /dev/null +++ b/packages/labs/compiler/test_files/do_not_compile_lit_static.ts @@ -0,0 +1,3 @@ +import {html, literal} from 'lit-html/static.js'; +import {render} from 'lit'; +render(html`${literal`

Hello

`}`, document.body); From f8ae2b2883795b3299a710e737173468ef95c7de Mon Sep 17 00:00:00 2001 From: Andrew Jakubowicz Date: Thu, 27 Jul 2023 06:42:24 -0700 Subject: [PATCH 2/2] add empty changeset --- .changeset/large-spoons-scream.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/large-spoons-scream.md diff --git a/.changeset/large-spoons-scream.md b/.changeset/large-spoons-scream.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/large-spoons-scream.md @@ -0,0 +1,2 @@ +--- +---