Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sveltejs/svelte
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: svelte@5.23.2
Choose a base ref
...
head repository: sveltejs/svelte
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: svelte@5.24.0
Choose a head ref
  • 10 commits
  • 36 files changed
  • 4 contributors

Commits on Mar 19, 2025

  1. docs: use function bindings in "when not to use effect" (#15544)

    Rich-Harris authored Mar 19, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    8f940ee View commit details
  2. docs: rewrite context docs (#15541)

    Rich-Harris authored Mar 19, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    701f085 View commit details
  3. chore: create stack lazily when proxying value (#15547)

    Rich-Harris authored Mar 19, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    99ca7a4 View commit details
  4. fix: simplify set calls for proxyable values (#15548)

    * chore: simplify set calls for proxyable values
    
    * changeset
    Rich-Harris authored Mar 19, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    c436b6c View commit details

Commits on Mar 20, 2025

  1. fix benchmarks (#15560)

    Rich-Harris authored Mar 20, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    c7ce9fc View commit details
  2. feat: allow state created in deriveds/effects to be written/read loca…

    …lly without self-invalidation (#15553)
    
    * move parent property onto Signal
    
    * don't self-invalidate when updating a source create inside current reaction
    
    * lazily create deep state with parent reaction
    
    * no need to push_derived_source with mutable_state, as it never coexists with $.derived
    
    * reduce indirection
    
    * remove state_unsafe_local_read error
    
    * changeset
    
    * tests
    
    * fix test
    
    * inelegant fix
    
    * remove arg
    
    * tweak
    
    * some progress
    
    * more
    
    * tidy up
    
    * parent -> p
    
    * tmp
    
    * alternative approach
    
    * tidy up
    
    * reduce diff size
    
    * more
    
    * update comment
    Rich-Harris authored Mar 20, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    6915c12 View commit details

Commits on Mar 21, 2025

  1. fix: Keep inlined JSDoc comments in property conversion of svelte-mig…

    …rate (#15567)
    
    * Add failing JSDoc property svelte-migrate conversion tests
    
    * Add further test case and remove default value in JSDoc output
    
    * Look for inlined JSDoc comments after a hyphen
    
    * Add changeset
    rgieseke authored Mar 21, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1a5fb8f View commit details
  2. fix: check if DOM prototypes are extensible (#15569)

    trueadm authored Mar 21, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1d10a65 View commit details
  3. fix: don't depend on deriveds created inside the current reaction (#1…

    …5564)
    
    * WIP
    
    * WIP
    
    * add test
    
    * update test
    
    * changeset
    
    * oops
    
    * lint
    Rich-Harris authored Mar 21, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    d2e7932 View commit details
  4. Version Packages (#15551)

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    github-actions[bot] authored Mar 21, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    e25c281 View commit details
Showing with 423 additions and 314 deletions.
  1. +0 −1 benchmarking/compare/index.js
  2. +2 −2 benchmarking/compare/runner.js
  3. +7 −35 documentation/docs/02-runes/04-$effect.md
  4. +86 −78 documentation/docs/06-runtime/02-context.md
  5. +0 −6 documentation/docs/98-reference/.generated/client-errors.md
  6. +16 −0 packages/svelte/CHANGELOG.md
  7. +0 −4 packages/svelte/messages/client-errors/errors.md
  8. +1 −1 packages/svelte/package.json
  9. +5 −2 packages/svelte/src/compiler/migrate/index.js
  10. +4 −1 packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
  11. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/types.d.ts
  12. +0 −8 packages/svelte/src/compiler/phases/3-transform/client/utils.js
  13. +17 −29 packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js
  14. +3 −12 packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js
  15. +2 −2 packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js
  16. +2 −2 packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js
  17. +1 −0 packages/svelte/src/internal/client/constants.js
  18. +20 −15 packages/svelte/src/internal/client/dom/operations.js
  19. +0 −15 packages/svelte/src/internal/client/errors.js
  20. +2 −2 packages/svelte/src/internal/client/index.js
  21. +56 −20 packages/svelte/src/internal/client/proxy.js
  22. +15 −1 packages/svelte/src/internal/client/reactivity/deriveds.js
  23. +21 −38 packages/svelte/src/internal/client/reactivity/sources.js
  24. +46 −27 packages/svelte/src/internal/client/runtime.js
  25. +1 −0 packages/svelte/src/internal/shared/utils.js
  26. +1 −1 packages/svelte/src/version.js
  27. +9 −0 packages/svelte/tests/migrate/samples/jsdoc-with-comments/input.svelte
  28. +13 −1 packages/svelte/tests/migrate/samples/jsdoc-with-comments/output.svelte
  29. +1 −1 packages/svelte/tests/runtime-runes/samples/effect-cleanup/_config.js
  30. +20 −0 packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/_config.js
  31. +26 −0 packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/main.svelte
  32. +39 −3 packages/svelte/tests/signals/test.ts
  33. +1 −1 packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js
  34. +2 −2 .../tests/snapshot/samples/class-state-field-constructor-assignment/_expected/client/index.svelte.js
  35. +2 −2 packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js
  36. +1 −1 packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js
1 change: 0 additions & 1 deletion benchmarking/compare/index.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ import fs from 'node:fs';
import path from 'node:path';
import { execSync, fork } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { benchmarks } from '../benchmarks.js';

// if (execSync('git status --porcelain').toString().trim()) {
// console.error('Working directory is not clean');
4 changes: 2 additions & 2 deletions benchmarking/compare/runner.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { benchmarks } from '../benchmarks.js';
import { reactivity_benchmarks } from '../benchmarks/reactivity/index.js';

const results = [];
for (const benchmark of benchmarks) {
for (const benchmark of reactivity_benchmarks) {
const result = await benchmark();
console.error(result.benchmark);
results.push(result);
42 changes: 7 additions & 35 deletions documentation/docs/02-runes/04-$effect.md
Original file line number Diff line number Diff line change
@@ -280,62 +280,34 @@ You might be tempted to do something convoluted with effects to link one value t
</label>
```

Instead, use callbacks where possible ([demo](/playground/untitled#H4sIAAAAAAAACo1SMW6EMBD8imWluFMSIEUaDiKlvy5lSOHjlhOSMRZeTiDkv8deMEEJRcqdmZ1ZjzzxqpZgePo5cRw18JQA_sSVaPz0rnVk7iDRYxdhYA8vW4Wg0NnwzJRdrfGtUAVKQIYtCsly9pIkp4AZ7cQOezAoEA7JcWUkVBuCdol0dNWrEutWsV5fHfnhPQ5wZJMnCwyejxCh6G6A0V3IHk4zu_jOxzzPBxBld83PTr7xXrb3rUNw8PbiYJ3FP22oTIoLSComq5XuXTeu8LzgnVA3KDgj13wiQ8taRaJ82rzXskYM-URRlsXktejjgNLoo9e4fyf70_8EnwncySX1GuunX6kGRwnzR_BgaPNaGy3FmLJKwrCUeBM6ZUn0Cs2mOlp3vwthQJ5i14P9st9vZqQlsQIAAA==)):
Instead, use `oninput` callbacks or — better still — [function bindings](bind#Function-bindings) where possible ([demo](/playground/untitled#H4sIAAAAAAAAE51SsW6DMBT8FcvqABINdOhCIFKXTt06lg4GHpElYyz8iECIf69tcIIipo6-u3f3fPZMJWuBpvRzkBXyTpKSy5rLq6YRbbgATdOfmeKkrMgCBt9GPpQ66RsItFjJNBzhVScRJBobmumq5wovhSxQABLskAmSk7ckOXtMKyM22ItGhhAk4Z0R0OwIN-tIQzd-90HVhvy2HsGNiQFCMltBgd7XoecV2xzXNV7XaEcth7ZfRv7kujnsTX2Qd7USb5rFjwZkJlgJwpWRcakG04cpOS9oz-QVCuoeInXW-RyEJL-sG0b7Wy6kZWM-u7CFxM5tdrIl9qg72vB74H-y7T2iXROHyVb0CLanp1yNk4D1A1jQ91hzrQSbUtIIGLcir0ylJDm9Q7urz42bX4UwIk2xH2D5Xf4A7SeMcMQCAAA=)):

```svelte
<script>
let total = 100;
let spent = $state(0);
let left = $state(total);
function updateSpent(e) {
spent = +e.target.value;
function updateSpent(value) {
spent = value;
left = total - spent;
}
function updateLeft(e) {
left = +e.target.value;
function updateLeft(value) {
left = value;
spent = total - left;
}
</script>
<label>
<input type="range" value={spent} oninput={updateSpent} max={total} />
<input type="range" bind:value={() => spent, updateSpent} max={total} />
{spent}/{total} spent
</label>
<label>
<input type="range" value={left} oninput={updateLeft} max={total} />
<input type="range" bind:value={() => left, updateLeft} max={total} />
{left}/{total} left
</label>
```

If you need to use bindings, for whatever reason (for example when you want some kind of "writable `$derived`"), consider using getters and setters to synchronise state ([demo](/playground/untitled#H4sIAAAAAAAACpWRwW6DMBBEf8WyekikFOihFwcq9TvqHkyyQUjGsfCCQMj_XnvBNKpy6Qn2DTOD1wu_tRocF18Lx9kCFwT4iRvVxenT2syNoDGyWjl4xi93g2AwxPDSXfrW4oc0EjUgwzsqzSr2VhTnxJwNHwf24lAhHIpjVDZNwy1KS5wlNoGMSg9wOCYksQccerMlv65p51X0p_Xpdt_4YEy9yTkmV3z4MJT579-bUqsaNB2kbI0dwlnCgirJe2UakJzVrbkKaqkWivasU1O1ULxnOVk3JU-Uxti0p_-vKO4no_enbQ_yXhnZn0aHs4b1jiJMK7q2zmo1C3bTMG3LaZQVrMjeoSPgaUtkDxePMCEX2Ie6b_8D4WyJJEwCAAA=)):

```svelte
<script>
let total = 100;
let spent = $state(0);
let left = {
get value() {
return total - spent;
},
set value(v) {
spent = total - v;
}
};
</script>
<label>
<input type="range" bind:value={spent} max={total} />
{spent}/{total} spent
</label>
<label>
<input type="range" bind:value={left.value} max={total} />
{left.value}/{total} left
</label>
```

If you absolutely have to update `$state` within an effect and run into an infinite loop because you read and write to the same `$state`, use [untrack](svelte#untrack).
164 changes: 86 additions & 78 deletions documentation/docs/06-runtime/02-context.md
Original file line number Diff line number Diff line change
@@ -2,129 +2,137 @@
title: Context
---

<!-- - get/set/hasContext
- how to use, best practises (like encapsulating them) -->
Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as 'prop-drilling'). The parent component sets context with `setContext(key, value)`...

Most state is component-level state that lives as long as its component lives. There's also section-wide or app-wide state however, which also needs to be handled somehow.

The easiest way to do that is to create global state and just import that.
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
```ts
/// file: state.svelte.js
export const myGlobalState = $state({
user: {
/* ... */
}
/* ... */
});
setContext('my-context', 'hello from Parent.svelte');
</script>
```

...and the child retrieves it with `getContext`:

```svelte
<!--- file: App.svelte --->
<!--- file: Child.svelte --->
<script>
import { myGlobalState } from './state.svelte.js';
// ...
import { getContext } from 'svelte';
const message = getContext('my-context');
</script>
<h1>{message}, inside Child.svelte</h1>
```

This has a few drawbacks though:
This is particularly useful when `Parent.svelte` is not directly aware of `Child.svelte`, but instead renders it as part of a `children` [snippet](snippet) ([demo](/playground/untitled#H4sIAAAAAAAAE42Q3W6DMAyFX8WyJgESK-oto6hTX2D3YxcM3IIUQpR40yqUd58CrCXsp7tL7HNsf2dAWXaEKR56yfTBGOOxFWQwfR6Qz8q1XAHjL-GjUhvzToJd7bU09FO9ctMkG0wxM5VuFeeFLLjtVK8ZnkpNkuGo-w6CTTJ9Z3PwsBAemlbUF934W8iy5DpaZtOUcU02-ZLcaS51jHEkTFm_kY1_wfOO8QnXrb8hBzDEc6pgZ4gFoyz4KgiD7nxfTe8ghqAhIfrJ46cTzVZBbkPlODVJsLCDO6V7ZcJoncyw1yRr0hd1GNn_ZbEM3I9i1bmVxOlWElUvDUNHxpQngt3C4CXzjS1rtvkw22wMrTRtTbC8Lkuabe7jvthPPe3DofYCAAA=)):

```svelte
<Parent>
<Child />
</Parent>
```

- it only safely works when your global state is only used client-side - for example, when you're building a single page application that does not render any of your components on the server. If your state ends up being managed and updated on the server, it could end up being shared between sessions and/or users, causing bugs
- it may give the false impression that certain state is global when in reality it should only be used in a certain part of your app
The key (`'my-context'`, in the example above) and the context itself can be any JavaScript value.

To solve these drawbacks, Svelte provides a few `context` primitives which alleviate these problems.
In addition to [`setContext`](svelte#setContext) and [`getContext`](svelte#getContext), Svelte exposes [`hasContext`](svelte#hasContext) and [`getAllContexts`](svelte#getAllContexts) functions.

## Setting and getting context
## Using context with state

To associate an arbitrary object with the current component, use `setContext`.
You can store reactive state in context ([demo](/playground/untitled#H4sIAAAAAAAAE41R0W6DMAz8FSuaBNUQdK8MkKZ-wh7HHihzu6hgosRMm1D-fUpSVNq12x4iEvvOx_kmQU2PIhfP3DCCJGgHYvxkkYid7NCI_GUS_KUcxhVEMjOelErNB3bsatvG4LW6n0ZsRC4K02qpuKqpZtmrQTNMYJA3QRAs7PTQQxS40eMCt3mX3duxnWb-lS5h7nTI0A4jMWoo4c44P_Hku-zrOazdy64chWo-ScfRkRgl8wgHKrLTH1OxHZkHgoHaTraHcopXUFYzPPVfuC_hwQaD1GrskdiNCdQwJljJqlvXfyqVsA5CGg0uRUQifHw56xFtciO75QrP07vo_JXf_tf8yK2ezDKY_ZWt_1y2qqYzv7bI1IW1V_sN19m-07wCAAA=))...

```svelte
<script>
import { setContext } from 'svelte';
import Child from './Child.svelte';
setContext('key', value);
let counter = $state({
count: 0
});
setContext('counter', counter);
</script>
<button onclick={() => counter.count += 1}>
increment
</button>
<Child />
<Child />
<Child />
```

The context is then available to children of the component (including slotted content) with `getContext`.
...though note that if you _reassign_ `counter` instead of updating it, you will 'break the link' — in other words instead of this...

```svelte
<script>
import { getContext } from 'svelte';
const value = getContext('key');
</script>
<button onclick={() => counter = { count: 0 }}>
reset
</button>
```

`setContext` and `getContext` solve the above problems:
...you must do this:

- the state is not global, it's scoped to the component. That way it's safe to render your components on the server and not leak state
- it's clear that the state is not global but rather scoped to a specific component tree and therefore can't be used in other parts of your app
```svelte
<button onclick={() => +++counter.count = 0+++}>
reset
</button>
```

> [!NOTE] `setContext`/`getContext` must be called during component initialisation.
Svelte will warn you if you get it wrong.

Context is not inherently reactive. If you need reactive values in context then you can pass a `$state` object into context, whose properties _will_ be reactive.
## Type-safe context

```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
A useful pattern is to wrap the calls to `setContext` and `getContext` inside helper functions that let you preserve type safety:

let value = $state({ count: 0 });
setContext('counter', value);
</script>
```js
/// file: context.js
// @filename: ambient.d.ts
interface User {}

<button onclick={() => value.count++}>increment</button>
```
// @filename: index.js
// ---cut---
import { getContext, setContext } from 'svelte';

```svelte
<!--- file: Child.svelte --->
<script>
import { getContext } from 'svelte';
let key = {};

const value = getContext('counter');
</script>
/** @param {User} user */
export function setUserContext(user) {
setContext(key, user);
}

<p>Count is {value.count}</p>
export function getUserContext() {
return /** @type {User} */ (getContext(key));
}
```

To check whether a given `key` has been set in the context of a parent component, use `hasContext`.
## Replacing global state

```svelte
<script>
import { hasContext } from 'svelte';
When you have state shared by many different components, you might be tempted to put it in its own module and just import it wherever it's needed:

if (hasContext('key')) {
// do something
```js
/// file: state.svelte.js
export const myGlobalState = $state({
user: {
// ...
}
</script>
// ...
});
```

You can also retrieve the whole context map that belongs to the closest parent component using `getAllContexts`. This is useful, for example, if you programmatically create a component and want to pass the existing context to it.
In many cases this is perfectly fine, but there is a risk: if you mutate the state during server-side rendering (which is discouraged, but entirely possible!)...

```svelte
<!--- file: App.svelte ---->
<script>
import { getAllContexts } from 'svelte';
import { myGlobalState } from 'svelte';
const contexts = getAllContexts();
let { data } = $props();
if (data.user) {
myGlobalState.user = data.user;
}
</script>
```

## Encapsulating context interactions

The above methods are very unopinionated about how to use them. When your app grows in scale, it's worthwhile to encapsulate setting and getting the context into functions and properly type them.

```ts
// @errors: 2304
import { getContext, setContext } from 'svelte';

let userKey = Symbol('user');

export function setUserContext(user: User) {
setContext(userKey, user);
}

export function getUserContext(): User {
return getContext(userKey) as User;
}
```
...then the data may be accessible by the _next_ user. Context solves this problem because it is not shared between requests.
6 changes: 0 additions & 6 deletions documentation/docs/98-reference/.generated/client-errors.md
Original file line number Diff line number Diff line change
@@ -122,12 +122,6 @@ Property descriptors defined on `$state` objects must contain `value` and always
Cannot set prototype of `$state` object
```

### state_unsafe_local_read

```
Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
```

### state_unsafe_mutation

```
16 changes: 16 additions & 0 deletions packages/svelte/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# svelte

## 5.24.0

### Minor Changes

- feat: allow state created in deriveds/effects to be written/read locally without self-invalidation ([#15553](https://github.com/sveltejs/svelte/pull/15553))

### Patch Changes

- fix: check if DOM prototypes are extensible ([#15569](https://github.com/sveltejs/svelte/pull/15569))

- Keep inlined trailing JSDoc comments of properties when running svelte-migrate ([#15567](https://github.com/sveltejs/svelte/pull/15567))

- fix: simplify set calls for proxyable values ([#15548](https://github.com/sveltejs/svelte/pull/15548))

- fix: don't depend on deriveds created inside the current reaction ([#15564](https://github.com/sveltejs/svelte/pull/15564))

## 5.23.2

### Patch Changes
4 changes: 0 additions & 4 deletions packages/svelte/messages/client-errors/errors.md
Original file line number Diff line number Diff line change
@@ -80,10 +80,6 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long

> Cannot set prototype of `$state` object
## state_unsafe_local_read

> Reading state that was created inside the same derived is forbidden. Consider using `untrack` to read locally created state
## state_unsafe_mutation

> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
2 changes: 1 addition & 1 deletion packages/svelte/package.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.23.2",
"version": "5.24.0",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
7 changes: 5 additions & 2 deletions packages/svelte/src/compiler/migrate/index.js
Original file line number Diff line number Diff line change
@@ -1592,7 +1592,6 @@ function extract_type_and_comment(declarator, state, path) {
const comment_start = /** @type {any} */ (comment_node)?.start;
const comment_end = /** @type {any} */ (comment_node)?.end;
let comment = comment_node && str.original.substring(comment_start, comment_end);

if (comment_node) {
str.update(comment_start, comment_end, '');
}
@@ -1673,6 +1672,11 @@ function extract_type_and_comment(declarator, state, path) {
state.has_type_or_fallback = true;
const match = /@type {(.+)}/.exec(comment_node.value);
if (match) {
// try to find JSDoc comments after a hyphen `-`
const jsdocComment = /@type {.+} (?:\w+|\[.*?\]) - (.+)/.exec(comment_node.value);

Check failure on line 1676 in packages/svelte/src/compiler/migrate/index.js

GitHub Actions / Lint

Identifier 'jsdocComment' does not match for svelte's naming conventions
if (jsdocComment) {

Check failure on line 1677 in packages/svelte/src/compiler/migrate/index.js

GitHub Actions / Lint

Identifier 'jsdocComment' does not match for svelte's naming conventions
cleaned_comment += jsdocComment[1]?.trim();

Check failure on line 1678 in packages/svelte/src/compiler/migrate/index.js

GitHub Actions / Lint

Identifier 'jsdocComment' does not match for svelte's naming conventions
}
return {
type: match[1],
comment: cleaned_comment,
@@ -1693,7 +1697,6 @@ function extract_type_and_comment(declarator, state, path) {
};
}
}

return {
type: 'any',
comment: state.uses_ts ? comment : cleaned_comment,
Original file line number Diff line number Diff line change
@@ -219,7 +219,10 @@ export function client_component(analysis, options) {
for (const [name, binding] of analysis.instance.scope.declarations) {
if (binding.kind === 'legacy_reactive') {
legacy_reactive_declarations.push(
b.const(name, b.call('$.mutable_state', undefined, analysis.immutable ? b.true : undefined))
b.const(
name,
b.call('$.mutable_source', undefined, analysis.immutable ? b.true : undefined)
)
);
}
if (binding.kind === 'store_sub') {
Loading