-
Notifications
You must be signed in to change notification settings - Fork 955
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 unsafeHTML #703
Fix unsafeHTML #703
Conversation
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
Oops... I tried to push a change I med to this PR, but I accidentally brought in too many commits. Sorry. I'll clean it up |
…render with with unsafeHTML.
f35e2bb
to
21d3668
Compare
CLAs look good, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ruphin thanks! I made a change to this PR that only keeps around the previous empty DocumentFragment as a way to check that the previous value was rendered by the directive, not something else. This will save memory from not keeping the template.
I think it's reasonable to only take primitive values to avoid having to cache Templates, but I'm not sure if it's a good idea to not have any template caching at all. With this implementation, each instance of Something like this seems somewhat reasonable: const content = [
{ visible: true, html: '<div></div>' },
{ visible: false, html: '<div></div>' },
{ visible: true, html: '<div></div>' },
{ visible: false, html: '<div></div>' },
{ visible: true, html: '<div>Something interesting</div>' },
{ visible: false, html: '<div>Unique content</div>' },
{ visible: false, html: '<div></div>' },
{ visible: true, html: '<div></div>' }
];
html`${content.map(item => item.visible ? unsafeHTML(item.html) : '')}` This implementation will re-parse each |
Interesting. I think we should open a unsafeHTML performance issue to discuss this. My first instinct is that re-rendering the same HTML across alternating updates isn't likely to be a common case, and someone doing that amount of perf-critical low-level HTML management isn't really taking advantage of lit-html at that point and should do something custom like write their own directive or hand lit-html a DOM node that they manually manage. |
This fixes #702 - and adds a regression test for this case.
Unfortunately fixing the problem requires keeping a cache for previously rendered
HTMLTemplateElements
andDocumentFragments
, so we can compare vs the currentPart.value
. Without this there is no way to check if the part rendered another value after the previous unsafeHTML render. This means there is some additional memory overhead, but I don't see how it can be avoided.I added a cache for
HTMLTemplateElement
to ensure the same input string is never parsed twice. Previously, this directive would build duplicate templates if the same input was used across multiple instances. This will generally speed up execution, depending on how often similar strings are used. This also obviates the need for an 'isPrimitive' check.