Skip to content

Commit cbb08ad

Browse files
committed
init
1 parent 3d9a9ab commit cbb08ad

File tree

2 files changed

+138
-4
lines changed
  • packages/svelte/src/compiler/phases

2 files changed

+138
-4
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,14 @@ export function build_template_chunk(
6969
node.metadata.expression
7070
);
7171

72-
has_state ||= node.metadata.expression.has_state;
73-
7472
if (values.length === 1) {
7573
// If we have a single expression, then pass that in directly to possibly avoid doing
7674
// extra work in the template_effect (instead we do the work in set_text).
75+
const evaluated = state.scope.evaluate(value);
76+
has_state ||= node.metadata.expression.has_state && !evaluated.is_known;
77+
if (evaluated.is_known) {
78+
value = b.literal(evaluated.value);
79+
}
7780
return { value, has_state };
7881
}
7982

@@ -91,6 +94,8 @@ export function build_template_chunk(
9194

9295
const evaluated = state.scope.evaluate(value);
9396

97+
has_state ||= node.metadata.expression.has_state && !evaluated.is_known;
98+
9499
if (evaluated.is_known) {
95100
quasi.value.cooked += evaluated.value + '';
96101
} else {

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

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import { is_reserved, is_rune } from '../../utils.js';
1616
import { determine_slot } from '../utils/slot.js';
1717
import { validate_identifier_name } from './2-analyze/visitors/shared/utils.js';
18+
import { bind_window_scroll } from 'svelte/internal/client';
1819

1920
export const UNKNOWN = Symbol('unknown');
2021
/** Includes `BigInt` */
@@ -173,14 +174,24 @@ class Evaluation {
173174
binding.kind === 'bindable_prop';
174175

175176
if (!binding.updated && binding.initial !== null && !is_prop) {
177+
console.log(binding.initial);
176178
const evaluation = binding.scope.evaluate(/** @type {Expression} */ (binding.initial));
177179
for (const value of evaluation.values) {
178180
this.values.add(value);
179181
}
180182
break;
181183
}
182-
183-
// TODO each index is always defined
184+
if (
185+
binding.kind === 'each' &&
186+
binding.initial?.type === 'EachBlock' &&
187+
binding.initial.index === expression.name
188+
) {
189+
this.values.add(NUMBER);
190+
break;
191+
}
192+
} else if (expression.name === 'undefined') {
193+
this.values.add(undefined);
194+
break;
184195
}
185196

186197
// TODO glean what we can from reassignments
@@ -336,6 +347,124 @@ class Evaluation {
336347
break;
337348
}
338349

350+
case 'CallExpression':
351+
{
352+
const rune = get_rune(expression, scope);
353+
if (
354+
rune &&
355+
scope.get(
356+
object(/** @type {Identifier | MemberExpression} */ (expression.callee))?.name ?? ''
357+
) === null
358+
) {
359+
switch (rune) {
360+
case '$state':
361+
case '$state.raw':
362+
if (expression.arguments.length) {
363+
const evaluated = scope.evaluate(
364+
/** @type {Expression} */ (expression.arguments[0])
365+
);
366+
for (let value of evaluated.values) {
367+
this.values.add(value);
368+
}
369+
} else {
370+
this.values.add(undefined);
371+
}
372+
break;
373+
case '$props.id':
374+
this.values.add(STRING);
375+
break;
376+
case '$effect.tracking':
377+
this.values.add(false);
378+
this.values.add(true);
379+
break;
380+
case '$derived': {
381+
const evaluated = scope.evaluate(
382+
/** @type {Expression} */ (expression.arguments[0])
383+
);
384+
for (let value of evaluated.values) {
385+
this.values.add(value);
386+
}
387+
break;
388+
}
389+
case '$derived.by':
390+
if (expression.arguments[0]?.type === 'ArrowFunctionExpression') {
391+
if (expression.arguments[0].body?.type !== 'BlockStatement') {
392+
const evaluated = scope.evaluate(
393+
/** @type {Expression} */ (expression.arguments[0].body)
394+
);
395+
for (let value of evaluated.values) {
396+
this.values.add(value);
397+
}
398+
break;
399+
}
400+
}
401+
default: {
402+
this.values.add(UNKNOWN);
403+
}
404+
}
405+
} else if (
406+
expression.callee.type === 'Identifier' &&
407+
scope.get(expression.callee.name) === null
408+
) {
409+
switch (expression.callee.name) {
410+
case 'Number': {
411+
if (expression.arguments.length) {
412+
const arg = scope.evaluate(/** @type {Expression} */ (expression.arguments[0]));
413+
if (arg.is_known) {
414+
this.values.add(Number(arg.value));
415+
} else if (arg.is_number) {
416+
this.values.add(NUMBER);
417+
} else {
418+
for (let value of arg.values) {
419+
switch (value) {
420+
case STRING:
421+
case NUMBER:
422+
case UNKNOWN:
423+
this.values.add(NUMBER);
424+
break;
425+
default:
426+
this.values.add(Number(value));
427+
}
428+
}
429+
}
430+
} else {
431+
this.values.add(0);
432+
}
433+
break;
434+
}
435+
case 'String':
436+
if (expression.arguments.length) {
437+
const arg = scope.evaluate(/** @type {Expression} */ (expression.arguments[0]));
438+
if (arg.is_known) {
439+
this.values.add(String(arg.value));
440+
} else if (arg.is_number || arg.is_string) {
441+
this.values.add(STRING);
442+
} else {
443+
for (let value of arg.values) {
444+
switch (value) {
445+
case STRING:
446+
case NUMBER:
447+
case UNKNOWN:
448+
this.values.add(STRING);
449+
break;
450+
default:
451+
this.values.add(String(value));
452+
}
453+
}
454+
}
455+
} else {
456+
this.values.add('');
457+
}
458+
break;
459+
default:
460+
this.values.add(UNKNOWN);
461+
}
462+
} else {
463+
this.values.add(UNKNOWN);
464+
}
465+
}
466+
break;
467+
339468
default: {
340469
this.values.add(UNKNOWN);
341470
}

0 commit comments

Comments
 (0)