-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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: throw runtime error when template returns different html #15524
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 62a6a15 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
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.
Nice idea! This would be a breaking change though so it would need to be a warning rather than an error. I suspect the proposed alternative approach would work better — details inline. (It wouldn't work for {@html ...}
though... so maybe we need both?)
Also, we should do this checking eagerly, otherwise no warning will be issued for malformed HTML in a block that happens not to get rendered
@@ -99,7 +99,7 @@ export function html(node, get_value, svg, mathml, skip_warning) { | |||
// Don't use create_fragment_with_script_from_html here because that would mean script tags are executed. | |||
// @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons. | |||
/** @type {DocumentFragment | Element} */ | |||
var node = create_fragment_from_html(html); | |||
var node = create_fragment_from_html(html, false); |
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.
can you elaborate on why we're not doing this for {@html ...}
? It may survive hydration but it's still delivering an unexpected outcome. Feels like we should just do it in all cases
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.
It mainly goes down to self-closing-but-not-really tags.
{@html "<div />"}
This will yield an error (I suppose if we switch to a warning it could be fine tho)
// we remove the text within the elements because the template change & to & (and similar) | ||
.replace(/>([^<>]*)/g, '>'); | ||
if (remove_attributes_and_text_input !== remove_attributes_and_text_output) { | ||
e.invalid_html_structure(remove_attributes_and_text_input, remove_attributes_and_text_output); |
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.
The HTML snippets could become arbitrarily large (especially if we enabled this for {@html ...}
as well), we may need to adding truncation here, or remove common prefixes/suffixes etc
The alternative approach of checking the structure manually could help here since it means we can point to the specific element that's being mishandled. (Perhaps add_locations
becomes a validation function as well — it already knows the intended structure.)
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.
Yeah I though about that but also thought a diffing algorithm would be too much and not showing complete information would be not really helpful.
I can try to put up a PR for the alternative method tomorrow to check if it could yield better results
Can you think of some cases where having the wrong output from the template would not lead to a runtime error anyway? I thought of making it a warning but I also thought that it would be a runtime error anyway. |
Many cases where you're not hydrating (the test case in this PR, for example). Hopefully there aren't too many of those cases in the wild but there's probably some where it's 'failing' in a way that's harmless |
Mmm that's annoying...well gonna move it to warning tomorrow 😁 |
Do I miss something or the issue example still throws the same error? And I don't see how it will help when the problem caused by invalid composition of valid components, e.g. |
Yes because now it's just a warning that you can see in the console. Also no, it will not solve that issue, only local marching problems |
Come to think of it, couldn't we find these issues at compile time? |
(I mean not for |
The main issue i see with this is that I'm pretty sure this is browser dependent...a browser might correct in a different way. Also keeping up with the actual transformation the browser does would be very error prone. |
I would be very surprised if browsers differed — this stuff is all spec'd, it's not open to interpretation. I'm not sure exactly what rules we'd need to follow but I bet we could figure it out |
Closes #15502
I've added a runtime error that checks if the html generated by the
template
is the same structure as the passed in string. This should prevent more obscure errors because if the structure is different our marching of the dom will still fail at runtime.To properly check i had to transform both the innerHTML and the incoming structure to remove inner texts (that get's converted in html entities) and attributes (because boolean attributes get
=""
appended automatically.Also i don't do this check in
{@html}
because you could technically pass invalid html there but that doesn't affect the marching algorithm.Another idea I had (might still open a PR as an alternative) is to add a
validate_element
call after everynext
orchild
...basically like thisbut i think this would be more unreliable.
Before submitting the PR, please make sure you do the following
feat:
,fix:
,chore:
, ordocs:
.packages/svelte/src
, add a changeset (npx changeset
).Tests and linting
pnpm test
and lint the project withpnpm lint