svelte 5.46.0 → 5.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "svelte",
3
3
  "description": "Cybernetically enhanced web apps",
4
4
  "license": "MIT",
5
- "version": "5.46.0",
5
+ "version": "5.46.1",
6
6
  "type": "module",
7
7
  "types": "./types/index.d.ts",
8
8
  "engines": {
@@ -519,14 +519,9 @@ export function client_component(analysis, options) {
519
519
 
520
520
  if (options.hmr) {
521
521
  const id = b.id(analysis.name);
522
- const HMR = b.id('$.HMR');
523
-
524
- const existing = b.member(id, HMR, true);
525
- const incoming = b.member(b.id('module.default'), HMR, true);
526
522
 
527
523
  const accept_fn_body = [
528
- b.stmt(b.assignment('=', b.member(incoming, 'source'), b.member(existing, 'source'))),
529
- b.stmt(b.call('$.set', b.member(existing, 'source'), b.member(incoming, 'original')))
524
+ b.stmt(b.call(b.member(b.member(id, b.id('$.HMR'), true), 'update'), b.id('module.default')))
530
525
  ];
531
526
 
532
527
  if (analysis.css.hash) {
@@ -535,8 +530,7 @@ export function client_component(analysis, options) {
535
530
  }
536
531
 
537
532
  const hmr = b.block([
538
- b.stmt(b.assignment('=', id, b.call('$.hmr', id, b.thunk(b.member(existing, 'source'))))),
539
-
533
+ b.stmt(b.assignment('=', id, b.call('$.hmr', id))),
540
534
  b.stmt(b.call('import.meta.hot.accept', b.arrow([b.id('module')], b.block(accept_fn_body))))
541
535
  ]);
542
536
 
@@ -336,7 +336,9 @@ export function RegularElement(node, context) {
336
336
  trimmed.every(
337
337
  (node) =>
338
338
  node.type === 'Text' ||
339
- (!node.metadata.expression.has_state && !node.metadata.expression.has_await)
339
+ (!node.metadata.expression.has_state &&
340
+ !node.metadata.expression.has_await &&
341
+ !node.metadata.expression.has_blockers())
340
342
  ) &&
341
343
  trimmed.some((node) => node.type === 'ExpressionTag');
342
344
 
@@ -134,7 +134,7 @@ export function build_template_chunk(
134
134
 
135
135
  const evaluated = state.scope.evaluate(value);
136
136
 
137
- has_await ||= node.metadata.expression.has_await;
137
+ has_await ||= node.metadata.expression.has_await || node.metadata.expression.has_blockers();
138
138
  has_state ||= has_await || (node.metadata.expression.has_state && !evaluated.is_known);
139
139
 
140
140
  if (values.length === 1) {
@@ -1,23 +1,25 @@
1
- /** @import { Source, Effect, TemplateNode } from '#client' */
1
+ /** @import { Effect, TemplateNode } from '#client' */
2
2
  import { FILENAME, HMR } from '../../../constants.js';
3
3
  import { EFFECT_TRANSPARENT } from '#client/constants';
4
4
  import { hydrate_node, hydrating } from '../dom/hydration.js';
5
5
  import { block, branch, destroy_effect } from '../reactivity/effects.js';
6
- import { source } from '../reactivity/sources.js';
6
+ import { set, source } from '../reactivity/sources.js';
7
7
  import { set_should_intro } from '../render.js';
8
8
  import { get } from '../runtime.js';
9
9
 
10
10
  /**
11
11
  * @template {(anchor: Comment, props: any) => any} Component
12
- * @param {Component} original
13
- * @param {() => Source<Component>} get_source
12
+ * @param {Component} fn
14
13
  */
15
- export function hmr(original, get_source) {
14
+ export function hmr(fn) {
15
+ const current = source(fn);
16
+
16
17
  /**
17
18
  * @param {TemplateNode} anchor
18
19
  * @param {any} props
19
20
  */
20
21
  function wrapper(anchor, props) {
22
+ let component = {};
21
23
  let instance = {};
22
24
 
23
25
  /** @type {Effect} */
@@ -26,8 +28,9 @@ export function hmr(original, get_source) {
26
28
  let ran = false;
27
29
 
28
30
  block(() => {
29
- const source = get_source();
30
- const component = get(source);
31
+ if (component === (component = get(current))) {
32
+ return;
33
+ }
31
34
 
32
35
  if (effect) {
33
36
  // @ts-ignore
@@ -62,16 +65,24 @@ export function hmr(original, get_source) {
62
65
  }
63
66
 
64
67
  // @ts-expect-error
65
- wrapper[FILENAME] = original[FILENAME];
68
+ wrapper[FILENAME] = fn[FILENAME];
66
69
 
67
70
  // @ts-ignore
68
71
  wrapper[HMR] = {
69
- // When we accept an update, we set the original source to the new component
70
- original,
71
- // The `get_source` parameter reads `wrapper[HMR].source`, but in the `accept`
72
- // function we always replace it with `previous[HMR].source`, which in practice
73
- // means we only ever update the original
74
- source: source(original)
72
+ fn,
73
+ current,
74
+ update: (/** @type {any} */ incoming) => {
75
+ // This logic ensures that the first version of the component is the one
76
+ // whose update function and therefore block effect is preserved across updates.
77
+ // If we don't do this dance and instead just use `incoming` as the new component
78
+ // and then update, we'll create an ever-growing stack of block effects.
79
+
80
+ // Trigger the original block effect
81
+ set(wrapper[HMR].current, incoming[HMR].fn);
82
+
83
+ // Replace the incoming source with the original one
84
+ incoming[HMR].current = wrapper[HMR].current;
85
+ }
75
86
  };
76
87
 
77
88
  return wrapper;
package/src/version.js CHANGED
@@ -4,5 +4,5 @@
4
4
  * The current version, as set in package.json.
5
5
  * @type {string}
6
6
  */
7
- export const VERSION = '5.46.0';
7
+ export const VERSION = '5.46.1';
8
8
  export const PUBLIC_VERSION = '5';
package/types/index.d.ts CHANGED
@@ -2810,7 +2810,7 @@ declare module 'svelte/events' {
2810
2810
  export function on<Type extends keyof WindowEventMap>(
2811
2811
  window: Window,
2812
2812
  type: Type,
2813
- handler: (this: Window, event: WindowEventMap[Type]) => any,
2813
+ handler: (this: Window, event: WindowEventMap[Type] & { currentTarget: Window }) => any,
2814
2814
  options?: AddEventListenerOptions | undefined
2815
2815
  ): () => void;
2816
2816
  /**
@@ -2821,7 +2821,7 @@ declare module 'svelte/events' {
2821
2821
  export function on<Type extends keyof DocumentEventMap>(
2822
2822
  document: Document,
2823
2823
  type: Type,
2824
- handler: (this: Document, event: DocumentEventMap[Type]) => any,
2824
+ handler: (this: Document, event: DocumentEventMap[Type] & { currentTarget: Document }) => any,
2825
2825
  options?: AddEventListenerOptions | undefined
2826
2826
  ): () => void;
2827
2827
  /**
@@ -2832,7 +2832,7 @@ declare module 'svelte/events' {
2832
2832
  export function on<Element extends HTMLElement, Type extends keyof HTMLElementEventMap>(
2833
2833
  element: Element,
2834
2834
  type: Type,
2835
- handler: (this: Element, event: HTMLElementEventMap[Type]) => any,
2835
+ handler: (this: Element, event: HTMLElementEventMap[Type] & { currentTarget: Element }) => any,
2836
2836
  options?: AddEventListenerOptions | undefined
2837
2837
  ): () => void;
2838
2838
  /**
@@ -2843,7 +2843,7 @@ declare module 'svelte/events' {
2843
2843
  export function on<Element extends MediaQueryList, Type extends keyof MediaQueryListEventMap>(
2844
2844
  element: Element,
2845
2845
  type: Type,
2846
- handler: (this: Element, event: MediaQueryListEventMap[Type]) => any,
2846
+ handler: (this: Element, event: MediaQueryListEventMap[Type] & { currentTarget: Element }) => any,
2847
2847
  options?: AddEventListenerOptions | undefined
2848
2848
  ): () => void;
2849
2849
  /**