The detection whether or not props are writable is buggy; it doesn't take into account the case when instantiating components via `mount` or legacy-`new`
Fixes#14161
This posed an interesting question: What to do about (non-)`bind:`able properties? The answer I arrived on was: Treat it as if everything that _can_ be bound _is_ treated as bound, and everything else as readonly. In other words, if you're reassigning a prop, it will diverge from the passed in props if it's not bindable or not set in the parent, otherwise it will mutate the passed in props. I think that makes the most sense, given that you can't control this behavior from the outside.
* fix: avoid marking subtree as dynamic for inlined attributes
* fix: i'm a silly goose 🪿
* chore: refactor `is_inlinable_expression` to accept the attribute
* feat: inline dom expression too
* fix: special case literals with `"` in it and fix standalone case
* chore: simpler check first
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
* typo
* add more stuff to snapshot test
* simplify/speedup by doing the work once, during analysis
* simplify
* simplify - no reason these cases should prevent inlining
* return template
* name is incorrect
* name is incorrect
* fix escaping
* no longer necessary
* remove obsolete description
* better concatenation
* fix test
* do the work at runtime
* fix another thing
* tidy
* tidy up
* simplify
* simplify
* fix
* note to self
* another
* simplify
* more accurate name
* simplify
* simplify
* explain what is happening
* tidy up
* simplify
* better inlining
* update test
* colocate some code
* better inlining
* use attribute metadata
* Update packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
* Apply suggestions from code review
---------
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
We previously marked all `:root` selectors as global-like, which excempted them from further analysis. This causes problems:
- things like `:not(...)` are never visited and therefore never marked as used -> we gotta do that directly when coming across this
- `:has(...)` was never visited, too. Just marking it as used is not enough though, because we might need to scope its contents
Therefore the logic is enhanced to account for these special cases. Fixes#14118
While fixing this I cleaned up some inconsistencies in what we mark as global. This simplified code and fixed some adjacent bugs, which conindicentally also fixes#14189
* fix: consider static attributes that are inlined in the template
* fix: use `is_inlinable_expression`
* fix: move check for inlinable expression as last
* fix: simplify and correct
* chore: accept single node in `is_inlinable_expression`
* chore: update comment
* chore: add snapshots for non static nodes
Previously, we were applying an explicit nesting selector to the start of a relative selector chain only when starting the traversal. Prepending the selector is important because it ensures we traverse upwards to the parent rule when the current selectors all matched and there's still more to do. But we forgot to do the prepend for parent rules, which meant that if we were nested two levels deep, we would stop too early. This fix ensures we prepend in that case, too.
Fixes#14178
fixes#14168
This reverts the whole "selectors inside `:not` are scoped" logic. Scoping is done so that styles don't bleed. But within `:not`,everything is reversed, which means scoping the selectors now means they are more likely to bleed. That is the opposite of what we want to achieve, therefore we should just leave those selectors alone.
The exception are `:not` selectors with descendant selectors, as that means "look up the tree" and we need to scope all ancestor elements in that case.