Since async-await was introduced into the code base a lot has changed. This lifts the restriction.
Closes#17131 (though I still wonder why Skeleton does that)
We have to take non-tracking contexts into account, especially while in the original `fork(() => ...)` context.
Closes#17206
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
* fix: don't execute attachments and attribute effects eagerly
attributes_effect and attachments are blocks since they need the managed "don't just destroy children effects"-behavior, but they're not block effects in the sense of "run them eagerly while traversing the effect tree or while flushing effects". Since the latter was the case until now, it meant that forks could cause visible UI updates.
This PR introduces a new flag to fix that. `BLOCK_NON_EAGER` is basically a combination of block effects (with respects to the managed behavior) and render effects (with respects to the execution timing).
Fixes https://github.com/sveltejs/kit/issues/14931
* managed_effect
* fix: take async into account for bindings/transitions/animations/attachments
- block on async work
- error at compile time on await expressions. Right now it gives confusing errors later at compile time or at runtime
Fixes#17194
* this was weird
* chore: failing test for derived + fork + block
* fix: don't set derived values during time travel
* fix: skip no async
* fix: only set `derived.v` outside a fork
* chore: simplify
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* tidy up test a bit (missing text makes things confusing in the sandbox)
* update comment
* tweak
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: maintain correct linked list of effects when updating each blocks
* working
* tidy up
* changeset
* remove unnecessary assignment, add comment explaining unidirectionality
* fix: don't cancel transition of already outroing elements
#16977 forgot one detail: While an element is outroing, the block of e.g. an if block can be triggered again, resolving to the same condition. In that case we have an in-between state where the element is still onscreen but already outroing. We have to detect this to not eagerly destroy the corresponding effect when we arrive at the outro/destroy logic.
Fixes#16982
* fix
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* perf: don't use tracing overeager during dev
#17176 is a case where many sources are created and then written to (due to Svelte 4 prop mechanics), and our tracing kicked in eagerly. That combined with the excessive depth of the related stack traces slowed things down tremendously.
The fix is simple: Don't record stack traces until we've seen this source get updated for a couple of times. Additionally we now delete the `updates` map after a flush. Previously it was just an ever-growing stack trace map.
* fix
* fix
* fix: avoid other batches running with queued root effects of main batch
When `#traverse_effect_tree` runs, it can execute block effects, which in turn can create effects which are scheduled, which means `queued_root_effects` is now filled again. We didn't take that into account and assumed that in `#commit` we would have no queued root effects. As a result another batch could wrongfully run with the queued root effects of the main batch. That in turn can mean that `skipped_effects` is different on the other batch, leading to some branches not getting traversed into. As a result part of the tree is marked clean while further below batches are still not marked clean. That then breaks reactivity as soon as you schedule an effect in this still-not-clean sub tree, as it will not bubble all the way up to the root, since it comes across a not-clean branch, assuming something was already scheduled.
The fix is simple: Stash the queued root effects before rebasing branches.
Fixes#17118
* add note to self
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Execution of eager effects didn't set `is_updating_effect`, which meant the logic in `get` would wrongfully prevent dependencies being added to `reactions` of sources/deriveds.
Fixes#17133
* fix: correctly handle functions when determining async blockers
We didn't properly handle functions (function declarations/expressions/arrow functions) when calculating what is a blocker. More specifically
- we did defer assignment of variable declarations even for arrow functions and function expressions, which is unnecessary and causes bugs when they're then referenced eagerly further below
- we did not compute blockers for functions. They could reference blockers themselves, as such other code referencing them should wait on the related blockers
Fixes#17129
* put into its own function
* fix: take blockers into account when creating `#await` blocks
The unrelated-but-in-the-same-issue-referenced-bug
* oops
* fix
* minimize compiled output changes
* no idea why editor showed these as unused
Use case: Remote queries that are created on one screen, then are used again on another screen. Original parent effect is destroyed in that case but derived should still be reactive. It wasn't prior to this fix because inside `get` the `destroyed` variable would be true and so deps would not properly be recorded.
Fixes https://github.com/sveltejs/kit/issues/14814
* fix: parallelize async `@const`s in the template
This fixes#17075 by solving the TODO of #17038 to add out of order rendering for async `@const` declarations in the template.
It's implemented by a new field on the component state which is set as soon as we come across an async const. All async const declarations and those after it will be added to that field, and the existing blockers mechanism is then used to line up the async work correctly. After processing a fragment a `run` command is created from the collected consts.
* fix
* tweak
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
#17061 didn't properly handle the case where the title is sync but reactive and async work outside is pending. Handle this by creating a proper effect for the document title, and make sure to wait on it and flush it once ready.
Fixes#17114
There's a possibility of a race condition where `batch.deactivate()` is called while `current_batch !== batch`, and so it would deactivate another batch, which can lead to zombie batches that are never flushed, subsequently leading to wrong `batch_values`. This fixes that by checking if the current batch is the own batch.
Fixes#17109
* fix: wait on dependencies of async bindings
Correctly takes into account blockers for bindings. Also ensures it works for functional bindings.
During that I also noticed a bug in our `nodes_end` assignment logic, which the added test also regresses against.
Fixes#17092Fixes#17090
* ensure async static props/attributes are awaited
* wait on blockers in binding validation
* await dependencies of style directives
* tidy
Fixes#17024Fixes#17049 (comment) (and therefore everything that was still buggy in that issue I think)
* chore: remove unowned check when calling `e.effect_in_unowned_derived`
* WIP
* all non-unit tests passing
* tidy
* WIP
* WIP
* WIP
* note to self
* fix
* fix
* hmm maybe not
* try this
* simplify
* remove skip_reaction
* docs
* add changeset, in case this results in changed behaviour
* Update packages/svelte/src/internal/client/reactivity/effects.js
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* fix#17024
* fix comment
* revert
* fix
* dry
* changeset
* fix WAS_MARKED logic
* failing test (that uncovered other unrelated bug) + fix
* fix: delete from batch_values on updates (#17115)
* fix: delete from batch_values on updates
This fixes a bug where a derived would still show its old value even after it was indirectly updated again within the same batch. This can for example happen by reading a derived on an effect, then writing to a source in that same effect that makes the derived update, and then read the derived value in a sibling effect - it still shows the old value without the fix.
The fix is to _delete_ the value from batch_values, as it's now the newest value across all batches. In order to not prevent breakage on other batches we have to leave the status of deriveds as-is, i.e. within is_dirty and update_derived we cannot update its status. That might be a bit more inefficient as you now have to traverse the graph for each `get` of that derived (it's a bit like they are all disconnected) but we can always optimize that later if need be.
Another advantage of this fix is that we can get rid of duplicate logic we had to add about unmarking and reconnecting deriveds, because that logic was only needed for the case where deriveds are read after they are updated, which now no longer hits that if-branch
* keep derived cache, but clear it in mark_reactions (#17116)
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Not all batches will flush right after being activated, some will be activated and then `get` is called on a signal. In that case the value was wrong because we did not apply the changes of that batch. By doing `this.apply()` during `activate()` we ensure we do, which fixes (among other things, likely) a forking bug where old values where sneaking in.
Fixes#17079
* fix: change title only after any pending work has completed
We have to use an effect - not a render effect - for updating the title, and always. That way we change the title only after any pending work has completed.
Fixes#17060
* fix
#16977 had one slight regression which might contribute to #16990: The batch from earlier was restored, but that doesn't make sense in this situations since this has nothing to do with our new async logic of batches suspending until pending work is done. As a result you could end up with a batch being created, and then the restore then instead reverting to an earlier batch that was already done, which means a ghost-batch ends up in the set of batches, subsequently triggering time traveling when it shouldn't. This may help with #16990
No test because basically impossible to do so
The previous check was flawed because EFFECT_RAN would be set by the time it is checked, since a promise in a parent component will cause a delay of the inner component being instantiated. Instead we have a new field on the component context checking if the component was already popped (if se we are indeed too late). Don't love it to have a field just for this but I don't see another way to reliably check it.
Fixes#16629
* chore: run boundary async effects in the context of the current batch
* WIP
* reinstate kludge
* fix test
* WIP
* WIP
* WIP
* remove kludge
* restore batch_values after commit
* make private
* tidy up
* fix tests
* update test
* reset #dirty_effects and #maybe_dirty_effects
* add test
* WIP
* add test, fix block resolution
* bring async-effect-after-await test from defer-effects-in-pending-boundary branch
* avoid reawakening committed batches
* changeset
* cheat
* better API
* regenerate
* slightly better approach
* lint
* revert this whatever it is
* add test
* Update feature description for fork API
* error if missing experimental flag
* rename inspect effects to eager effects, run them in prod
* regenerate
* Apply suggestions from code review
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* tidy up
* add some minimal prose. probably don't need to go super deep here as it's not really meant for non-framework authors
* bit more detail
* add a fork_timing error, regenerate
* unused
* add note
* add fork_discarded error
* require users to discard forks
* add docs
* regenerate
* tweak docs
* fix leak
* fix
* preload on focusin as well
* missed a spot
* reduce nesting
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* fix: coordinate mount of snippets with await expressions
* try this
* deduplicate
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
The "is this a transparent effect we can ignore" logic for determining whether or not to play a local transition didn't account for pruned block effects. This fix marks the child branch as transparent if the block effect was, and during traversal then checks if the branch is the child of a block - if not that means it's the child of a pruned block effect.
fixes#16826
* perf: skip repeatedly traversing the same derived
We introduce a new flag which marks a derived during the mark_reaction phase and lift it during the execution phase.
* fix
This introduces a new flag which marks a derived as visited during the mark_reaction phase and lifts it during the dirty-check/execution phase (both are necessary because not all deriveds are necessarily executed, but they're always checked).
We could've used a Set on mark_reactions which would've been simpler to reason about, alas it was performing consistenly worse on the kairo_mux_unowned / kairo_mux_owned benchmarks (it kinda makes sense generally, creating and filling a set is more expensive than juggling flags).
Closes#16658, which showcases are particularly gnarly signal graph where many deriveds point to the same deriveds, where we would be traversing the same reactions over and over if we didn't do this.
I also added a similar measure (this time a set/map is unavoidable/makes more sense) for mark_effects, hopefully this helps for #16990
at present we only call batch.increment() when something async happens if we're not inside a pending boundary, but that's incorrect — it means that a batch is committed before everything resolves. When work inside a pending boundary does resolve, the batch becomes a zombie.
At the same time, we don't handle effects inside pending boundaries correctly. They should be deferred until the boundary (and all its parents) are ready.
This PR attempts to fix that — during traversal, when we exit a pending boundary, any effects that were collected get deferred until the next flush. We also distinguish between batch.#pending (any ongoing async work) and batch.#blocking_pending (any async work that should prevent effects outside pending boundaries from being flushed).
* fix: make `$inspect` logs come from the callsite
* default to showing stack trace
* reuse id
* DRY out, improve server-side inspect
* update docs
* ugh
* fix the dang tests
* ugh windows is there no punch bowl you won't poop in?
* argh
* how about this
* alright finally
Fixes#16850, fixes#16775, fixes#16795, fixes#16982#16631 introduced a bug that results in the effects within guards being evaluated before the guards themselves. This fix makes sure to iterate the block effects in the correct order (top down)
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
* WIP implement `$effect.pending(...)`
* feat: `$state.eager(value)` (#16926)
* runtime-first approach
* revert these
* type safety, lint
* fix: better input cursor restoration for `bind:value` (#16925)
If cursor was at end and new input is longer, move cursor to new end
No test because not possible to reproduce using our test setup.
Follow-up to #14649, helps with #16577
* Version Packages (#16920)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* docs: await no longer need pending (#16900)
* docs: link to custom renderer issue in Svelte Native discussion (#16896)
* fix code block (#16937)
Updated code block syntax from Svelte to JavaScript for clarity.
* fix: unset context on stale promises (#16935)
* fix: unset context on stale promises
When a stale promise is rejected in `async_derived`, and the promise eventually resolves, `d.resolve` will be noop and `d.promise.then(handler, ...)` will never run. That in turns means any restored context (via `(await save(..))()`) will never be unset. We have to handle this case and unset the context to prevent errors such as false-positive state mutation errors
* fix: unset context on stale promises (slightly different approach) (#16936)
* slightly different approach to #16935
* move unset_context call
* get rid of logs
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: svg `radialGradient` `fr` attribute missing in types (#16943)
* fix(svg radialGradient): fr attribute missing in types
* chore: add changeset
* Version Packages (#16940)
* Version Packages
* Update packages/svelte/CHANGELOG.md
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* chore: simplify `batch.apply()` (#16945)
* chore: simplify `batch.apply()`
* belt and braces
* note to self
* unused
* fix: don't rerun async effects unnecessarily (#16944)
Since #16866, when an async effect runs multiple times, we rebase older batches and rerun those effects. This can have unintended consequences: In a case where an async effect only depends on a single source, and that single source was updated in a later batch, we know that we don't need to / should not rerun the older batch.
This PR makes it so: We collect all the sources of older batches that are not part of the current batch that just committed, and then only mark those async effects as dirty which depend on one of those other sources. Fixes the bug I noticed while working on #16935
* fix: ensure map iteration order is correct (#16947)
quick follow-up to #16944
Resetting a map entry does not change its position in the map when iterating. We need to make sure that reset makes that batch jump "to the front" for the "reject all stale batches" logic below. Edge case for which I can't come up with a test case but it _is_ a possibility.
* feat: add `createContext` utility for type-safe context (#16948)
* feat: add `createContext` utility for type-safe context
* regenerate
* Version Packages (#16946)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* chore: Remove annoying sync-async warning (#16949)
* fix
* use `$state.eager(value)` instead of `$effect.pending(value)`
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hyunbin Seo <47051820+hyunbinseo@users.noreply.github.com>
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Co-authored-by: Hannes Rüger <hannes@hannesrueger.de>
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* decouple from boundaries
* use queue_micro_task
* add test
* fix
* changeset
* revert
* tidy up
* update docs
* Update packages/svelte/src/internal/client/reactivity/batch.js
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* minor tweak
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hyunbin Seo <47051820+hyunbinseo@users.noreply.github.com>
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Hannes Rüger <hannes@hannesrueger.de>
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
quick follow-up to #16944
Resetting a map entry does not change its position in the map when iterating. We need to make sure that reset makes that batch jump "to the front" for the "reject all stale batches" logic below. Edge case for which I can't come up with a test case but it _is_ a possibility.
Since #16866, when an async effect runs multiple times, we rebase older batches and rerun those effects. This can have unintended consequences: In a case where an async effect only depends on a single source, and that single source was updated in a later batch, we know that we don't need to / should not rerun the older batch.
This PR makes it so: We collect all the sources of older batches that are not part of the current batch that just committed, and then only mark those async effects as dirty which depend on one of those other sources. Fixes the bug I noticed while working on #16935
* fix: unset context on stale promises
When a stale promise is rejected in `async_derived`, and the promise eventually resolves, `d.resolve` will be noop and `d.promise.then(handler, ...)` will never run. That in turns means any restored context (via `(await save(..))()`) will never be unset. We have to handle this case and unset the context to prevent errors such as false-positive state mutation errors
* fix: unset context on stale promises (slightly different approach) (#16936)
* slightly different approach to #16935
* move unset_context call
* get rid of logs
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
If cursor was at end and new input is longer, move cursor to new end
No test because not possible to reproduce using our test setup.
Follow-up to #14649, helps with #16577
Test for #16912
Also some explanation what the bug was:
1. async batch kicks off
2. outer async work succeeds, still something pending, so doesn't do anything for now
3. something unrelated writes to a signal (in the remote functions case it's the query writing to loading, raw etc), which creates a new batch
4. new batch executes. since there are multiple batches it takes the previous value which means if block is still alive. commits that, since no async work from the perspective of this branch
5. inner async work succeeds. now the batch has zero pending async work so it can flush. But the if block is no longer dirty since it was done by the other batch already -> never undos the other work
#16912 fixes it by still traversing the tree which means the if block deletion is scheduled to commit later, which it then does
We have an each block optimization that omits the comment when the each block is the sole child of an element. This optimization clashes with async which wants to skip ahead to the sibling closing comment.
For now we therefore remove that optimization when the each block is async. In the long run we should instead optimize _all_ cases where _any_ block is the sole child of an element, in both async and sync mode, consistently.
fixes#16905fixes#16907
* fix: update error message to clarify usage with radio inputs
* show an extra bind checked error when a radio type
* typo
* replace 'group' binding with , drive-by fix some other messages
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Race them against each other - in almost all cases requestAnimationFrame will fire first, but e.g. in case the window is not focused or a view transition happens, requestAnimationFrame will be delayed and setTimeout helps us resolve fast enough in that case
Fixes#16429
Fixes https://github.com/sveltejs/kit/issues/14220
* fix: depend on reads of deriveds created within reaction (async mode)
As part of https://github.com/sveltejs/kit/pull/14481 we discovered that deriveds created within reactions and reading from them in that same reaction is actually useful in some cases, as such a use case we couldn't imagine yet in #15564 has appeared.
We think it's ultimately better to rerun on those cases, so we're going to make this change in async mode (that way the behavior doesn't change unless you have enabled the experimental flag)
* fix tests
Fixes#16816Fixes#16811
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* feat: First pass at payload
* first crack
* snapshots
* checkpoint
* fix: cloning
* add test option
* big dumb
* today's hard work; few tests left to fix
* improve
* tests passing no wayyyyy yo
* lots of progress, couple of failing tests around selects
* meh
* solve async tree stuff
* fix select/option stuff
* whoop, tests
* simplify
* feat: hoisting
* fix: `$effect.pending` sends updates to incorrect boundary
* changeset
* stuff from upstream
* feat: first hydrationgaa
* remove docs
* snapshots
* silly fix
* checkpoint
* meh
* ALKASJDFALSKDFJ the test passes
* chore: Update a bunch of tests for hydration markers
* chore: remove snippet and is_async
* naming
* better errors for sync-in-async
* test improvements
* idk man
* merge local branches (#16757)
* use fragment as async hoist boundary
* remove async_hoist_boundary
* only dewaterfall when necessary
* unused
* simplify/fix
* de-waterfall awaits in separate elements
* update snapshots
* remove unnecessary wrapper
* fix
* fix
* remove suspends_without_fallback
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Update payload.js
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* checkpoint
* got the extra children to go away
* just gonna go ahead and merge this as the review comments take up too much space
* chore: remove hoisted_promises (#16766)
* chore: remove hoisted_promises
* WIP optimise promises
* WIP
* fix <slot> with await in prop
* tweak
* fix type error
* Update packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteHead.js
* chore: fix hydration treeshaking (#16767)
* chore: fix hydration treeshaking
* fix
* remove await_outside_boundary error (#16762)
* chore: remove unused analysis.boundary (#16763)
* chore: simplify slots (#16765)
* chore: simplify slots
* unused
* Apply suggestions from code review
* chore: remove metadata.pending (#16764)
* Update packages/svelte/src/compiler/phases/3-transform/server/visitors/SnippetBlock.js
* put this back where it was, keep the diff small
* Update packages/svelte/src/compiler/phases/types.d.ts
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* chore: remove analysis.state.title (#16771)
* chore: remove analysis.state.title
* unused
* chore: remove is_async (#16769)
* chore: remove is_async
* unused
* Apply suggestions from code review
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* cleanup
* lint
* clean up payload a bit
* compiler work
* run ssr on sync and async
* prettier
* inline capture
* Update packages/svelte/src/compiler/phases/3-transform/server/visitors/EachBlock.js
* chore: simplify build_template (#16780)
* small tweak to aid greppability
* chore: fix SSR context (#16781)
* at least passing
* cleanup
* fix
* remove push/pop from exports, not needed with payload
* I think this is better but tbh not sure
* async SSR
* qualification
* errors:
* I have lost the plot
* finally
* ugh
* tweak error codes to better align with existing conventions, such as they are
* tweak messages
* remove unused args
* DRY out a bit
* unused
* unused
* unused
* simplify - we can enforce readonly at a type level
* unused
* simplify
* avoid magical accessors
* simplify algorithm
* unused
* unused
* reduce indirection
* TreeState -> SSRState
* mark deprecated methods
* grab this.local from parent directly
* rename render -> fn per conventions (fn indicates 'arbitrary code')
* reduce indirection
* Revert "reduce indirection"
This reverts commit 3ec461baad.
* tweak
* okay works this time
* no way chat, it works
* fix context stuff
* tweak
* make it chainable
* lint
* clean up
* lint
* Update packages/svelte/src/internal/server/types.d.ts
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* sunset html for async
* types
* we use 'deprecated' in other messages
* oops
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
#16773 added a test with _expected.html to a wrong suit, so it was ignored, and this allowed to slip in a new bug of printing the falsy hidden attribute as hidden (shortened enabled form).
That fix wasn't released yet, so no changeset.
* chore: generate CSS hash using the filename
* fix all tests but one
* slightly kludgy fix
* try this
* fix
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Consolidates our scheduling system that had diverged into two - queue_micro_task and Batch.ensure-queues and resolves some edge case race conditions related to flushSync along the way.
* fix: send `$effect.pending` count to the correct boundary
* make boundary.pending private, use boundary.is_pending consistently
* move error to correct place
* we need that error
* update JSDoc
When an async derived already has a previous promise that is still pending, we were not accessing the `then` property of the new promise. If that property access causes signals to be read, that meant that those dependencies were lost and as such the derived wouldn't rerun anymore when it should. The fix is to make sure to always access the thennable.
* fix : remove cursor manipulation for input bindings
Old Fix: Restore input binding selection position (#14649)
Current Fix: Remove unnecessary cursor manipulation as the presence of runes no longer requires special handling.
* fix : add change set to my previous commit
* Revert "fix : add change set to my previous commit"
This reverts commit 6ca8ef3f97.
* fix: revert previous changeset added new to fix lint errors
* chore : resolve lint error to fix pipeline issue
* Revert "fix: revert previous changeset added new to fix lint errors"
This reverts commit 91094949a6.
* fix: input binding to handle code in a synchronous manner
Introduced Promise.resolve to ensure that the 'set' operation completes before the 'get' operation Minimizing update delays.
* Fix: resolve cursor jumps and change sets
* better fix
* test
* changeset
* simplify
* failing test
* gah we can't fix the input in an effect, need to do it here, but after a tick so that changes have been flushed through each blocks
* add explanatory comment
* fix test
* this seems to work?
---------
Co-authored-by: Hariharan Srinivasan <hariharan.srinivasan@kadfire.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Fixes#16591
This PR introduces a check for builtin custom elements (is attribute) inside the set_custom_element_data helper in order to correctly set properties that have a setter.
Implemented by reusing the `async_body` function inside `Fragment.js`. Also removes the ability to reference a `{@const ...}` of an implicit child inside a boundary pending/failed snippet:
- existing duplication of consts can have unintended side effects, e.g. async consts would unexpectedly called multiple times
- what if a const is the reason for the failure of a boundary, but is then referenced in the failed snippet?
- what if an async const is referenced in a pending snippet? deadlock
- inconsistent with how it behaves for components where this already does not work
Implemented via the experimental flag so the behavior change only applies there as this is a breaking change strictly speaking. Also added a compiler error for this.
closes#16462
* fix: properly catch top level await errors
async errors within the template and derived etc are properly handled because they know about the last active effect and invoke the error boundary correctly as a response. This logic was missing for our top level await output.
Fixes#16613
* test
* use helper for async bodies (#16641)
* use helper for async bodies
* unused
* fix
* failing test + fix
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: skip effects inside dynamic component that is about to be destroyed
When a dynamic component was updated to a different instance and its props were updated at the same time, effects inside the component were still called with the already-changed props.
The fix is to mark the branch as skipped to never got to those effects.
Fixes#16387
* undo accidental commit
* fix: wrap `abort` in `without_reactive_context`
* only call without_reactive_context when the controller exists
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Update for TS7
I am testing Typescript 7's JS support, which I've largely rewritten
during the switch to Go. That means Javascript code will need to change
much more than Typescript code. Fortunately, most of the changes are for
the better: Javascript semantics are now nearly identical to Typescript
semantics. It's much stricter and no longer has some persistent bugs
that arose from shady JS handling I wrote years ago.
This PR changes Svelte so that it compiles both with TS5.* and TS7,
which means that occasionally there are duplicative or non-obvious
changes. I'll annotate the interesting changes to explain why I made them.
Because TS7 is quite a way off, I don't know whether you'll want to take
this PR. Most of the changes are for the better, because they're due to
stricter TS-aligned checking. But some are neutral and there is the
previously mentioned duplication in a few places.
* add changeset
* revert scribbles mistakenly added
* pnpm run format
* revert mistaken edit
* return to function declarations w/type tag
* add job to ci.yml
* skipLibCheck for now
* no need for a changeset here
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Co-authored-by: Rich Harris <hello@rich-harris.dev>
* fix: emit `snippet_invalid_export` instead of `undefined_export` for exported snippets
* try this
* this should work
* remove some junk (this never did anything)
* add test
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Add missing hyphen in "server-side rendering"
* Fix incorrect use of "as such"
* regenerate types
---------
Co-authored-by: Chew Tee Ming <chew.tee.ming@nindatech.com>
* Fix double event processing (#16522)
Firefox seems to garbage collect event objects during event propagation if no global reference to the event object is kept.
That discards the __root marker set on the event object to early,
leading to duplicate processing.
* minor tweaks
---------
Co-authored-by: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
* use sh instead of bash in source blocks
no bash-specific functionality is used
* regenerate
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: throw on duplicate class field declarations
* doh
* handle assignment in constructor
* fix
* apply suggestion from review
* fix
* fix failing test
mini-cleanup post #16487 - we don't need to do the work of scheduling an effect that's already dirty which means it already scheduled its root effect to run
* don't mark_reactions inside decrement, it can cause infinite loops
* revert mark_reactions changes
* preserve DIRTY/MAYBE_DIRTY status of deferred effects
* changeset
* tweak
* - add state changes resulting from an $effect to a separate new batch
- schedule rerunning effects based on the sources that are dirty, not just rerunning them all blindly (excempting async effects which will have run by that time already)
* test
* better fix
* tests
* this fixes the last test somehow
* fix#16477
* typo
* copy over changeset from #16477
* copy over changeset from #16464
* changeset
* dedupe
* move flushing_sync check inside Batch.ensure
* unused
* flushing_sync -> is_flushing_sync
* remove flush_effects method
* dedupe declaration
* tweak
* tweak
* update comment — it _does_ feel slightly wrong, but no wronger than the rest of this cursed function
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Increment the version to ensure any dependent deriveds are marked dirty when the subscription is picked up again later. If we didn't do this then the comparison of write versions would determine that the derived has a later version than the subscriber, and it would not be re-run.
Fixes#16311Fixes#15888
The prior logic was wrong because it reexecuted when something was clean, but we want to when it's not. The remaining fix was to also check the reactions: If an effect is destroyed and it was the last reaction of a derived then the derived is set to `MAYBE_DIRTY`. We therefore also need to check if the derived still has anyone listening to it, and only then reexecute it.
Fixes#16363
Since #9070 it's prefered to use the "enhance svelte elements" way of doing things. That's so long ago that we can now remove the other option from the docs, and eventually remove the backwards compatibility that still allows the old way of doing things.
Fixes#16134
* Add a warning when the misuse of `reset` in an `error:boundary` causes an error to be thrown when flushing the boundary content
* Prevent uncaught errors to make test fails when they are expected and are fired during template effects flush
* reset should just be a noop after the first call
* correctly handle errors inside boundary during reset
* handle errors in the correct boundary
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
#16268 introduced a slight regression where the state is not reset completely upon compilation. It did reset warnings but not other state, which meant if file A succeeds but file B fails in the parsing state (before the state was reset for real) it would get wrong filename info. This fixes it by setting the filename at the very beginning.
* tidy
* tidy
* yes it can, apparently
* tidy up
* unused
* complete merge
* WIP
* simplify
* debugging help
* WIP
* unused
* partial merge
* WIP
* fix
* add test
* rename
* fix
* unused
* oops
* chore: merge main into async branch (#16197)
* chore: merge main into async branch
* adjust test
* fix: make effects depend on state created inside them (#16198)
* make effects depend on state created inside them
* fix, add github action
* disable test in async mode
* make batch.#deferred private
* fix settled when awaits occur inside pending boundary
* tweak
* change behaviour of `tick()` to be requestAnimationFrame-based
* get rid of a bunch of Promise.resolve chains
* more
* more
* fix test
* disallow `flushSync()` inside effects
* regenerate
* handle errors in block expressions
* make validate_each_keys async-aware
* for unowned deriveds, throw errors lazily
* rename ASYNC_ERROR -> ERROR_VALUE, and avoid conflicts with other flags now that it's used with deriveds as well as sources
* invoke boundary directly
* local effect pending
* update test
* fix
* fix
* fix weird bug in tests
* delete old changeset that somehow got left over here
* Update .changeset/eleven-weeks-dance.md
* update error details
* unused
* simplify
* tweak
* tweak
* tweak
* tweak
* tidy up
* handle errors in async block expressions
* tweak
* groundwork for async attribute_effect
* dry out
* fix async directives
* tidy up
* initialize option values before initing select values
* simplify init_select
* simplify
* tweak
* tidy up
* tweak
* on second thoughts just simplify it here
* tidy
* handle awaits in `<slot>`
* unused
* tidy up
* tidy up
* dry out
* dry out
* Revert "dry out"
This reverts commit 25855163bf.
* dry out
* dry out
* use let for block-scoped stuff
* dry out
* dry out
* tidy up
* only wrap awaits in `$.save` when necessary
* oops
* remove TODO comment (just checked)
* oops, leftover
* simplify
* unused
* remove logging
* tweak
* unused
* unused
* remove logging
* partial fix
* fix
* remove unused EFFECT_HAS_DERIVED
* Update packages/svelte/src/reactivity/create-subscriber.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* Update packages/svelte/src/index-client.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* Update packages/svelte/src/internal/client/runtime.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* unused
* Update packages/svelte/src/internal/client/reactivity/sources.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* Update packages/svelte/src/internal/client/reactivity/deriveds.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* Update packages/svelte/src/internal/client/reactivity/deriveds.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* prettier
* unused
* fix flags
* tweak
* tweak
* unused
* fix
* no idea what a 'boundary micro task' is or why it was deemed necessary but evidently it isn't
* remove queue_boundary_micro_task
* oops
* note
* tidy up
* remove TODO
* make method private
* simplify
* flesh out await_reactivity_loss warning
* tweak
* update test
* fix
* null out from_async_derived in more places
* tidy up test
* failing test
* unused
* fix test
* fix
* simplify. no idea what the async_mode_flag stuff is about, but it appears unnecessary
* add async_derived_orphan error
* regenerate
* flesh out await_outside_boundary message
* add some JSDoc
* only update `$effect.pending()` if someone is listening, since it causes a double flush and makes debugging harder
* tweak logic to make it clearer why and when we commit a batch
* add a couple of comments
* false -> 0
* add comment
* unused
* silence warning
* add effect_pending_outside_reaction error
* Update packages/svelte/src/compiler/types/index.d.ts
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* suspend batch, not boundary
* rename from_async_derived -> current_async_derived
* tweak
* remove TODO - this method is only called when pending snippet exists
* use error boundary for test - vitest does some weird error swallowing afaict
* flush less often
* restore -> activate
* remove TODO
* move batch-related code into batch.js
* make flush_queued_root_effects a method of batch
* make process_effects a method of batch
* make stuff private
* unused
* regenerate
* update test
* more JSDoc
* add more JSDoc
* branch and block effects do not also need to be render effects
* tidy up
* simplify
* unused
* move code where it belongs
* remove, for now
* fix
* only apply error adjustments when error escapes boundaries
* remove EFFECT_IS_UPDATING
* is_dirty is a better name than check_dirtiness
* duplicates are rare and harmless
* apparently we no longer need the merging logic? we can simplify and fix stuff by removing it
* tidy
* don't commit stale batches
* add skipped failing test
* partial merge
* WIP
* WIP
* WIP
* tweak
* tidy up
* dont update derived status when time-travelling
* tidy up
* tidy up
* tag async deriveds
* tweak
* bail out of secondary flushes
* re-run blocks on subsequent flushes
* add test
* fix
* add tests, one failing
* fix
* flesh out await_waterfall message
* tidy up
* dry out
* unused
* tweak
* tidy up
* TODO
* tweak
* tidy up
* remove TODO
* unused export
* add optimisation back
* revert unneeded changes
* revert
* update some tests
* more
* more
* move some code
* rename
* WIP
* unset context synchronously
* remove unused argument
* Apply suggestions from code review
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* add comment
* add comment
* use queue_micro_task in createSubscriber
* Update packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* prettier
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Co-authored-by: Elliott Johnson <sejohnson@torchcloudconsulting.com>
* fix: use `state` instead of `source` in reactive classes
* fix: use `active_reaction` as indication to use `source` or `state`
* fix: cleanup `#initial_reaction` on `teardown` to free memory
* fix: use `#source` in `set` too
* unused
* chore: use WeakRef
* use update_version instead of WeakRef in SvelteSet/SvelteMap (#16324)
* tidy up
* tweak comment to remove active_reaction reference
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Store deriveds old value before updating them for consistency with directly assigned sources when reading in teardown functions
* Add tests for derived old values in teardown functions
* Add tests for props old values in onDestroy hooks to prevent regressions
* Add changeset
* Update comment
* remove extraneous tests - these pass with or without the src change
* revert
* WIP
* simplify props
* simplify
* tweak
* reorder a bit
* simplify
* unused
* more
* more
* tweak
* also appears to be unnecessary
* changeset
* fix
* Update .changeset/light-rivers-jump.md
* easier debugging
* fix
* WIP
* fix
---------
Co-authored-by: raythurnvoid <53383860+raythurnvoid@users.noreply.github.com>
* feat: add parent hierarchy to `__svelte_meta` objects at dev time
This adds a `parent` property to the `__svelte_meta` properties that are added to elements at dev time. This property represents the closest non-element parent the element is related to. For example for `{#if ...}<div>foo</div>{/if}` the `parent` of the div would be the line/column of the if block.
The parent is recursive and goes upwards (through component boundaries) until the root component is reached, which has no parent.
part of #11389
* oops
* Apply suggestions from code review
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* tweak
* original component tag
* make render appear in tree, keep tree in sync when rerenders occur
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
#16270 removed a condition which seemed to keep passing the corresponding test, but it actually introduced a regression since the PROPS_IS_UPDATED is always set when accessors should be created, which is the case by default in legacy mode tests. Setting accessors to false in the test reveals the regression, so this reverts that part of the refactoring
* simplify props
* simplify
* tweak
* reorder a bit
* simplify
* unused
* more
* more
* tweak
* also appears to be unnecessary
* changeset
* apparently this is also unnecessary
* explanatory comment
* break out locator stuff from the rest of global state
* move some stuff around
* tighten up
* make runes globally available
* make component_name globally available
* unused
an unowned derived should still add itself as a reaction while it is properly connected, which means it can be cleaned up correctly - and this connection is indicated by it having reactions.
Fixes#15829 and potentially #15853
* initialize option values before initing select values
* simplify init_select
* simplify
* tweak
* tidy up
* tweak
* on second thoughts just simplify it here
* fix: use fine grained for template if the component is not explicitly in legacy mode
* chore: add comment
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* fix: add `LabeledStatement` to `instance.ast` check
* fix: spread `keys`
* fix: snapshots
* fix: use `compileOption.runes` if defined + add other tests
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* fix: ensure undefined attributes are removed during hydration
Attributes that are `undefined` on the client should be removed during hydration,
even if their value hasn't changed compared to `prev_value`.
* Create plenty-wasps-sleep.md
* added test
* Update .changeset/plenty-wasps-sleep.md
---------
Co-authored-by: Rich Harris <hello@rich-harris.dev>
* fix: keep spread non-delegated event handlers up to date
#15961 introduced a regression where non-delegated events that were spread and updated were not getting updated. This fixes that by ensuring prev is actually updated to the most recent value
* fix
* fix: avoid shadowing a variable in dynamic components
* split component name and intermediate name
---------
Co-authored-by: 7nik <kifiranet@gmail.com>
* fix: ensure sources within nested effects still register correctly
When an effect creates another effect and a proxy property is read that wasn't before, the proxy will have logic where it creates the new signal in its original reaction context. But it did not have logic to correctly handle the `reaction_sources` array which prevents effects/deriveds rerunning when state created inside themselves is read and then changed inside them: Since `reaction_sources` wasn't take the reaction context into account, false positives could occur where nested effects would not register the sources as dependencies.
Fixes#15870
* oops forgot to push this
Make sure we track statically visible dependencies and untrack indirect dependencies
Fixes#14351
---------
Co-authored-by: 7nik <kifiranet@gmail.com>
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Closes#16164
We can't set everywhere within with_parent otherwise if it's the first time we are reading a derived it could look like we are setting state in a derived (which you are not).
* Add failing test
* Add {@const} test case
* Fix the bug
* Add yet another test case
* Better fix
* Changeset
* simplify
* this appears to be unnecessary
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* remove code thatcan't be reached and would error if it could
* tidy up types, fix duplication
* this seems needless
* better naming
* tidy up
* reorder
* this code doesn't appear to do anything useful, and no tests fail without it
* unused
* WIP
* revert part of #14811. it makes no sense to show the initial value, it just makes things inconsistent with deriveds. personally i find it more confusing anyway
* explanatory comment on both sides
* make things a bit more self-explanatory
* simplify
* missing type
* only log UpdatedAt for dirty signals
* changeset
* lint
* Revert "unused"
This reverts commit a95b625800.
* complete revert
* ok it works now
* init
* improve symbol logging
* doh
* remove proxy path name when reassigned to a source
* try this
* fix
* oops
* fix
* "unown" proxy when in another source declaration
* fix
* tag proxy version
* proxy bindable props
* tag iterables used in destructuring
* add changeset, fix failing tests
* add comments, minor tweak
* lint
* somehow forgot to add support for class fields
* more class fields
* tag_source -> tag, since it applies to deriveds as well
* private class fields
* this condition is impossible
* explicit type narrowing lets us avoid coercion
* simplify
* unused
* tweak
* oops, never meant to commit that
* minor tweaks
* fix private field tagging, only get `declaration` once
* fix state declarations in constructors
* fix
* tag `svelte/reactivity`, `svelte/motion` sources in DEV
* try fixing lint
* fix intellisense formatting
* actually fix lint
* replace tag_if_necessary with conditional tagging
* avoid [[object Object]] in labels
* remove PROXY_REMOVE_PATH
* simplify a bit
* simplify
* tweak
* tweak implementation
* tweak implementation
* tweak implementation
* hoist
* tweak
* fix
* WIP (reduce number of with_parent calls, move towards possibility of combining tag and tag_proxy)
* DRY out
* tweak labels
* remove PROXY_REMOVE_PATH (#16126)
* remove PROXY_REMOVE_PATH
* simplify a bit
* simplify
* tweak
* tweak implementation
* tweak implementation
* tweak implementation
* hoist
* tweak
* fix
* WIP (reduce number of with_parent calls, move towards possibility of combining tag and tag_proxy)
* DRY out
* come on this was just lazy
* fix tests
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Add `xmlns` attribute to HTMLAttributes type
The `xmlns` attribute is not only allowed on SVG elements, but on all HTML elements.
* move to DOMAttributes
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* chore: better HTML normalization test helper
* simplify
* simplify/robustify
* tweak
* Apply suggestions from code review
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>