svelte 5.55.1 → 5.55.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.
- package/compiler/index.js +1 -1
- package/elements.d.ts +3 -3
- package/package.json +1 -1
- package/src/compiler/phases/1-parse/acorn.js +58 -31
- package/src/compiler/phases/1-parse/index.js +0 -10
- package/src/compiler/phases/1-parse/read/context.js +28 -34
- package/src/compiler/phases/1-parse/read/expression.js +4 -38
- package/src/compiler/phases/1-parse/read/script.js +1 -8
- package/src/compiler/phases/1-parse/state/tag.js +1 -6
- package/src/compiler/phases/2-analyze/visitors/shared/function.js +1 -1
- package/src/compiler/phases/3-transform/client/transform-client.js +1 -1
- package/src/internal/client/dom/blocks/each.js +5 -0
- package/src/internal/client/reactivity/batch.js +39 -15
- package/src/internal/client/reactivity/deriveds.js +5 -3
- package/src/internal/client/reactivity/sources.js +2 -10
- package/src/internal/client/runtime.js +8 -1
- package/src/internal/server/errors.js +12 -0
- package/src/internal/server/renderer.js +4 -0
- package/src/reactivity/date.js +4 -0
- package/src/version.js +1 -1
- package/types/index.d.ts.map +1 -1
package/elements.d.ts
CHANGED
|
@@ -952,9 +952,9 @@ export interface HTMLDetailsAttributes extends HTMLAttributes<HTMLDetailsElement
|
|
|
952
952
|
|
|
953
953
|
'bind:open'?: boolean | undefined | null;
|
|
954
954
|
|
|
955
|
-
'on:toggle'?:
|
|
956
|
-
ontoggle?:
|
|
957
|
-
ontogglecapture?:
|
|
955
|
+
'on:toggle'?: ToggleEventHandler<HTMLDetailsElement> | undefined | null;
|
|
956
|
+
ontoggle?: ToggleEventHandler<HTMLDetailsElement> | undefined | null;
|
|
957
|
+
ontogglecapture?: ToggleEventHandler<HTMLDetailsElement> | undefined | null;
|
|
958
958
|
}
|
|
959
959
|
|
|
960
960
|
export interface HTMLDelAttributes extends HTMLAttributes<HTMLModElement> {
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/** @import { Comment, Program } from 'estree' */
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
|
+
/** @import { Parser } from './index.js' */
|
|
3
4
|
import * as acorn from 'acorn';
|
|
4
5
|
import { walk } from 'zimmerframe';
|
|
5
6
|
import { tsPlugin } from '@sveltejs/acorn-typescript';
|
|
7
|
+
import * as e from '../../errors.js';
|
|
6
8
|
|
|
7
|
-
const
|
|
9
|
+
const JSParser = acorn.Parser;
|
|
10
|
+
const TSParser = JSParser.extend(tsPlugin());
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* @typedef {Comment & {
|
|
@@ -20,15 +23,15 @@ const ParserWithTS = acorn.Parser.extend(tsPlugin());
|
|
|
20
23
|
* @param {boolean} [is_script]
|
|
21
24
|
*/
|
|
22
25
|
export function parse(source, comments, typescript, is_script) {
|
|
23
|
-
const
|
|
26
|
+
const acorn = typescript ? TSParser : JSParser;
|
|
24
27
|
|
|
25
28
|
const { onComment, add_comments } = get_comment_handlers(
|
|
26
29
|
source,
|
|
27
30
|
/** @type {CommentWithLocation[]} */ (comments)
|
|
28
31
|
);
|
|
29
32
|
|
|
30
|
-
// @ts-
|
|
31
|
-
const parse_statement =
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
const parse_statement = acorn.prototype.parseStatement;
|
|
32
35
|
|
|
33
36
|
// If we're dealing with a <script> then it might contain an export
|
|
34
37
|
// for something that doesn't exist directly inside but is inside the
|
|
@@ -36,7 +39,7 @@ export function parse(source, comments, typescript, is_script) {
|
|
|
36
39
|
// an error in these cases
|
|
37
40
|
if (is_script) {
|
|
38
41
|
// @ts-ignore
|
|
39
|
-
|
|
42
|
+
acorn.prototype.parseStatement = function (...args) {
|
|
40
43
|
const v = parse_statement.call(this, ...args);
|
|
41
44
|
// @ts-ignore
|
|
42
45
|
this.undefinedExports = {};
|
|
@@ -44,53 +47,77 @@ export function parse(source, comments, typescript, is_script) {
|
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
let ast;
|
|
48
|
-
|
|
49
50
|
try {
|
|
50
|
-
ast =
|
|
51
|
+
const ast = acorn.parse(source, {
|
|
51
52
|
onComment,
|
|
52
53
|
sourceType: 'module',
|
|
53
54
|
ecmaVersion: 16,
|
|
54
55
|
locations: true
|
|
55
56
|
});
|
|
57
|
+
|
|
58
|
+
add_comments(ast);
|
|
59
|
+
|
|
60
|
+
return /** @type {Program} */ (ast);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
// TODO the `return` in necessary for TS<7 due to a bug; otherwise
|
|
63
|
+
// the `finally` block is regarded as unreachable
|
|
64
|
+
return handle_parse_error(err);
|
|
56
65
|
} finally {
|
|
57
66
|
if (is_script) {
|
|
58
|
-
// @ts-
|
|
59
|
-
|
|
67
|
+
// @ts-expect-error
|
|
68
|
+
acorn.prototype.parseStatement = parse_statement;
|
|
60
69
|
}
|
|
61
70
|
}
|
|
62
|
-
|
|
63
|
-
add_comments(ast);
|
|
64
|
-
|
|
65
|
-
return /** @type {Program} */ (ast);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/**
|
|
74
|
+
* @param {Parser} parser
|
|
69
75
|
* @param {string} source
|
|
70
|
-
* @param {Comment[]} comments
|
|
71
|
-
* @param {boolean} typescript
|
|
72
76
|
* @param {number} index
|
|
73
77
|
* @returns {acorn.Expression & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }}
|
|
74
78
|
*/
|
|
75
|
-
export function parse_expression_at(
|
|
76
|
-
const
|
|
79
|
+
export function parse_expression_at(parser, source, index) {
|
|
80
|
+
const acorn = parser.ts ? TSParser : JSParser;
|
|
77
81
|
|
|
78
|
-
const { onComment, add_comments } = get_comment_handlers(
|
|
79
|
-
source,
|
|
80
|
-
/** @type {CommentWithLocation[]} */ (comments),
|
|
81
|
-
index
|
|
82
|
-
);
|
|
82
|
+
const { onComment, add_comments } = get_comment_handlers(source, parser.root.comments, index);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
try {
|
|
85
|
+
const ast = acorn.parseExpressionAt(source, index, {
|
|
86
|
+
onComment,
|
|
87
|
+
sourceType: 'module',
|
|
88
|
+
ecmaVersion: 16,
|
|
89
|
+
locations: true,
|
|
90
|
+
preserveParens: true
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
add_comments(ast);
|
|
94
|
+
|
|
95
|
+
return ast;
|
|
96
|
+
} catch (e) {
|
|
97
|
+
handle_parse_error(e);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const regex_position_indicator = / \(\d+:\d+\)$/;
|
|
90
102
|
|
|
91
|
-
|
|
103
|
+
/**
|
|
104
|
+
* @param {any} err
|
|
105
|
+
* @returns {never}
|
|
106
|
+
*/
|
|
107
|
+
function handle_parse_error(err) {
|
|
108
|
+
e.js_parse_error(err.pos, err.message.replace(regex_position_indicator, ''));
|
|
109
|
+
}
|
|
92
110
|
|
|
93
|
-
|
|
111
|
+
/**
|
|
112
|
+
* @param {acorn.Expression} node
|
|
113
|
+
* @returns {acorn.Expression}
|
|
114
|
+
*/
|
|
115
|
+
export function remove_parens(node) {
|
|
116
|
+
return walk(node, null, {
|
|
117
|
+
ParenthesizedExpression(node, context) {
|
|
118
|
+
return context.visit(node.expression);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
94
121
|
}
|
|
95
122
|
|
|
96
123
|
/**
|
|
@@ -11,8 +11,6 @@ import { is_reserved } from '../../../utils.js';
|
|
|
11
11
|
import { disallow_children } from '../2-analyze/visitors/shared/special-element.js';
|
|
12
12
|
import * as state from '../../state.js';
|
|
13
13
|
|
|
14
|
-
const regex_position_indicator = / \(\d+:\d+\)$/;
|
|
15
|
-
|
|
16
14
|
/** @param {number} cc */
|
|
17
15
|
function is_whitespace(cc) {
|
|
18
16
|
// fast path for common whitespace
|
|
@@ -175,14 +173,6 @@ export class Parser {
|
|
|
175
173
|
return this.stack[this.stack.length - 1];
|
|
176
174
|
}
|
|
177
175
|
|
|
178
|
-
/**
|
|
179
|
-
* @param {any} err
|
|
180
|
-
* @returns {never}
|
|
181
|
-
*/
|
|
182
|
-
acorn_error(err) {
|
|
183
|
-
e.js_parse_error(err.pos, err.message.replace(regex_position_indicator, ''));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
176
|
/**
|
|
187
177
|
* @param {string} str
|
|
188
178
|
* @param {boolean} required
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @import { Pattern } from 'estree' */
|
|
2
2
|
/** @import { Parser } from '../index.js' */
|
|
3
3
|
import { match_bracket } from '../utils/bracket.js';
|
|
4
|
-
import { parse_expression_at } from '../acorn.js';
|
|
4
|
+
import { parse_expression_at, remove_parens } from '../acorn.js';
|
|
5
5
|
import { regex_not_newline_characters } from '../../patterns.js';
|
|
6
6
|
import * as e from '../../../errors.js';
|
|
7
7
|
|
|
@@ -35,38 +35,32 @@ export default function read_pattern(parser) {
|
|
|
35
35
|
|
|
36
36
|
const pattern_string = parser.template.slice(start, i);
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
space_with_newline
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
expression.typeAnnotation = read_type_annotation(parser);
|
|
62
|
-
if (expression.typeAnnotation) {
|
|
63
|
-
expression.end = expression.typeAnnotation.end;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return expression;
|
|
67
|
-
} catch (error) {
|
|
68
|
-
parser.acorn_error(error);
|
|
38
|
+
// the length of the `space_with_newline` has to be start - 1
|
|
39
|
+
// because we added a `(` in front of the pattern_string,
|
|
40
|
+
// which shifted the entire string to right by 1
|
|
41
|
+
// so we offset it by removing 1 character in the `space_with_newline`
|
|
42
|
+
// to achieve that, we remove the 1st space encountered,
|
|
43
|
+
// so it will not affect the `column` of the node
|
|
44
|
+
let space_with_newline = parser.template
|
|
45
|
+
.slice(0, start)
|
|
46
|
+
.replace(regex_not_newline_characters, ' ');
|
|
47
|
+
const first_space = space_with_newline.indexOf(' ');
|
|
48
|
+
space_with_newline =
|
|
49
|
+
space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
|
|
50
|
+
|
|
51
|
+
/** @type {any} */
|
|
52
|
+
let expression = remove_parens(
|
|
53
|
+
parse_expression_at(parser, `${space_with_newline}(${pattern_string} = 1)`, start - 1)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expression = expression.left;
|
|
57
|
+
|
|
58
|
+
expression.typeAnnotation = read_type_annotation(parser);
|
|
59
|
+
if (expression.typeAnnotation) {
|
|
60
|
+
expression.end = expression.typeAnnotation.end;
|
|
69
61
|
}
|
|
62
|
+
|
|
63
|
+
return expression;
|
|
70
64
|
}
|
|
71
65
|
|
|
72
66
|
/**
|
|
@@ -92,13 +86,13 @@ function read_type_annotation(parser) {
|
|
|
92
86
|
// parameters as part of a sequence expression instead, and will then error on optional
|
|
93
87
|
// parameters (`?:`). Therefore replace that sequence with something that will not error.
|
|
94
88
|
parser.template.slice(parser.index).replace(/\?\s*:/g, ':');
|
|
95
|
-
let expression = parse_expression_at(
|
|
89
|
+
let expression = remove_parens(parse_expression_at(parser, template, a));
|
|
96
90
|
|
|
97
91
|
// `foo: bar = baz` gets mangled — fix it
|
|
98
92
|
if (expression.type === 'AssignmentExpression') {
|
|
99
93
|
let b = expression.right.start;
|
|
100
94
|
while (template[b] !== '=') b -= 1;
|
|
101
|
-
expression = parse_expression_at(template.slice(0, b),
|
|
95
|
+
expression = remove_parens(parse_expression_at(parser, template.slice(0, b), a));
|
|
102
96
|
}
|
|
103
97
|
|
|
104
98
|
// `array as item: string, index` becomes `string, index`, which is mistaken as a sequence expression - fix that
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { Expression } from 'estree' */
|
|
2
2
|
/** @import { Parser } from '../index.js' */
|
|
3
|
-
import { parse_expression_at } from '../acorn.js';
|
|
3
|
+
import { parse_expression_at, remove_parens } from '../acorn.js';
|
|
4
4
|
import { regex_whitespace } from '../../patterns.js';
|
|
5
5
|
import * as e from '../../../errors.js';
|
|
6
6
|
import { find_matching_bracket } from '../utils/bracket.js';
|
|
@@ -34,50 +34,16 @@ export function get_loose_identifier(parser, opening_token) {
|
|
|
34
34
|
*/
|
|
35
35
|
export default function read_expression(parser, opening_token, disallow_loose) {
|
|
36
36
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const node = parse_expression_at(
|
|
40
|
-
parser.template,
|
|
41
|
-
parser.root.comments,
|
|
42
|
-
parser.ts,
|
|
43
|
-
parser.index
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
let num_parens = 0;
|
|
47
|
-
|
|
48
|
-
let i = parser.root.comments.length;
|
|
49
|
-
while (i-- > comment_index) {
|
|
50
|
-
const comment = parser.root.comments[i];
|
|
51
|
-
if (comment.end < node.start) {
|
|
52
|
-
parser.index = comment.end;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
for (let i = parser.index; i < /** @type {number} */ (node.start); i += 1) {
|
|
58
|
-
if (parser.template[i] === '(') num_parens += 1;
|
|
59
|
-
}
|
|
37
|
+
const node = parse_expression_at(parser, parser.template, parser.index);
|
|
60
38
|
|
|
61
39
|
let index = /** @type {number} */ (node.end);
|
|
62
40
|
|
|
63
41
|
const last_comment = parser.root.comments.at(-1);
|
|
64
42
|
if (last_comment && last_comment.end > index) index = last_comment.end;
|
|
65
43
|
|
|
66
|
-
while (num_parens > 0) {
|
|
67
|
-
const char = parser.template[index];
|
|
68
|
-
|
|
69
|
-
if (char === ')') {
|
|
70
|
-
num_parens -= 1;
|
|
71
|
-
} else if (!regex_whitespace.test(char)) {
|
|
72
|
-
e.expected_token(index, ')');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
index += 1;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
44
|
parser.index = index;
|
|
79
45
|
|
|
80
|
-
return /** @type {Expression} */ (node);
|
|
46
|
+
return /** @type {Expression} */ (remove_parens(node));
|
|
81
47
|
} catch (err) {
|
|
82
48
|
// If we are in an each loop we need the error to be thrown in cases like
|
|
83
49
|
// `as { y = z }` so we still throw and handle the error there
|
|
@@ -88,6 +54,6 @@ export default function read_expression(parser, opening_token, disallow_loose) {
|
|
|
88
54
|
}
|
|
89
55
|
}
|
|
90
56
|
|
|
91
|
-
|
|
57
|
+
throw err;
|
|
92
58
|
}
|
|
93
59
|
}
|
|
@@ -31,14 +31,7 @@ export function read_script(parser, start, attributes) {
|
|
|
31
31
|
parser.template.slice(0, script_start).replace(regex_not_newline_characters, ' ') + data;
|
|
32
32
|
parser.read(regex_starts_with_closing_script_tag);
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
let ast;
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
ast = acorn.parse(source, parser.root.comments, parser.ts, true);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
parser.acorn_error(err);
|
|
41
|
-
}
|
|
34
|
+
const ast = acorn.parse(source, parser.root.comments, parser.ts, true);
|
|
42
35
|
|
|
43
36
|
ast.start = script_start;
|
|
44
37
|
|
|
@@ -392,12 +392,7 @@ function open(parser) {
|
|
|
392
392
|
|
|
393
393
|
let function_expression = matched
|
|
394
394
|
? /** @type {ArrowFunctionExpression} */ (
|
|
395
|
-
parse_expression_at(
|
|
396
|
-
prelude + `${params} => {}`,
|
|
397
|
-
parser.root.comments,
|
|
398
|
-
parser.ts,
|
|
399
|
-
params_start
|
|
400
|
-
)
|
|
395
|
+
parse_expression_at(parser, prelude + `${params} => {}`, params_start)
|
|
401
396
|
)
|
|
402
397
|
: { params: [] };
|
|
403
398
|
|
|
@@ -10,7 +10,7 @@ export function visit_function(node, context) {
|
|
|
10
10
|
for (const [name] of context.state.scope.references) {
|
|
11
11
|
const binding = context.state.scope.get(name);
|
|
12
12
|
|
|
13
|
-
if (binding && binding.scope
|
|
13
|
+
if (binding && binding.scope !== context.state.scope) {
|
|
14
14
|
context.state.expression.references.add(binding);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -352,7 +352,7 @@ export function client_component(analysis, options) {
|
|
|
352
352
|
)
|
|
353
353
|
);
|
|
354
354
|
} else if (dev) {
|
|
355
|
-
component_returned_object.
|
|
355
|
+
component_returned_object.unshift(b.spread(b.call(b.id('$.legacy_api'))));
|
|
356
356
|
}
|
|
357
357
|
|
|
358
358
|
const push_args = [b.id('$$props'), b.literal(analysis.runes)];
|
|
@@ -42,6 +42,7 @@ import { DEV } from 'esm-env';
|
|
|
42
42
|
import { derived_safe_equal } from '../../reactivity/deriveds.js';
|
|
43
43
|
import { current_batch } from '../../reactivity/batch.js';
|
|
44
44
|
import * as e from '../../errors.js';
|
|
45
|
+
import { tag } from '../../dev/tracing.js';
|
|
45
46
|
|
|
46
47
|
// When making substantive changes to this file, validate them with the each block stress test:
|
|
47
48
|
// https://svelte.dev/playground/1972b2cf46564476ad8c8c6405b23b7b
|
|
@@ -205,6 +206,10 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
205
206
|
return is_array(collection) ? collection : collection == null ? [] : array_from(collection);
|
|
206
207
|
});
|
|
207
208
|
|
|
209
|
+
if (DEV) {
|
|
210
|
+
tag(each_array, '{#each ...}');
|
|
211
|
+
}
|
|
212
|
+
|
|
208
213
|
/** @type {V[]} */
|
|
209
214
|
var array;
|
|
210
215
|
|
|
@@ -172,6 +172,12 @@ export class Batch {
|
|
|
172
172
|
*/
|
|
173
173
|
#skipped_branches = new Map();
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Inverse of #skipped_branches which we need to tell prior batches to unskip them when committing
|
|
177
|
+
* @type {Set<Effect>}
|
|
178
|
+
*/
|
|
179
|
+
#unskipped_branches = new Set();
|
|
180
|
+
|
|
175
181
|
is_fork = false;
|
|
176
182
|
|
|
177
183
|
#decrement_queued = false;
|
|
@@ -215,28 +221,31 @@ export class Batch {
|
|
|
215
221
|
if (!this.#skipped_branches.has(effect)) {
|
|
216
222
|
this.#skipped_branches.set(effect, { d: [], m: [] });
|
|
217
223
|
}
|
|
224
|
+
this.#unskipped_branches.delete(effect);
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
/**
|
|
221
228
|
* Remove an effect from the #skipped_branches map and reschedule
|
|
222
229
|
* any tracked dirty/maybe_dirty child effects
|
|
223
230
|
* @param {Effect} effect
|
|
231
|
+
* @param {(e: Effect) => void} callback
|
|
224
232
|
*/
|
|
225
|
-
unskip_effect(effect) {
|
|
233
|
+
unskip_effect(effect, callback = (e) => this.schedule(e)) {
|
|
226
234
|
var tracked = this.#skipped_branches.get(effect);
|
|
227
235
|
if (tracked) {
|
|
228
236
|
this.#skipped_branches.delete(effect);
|
|
229
237
|
|
|
230
238
|
for (var e of tracked.d) {
|
|
231
239
|
set_signal_status(e, DIRTY);
|
|
232
|
-
|
|
240
|
+
callback(e);
|
|
233
241
|
}
|
|
234
242
|
|
|
235
243
|
for (e of tracked.m) {
|
|
236
244
|
set_signal_status(e, MAYBE_DIRTY);
|
|
237
|
-
|
|
245
|
+
callback(e);
|
|
238
246
|
}
|
|
239
247
|
}
|
|
248
|
+
this.#unskipped_branches.add(effect);
|
|
240
249
|
}
|
|
241
250
|
|
|
242
251
|
#process() {
|
|
@@ -349,7 +358,9 @@ export class Batch {
|
|
|
349
358
|
next_batch.#process();
|
|
350
359
|
}
|
|
351
360
|
|
|
352
|
-
|
|
361
|
+
// In sync mode flushSync can cause #commit to wrongfully think that there needs to be a rebase, so we only do it in async mode
|
|
362
|
+
// TODO fix the underlying cause, otherwise this will likely regress when non-async mode is removed
|
|
363
|
+
if (async_mode_flag && !batches.has(this)) {
|
|
353
364
|
this.#commit();
|
|
354
365
|
}
|
|
355
366
|
}
|
|
@@ -419,18 +430,22 @@ export class Batch {
|
|
|
419
430
|
* Associate a change to a given source with the current
|
|
420
431
|
* batch, noting its previous and current values
|
|
421
432
|
* @param {Value} source
|
|
422
|
-
* @param {any}
|
|
433
|
+
* @param {any} value
|
|
423
434
|
* @param {boolean} [is_derived]
|
|
424
435
|
*/
|
|
425
|
-
capture(source,
|
|
426
|
-
if (
|
|
427
|
-
this.previous.set(source,
|
|
436
|
+
capture(source, value, is_derived = false) {
|
|
437
|
+
if (source.v !== UNINITIALIZED && !this.previous.has(source)) {
|
|
438
|
+
this.previous.set(source, source.v);
|
|
428
439
|
}
|
|
429
440
|
|
|
430
441
|
// Don't save errors in `batch_values`, or they won't be thrown in `runtime.js#get`
|
|
431
442
|
if ((source.f & ERROR_VALUE) === 0) {
|
|
432
|
-
this.current.set(source, [
|
|
433
|
-
batch_values?.set(source,
|
|
443
|
+
this.current.set(source, [value, is_derived]);
|
|
444
|
+
batch_values?.set(source, value);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (!this.is_fork) {
|
|
448
|
+
source.v = value;
|
|
434
449
|
}
|
|
435
450
|
}
|
|
436
451
|
|
|
@@ -526,6 +541,19 @@ export class Batch {
|
|
|
526
541
|
invariant(batch.#roots.length === 0, 'Batch has scheduled roots');
|
|
527
542
|
}
|
|
528
543
|
|
|
544
|
+
// A batch was unskipped in a later batch -> tell prior batches to unskip it, too
|
|
545
|
+
if (is_earlier) {
|
|
546
|
+
for (const unskipped of this.#unskipped_branches) {
|
|
547
|
+
batch.unskip_effect(unskipped, (e) => {
|
|
548
|
+
if ((e.f & (BLOCK_EFFECT | ASYNC)) !== 0) {
|
|
549
|
+
batch.schedule(e);
|
|
550
|
+
} else {
|
|
551
|
+
batch.#defer_effects([e]);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
529
557
|
batch.activate();
|
|
530
558
|
|
|
531
559
|
/** @type {Set<Value>} */
|
|
@@ -787,6 +815,7 @@ export class Batch {
|
|
|
787
815
|
}
|
|
788
816
|
}
|
|
789
817
|
|
|
818
|
+
// TODO Svelte@6 think about removing the callback argument.
|
|
790
819
|
/**
|
|
791
820
|
* Synchronously flush any pending updates.
|
|
792
821
|
* Returns void if no callback is provided, otherwise returns the result of calling the callback.
|
|
@@ -1162,11 +1191,6 @@ export function fork(fn) {
|
|
|
1162
1191
|
|
|
1163
1192
|
flushSync(fn);
|
|
1164
1193
|
|
|
1165
|
-
// revert state changes
|
|
1166
|
-
for (var [source, value] of batch.previous) {
|
|
1167
|
-
source.v = value;
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
1194
|
return {
|
|
1171
1195
|
commit: async () => {
|
|
1172
1196
|
if (committed) {
|
|
@@ -384,7 +384,6 @@ export function execute_derived(derived) {
|
|
|
384
384
|
* @returns {void}
|
|
385
385
|
*/
|
|
386
386
|
export function update_derived(derived) {
|
|
387
|
-
var old_value = derived.v;
|
|
388
387
|
var value = execute_derived(derived);
|
|
389
388
|
|
|
390
389
|
if (!derived.equals(value)) {
|
|
@@ -395,8 +394,11 @@ export function update_derived(derived) {
|
|
|
395
394
|
// otherwise, the next time we get here after a 'real world' state
|
|
396
395
|
// change, `derived.equals` may incorrectly return `true`
|
|
397
396
|
if (!current_batch?.is_fork || derived.deps === null) {
|
|
398
|
-
|
|
399
|
-
|
|
397
|
+
if (current_batch !== null) {
|
|
398
|
+
current_batch.capture(derived, value, true);
|
|
399
|
+
} else {
|
|
400
|
+
derived.v = value;
|
|
401
|
+
}
|
|
400
402
|
|
|
401
403
|
// deriveds without dependencies should never be recomputed
|
|
402
404
|
if (derived.deps === null) {
|
|
@@ -180,18 +180,10 @@ export function set(source, value, should_proxy = false) {
|
|
|
180
180
|
*/
|
|
181
181
|
export function internal_set(source, value, updated_during_traversal = null) {
|
|
182
182
|
if (!source.equals(value)) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (is_destroying_effect) {
|
|
186
|
-
old_values.set(source, value);
|
|
187
|
-
} else {
|
|
188
|
-
old_values.set(source, old_value);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
source.v = value;
|
|
183
|
+
old_values.set(source, is_destroying_effect ? value : source.v);
|
|
192
184
|
|
|
193
185
|
var batch = Batch.ensure();
|
|
194
|
-
batch.capture(source,
|
|
186
|
+
batch.capture(source, value);
|
|
195
187
|
|
|
196
188
|
if (DEV) {
|
|
197
189
|
if (tracing_mode_flag || active_effect !== null) {
|
|
@@ -399,7 +399,14 @@ function remove_reaction(signal, dependency) {
|
|
|
399
399
|
derived.f &= ~WAS_MARKED;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
// In a fork it's possible that a derived is executed and gets reactions, then commits, but is
|
|
403
|
+
// never re-executed. This is possible when the derived is only executed once in the context
|
|
404
|
+
// of a new branch which happens before fork.commit() runs. In this case, the derived still has
|
|
405
|
+
// UNINITIALIZED as its value, and then when it's loosing its reactions we need to ensure it stays
|
|
406
|
+
// DIRTY so it is reexecuted once someone wants its value again.
|
|
407
|
+
if (derived.v !== UNINITIALIZED) {
|
|
408
|
+
update_derived_status(derived);
|
|
409
|
+
}
|
|
403
410
|
|
|
404
411
|
// freeze any effects inside this derived
|
|
405
412
|
freeze_derived_effects(derived);
|
|
@@ -105,6 +105,18 @@ export function invalid_csp() {
|
|
|
105
105
|
throw error;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/**
|
|
109
|
+
* The `idPrefix` option cannot include `--`.
|
|
110
|
+
* @returns {never}
|
|
111
|
+
*/
|
|
112
|
+
export function invalid_id_prefix() {
|
|
113
|
+
const error = new Error(`invalid_id_prefix\nThe \`idPrefix\` option cannot include \`--\`.\nhttps://svelte.dev/e/invalid_id_prefix`);
|
|
114
|
+
|
|
115
|
+
error.name = 'Svelte error';
|
|
116
|
+
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
|
|
108
120
|
/**
|
|
109
121
|
* `%name%(...)` is not available on the server
|
|
110
122
|
* @param {string} name
|
package/src/reactivity/date.js
CHANGED
package/src/version.js
CHANGED