svelte 5.57.0 → 5.57.2

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.
Files changed (78) hide show
  1. package/compiler/index.js +1 -1
  2. package/package.json +8 -8
  3. package/src/compiler/errors.js +10 -0
  4. package/src/compiler/migrate/index.js +15 -4
  5. package/src/compiler/phases/1-parse/acorn.js +36 -2
  6. package/src/compiler/phases/1-parse/index.js +23 -22
  7. package/src/compiler/phases/1-parse/read/context.js +3 -18
  8. package/src/compiler/phases/1-parse/read/expression.js +110 -2
  9. package/src/compiler/phases/1-parse/read/script.js +1 -1
  10. package/src/compiler/phases/1-parse/read/style.js +3 -5
  11. package/src/compiler/phases/1-parse/state/element.js +68 -40
  12. package/src/compiler/phases/1-parse/state/tag.js +8 -6
  13. package/src/compiler/phases/1-parse/utils/html.js +2 -0
  14. package/src/compiler/phases/1-parse/utils/whitespace.js +18 -0
  15. package/src/compiler/phases/2-analyze/css/css-prune.js +7 -6
  16. package/src/compiler/phases/2-analyze/index.js +1 -1
  17. package/src/compiler/phases/2-analyze/visitors/BindDirective.js +1 -1
  18. package/src/compiler/phases/2-analyze/visitors/ClassDeclaration.js +1 -1
  19. package/src/compiler/phases/2-analyze/visitors/FunctionDeclaration.js +1 -1
  20. package/src/compiler/phases/2-analyze/visitors/Identifier.js +1 -2
  21. package/src/compiler/phases/2-analyze/visitors/LetDirective.js +22 -0
  22. package/src/compiler/phases/2-analyze/visitors/SvelteBody.js +1 -1
  23. package/src/compiler/phases/2-analyze/visitors/SvelteDocument.js +1 -1
  24. package/src/compiler/phases/2-analyze/visitors/SvelteWindow.js +1 -1
  25. package/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js +2 -2
  26. package/src/compiler/phases/2-analyze/visitors/shared/a11y/constants.js +1 -1
  27. package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +3 -3
  28. package/src/compiler/phases/2-analyze/visitors/shared/utils.js +0 -38
  29. package/src/compiler/phases/3-transform/client/utils.js +0 -38
  30. package/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +2 -2
  31. package/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js +2 -1
  32. package/src/compiler/phases/3-transform/client/visitors/CallExpression.js +1 -2
  33. package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +3 -8
  34. package/src/compiler/phases/3-transform/client/visitors/shared/events.js +3 -2
  35. package/src/compiler/phases/3-transform/server/visitors/shared/element.js +8 -0
  36. package/src/compiler/phases/3-transform/utils.js +1 -1
  37. package/src/compiler/phases/nodes.js +30 -0
  38. package/src/compiler/phases/scope.js +85 -2
  39. package/src/compiler/print/index.js +3 -1
  40. package/src/compiler/state.js +9 -5
  41. package/src/compiler/utils/ast.js +2 -5
  42. package/src/compiler/utils/compile_diagnostic.js +1 -1
  43. package/src/compiler/utils/extract_svelte_ignore.js +1 -1
  44. package/src/compiler/utils/mapped_code.js +13 -1
  45. package/src/index-client.js +1 -1
  46. package/src/internal/client/constants.js +0 -9
  47. package/src/internal/client/dev/debug.js +0 -2
  48. package/src/internal/client/dev/tracing.js +3 -1
  49. package/src/internal/client/dom/blocks/boundary.js +39 -8
  50. package/src/internal/client/dom/blocks/each.js +8 -6
  51. package/src/internal/client/dom/blocks/svelte-element.js +3 -1
  52. package/src/internal/client/dom/css.js +1 -1
  53. package/src/internal/client/dom/elements/attributes.js +168 -148
  54. package/src/internal/client/dom/elements/bindings/document.js +3 -2
  55. package/src/internal/client/dom/elements/events.js +6 -1
  56. package/src/internal/client/dom/elements/transitions.js +3 -3
  57. package/src/internal/client/error-handling.js +5 -1
  58. package/src/internal/client/errors.js +0 -16
  59. package/src/internal/client/proxy.js +12 -7
  60. package/src/internal/client/reactivity/async.js +5 -0
  61. package/src/internal/client/reactivity/batch.js +103 -75
  62. package/src/internal/client/reactivity/deriveds.js +0 -3
  63. package/src/internal/client/reactivity/sources.js +31 -19
  64. package/src/internal/client/reactivity/utils.js +2 -23
  65. package/src/internal/client/runtime.js +18 -25
  66. package/src/internal/server/context.js +9 -2
  67. package/src/internal/server/index.js +9 -2
  68. package/src/internal/server/renderer.js +101 -69
  69. package/src/internal/shared/errors.js +16 -0
  70. package/src/reactivity/date.js +2 -2
  71. package/src/reactivity/url-search-params.js +1 -1
  72. package/src/version.js +1 -1
  73. package/types/index.d.ts.map +1 -1
  74. package/src/compiler/phases/1-parse/utils/create.js +0 -16
  75. package/src/compiler/phases/2-analyze/visitors/shared/special-element.js +0 -16
  76. package/src/compiler/utils/push_array.js +0 -13
  77. /package/src/compiler/{phases/2-analyze/utils → utils}/check_graph_for_cycles.js +0 -0
  78. /package/src/compiler/{phases/1-parse/utils → utils}/fuzzymatch.js +0 -0
@@ -298,182 +298,202 @@ function set_attributes(
298
298
  var is_option_element = element.nodeName === OPTION_TAG;
299
299
  var is_select_element = element.nodeName === SELECT_TAG;
300
300
 
301
- for (var key in prev) {
302
- // don't null our internal $$onX listeners
303
- if (!(key in next) && key[0] + key[1] !== '$$') {
304
- next[key] = null;
305
- }
306
- }
307
-
308
- if (next.class) {
309
- next.class = clsx(next.class);
310
- } else if (css_hash || next[CLASS]) {
311
- next.class = null; /* force call to set_class() */
312
- }
313
-
314
- if (next[STYLE]) {
315
- next.style ??= null; /* force call to set_style() */
316
- }
317
-
318
- var setters = get_setters(element);
319
-
320
- if (element.nodeName === INPUT_TAG && 'type' in next && ('value' in next || '__value' in next)) {
321
- var type = next.type;
322
-
323
- if (type !== current.type || (type === undefined && element.hasAttribute('type'))) {
324
- current.type = type;
325
- set_attribute(element, 'type', type, skip_warning);
301
+ try {
302
+ for (var key in prev) {
303
+ // don't null our internal $$onX listeners
304
+ if (!(key in next) && key[0] + key[1] !== '$$') {
305
+ next[key] = null;
306
+ }
326
307
  }
327
- }
328
308
 
329
- // since key is captured we use const
330
- for (const key in next) {
331
- // let instead of var because referenced in a closure
332
- let value = next[key];
333
-
334
- // Up here because we want to do this for the initial value, too, even if it's undefined,
335
- // and this wouldn't be reached in case of undefined because of the equality check below
336
- if (is_option_element && key === 'value' && value == null) {
337
- // The <option> element is a special case because removing the value attribute means
338
- // the value is set to the text content of the option element, and setting the value
339
- // to null or undefined means the value is set to the string "null" or "undefined".
340
- // To align with how we handle this case in non-spread-scenarios, this logic is needed.
341
- // There's a super-edge-case bug here that is left in in favor of smaller code size:
342
- // Because of the "set missing props to null" logic above, we can't differentiate
343
- // between a missing value and an explicitly set value of null or undefined. That means
344
- // that once set, the value attribute of an <option> element can't be removed. This is
345
- // a very rare edge case, and removing the attribute altogether isn't possible either
346
- // for the <option value={undefined}> case, so we're not losing any functionality here.
347
- // @ts-ignore
348
- element.value = element.__value = '';
349
- current[key] = value;
350
- continue;
309
+ if (next.class) {
310
+ next.class = clsx(next.class);
311
+ } else if (css_hash || next[CLASS]) {
312
+ next.class = null; /* force call to set_class() */
351
313
  }
352
314
 
353
- if (key === 'class') {
354
- var is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
355
- set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
356
- current[key] = value;
357
- current[CLASS] = next[CLASS];
358
- continue;
315
+ if (next[STYLE]) {
316
+ next.style ??= null; /* force call to set_style() */
359
317
  }
360
318
 
361
- if (key === 'style') {
362
- set_style(element, value, prev?.[STYLE], next[STYLE]);
363
- current[key] = value;
364
- current[STYLE] = next[STYLE];
365
- continue;
366
- }
319
+ var setters = get_setters(element);
367
320
 
368
- var prev_value = current[key];
321
+ if (
322
+ element.nodeName === INPUT_TAG &&
323
+ 'type' in next &&
324
+ ('value' in next || '__value' in next)
325
+ ) {
326
+ var type = next.type;
369
327
 
370
- // Skip if value is unchanged, unless it's `undefined` and the element still has the attribute
371
- if (value === prev_value && !(value === undefined && element.hasAttribute(key))) {
372
- continue;
328
+ if (type !== current.type || (type === undefined && element.hasAttribute('type'))) {
329
+ current.type = type;
330
+ set_attribute(element, 'type', type, skip_warning);
331
+ }
373
332
  }
374
333
 
375
- current[key] = value;
376
-
377
- var prefix = key[0] + key[1]; // this is faster than key.slice(0, 2)
378
- if (prefix === '$$') continue;
334
+ // since key is captured we use const
335
+ for (const key in next) {
336
+ // let instead of var because referenced in a closure
337
+ let value = next[key];
338
+
339
+ // Up here because we want to do this for the initial value, too, even if it's undefined,
340
+ // and this wouldn't be reached in case of undefined because of the equality check below
341
+ if (is_option_element && key === 'value' && value == null) {
342
+ // The <option> element is a special case because removing the value attribute means
343
+ // the value is set to the text content of the option element, and setting the value
344
+ // to null or undefined means the value is set to the string "null" or "undefined".
345
+ // To align with how we handle this case in non-spread-scenarios, this logic is needed.
346
+ // There's a super-edge-case bug here that is left in in favor of smaller code size:
347
+ // Because of the "set missing props to null" logic above, we can't differentiate
348
+ // between a missing value and an explicitly set value of null or undefined. That means
349
+ // that once set, the value attribute of an <option> element can't be removed. This is
350
+ // a very rare edge case, and removing the attribute altogether isn't possible either
351
+ // for the <option value={undefined}> case, so we're not losing any functionality here.
352
+ // @ts-ignore
353
+ element.value = element.__value = '';
354
+ current[key] = value;
355
+ continue;
356
+ }
379
357
 
380
- if (prefix === 'on') {
381
- /** @type {{ capture?: true }} */
382
- const opts = {};
383
- const event_handle_key = '$$' + key;
384
- let event_name = key.slice(2);
385
- var is_delegated = can_delegate_event(event_name);
358
+ if (key === 'class') {
359
+ var is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
360
+ set_class(element, is_html, value, css_hash, prev?.[CLASS], next[CLASS]);
361
+ current[key] = value;
362
+ current[CLASS] = next[CLASS];
363
+ continue;
364
+ }
386
365
 
387
- if (is_capture_event(event_name)) {
388
- event_name = event_name.slice(0, -7);
389
- opts.capture = true;
366
+ if (key === 'style') {
367
+ set_style(element, value, prev?.[STYLE], next[STYLE]);
368
+ current[key] = value;
369
+ current[STYLE] = next[STYLE];
370
+ continue;
390
371
  }
391
372
 
392
- if (!is_delegated && prev_value) {
393
- // Listening to same event but different handler -> our handle function below takes care of this
394
- // If we were to remove and add listeners in this case, it could happen that the event is "swallowed"
395
- // (the browser seems to not know yet that a new one exists now) and doesn't reach the handler
396
- // https://github.com/sveltejs/svelte/issues/11903
397
- if (value != null) continue;
373
+ var prev_value = current[key];
398
374
 
399
- element.removeEventListener(event_name, current[event_handle_key], opts);
400
- current[event_handle_key] = null;
375
+ // Skip if value is unchanged, unless it's `undefined` and the element still has the attribute
376
+ if (value === prev_value && !(value === undefined && element.hasAttribute(key))) {
377
+ continue;
401
378
  }
402
379
 
403
- if (is_delegated) {
404
- delegated(event_name, element, value);
405
- delegate([event_name]);
406
- } else if (value != null) {
407
- /**
408
- * @this {any}
409
- * @param {Event} evt
410
- */
411
- function handle(evt) {
412
- current[key].call(this, evt);
380
+ current[key] = value;
381
+
382
+ var prefix = key[0] + key[1]; // this is faster than key.slice(0, 2)
383
+ if (prefix === '$$') continue;
384
+
385
+ if (prefix === 'on') {
386
+ /** @type {{ capture?: true }} */
387
+ const opts = {};
388
+ const event_handle_key = '$$' + key;
389
+ let event_name = key.slice(2);
390
+ var is_delegated = can_delegate_event(event_name);
391
+
392
+ if (is_capture_event(event_name)) {
393
+ event_name = event_name.slice(0, -7);
394
+ opts.capture = true;
413
395
  }
414
396
 
415
- current[event_handle_key] = create_event(event_name, element, handle, opts);
416
- }
417
- } else if (key === 'style') {
418
- // avoid using the setter
419
- set_attribute(element, key, value);
420
- } else if (key === 'autofocus') {
421
- autofocus(/** @type {HTMLElement} */ (element), Boolean(value));
422
- } else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) {
423
- // @ts-ignore We're not running this for custom elements because __value is actually
424
- // how Lit stores the current value on the element, and messing with that would break things.
425
- element.value = element.__value = value;
426
- } else if (key === 'selected' && is_option_element) {
427
- set_selected(/** @type {HTMLOptionElement} */ (element), value);
428
- } else {
429
- var name = key;
430
- if (!preserve_attribute_case) {
431
- name = normalize_attribute(name);
432
- }
397
+ if (!is_delegated && prev_value) {
398
+ // Listening to same event but different handler -> our handle function below takes care of this
399
+ // If we were to remove and add listeners in this case, it could happen that the event is "swallowed"
400
+ // (the browser seems to not know yet that a new one exists now) and doesn't reach the handler
401
+ // https://github.com/sveltejs/svelte/issues/11903
402
+ if (value != null) continue;
433
403
 
434
- var is_default = name === 'defaultValue' || name === 'defaultChecked';
404
+ element.removeEventListener(event_name, current[event_handle_key], opts);
405
+ current[event_handle_key] = null;
406
+ }
435
407
 
436
- // A select's default value is represented by selected options, not a property.
437
- if (is_select_element && name === 'defaultValue') continue;
408
+ if (is_delegated) {
409
+ delegated(event_name, element, value);
410
+ delegate([event_name]);
411
+ } else if (value != null) {
412
+ /**
413
+ * @this {any}
414
+ * @param {Event} evt
415
+ */
416
+ function handle(evt) {
417
+ current[key].call(this, evt);
418
+ }
438
419
 
439
- if (value == null && !is_custom_element && !is_default) {
440
- attributes[key] = null;
420
+ current[event_handle_key] = create_event(event_name, element, handle, opts);
421
+ }
422
+ } else if (key === 'style') {
423
+ // avoid using the setter
424
+ set_attribute(element, key, value);
425
+ } else if (key === 'autofocus') {
426
+ autofocus(/** @type {HTMLElement} */ (element), Boolean(value));
427
+ } else if (!is_custom_element && (key === '__value' || (key === 'value' && value != null))) {
428
+ // @ts-ignore We're not running this for custom elements because __value is actually
429
+ // how Lit stores the current value on the element, and messing with that would break things.
430
+ element.__value = value;
431
+ // we don't set the value if it hasn't changed. This supports invalid number inputs like `1e` because
432
+ // 1. user types 1e
433
+ // 2. the state is updated reading e.target.value which is ''
434
+ // 3. the spreaded value is ''
435
+ // 4. updating input.value would thus, clear the user value
436
+ if (
437
+ prev_value == null ||
438
+ // @ts-ignore
439
+ element.value !== value ||
440
+ (value === 0 && element.nodeName === PROGRESS_TAG)
441
+ ) {
442
+ // @ts-ignore
443
+ element.value = value;
444
+ }
445
+ } else if (key === 'selected' && is_option_element) {
446
+ set_selected(/** @type {HTMLOptionElement} */ (element), value);
447
+ } else {
448
+ var name = key;
449
+ if (!preserve_attribute_case) {
450
+ name = normalize_attribute(name);
451
+ }
441
452
 
442
- if (name === 'value' || name === 'checked') {
443
- // removing value/checked also removes defaultValue/defaultChecked — preserve
444
- let input = /** @type {HTMLInputElement} */ (element);
445
- const use_default = prev === undefined;
446
- if (name === 'value') {
447
- let previous = input.defaultValue;
448
- input.removeAttribute(name);
449
- input.defaultValue = previous;
450
- // @ts-ignore
451
- input.value = input.__value = use_default ? previous : null;
453
+ var is_default = name === 'defaultValue' || name === 'defaultChecked';
454
+
455
+ // A select's default value is represented by selected options, not a property.
456
+ if (is_select_element && name === 'defaultValue') continue;
457
+
458
+ if (value == null && !is_custom_element && !is_default) {
459
+ attributes[key] = null;
460
+
461
+ if (name === 'value' || name === 'checked') {
462
+ // removing value/checked also removes defaultValue/defaultChecked — preserve
463
+ let input = /** @type {HTMLInputElement} */ (element);
464
+ const use_default = prev === undefined;
465
+ if (name === 'value') {
466
+ let previous = input.defaultValue;
467
+ input.removeAttribute(name);
468
+ input.defaultValue = previous;
469
+ // @ts-ignore
470
+ input.value = input.__value = use_default ? previous : null;
471
+ } else {
472
+ let previous = input.defaultChecked;
473
+ input.removeAttribute(name);
474
+ input.defaultChecked = previous;
475
+ input.checked = use_default ? previous : false;
476
+ }
452
477
  } else {
453
- let previous = input.defaultChecked;
454
- input.removeAttribute(name);
455
- input.defaultChecked = previous;
456
- input.checked = use_default ? previous : false;
478
+ element.removeAttribute(key);
457
479
  }
458
- } else {
459
- element.removeAttribute(key);
480
+ } else if (
481
+ is_default ||
482
+ ((is_custom_element || typeof value !== 'string') && setters.has(name))
483
+ ) {
484
+ // @ts-ignore
485
+ element[name] = value;
486
+ // remove it from attributes's cache
487
+ if (name in attributes) attributes[name] = UNINITIALIZED;
488
+ } else if (typeof value !== 'function') {
489
+ set_attribute(element, name, value, skip_warning);
460
490
  }
461
- } else if (
462
- is_default ||
463
- ((is_custom_element || typeof value !== 'string') && setters.has(name))
464
- ) {
465
- // @ts-ignore
466
- element[name] = value;
467
- // remove it from attributes's cache
468
- if (name in attributes) attributes[name] = UNINITIALIZED;
469
- } else if (typeof value !== 'function') {
470
- set_attribute(element, name, value, skip_warning);
471
491
  }
472
492
  }
473
- }
474
-
475
- if (is_hydrating_custom_element) {
476
- set_hydrating(true);
493
+ } finally {
494
+ if (is_hydrating_custom_element) {
495
+ set_hydrating(true);
496
+ }
477
497
  }
478
498
 
479
499
  return current;
@@ -1,4 +1,4 @@
1
- import { listen } from './shared.js';
1
+ import { listen, without_reactive_context } from './shared.js';
2
2
 
3
3
  /**
4
4
  * @param {(activeElement: Element | null) => void} update
@@ -12,6 +12,7 @@ export function bind_active_element(update) {
12
12
  return;
13
13
  }
14
14
 
15
- update(document.activeElement);
15
+ // Removing the focused element fires `focusout` while an effect is running
16
+ without_reactive_context(() => update(document.activeElement));
16
17
  });
17
18
  }
@@ -78,8 +78,11 @@ export function create_event(event_name, dom, handler, options = {}) {
78
78
  event_name.startsWith('touch') ||
79
79
  event_name === 'wheel'
80
80
  ) {
81
+ target_handler.__removed = false;
81
82
  queue_micro_task(() => {
82
- dom.addEventListener(event_name, target_handler, options);
83
+ if (!target_handler.__removed) {
84
+ dom.addEventListener(event_name, target_handler, options);
85
+ }
83
86
  });
84
87
  } else {
85
88
  dom.addEventListener(event_name, target_handler, options);
@@ -102,6 +105,7 @@ export function on(element, type, handler, options = {}) {
102
105
  var target_handler = create_event(type, element, handler, options);
103
106
 
104
107
  return () => {
108
+ target_handler.__removed = true;
105
109
  element.removeEventListener(type, target_handler, options);
106
110
  };
107
111
  }
@@ -128,6 +132,7 @@ export function event(event_name, dom, handler, capture, passive) {
128
132
  dom instanceof HTMLMediaElement
129
133
  ) {
130
134
  teardown(() => {
135
+ target_handler.__removed = true;
131
136
  dom.removeEventListener(event_name, target_handler, options);
132
137
  });
133
138
  }
@@ -359,9 +359,9 @@ function animate(element, options, counterpart, t2, on_begin, on_finish) {
359
359
  aborted = true;
360
360
  a?.abort();
361
361
  },
362
- deactivate: () => a.deactivate(),
363
- reset: () => a.reset(),
364
- t: () => a.t()
362
+ deactivate: () => a?.deactivate(),
363
+ reset: () => a?.reset(),
364
+ t: () => a?.t() ?? 1 - t2
365
365
  };
366
366
  }
367
367
 
@@ -1,7 +1,7 @@
1
1
  /** @import { Derived, Effect } from '#client' */
2
2
  /** @import { Boundary } from './dom/blocks/boundary.js' */
3
3
  import { DEV } from 'esm-env';
4
- import { FILENAME } from '../../constants.js';
4
+ import { FILENAME, HYDRATION_ERROR } from '../../constants.js';
5
5
  import { is_firefox } from './dom/operations.js';
6
6
  import {
7
7
  ERROR_VALUE,
@@ -52,6 +52,10 @@ export function handle_error(error) {
52
52
  * @param {Effect | null} effect
53
53
  */
54
54
  export function invoke_error_boundary(error, effect) {
55
+ if (error === HYDRATION_ERROR) {
56
+ throw error;
57
+ }
58
+
55
59
  if (effect !== null && (effect.f & DESTROYED) !== 0) {
56
60
  return;
57
61
  }
@@ -429,22 +429,6 @@ export function rune_outside_svelte(rune) {
429
429
  }
430
430
  }
431
431
 
432
- /**
433
- * `setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression
434
- * @returns {never}
435
- */
436
- export function set_context_after_init() {
437
- if (DEV) {
438
- const error = new Error(`set_context_after_init\n\`setContext\` must be called when a component first initializes, not in a subsequent effect or after an \`await\` expression\nhttps://svelte.dev/e/set_context_after_init`);
439
-
440
- error.name = 'Svelte error';
441
-
442
- throw error;
443
- } else {
444
- throw new Error(`https://svelte.dev/e/set_context_after_init`);
445
- }
446
- }
447
-
448
432
  /**
449
433
  * Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.
450
434
  * @returns {never}
@@ -204,16 +204,21 @@ export function proxy(value) {
204
204
  },
205
205
 
206
206
  getOwnPropertyDescriptor(target, prop) {
207
+ this.has?.(target, prop);
208
+
207
209
  var descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
210
+ var s = sources.get(prop);
208
211
 
209
- if (descriptor && 'value' in descriptor) {
210
- var s = sources.get(prop);
211
- if (s) descriptor.value = get(s);
212
- } else if (descriptor === undefined) {
213
- var source = sources.get(prop);
214
- var value = source?.v;
212
+ if (s !== undefined) {
213
+ var value = get(s);
214
+
215
+ if (value === UNINITIALIZED) {
216
+ return undefined;
217
+ }
215
218
 
216
- if (source !== undefined && value !== UNINITIALIZED) {
219
+ if (descriptor && 'value' in descriptor) {
220
+ descriptor.value = value;
221
+ } else {
217
222
  return {
218
223
  enumerable: true,
219
224
  configurable: true,
@@ -103,6 +103,11 @@ export function flatten(blockers, sync, async, fn) {
103
103
 
104
104
  if (blocker_promise) {
105
105
  blocker_promise.then(() => {
106
+ if ((parent.f & DESTROYED) !== 0) {
107
+ decrement_pending();
108
+ return;
109
+ }
110
+
106
111
  restore();
107
112
  run();
108
113
  unset_context();