Skip to content

Commit a34c233

Browse files
committed
skip the noop if known to be a function
1 parent 8f152de commit a34c233

File tree

4 files changed

+27
-13
lines changed

4 files changed

+27
-13
lines changed

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,17 @@ export function build_component(node, component_name, context, anchor = context.
258258
}
259259
}
260260
} else if (attribute.type === 'AttachTag') {
261+
const evaluated = context.state.scope.evaluate(attribute.expression);
262+
261263
let expression = /** @type {Expression} */ (context.visit(attribute.expression));
262264

263265
if (attribute.metadata.expression.has_state) {
264266
expression = b.arrow(
265267
[b.id('$$node')],
266-
b.call(b.call('$.safe_call', expression), b.id('$$node'))
268+
b.call(
269+
evaluated.is_function ? expression : b.logical('||', expression, b.id('$.noop')),
270+
b.id('$$node')
271+
)
267272
);
268273
}
269274

packages/svelte/src/compiler/phases/scope.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const UNKNOWN = Symbol('unknown');
2020
/** Includes `BigInt` */
2121
export const NUMBER = Symbol('number');
2222
export const STRING = Symbol('string');
23+
export const FUNCTION = Symbol('string');
2324

2425
/** @type {Record<string, [type: NUMBER | STRING | UNKNOWN, fn?: Function]>} */
2526
const globals = {
@@ -200,6 +201,13 @@ class Evaluation {
200201
*/
201202
is_number = true;
202203

204+
/**
205+
* True if the value is known to be a function
206+
* @readonly
207+
* @type {boolean}
208+
*/
209+
is_function = true;
210+
203211
/**
204212
* @readonly
205213
* @type {any}
@@ -209,7 +217,7 @@ class Evaluation {
209217
/**
210218
*
211219
* @param {Scope} scope
212-
* @param {Expression} expression
220+
* @param {Expression | FunctionDeclaration} expression
213221
* @param {Set<any>} values
214222
*/
215223
constructor(scope, expression, values) {
@@ -500,6 +508,13 @@ class Evaluation {
500508
break;
501509
}
502510

511+
case 'ArrowFunctionExpression':
512+
case 'FunctionExpression':
513+
case 'FunctionDeclaration': {
514+
this.values.add(FUNCTION);
515+
break;
516+
}
517+
503518
default: {
504519
this.values.add(UNKNOWN);
505520
}
@@ -516,6 +531,10 @@ class Evaluation {
516531
this.is_number = false;
517532
}
518533

534+
if (value !== FUNCTION) {
535+
this.is_function = false;
536+
}
537+
519538
if (value == null || value === UNKNOWN) {
520539
this.is_defined = false;
521540
}

packages/svelte/src/internal/client/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ export {
155155
} from './dom/operations.js';
156156
export { attr, clsx } from '../shared/attributes.js';
157157
export { snapshot } from '../shared/clone.js';
158-
export { noop, fallback, safe_call, to_array } from '../shared/utils.js';
158+
export { noop, fallback, to_array } from '../shared/utils.js';
159159
export {
160160
invalid_default_snippet,
161161
validate_dynamic_element_tag,

packages/svelte/src/internal/shared/utils.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,6 @@ export function fallback(value, fallback, lazy = false) {
8282
: value;
8383
}
8484

85-
/**
86-
* @param {*} value
87-
*/
88-
export function safe_call(value) {
89-
if (is_function(value)) {
90-
return value;
91-
}
92-
return noop;
93-
}
94-
9585
/**
9686
* When encountering a situation like `let [a, b, c] = $derived(blah())`,
9787
* we need to stash an intermediate value that `a`, `b`, and `c` derive

0 commit comments

Comments
 (0)