htm icon indicating copy to clipboard operation
htm copied to clipboard

Improve runtime error handling for missing close tags

Open dfabulich opened this issue 5 years ago • 5 comments

Consider this sample code, which accidentally omits a closing tag.

import htm from 'https://unpkg.com/htm?module'
const h = (type, props, ...children) => ({type, props, children});
const html = htm.bind(h)

console.log(JSON.stringify(html`<h1>Hello, world!`));

In this case, the user intended to include a closing tag </h1>, and so the user's desired logged result is {"type":"h1","props":null,"children":["Hello, world!"]}

Actual: ["h1","Hello, world!"] The element name is incorrectly handled as a text node.

Expected: Throw an exception.

dfabulich avatar May 04 '20 19:05 dfabulich

Btw innerHTML parser does not throw errors and silently returns wrongly parsed markup. Implementing validation in parser would be size overhead. Maybe linter package?

dy avatar May 13 '20 00:05 dy

I think it's worth investigating the runtime size overhead. It might not be that much.

I filed a separate bug that the transpiler also silently ignores errors; that's definitely a bad thing. The transpiler should use as many bytes as it needs to ensure correctness and report clear errors. (Plus, the transpiler itself can be a linter with babel-eslint.)

dfabulich avatar May 13 '20 01:05 dfabulich

investigating the runtime size overhead

Ok, some possible error cases then.

html`<a`
html`<a${'b'}>`
html`<a${'b'}`
html`<${'b'}a>`
html`<a></${''}>`
html`<a><${''}/>`
html`<a></`
html`<a ${'b'}></a>`
html`<a a${'b'}></a>`
html`<a "a${'b'}"></a>`
html`<a <!--"a${'b'}"></a>`
...

That list grows to hundreds - there are too many combinations of modes ('"quotes, comments, attrib names, attrib values, spread, fields, closing tag, tag/text, fragment). I am pretty sure there's no silver bullet, the parser is super minimalistic. Maybe transpiler indeed?

dy avatar May 13 '20 01:05 dy

It's not possible to implement runtime error checking in a way that represents a reasonable size tradeoff. This is particularly true because 100% of the classes of error that would be caught are also the classes of error that can be detected via static analysis.

Some solutions:

  • compile from JSX (enables full linting & type safety)
  • write an ESLint plugin for HTM
  • Lobby for first-class Tagged Template DSL support in TypeScript and Babel

developit avatar May 28 '20 03:05 developit

this is probably a duplicate of #56 & #122

developit avatar Feb 05 '21 03:02 developit