Skip to content

Commit

Permalink
Merge branch 'main' into bind-get-set
Browse files Browse the repository at this point in the history
  • Loading branch information
dummdidumm committed Nov 21, 2024
2 parents cda50c4 + 6a5f30b commit de3b74c
Show file tree
Hide file tree
Showing 87 changed files with 764 additions and 414 deletions.
5 changes: 0 additions & 5 deletions .changeset/fast-ligers-repeat.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/fresh-pigs-divide.md

This file was deleted.

1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- [ ] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
- [ ] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.
- [ ] If this PR changes code within `packages/svelte/src`, add a changeset (`npx changeset`).

### Tests and linting

Expand Down
1 change: 1 addition & 0 deletions benchmarking/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import {
kairo_avoidable_owned,
kairo_avoidable_unowned
} from './benchmarks/kairo/kairo_avoidable.js';
import { kairo_broad_owned, kairo_broad_unowned } from './benchmarks/kairo/kairo_broad.js';
import { kairo_deep_owned, kairo_deep_unowned } from './benchmarks/kairo/kairo_deep.js';
import { kairo_diamond_owned, kairo_diamond_unowned } from './benchmarks/kairo/kairo_diamond.js';
import { kairo_mux_unowned, kairo_mux_owned } from './benchmarks/kairo/kairo_mux.js';
import { kairo_repeated_unowned, kairo_repeated_owned } from './benchmarks/kairo/kairo_repeated.js';
import { kairo_triangle_owned, kairo_triangle_unowned } from './benchmarks/kairo/kairo_triangle.js';
import { kairo_unstable_owned, kairo_unstable_unowned } from './benchmarks/kairo/kairo_unstable.js';
import { mol_bench_owned, mol_bench_unowned } from './benchmarks/mol_bench.js';
import { kairo_avoidable_owned, kairo_avoidable_unowned } from './kairo/kairo_avoidable.js';
import { kairo_broad_owned, kairo_broad_unowned } from './kairo/kairo_broad.js';
import { kairo_deep_owned, kairo_deep_unowned } from './kairo/kairo_deep.js';
import { kairo_diamond_owned, kairo_diamond_unowned } from './kairo/kairo_diamond.js';
import { kairo_mux_unowned, kairo_mux_owned } from './kairo/kairo_mux.js';
import { kairo_repeated_unowned, kairo_repeated_owned } from './kairo/kairo_repeated.js';
import { kairo_triangle_owned, kairo_triangle_unowned } from './kairo/kairo_triangle.js';
import { kairo_unstable_owned, kairo_unstable_unowned } from './kairo/kairo_unstable.js';
import { mol_bench_owned, mol_bench_unowned } from './mol_bench.js';
import {
sbench_create_0to1,
sbench_create_1000to1,
Expand All @@ -21,12 +18,12 @@ import {
sbench_create_2to1,
sbench_create_4to1,
sbench_create_signals
} from './benchmarks/sbench.js';
} from './sbench.js';

// This benchmark has been adapted from the js-reactivity-benchmark (https://github.com/milomg/js-reactivity-benchmark)
// Not all tests are the same, and many parts have been tweaked to capture different data.

export const benchmarks = [
export const reactivity_benchmarks = [
sbench_create_signals,
sbench_create_0to1,
sbench_create_1to1,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';
import { busy } from './util.js';

function setup() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

function setup() {
let head = $.state(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

let len = 50;
const iter = 50;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

let width = 5;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

function setup() {
let heads = new Array(100).fill(null).map((_) => $.state(0));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

let size = 30;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

let width = 10;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../../utils.js';
import * as $ from 'svelte/internal/client';

function setup() {
let head = $.state(0);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assert, fastest_test } from '../utils.js';
import * as $ from '../../packages/svelte/src/internal/client/index.js';
import { assert, fastest_test } from '../../utils.js';
import * as $ from 'svelte/internal/client';

/**
* @param {number} n
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fastest_test } from '../utils.js';
import * as $ from '../../packages/svelte/src/internal/client/index.js';
import { fastest_test } from '../../utils.js';
import * as $ from '../../../packages/svelte/src/internal/client/index.js';

const COUNT = 1e5;

Expand Down
3 changes: 3 additions & 0 deletions benchmarking/benchmarks/ssr/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { wrapper_bench } from './wrapper/wrapper_bench.js';

export const ssr_benchmarks = [wrapper_bench];
31 changes: 31 additions & 0 deletions benchmarking/benchmarks/ssr/wrapper/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script>
const wrapperWidth = 960;
const wrapperHeight = 720;
const cellSize = 10;
const centerX = wrapperWidth / 2;
const centerY = wrapperHeight / 2;
let angle = 0;
let radius = 0;
let tiles = [];
const step = cellSize;
while (radius < Math.min(wrapperWidth, wrapperHeight) / 2) {
let x = centerX + Math.cos(angle) * radius;
let y = centerY + Math.sin(angle) * radius;
if (x >= 0 && x <= wrapperWidth - cellSize && y >= 0 && y <= wrapperHeight - cellSize) {
tiles.push({ x, y });
}
angle += 0.2;
radius += step * 0.015;
}
</script>

<div id="wrapper">
{#each tiles as { x, y }}
<div class="tile" style="left: {x.toFixed(2)}px; top: {y.toFixed(2)}px;"></div>
{/each}
</div>
36 changes: 36 additions & 0 deletions benchmarking/benchmarks/ssr/wrapper/wrapper_bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { render } from 'svelte/server';
import { fastest_test, read_file, write } from '../../../utils.js';
import { compile } from 'svelte/compiler';

const dir = `${process.cwd()}/benchmarking/benchmarks/ssr/wrapper`;

async function compile_svelte() {
const output = compile(read_file(`${dir}/App.svelte`), {
generate: 'server'
});
write(`${dir}/output/App.js`, output.js.code);

const module = await import(`${dir}/output/App.js`);

return module.default;
}

export async function wrapper_bench() {
const App = await compile_svelte();
// Do 3 loops to warm up JIT
for (let i = 0; i < 3; i++) {
render(App);
}

const { timing } = await fastest_test(10, () => {
for (let i = 0; i < 100; i++) {
render(App);
}
});

return {
benchmark: 'wrapper_bench',
time: timing.time.toFixed(2),
gc_time: timing.gc_time.toFixed(2)
};
}
41 changes: 32 additions & 9 deletions benchmarking/run.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
import * as $ from '../packages/svelte/src/internal/client/index.js';
import { benchmarks } from './benchmarks.js';
import { reactivity_benchmarks } from './benchmarks/reactivity/index.js';
import { ssr_benchmarks } from './benchmarks/ssr/index.js';

let total_time = 0;
let total_gc_time = 0;

const suites = [
{ benchmarks: reactivity_benchmarks, name: 'reactivity benchmarks' },
{ benchmarks: ssr_benchmarks, name: 'server-side rendering benchmarks' }
];

// eslint-disable-next-line no-console
console.log('-- Benchmarking Started --');
console.log('\x1b[1m', '-- Benchmarking Started --', '\x1b[0m');
$.push({}, true);
try {
for (const benchmark of benchmarks) {
const results = await benchmark();
for (const { benchmarks, name } of suites) {
let suite_time = 0;
let suite_gc_time = 0;
// eslint-disable-next-line no-console
console.log(`\nRunning ${name}...\n`);

for (const benchmark of benchmarks) {
const results = await benchmark();
// eslint-disable-next-line no-console
console.log(results);
total_time += Number(results.time);
total_gc_time += Number(results.gc_time);
suite_time += Number(results.time);
suite_gc_time += Number(results.gc_time);
}

console.log(`\nFinished ${name}.\n`);

// eslint-disable-next-line no-console
console.log(results);
total_time += Number(results.time);
total_gc_time += Number(results.gc_time);
console.log({
suite_time: suite_time.toFixed(2),
suite_gc_time: suite_gc_time.toFixed(2)
});
}
} catch (e) {
// eslint-disable-next-line no-console
console.error('-- Benchmarking Failed --');
console.log('\x1b[1m', '\n-- Benchmarking Failed --\n', '\x1b[0m');
// eslint-disable-next-line no-console
console.error(e);
process.exit(1);
}
$.pop();
// eslint-disable-next-line no-console
console.log('-- Benchmarking Complete --');
console.log('\x1b[1m', '\n-- Benchmarking Complete --\n', '\x1b[0m');
// eslint-disable-next-line no-console
console.log({
total_time: total_time.toFixed(2),
Expand Down
21 changes: 21 additions & 0 deletions benchmarking/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { performance, PerformanceObserver } from 'node:perf_hooks';
import v8 from 'v8-natives';
import * as fs from 'node:fs';
import * as path from 'node:path';

// Credit to https://github.com/milomg/js-reactivity-benchmark for the logic for timing + GC tracking.

Expand Down Expand Up @@ -96,3 +98,22 @@ export function assert(a) {
throw new Error('Assertion failed');
}
}

/**
* @param {string} file
*/
export function read_file(file) {
return fs.readFileSync(file, 'utf-8').replace(/\r\n/g, '\n');
}

/**
* @param {string} file
* @param {string} contents
*/
export function write(file, contents) {
try {
fs.mkdirSync(path.dirname(file), { recursive: true });
} catch {}

fs.writeFileSync(file, contents);
}
22 changes: 22 additions & 0 deletions documentation/docs/06-runtime/01-stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ Prior to Svelte 5, stores were the go-to solution for creating cross-component r
- when extracting logic, it's better to take advantage of runes' universal reactivity: You can use runes outside the top level of components and even place them into JavaScript or TypeScript files (using a `.svelte.js` or `.svelte.ts` file ending)
- when creating shared state, you can create a `$state` object containing the values you need and then manipulate said state

```ts
/// file: state.svelte.js
export const userState = $state({
name: 'name',
/* ... */
});
```

```svelte
<!--- file: App.svelte --->
<script>
import { userState } from './state.svelte';
</script>
<p>User name: {userState.name}</p>
<button onclick={() => {
userState.name = 'new name';
}}>
change name
</button>
```

Stores are still a good solution when you have complex asynchronous data streams or it's important to have more manual control over updating values or listening to changes. If you're familiar with RxJs and want to reuse that knowledge, the `$` also comes in handy for you.

## svelte/store
Expand Down
4 changes: 2 additions & 2 deletions documentation/docs/07-misc/03-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ In case you're writing a component that wraps a native element, you may want to
</script>
<button {...rest}>
{@render children()}
{@render children?.()}
</button>
```

Expand All @@ -156,7 +156,7 @@ Not all elements have a dedicated type definition. For those without one, use `S
</script>
<div {...rest}>
{@render children()}
{@render children?.()}
</div>
```

Expand Down
6 changes: 3 additions & 3 deletions documentation/docs/07-misc/07-v5-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ This function is deprecated in Svelte 5. Instead, components should accept _call
<Pump
---on:---inflate={(power) => {
size += power---.details---;
size += power---.detail---;
if (size > 75) burst = true;
}}
---on:---deflate={(power) => {
if (size > 0) size -= power---.details---;
if (size > 0) size -= power---.detail---;
}}
/>
Expand Down Expand Up @@ -317,7 +317,7 @@ When spreading props, local event handlers must go _after_ the spread, or they r
> - import the function
> - call the function to get a dispatch function
> - call said dispatch function with a string and possibly a payload
> - retrieve said payload on the other end through a `.details` property, because the event itself was always a `CustomEvent`
> - retrieve said payload on the other end through a `.detail` property, because the event itself was always a `CustomEvent`
>
> It was always possible to use component callback props, but because you had to listen to DOM events using `on:`, it made sense to use `createEventDispatcher` for component events due to syntactical consistency. Now that we have event attributes (`onclick`), it's the other way around: Callback props are now the more sensible thing to do.
>
Expand Down
Loading

0 comments on commit de3b74c

Please sign in to comment.