Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into dev/const-boundary
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloricciuti committed Feb 24, 2025
2 parents a85e1a1 + c2ec0d9 commit 6c13df9
Show file tree
Hide file tree
Showing 65 changed files with 1,045 additions and 743 deletions.
5 changes: 5 additions & 0 deletions .changeset/spotty-drinks-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: allow for duplicate `var` declarations
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2016-2025 [these people](https://github.com/sveltejs/svelte/graphs/contributors)
Copyright (c) 2016-2025 [Svelte Contributors](https://github.com/sveltejs/svelte/graphs/contributors)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</picture>
</a>

[![license](https://img.shields.io/npm/l/svelte.svg)](LICENSE.md) [![Chat](https://img.shields.io/discord/457912077277855764?label=chat&logo=discord)](https://svelte.dev/chat)
[![License](https://img.shields.io/npm/l/svelte.svg)](LICENSE.md) [![Chat](https://img.shields.io/discord/457912077277855764?label=chat&logo=discord)](https://svelte.dev/chat)

## What is Svelte?

Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_avoidable.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
assert($.get(computed5) === 6);
for (let i = 0; i < 1000; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(computed5) === 6);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_broad.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
counter = 0;
for (let i = 0; i < 50; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(last) === i + 50);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_deep.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
counter = 0;
for (let i = 0; i < iter; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(current) === len + i);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_diamond.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
assert($.get(sum) === 2 * width);
counter = 0;
for (let i = 0; i < 500; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(sum) === (i + 1) * width);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_mux.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ function setup() {
destroy,
run() {
for (let i = 0; i < 10; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(heads[i], i);
});
assert($.get(splited[i]) === i + 1);
}
for (let i = 0; i < 10; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(heads[i], i * 2);
});
assert($.get(splited[i]) === i * 2 + 1);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_repeated.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
assert($.get(current) === size);
counter = 0;
for (let i = 0; i < 100; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(current) === i * size);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_triangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ function setup() {
destroy,
run() {
const constant = count(width);
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
assert($.get(sum) === constant);
counter = 0;
for (let i = 0; i < 100; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
assert($.get(sum) === constant - width + i * width);
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/kairo/kairo_unstable.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ function setup() {
return {
destroy,
run() {
$.flush_sync(() => {
$.flush(() => {
$.set(head, 1);
});
assert($.get(current) === 40);
counter = 0;
for (let i = 0; i < 100; i++) {
$.flush_sync(() => {
$.flush(() => {
$.set(head, i);
});
}
Expand Down
4 changes: 2 additions & 2 deletions benchmarking/benchmarks/reactivity/mol_bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ function setup() {
*/
run(i) {
res.length = 0;
$.flush_sync(() => {
$.flush(() => {
$.set(B, 1);
$.set(A, 1 + i * 2);
});
$.flush_sync(() => {
$.flush(() => {
$.set(A, 2 + i * 2);
$.set(B, 2);
});
Expand Down
16 changes: 16 additions & 0 deletions packages/svelte/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# svelte

## 5.20.4

### Patch Changes

- fix: update types and inline docs for flushSync ([#15348](https://github.com/sveltejs/svelte/pull/15348))

## 5.20.3

### Patch Changes

- fix: allow `@const` inside `#key` ([#15377](https://github.com/sveltejs/svelte/pull/15377))

- fix: remove unnecessary `?? ''` on some expressions ([#15287](https://github.com/sveltejs/svelte/pull/15287))

- fix: correctly override class attributes with class directives ([#15352](https://github.com/sveltejs/svelte/pull/15352))

## 5.20.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.20.2",
"version": "5.20.4",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
Expand Down
96 changes: 32 additions & 64 deletions packages/svelte/src/compiler/phases/2-analyze/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,9 @@ export function analyze_module(ast, options) {
expression: null,
function_depth: 0,
has_props_rune: false,
instance_scope: /** @type {any} */ (null),
options: /** @type {ValidatedCompileOptions} */ (options),
parent_element: null,
reactive_statement: null,
reactive_statements: new Map()
reactive_statement: null
},
visitors
);
Expand Down Expand Up @@ -566,7 +564,7 @@ export function analyze_component(root, source, options) {
binding.declaration_kind !== 'import'
) {
binding.kind = 'state';
binding.mutated = binding.updated = true;
binding.mutated = true;
}
}
}
Expand Down Expand Up @@ -620,9 +618,7 @@ export function analyze_component(root, source, options) {
expression: null,
derived_state: [],
function_depth: scope.function_depth,
instance_scope: instance.scope,
reactive_statement: null,
reactive_statements: new Map()
reactive_statement: null
};

walk(/** @type {AST.SvelteNode} */ (ast), state, visitors);
Expand Down Expand Up @@ -684,9 +680,7 @@ export function analyze_component(root, source, options) {
parent_element: null,
has_props_rune: false,
ast_type: ast === instance.ast ? 'instance' : ast === template.ast ? 'template' : 'module',
instance_scope: instance.scope,
reactive_statement: null,
reactive_statements: analysis.reactive_statements,
component_slots: new Set(),
expression: null,
derived_state: [],
Expand Down Expand Up @@ -767,66 +761,40 @@ export function analyze_component(root, source, options) {
if (!should_ignore_unused) {
warn_unused(analysis.css.ast);
}
}

outer: for (const node of analysis.elements) {
if (node.metadata.scoped) {
// Dynamic elements in dom mode always use spread for attributes and therefore shouldn't have a class attribute added to them
// TODO this happens during the analysis phase, which shouldn't know anything about client vs server
if (node.type === 'SvelteElement' && options.generate === 'client') continue;

/** @type {AST.Attribute | undefined} */
let class_attribute = undefined;

for (const attribute of node.attributes) {
if (attribute.type === 'SpreadAttribute') {
// The spread method appends the hash to the end of the class attribute on its own
continue outer;
}
for (const node of analysis.elements) {
if (node.metadata.scoped && is_custom_element_node(node)) {
mark_subtree_dynamic(node.metadata.path);
}

if (attribute.type !== 'Attribute') continue;
if (attribute.name.toLowerCase() !== 'class') continue;
// The dynamic class method appends the hash to the end of the class attribute on its own
if (attribute.metadata.needs_clsx) continue outer;
let has_class = false;
let has_spread = false;
let has_class_directive = false;

class_attribute = attribute;
}
for (const attribute of node.attributes) {
// The spread method appends the hash to the end of the class attribute on its own
if (attribute.type === 'SpreadAttribute') {
has_spread = true;
break;
}
has_class_directive ||= attribute.type === 'ClassDirective';
has_class ||= attribute.type === 'Attribute' && attribute.name.toLowerCase() === 'class';
}

if (class_attribute && class_attribute.value !== true) {
if (is_text_attribute(class_attribute)) {
class_attribute.value[0].data += ` ${analysis.css.hash}`;
} else {
/** @type {AST.Text} */
const css_text = {
type: 'Text',
data: ` ${analysis.css.hash}`,
raw: ` ${analysis.css.hash}`,
start: -1,
end: -1
};

if (Array.isArray(class_attribute.value)) {
class_attribute.value.push(css_text);
} else {
class_attribute.value = [class_attribute.value, css_text];
}
// We need an empty class to generate the set_class() or class="" correctly
if (!has_spread && !has_class && (node.metadata.scoped || has_class_directive)) {
node.attributes.push(
create_attribute('class', -1, -1, [
{
type: 'Text',
data: '',
raw: '',
start: -1,
end: -1
}
} else {
node.attributes.push(
create_attribute('class', -1, -1, [
{
type: 'Text',
data: analysis.css.hash,
raw: analysis.css.hash,
start: -1,
end: -1
}
])
);
if (is_custom_element_node(node) && node.attributes.length === 1) {
mark_subtree_dynamic(node.metadata.path);
}
}
}
])
);
}
}

Expand Down
3 changes: 0 additions & 3 deletions packages/svelte/src/compiler/phases/2-analyze/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Scope } from '../scope.js';
import type { ComponentAnalysis, ReactiveStatement } from '../types.js';
import type { AST, ExpressionMetadata, ValidatedCompileOptions } from '#compiler';
import type { LabeledStatement } from 'estree';

export interface AnalysisState {
scope: Scope;
Expand All @@ -23,9 +22,7 @@ export interface AnalysisState {
function_depth: number;

// legacy stuff
instance_scope: Scope;
reactive_statement: null | ReactiveStatement;
reactive_statements: Map<LabeledStatement, ReactiveStatement>;
}

export type Context<State extends AnalysisState = AnalysisState> = import('zimmerframe').Context<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function get_delegated_event(event_name, handler, context) {
return unhoisted;
}

if (binding !== null && binding.initial !== null && !binding.updated && !binding.is_called) {
if (binding !== null && binding.initial !== null && !binding.updated) {
const binding_type = binding.initial.type;

if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
is_text_attribute,
object
} from '../../../utils/ast.js';
import { validate_no_const_assignment } from './shared/utils.js';
import { validate_assignment } from './shared/utils.js';
import * as e from '../../../errors.js';
import * as w from '../../../warnings.js';
import { binding_properties } from '../../bindings.js';
Expand Down Expand Up @@ -158,7 +158,7 @@ export function BindDirective(node, context) {
return;
}

validate_no_const_assignment(node, node.expression, context.state.scope, true);
validate_assignment(node, node.expression, context.state);

const assignee = node.expression;
const left = object(assignee);
Expand All @@ -184,14 +184,6 @@ export function BindDirective(node, context) {
) {
e.bind_invalid_value(node.expression);
}

if (context.state.analysis.runes && binding?.kind === 'each') {
e.each_item_invalid_assignment(node);
}

if (binding?.kind === 'snippet') {
e.snippet_parameter_assignment(node);
}
}

if (node.name === 'group') {
Expand Down
Loading

0 comments on commit 6c13df9

Please sign in to comment.