svelte 5.41.3 → 5.42.0

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 (38) hide show
  1. package/compiler/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/compiler/phases/2-analyze/index.js +1 -1
  4. package/src/compiler/phases/2-analyze/visitors/Attribute.js +5 -183
  5. package/src/compiler/phases/2-analyze/visitors/shared/function.js +0 -7
  6. package/src/compiler/phases/3-transform/client/utils.js +2 -124
  7. package/src/compiler/phases/3-transform/client/visitors/FunctionDeclaration.js +0 -11
  8. package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +0 -18
  9. package/src/compiler/phases/3-transform/client/visitors/shared/events.js +1 -29
  10. package/src/compiler/phases/3-transform/client/visitors/shared/function.js +0 -13
  11. package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +2 -2
  12. package/src/compiler/phases/3-transform/utils.js +0 -19
  13. package/src/compiler/phases/nodes.js +1 -1
  14. package/src/compiler/utils/ast.js +8 -4
  15. package/src/compiler/utils/builders.js +5 -8
  16. package/src/index-client.js +1 -1
  17. package/src/index-server.js +4 -0
  18. package/src/internal/client/constants.js +6 -2
  19. package/src/internal/client/context.js +8 -1
  20. package/src/internal/client/dev/inspect.js +12 -3
  21. package/src/internal/client/dev/tracing.js +1 -2
  22. package/src/internal/client/dom/blocks/boundary.js +29 -3
  23. package/src/internal/client/dom/blocks/branches.js +18 -3
  24. package/src/internal/client/dom/blocks/each.js +1 -1
  25. package/src/internal/client/dom/elements/attributes.js +2 -2
  26. package/src/internal/client/dom/elements/events.js +2 -7
  27. package/src/internal/client/error-handling.js +2 -2
  28. package/src/internal/client/errors.js +48 -0
  29. package/src/internal/client/proxy.js +5 -5
  30. package/src/internal/client/reactivity/batch.js +160 -22
  31. package/src/internal/client/reactivity/deriveds.js +5 -5
  32. package/src/internal/client/reactivity/effects.js +13 -5
  33. package/src/internal/client/reactivity/sources.js +19 -19
  34. package/src/internal/client/runtime.js +2 -2
  35. package/src/utils.js +1 -1
  36. package/src/version.js +1 -1
  37. package/types/index.d.ts +39 -5
  38. package/types/index.d.ts.map +5 -3
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.41.3",
5
+ "version": "5.42.0",
6
6
  "type": "module",
7
7
  "types": "./types/index.d.ts",
8
8
  "engines": {
@@ -6,7 +6,7 @@ import { walk } from 'zimmerframe';
6
6
  import { parse } from '../1-parse/acorn.js';
7
7
  import * as e from '../../errors.js';
8
8
  import * as w from '../../warnings.js';
9
- import { extract_identifiers } from '../../utils/ast.js';
9
+ import { extract_identifiers, has_await_expression } from '../../utils/ast.js';
10
10
  import * as b from '#compiler/builders';
11
11
  import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js';
12
12
  import check_graph_for_cycles from './utils/check_graph_for_cycles.js';
@@ -1,12 +1,7 @@
1
- /** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression } from 'estree' */
2
- /** @import { AST, DelegatedEvent } from '#compiler' */
1
+ /** @import { AST } from '#compiler' */
3
2
  /** @import { Context } from '../types' */
4
- import { cannot_be_set_statically, is_capture_event, is_delegated } from '../../../../utils.js';
5
- import {
6
- get_attribute_chunks,
7
- get_attribute_expression,
8
- is_event_attribute
9
- } from '../../../utils/ast.js';
3
+ import { cannot_be_set_statically, can_delegate_event } from '../../../../utils.js';
4
+ import { get_attribute_chunks, is_event_attribute } from '../../../utils/ast.js';
10
5
  import { mark_subtree_dynamic } from './shared/fragment.js';
11
6
 
12
7
  /**
@@ -64,181 +59,8 @@ export function Attribute(node, context) {
64
59
  context.state.analysis.uses_event_attributes = true;
65
60
  }
66
61
 
67
- const expression = get_attribute_expression(node);
68
- const delegated_event = get_delegated_event(node.name.slice(2), expression, context);
69
-
70
- if (delegated_event !== null) {
71
- if (delegated_event.hoisted) {
72
- delegated_event.function.metadata.hoisted = true;
73
- }
74
-
75
- node.metadata.delegated = delegated_event;
76
- }
77
- }
78
- }
79
- }
80
-
81
- /** @type {DelegatedEvent} */
82
- const unhoisted = { hoisted: false };
83
-
84
- /**
85
- * Checks if given event attribute can be delegated/hoisted and returns the corresponding info if so
86
- * @param {string} event_name
87
- * @param {Expression | null} handler
88
- * @param {Context} context
89
- * @returns {null | DelegatedEvent}
90
- */
91
- function get_delegated_event(event_name, handler, context) {
92
- // Handle delegated event handlers. Bail out if not a delegated event.
93
- if (!handler || !is_delegated(event_name)) {
94
- return null;
95
- }
96
-
97
- // If we are not working with a RegularElement, then bail out.
98
- const element = context.path.at(-1);
99
- if (element?.type !== 'RegularElement') {
100
- return null;
101
- }
102
-
103
- /** @type {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression | null} */
104
- let target_function = null;
105
- let binding = null;
106
-
107
- if (element.metadata.has_spread) {
108
- // event attribute becomes part of the dynamic spread array
109
- return unhoisted;
110
- }
111
-
112
- if (handler.type === 'ArrowFunctionExpression' || handler.type === 'FunctionExpression') {
113
- target_function = handler;
114
- } else if (handler.type === 'Identifier') {
115
- binding = context.state.scope.get(handler.name);
116
-
117
- if (context.state.analysis.module.scope.references.has(handler.name)) {
118
- // If a binding with the same name is referenced in the module scope (even if not declared there), bail out
119
- return unhoisted;
120
- }
121
-
122
- if (binding != null) {
123
- for (const { path } of binding.references) {
124
- const parent = path.at(-1);
125
- if (parent === undefined) return unhoisted;
126
-
127
- const grandparent = path.at(-2);
128
-
129
- /** @type {AST.RegularElement | null} */
130
- let element = null;
131
- /** @type {string | null} */
132
- let event_name = null;
133
- if (parent.type === 'OnDirective') {
134
- element = /** @type {AST.RegularElement} */ (grandparent);
135
- event_name = parent.name;
136
- } else if (
137
- parent.type === 'ExpressionTag' &&
138
- grandparent?.type === 'Attribute' &&
139
- is_event_attribute(grandparent)
140
- ) {
141
- element = /** @type {AST.RegularElement} */ (path.at(-3));
142
- const attribute = /** @type {AST.Attribute} */ (grandparent);
143
- event_name = get_attribute_event_name(attribute.name);
144
- }
145
-
146
- if (element && event_name) {
147
- if (
148
- element.type !== 'RegularElement' ||
149
- element.metadata.has_spread ||
150
- !is_delegated(event_name)
151
- ) {
152
- return unhoisted;
153
- }
154
- } else if (parent.type !== 'FunctionDeclaration' && parent.type !== 'VariableDeclarator') {
155
- return unhoisted;
156
- }
157
- }
62
+ node.metadata.delegated =
63
+ parent?.type === 'RegularElement' && can_delegate_event(node.name.slice(2));
158
64
  }
159
-
160
- // If the binding is exported, bail out
161
- if (context.state.analysis.exports.find((node) => node.name === handler.name)) {
162
- return unhoisted;
163
- }
164
-
165
- if (binding?.is_function()) {
166
- target_function = binding.initial;
167
- }
168
- }
169
-
170
- // If we can't find a function, or the function has multiple parameters, bail out
171
- if (target_function == null || target_function.params.length > 1) {
172
- return unhoisted;
173
- }
174
-
175
- const visited_references = new Set();
176
- const scope = target_function.metadata.scope;
177
- for (const [reference] of scope.references) {
178
- // Bail out if the arguments keyword is used or $host is referenced
179
- if (reference === 'arguments' || reference === '$host') return unhoisted;
180
- // Bail out if references a store subscription
181
- if (scope.get(`$${reference}`)?.kind === 'store_sub') return unhoisted;
182
-
183
- const binding = scope.get(reference);
184
- const local_binding = context.state.scope.get(reference);
185
-
186
- // if the function access a snippet that can't be hoisted we bail out
187
- if (
188
- local_binding !== null &&
189
- local_binding.initial?.type === 'SnippetBlock' &&
190
- !local_binding.initial.metadata.can_hoist
191
- ) {
192
- return unhoisted;
193
- }
194
-
195
- // If we are referencing a binding that is shadowed in another scope then bail out (unless it's declared within the function).
196
- if (
197
- local_binding !== null &&
198
- binding !== null &&
199
- local_binding.node !== binding.node &&
200
- scope.declarations.get(reference) !== binding
201
- ) {
202
- return unhoisted;
203
- }
204
-
205
- // If we have multiple references to the same store using $ prefix, bail out.
206
- if (
207
- binding !== null &&
208
- binding.kind === 'store_sub' &&
209
- visited_references.has(reference.slice(1))
210
- ) {
211
- return unhoisted;
212
- }
213
-
214
- // If we reference the index within an each block, then bail out.
215
- if (binding !== null && binding.initial?.type === 'EachBlock') return unhoisted;
216
-
217
- if (
218
- binding !== null &&
219
- // Bail out if the binding is a rest param
220
- (binding.declaration_kind === 'rest_param' ||
221
- // Bail out if we reference anything from the EachBlock (for now) that mutates in non-runes mode,
222
- (((!context.state.analysis.runes && binding.kind === 'each') ||
223
- // or any normal not reactive bindings that are mutated.
224
- binding.kind === 'normal') &&
225
- binding.updated))
226
- ) {
227
- return unhoisted;
228
- }
229
- visited_references.add(reference);
230
- }
231
-
232
- return { hoisted: true, function: target_function };
233
- }
234
-
235
- /**
236
- * @param {string} event_name
237
- */
238
- function get_attribute_event_name(event_name) {
239
- event_name = event_name.slice(2);
240
- if (is_capture_event(event_name)) {
241
- event_name = event_name.slice(0, -7);
242
65
  }
243
- return event_name;
244
66
  }
@@ -6,13 +6,6 @@
6
6
  * @param {Context} context
7
7
  */
8
8
  export function visit_function(node, context) {
9
- // TODO retire this in favour of a more general solution based on bindings
10
- node.metadata = {
11
- hoisted: false,
12
- hoisted_params: [],
13
- scope: context.state.scope
14
- };
15
-
16
9
  if (context.state.expression) {
17
10
  for (const [name] of context.state.scope.references) {
18
11
  const binding = context.state.scope.get(name);
@@ -1,6 +1,6 @@
1
- /** @import { ArrowFunctionExpression, AssignmentExpression, BlockStatement, Expression, FunctionDeclaration, FunctionExpression, Identifier, Node, Pattern, UpdateExpression } from 'estree' */
1
+ /** @import { BlockStatement, Expression, Identifier } from 'estree' */
2
2
  /** @import { Binding } from '#compiler' */
3
- /** @import { ClientTransformState, ComponentClientTransformState, ComponentContext } from './types.js' */
3
+ /** @import { ClientTransformState, ComponentClientTransformState } from './types.js' */
4
4
  /** @import { Analysis } from '../../types.js' */
5
5
  /** @import { Scope } from '../../scope.js' */
6
6
  import * as b from '#compiler/builders';
@@ -12,9 +12,6 @@ import {
12
12
  PROPS_IS_UPDATED,
13
13
  PROPS_IS_BINDABLE
14
14
  } from '../../../../constants.js';
15
- import { dev } from '../../../state.js';
16
- import { walk } from 'zimmerframe';
17
- import { validate_mutation } from './visitors/shared/utils.js';
18
15
 
19
16
  /**
20
17
  * @param {Binding} binding
@@ -46,125 +43,6 @@ export function build_getter(node, state) {
46
43
  return node;
47
44
  }
48
45
 
49
- /**
50
- * @param {FunctionDeclaration | FunctionExpression | ArrowFunctionExpression} node
51
- * @param {ComponentContext} context
52
- * @returns {Pattern[]}
53
- */
54
- function get_hoisted_params(node, context) {
55
- const scope = context.state.scope;
56
-
57
- /** @type {Identifier[]} */
58
- const params = [];
59
-
60
- /**
61
- * We only want to push if it's not already present to avoid name clashing
62
- * @param {Identifier} id
63
- */
64
- function push_unique(id) {
65
- if (!params.find((param) => param.name === id.name)) {
66
- params.push(id);
67
- }
68
- }
69
-
70
- for (const [reference] of scope.references) {
71
- let binding = scope.get(reference);
72
-
73
- if (binding !== null && !scope.declarations.has(reference) && binding.initial !== node) {
74
- if (binding.kind === 'store_sub') {
75
- // We need both the subscription for getting the value and the store for updating
76
- push_unique(b.id(binding.node.name));
77
- binding = /** @type {Binding} */ (scope.get(binding.node.name.slice(1)));
78
- }
79
-
80
- let expression = context.state.transform[reference]?.read(b.id(binding.node.name));
81
-
82
- if (
83
- // If it's a destructured derived binding, then we can extract the derived signal reference and use that.
84
- // TODO this code is bad, we need to kill it
85
- expression != null &&
86
- typeof expression !== 'function' &&
87
- expression.type === 'MemberExpression' &&
88
- expression.object.type === 'CallExpression' &&
89
- expression.object.callee.type === 'Identifier' &&
90
- expression.object.callee.name === '$.get' &&
91
- expression.object.arguments[0].type === 'Identifier'
92
- ) {
93
- push_unique(b.id(expression.object.arguments[0].name));
94
- } else if (
95
- // If we are referencing a simple $$props value, then we need to reference the object property instead
96
- (binding.kind === 'prop' || binding.kind === 'bindable_prop') &&
97
- !is_prop_source(binding, context.state)
98
- ) {
99
- push_unique(b.id('$$props'));
100
- } else if (
101
- // imports don't need to be hoisted
102
- binding.declaration_kind !== 'import'
103
- ) {
104
- // create a copy to remove start/end tags which would mess up source maps
105
- push_unique(b.id(binding.node.name));
106
- // rest props are often accessed through the $$props object for optimization reasons,
107
- // but we can't know if the delegated event handler will use it, so we need to add both as params
108
- if (binding.kind === 'rest_prop' && context.state.analysis.runes) {
109
- push_unique(b.id('$$props'));
110
- }
111
- }
112
- }
113
- }
114
-
115
- if (dev) {
116
- // this is a little hacky, but necessary for ownership validation
117
- // to work inside hoisted event handlers
118
-
119
- /**
120
- * @param {AssignmentExpression | UpdateExpression} node
121
- * @param {{ next: () => void, stop: () => void }} context
122
- */
123
- function visit(node, { next, stop }) {
124
- if (validate_mutation(node, /** @type {any} */ (context), node) !== node) {
125
- params.push(b.id('$$ownership_validator'));
126
- stop();
127
- } else {
128
- next();
129
- }
130
- }
131
-
132
- walk(/** @type {Node} */ (node), null, {
133
- AssignmentExpression: visit,
134
- UpdateExpression: visit
135
- });
136
- }
137
-
138
- return params;
139
- }
140
-
141
- /**
142
- * @param {FunctionDeclaration | FunctionExpression | ArrowFunctionExpression} node
143
- * @param {ComponentContext} context
144
- * @returns {Pattern[]}
145
- */
146
- export function build_hoisted_params(node, context) {
147
- const hoisted_params = get_hoisted_params(node, context);
148
- node.metadata.hoisted_params = hoisted_params;
149
-
150
- /** @type {Pattern[]} */
151
- const params = [];
152
-
153
- if (node.params.length === 0) {
154
- if (hoisted_params.length > 0) {
155
- // For the event object
156
- params.push(b.id(context.state.scope.generate('_')));
157
- }
158
- } else {
159
- for (const param of node.params) {
160
- params.push(/** @type {Pattern} */ (context.visit(param)));
161
- }
162
- }
163
-
164
- params.push(...hoisted_params);
165
- return params;
166
- }
167
-
168
46
  /**
169
47
  * @param {Binding} binding
170
48
  * @param {ComponentClientTransformState} state
@@ -1,7 +1,5 @@
1
1
  /** @import { FunctionDeclaration } from 'estree' */
2
2
  /** @import { ComponentContext } from '../types' */
3
- import { build_hoisted_params } from '../utils.js';
4
- import * as b from '#compiler/builders';
5
3
 
6
4
  /**
7
5
  * @param {FunctionDeclaration} node
@@ -10,14 +8,5 @@ import * as b from '#compiler/builders';
10
8
  export function FunctionDeclaration(node, context) {
11
9
  const state = { ...context.state, in_constructor: false, in_derived: false };
12
10
 
13
- if (node.metadata?.hoisted === true) {
14
- const params = build_hoisted_params(node, context);
15
- const body = context.visit(node.body, state);
16
-
17
- context.state.hoisted.push(/** @type {FunctionDeclaration} */ ({ ...node, params, body }));
18
-
19
- return b.empty;
20
- }
21
-
22
11
  context.next(state);
23
12
  }
@@ -7,7 +7,6 @@ import * as b from '#compiler/builders';
7
7
  import * as assert from '../../../../utils/assert.js';
8
8
  import { get_rune } from '../../../scope.js';
9
9
  import { get_prop_source, is_prop_source, is_state_source, should_proxy } from '../utils.js';
10
- import { is_hoisted_function } from '../../utils.js';
11
10
  import { get_value } from './shared/declarations.js';
12
11
 
13
12
  /**
@@ -32,13 +31,6 @@ export function VariableDeclaration(node, context) {
32
31
  rune === '$state.snapshot' ||
33
32
  rune === '$host'
34
33
  ) {
35
- if (init != null && is_hoisted_function(init)) {
36
- context.state.hoisted.push(
37
- b.const(declarator.id, /** @type {Expression} */ (context.visit(init)))
38
- );
39
-
40
- continue;
41
- }
42
34
  declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator)));
43
35
  continue;
44
36
  }
@@ -295,16 +287,6 @@ export function VariableDeclaration(node, context) {
295
287
  const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');
296
288
 
297
289
  if (!has_state && !has_props) {
298
- const init = declarator.init;
299
-
300
- if (init != null && is_hoisted_function(init)) {
301
- context.state.hoisted.push(
302
- b.const(declarator.id, /** @type {Expression} */ (context.visit(init)))
303
- );
304
-
305
- continue;
306
- }
307
-
308
290
  declarations.push(/** @type {VariableDeclarator} */ (context.visit(declarator)));
309
291
  continue;
310
292
  }
@@ -26,40 +26,12 @@ export function visit_event_attribute(node, context) {
26
26
  let handler = build_event_handler(tag.expression, tag.metadata.expression, context);
27
27
 
28
28
  if (node.metadata.delegated) {
29
- let delegated_assignment;
30
-
31
29
  if (!context.state.events.has(event_name)) {
32
30
  context.state.events.add(event_name);
33
31
  }
34
32
 
35
- // Hoist function if we can, otherwise we leave the function as is
36
- if (node.metadata.delegated.hoisted) {
37
- if (node.metadata.delegated.function === tag.expression) {
38
- const func_name = context.state.scope.root.unique('on_' + event_name);
39
- context.state.hoisted.push(b.var(func_name, handler));
40
- handler = func_name;
41
- }
42
-
43
- const hoisted_params = /** @type {Expression[]} */ (
44
- node.metadata.delegated.function.metadata.hoisted_params
45
- );
46
-
47
- // When we hoist a function we assign an array with the function and all
48
- // hoisted closure params.
49
- if (hoisted_params) {
50
- const args = [handler, ...hoisted_params];
51
- delegated_assignment = b.array(args);
52
- } else {
53
- delegated_assignment = handler;
54
- }
55
- } else {
56
- delegated_assignment = handler;
57
- }
58
-
59
33
  context.state.init.push(
60
- b.stmt(
61
- b.assignment('=', b.member(context.state.node, '__' + event_name), delegated_assignment)
62
- )
34
+ b.stmt(b.assignment('=', b.member(context.state.node, '__' + event_name), handler))
63
35
  );
64
36
  } else {
65
37
  const statement = b.stmt(
@@ -1,14 +1,11 @@
1
1
  /** @import { ArrowFunctionExpression, FunctionExpression, Node } from 'estree' */
2
2
  /** @import { ComponentContext } from '../../types' */
3
- import { build_hoisted_params } from '../../utils.js';
4
3
 
5
4
  /**
6
5
  * @param {ArrowFunctionExpression | FunctionExpression} node
7
6
  * @param {ComponentContext} context
8
7
  */
9
8
  export const visit_function = (node, context) => {
10
- const metadata = node.metadata;
11
-
12
9
  let state = { ...context.state, in_constructor: false, in_derived: false };
13
10
 
14
11
  if (node.type === 'FunctionExpression') {
@@ -16,15 +13,5 @@ export const visit_function = (node, context) => {
16
13
  state.in_constructor = parent.type === 'MethodDefinition' && parent.kind === 'constructor';
17
14
  }
18
15
 
19
- if (metadata?.hoisted === true) {
20
- const params = build_hoisted_params(node, context);
21
-
22
- return /** @type {FunctionExpression} */ ({
23
- ...node,
24
- params,
25
- body: context.visit(node.body, state)
26
- });
27
- }
28
-
29
16
  context.next(state);
30
17
  };
@@ -12,7 +12,7 @@ import {
12
12
  import * as b from '#compiler/builders';
13
13
  import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
14
14
  import { regex_whitespaces_strict } from '../../../../patterns.js';
15
- import { has_await } from '../../../../../utils/ast.js';
15
+ import { has_await_expression } from '../../../../../utils/ast.js';
16
16
 
17
17
  /** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
18
18
  export const block_open = b.literal(BLOCK_OPEN);
@@ -315,7 +315,7 @@ export class PromiseOptimiser {
315
315
 
316
316
  const promises = b.array(
317
317
  this.expressions.map((expression) => {
318
- return expression.type === 'AwaitExpression' && !has_await(expression.argument)
318
+ return expression.type === 'AwaitExpression' && !has_await_expression(expression.argument)
319
319
  ? expression.argument
320
320
  : b.call(b.thunk(expression, true));
321
321
  })
@@ -1,36 +1,17 @@
1
- /** @import { Context } from 'zimmerframe' */
2
1
  /** @import { TransformState } from './types.js' */
3
2
  /** @import { AST, Binding, Namespace, ValidatedCompileOptions } from '#compiler' */
4
3
  /** @import { Node, Expression, CallExpression, MemberExpression } from 'estree' */
5
4
  import {
6
5
  regex_ends_with_whitespaces,
7
6
  regex_not_whitespace,
8
- regex_starts_with_newline,
9
7
  regex_starts_with_whitespaces
10
8
  } from '../patterns.js';
11
- import * as b from '#compiler/builders';
12
9
  import * as e from '../../errors.js';
13
10
  import { walk } from 'zimmerframe';
14
11
  import { extract_identifiers } from '../../utils/ast.js';
15
12
  import check_graph_for_cycles from '../2-analyze/utils/check_graph_for_cycles.js';
16
13
  import is_reference from 'is-reference';
17
14
  import { set_scope } from '../scope.js';
18
- import { dev } from '../../state.js';
19
-
20
- /**
21
- * @param {Node} node
22
- * @returns {boolean}
23
- */
24
- export function is_hoisted_function(node) {
25
- if (
26
- node.type === 'ArrowFunctionExpression' ||
27
- node.type === 'FunctionExpression' ||
28
- node.type === 'FunctionDeclaration'
29
- ) {
30
- return node.metadata?.hoisted === true;
31
- }
32
- return false;
33
- }
34
15
 
35
16
  /**
36
17
  * Match Svelte 4 behaviour by sorting ConstTag nodes in topological order
@@ -59,7 +59,7 @@ export function create_attribute(name, start, end, value) {
59
59
  name,
60
60
  value,
61
61
  metadata: {
62
- delegated: null,
62
+ delegated: false,
63
63
  needs_clsx: false
64
64
  }
65
65
  };
@@ -611,16 +611,20 @@ export function build_assignment_value(operator, left, right) {
611
611
  }
612
612
 
613
613
  /**
614
- * @param {ESTree.Expression} expression
614
+ * @param {ESTree.Node} node
615
615
  */
616
- export function has_await(expression) {
616
+ export function has_await_expression(node) {
617
617
  let has_await = false;
618
618
 
619
- walk(expression, null, {
619
+ walk(node, null, {
620
620
  AwaitExpression(_node, context) {
621
621
  has_await = true;
622
622
  context.stop();
623
- }
623
+ },
624
+ // don't traverse into these
625
+ FunctionDeclaration() {},
626
+ FunctionExpression() {},
627
+ ArrowFunctionExpression() {}
624
628
  });
625
629
 
626
630
  return has_await;
@@ -2,7 +2,7 @@
2
2
  import { walk } from 'zimmerframe';
3
3
  import { regex_is_valid_identifier } from '../phases/patterns.js';
4
4
  import { sanitize_template_string } from './sanitize_template_string.js';
5
- import { has_await } from './ast.js';
5
+ import { has_await_expression } from './ast.js';
6
6
 
7
7
  /**
8
8
  * @param {Array<ESTree.Expression | ESTree.SpreadElement | null>} elements
@@ -42,8 +42,7 @@ export function arrow(params, body, async = false) {
42
42
  body,
43
43
  expression: body.type !== 'BlockStatement',
44
44
  generator: false,
45
- async,
46
- metadata: /** @type {any} */ (null) // should not be used by codegen
45
+ async
47
46
  };
48
47
  }
49
48
 
@@ -237,8 +236,7 @@ export function function_declaration(id, params, body, async = false) {
237
236
  params,
238
237
  body,
239
238
  generator: false,
240
- async,
241
- metadata: /** @type {any} */ (null) // should not be used by codegen
239
+ async
242
240
  };
243
241
  }
244
242
 
@@ -451,7 +449,7 @@ export function thunk(expression, async = false) {
451
449
  export function unthunk(expression) {
452
450
  // optimize `async () => await x()`, but not `async () => await x(await y)`
453
451
  if (expression.async && expression.body.type === 'AwaitExpression') {
454
- if (!has_await(expression.body.argument)) {
452
+ if (!has_await_expression(expression.body.argument)) {
455
453
  return unthunk(arrow(expression.params, expression.body.argument));
456
454
  }
457
455
  }
@@ -595,8 +593,7 @@ function function_builder(id, params, body, async = false) {
595
593
  params,
596
594
  body,
597
595
  generator: false,
598
- async,
599
- metadata: /** @type {any} */ (null) // should not be used by codegen
596
+ async
600
597
  };
601
598
  }
602
599
 
@@ -241,7 +241,7 @@ function init_update_callbacks(context) {
241
241
  return (l.u ??= { a: [], b: [], m: [] });
242
242
  }
243
243
 
244
- export { flushSync } from './internal/client/reactivity/batch.js';
244
+ export { flushSync, fork } from './internal/client/reactivity/batch.js';
245
245
  export {
246
246
  createContext,
247
247
  getContext,
@@ -33,6 +33,10 @@ export function unmount() {
33
33
  e.lifecycle_function_unavailable('unmount');
34
34
  }
35
35
 
36
+ export function fork() {
37
+ e.lifecycle_function_unavailable('fork');
38
+ }
39
+
36
40
  export async function tick() {}
37
41
 
38
42
  export async function settled() {}