Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(template-compiler): fix static td/th/etc elements #2888

Merged
merged 5 commits into from
Jun 20, 2022

Conversation

nolanlawson
Copy link
Collaborator

Details

Fixes #2887. Skips the static content optimization for elements like <th> and <td> that cannot be parsed at the top level of a fragment.

Does this pull request introduce a breaking change?

  • ✅ No, it does not introduce a breaking change.

Does this pull request introduce an observable change?

  • ⚠️ Yes, it does include an observable change.

Elements like <td> and <tr> with static content will no longer throw an error.

GUS work item

W-11308172

HTML_TAG.TH,
HTML_TAG.THEAD,
HTML_TAG.TR,
]);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why anybody would put an <html> inside of an LWC template, but we might as well cover every case.

isElement(element) &&
// Tags like <th> and <td> are okay as static fragments, but only if they're not at the top level
!isNonTopLevelTag(element)
) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually noticed this was a problem because in one of the snapshots we had a fragment like:

<table><tbody><tr><td></td></tr></tbody></table>

We should totally allow these kinds of fragments. There's no problem with them. The only problem is if elements like tbody and td appear at the top level of a fragment.

// Tags that cannot be parsed at the top level of a fragment. Generated from
// https://github.com/sindresorhus/html-tags/blob/95dcdd5/index.js
// using the test:
// document.createRange().createContextualFragment(`<${tag}></${tag}>`).firstChild === null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's important to call out that we are doing this because we still support IE11. If it wasn't for IE11, we wouldn't need to use Range.createContextFragment and use the <template> element to parse fragments.
Could we add a comment here and in createFragment under @lwc/engine-dom indicating that all of this should be dropped when we are moving away from IE11.

Another option worth calling out would be to disable entirely static VNode hoisting in compat node and transition to <template> element for parsing fragments.
Pros:

  • No need to maintain this special logic in the template compiler
  • Better performance for good citizens
    Cons:
  • Support for 2 template compiler outputs at runtime

At this stage of the release, I would favor the approach with the least amount of changes (the current PR).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I'll add the comment.

I looked back at the previous perf analysis I did (#2781 (comment)), and it looks like using a <template> and setting innerHTML on it is just as fast as createContextualFragment. So yeah, we could switch to using that, if not for IE11.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #2890

packages/@lwc/template-compiler/src/parser/tag.ts Outdated Show resolved Hide resolved
@nolanlawson nolanlawson merged commit ac7cc7e into master Jun 20, 2022
@nolanlawson nolanlawson deleted the nolan/static-td branch June 20, 2022 17:47
codeGen.staticNodes.has(element) &&
isElement(element) &&
// Tags like <th> and <td> are okay as static fragments, but only if they're not at the top level
!isUnsafeTopLevelSerializableElement(element)
Copy link
Contributor

@caridy caridy Jun 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of the double negation like this... a more elegant approach is to have something like: isSafeTopLevelSerializableElement(element) instead @nolanlawson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Static fragments of <td></td> result in runtime error
3 participants