mirror of https://github.com/sveltejs/svelte
commit
e95fad3b3b
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: allow comments after last selector in css
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: don't add scoping modifier to nesting selectors
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: migrate derivations without semicolons
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
chore: speedup hydration around input and select values
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: check for invalid bindings on window and document
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: inline pointer events now correctly work in Chrome
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: update value like attributes in a separate template_effect
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: improve handling of unowned derived signal
|
||||
@ -1,33 +1,63 @@
|
||||
import { run_all } from '../../shared/utils.js';
|
||||
|
||||
let is_task_queued = false;
|
||||
// Fallback for when requestIdleCallback is not available
|
||||
const request_idle_callback =
|
||||
typeof requestIdleCallback === 'undefined'
|
||||
? (/** @type {() => void} */ cb) => setTimeout(cb, 1)
|
||||
: requestIdleCallback;
|
||||
|
||||
let is_micro_task_queued = false;
|
||||
let is_idle_task_queued = false;
|
||||
|
||||
/** @type {Array<() => void>} */
|
||||
let current_queued_miro_tasks = [];
|
||||
/** @type {Array<() => void>} */
|
||||
let current_queued_tasks = [];
|
||||
let current_queued_idle_tasks = [];
|
||||
|
||||
function process_micro_tasks() {
|
||||
is_micro_task_queued = false;
|
||||
const tasks = current_queued_miro_tasks.slice();
|
||||
current_queued_miro_tasks = [];
|
||||
run_all(tasks);
|
||||
}
|
||||
|
||||
function process_task() {
|
||||
is_task_queued = false;
|
||||
const tasks = current_queued_tasks.slice();
|
||||
current_queued_tasks = [];
|
||||
function process_idle_tasks() {
|
||||
is_idle_task_queued = false;
|
||||
const tasks = current_queued_idle_tasks.slice();
|
||||
current_queued_idle_tasks = [];
|
||||
run_all(tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {() => void} fn
|
||||
*/
|
||||
export function queue_task(fn) {
|
||||
if (!is_task_queued) {
|
||||
is_task_queued = true;
|
||||
queueMicrotask(process_task);
|
||||
export function queue_micro_task(fn) {
|
||||
if (!is_micro_task_queued) {
|
||||
is_micro_task_queued = true;
|
||||
queueMicrotask(process_micro_tasks);
|
||||
}
|
||||
current_queued_miro_tasks.push(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {() => void} fn
|
||||
*/
|
||||
export function queue_idle_task(fn) {
|
||||
if (!is_idle_task_queued) {
|
||||
is_idle_task_queued = true;
|
||||
request_idle_callback(process_idle_tasks);
|
||||
}
|
||||
current_queued_tasks.push(fn);
|
||||
current_queued_idle_tasks.push(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously run any queued tasks.
|
||||
*/
|
||||
export function flush_tasks() {
|
||||
if (is_task_queued) {
|
||||
process_task();
|
||||
if (is_micro_task_queued) {
|
||||
process_micro_tasks();
|
||||
}
|
||||
if (is_idle_task_queued) {
|
||||
process_idle_tasks();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
|
||||
.foo.svelte-xyz, /* some comment */
|
||||
.bar.svelte-xyz /* some other comment */
|
||||
{
|
||||
color: red;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
<div class="foo">foo</div>
|
||||
<div class="bar">bar</div>
|
||||
|
||||
<style>
|
||||
.foo, /* some comment */
|
||||
.bar /* some other comment */
|
||||
{
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
let count = 0;
|
||||
$: doubled = count * 2
|
||||
$: ({ quadrupled } = { quadrupled: count * 4 })
|
||||
</script>
|
||||
|
||||
{count} / {doubled} / {quadrupled}
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
let count = 0;
|
||||
let doubled = $derived(count * 2);
|
||||
let { quadrupled } = $derived({ quadrupled: count * 4 });
|
||||
</script>
|
||||
|
||||
{count} / {doubled} / {quadrupled}
|
||||
@ -0,0 +1,34 @@
|
||||
import { test, ok } from '../../test';
|
||||
import { flushSync } from 'svelte';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
|
||||
async test({ assert, target }) {
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const input = target.querySelector('input[type=text]');
|
||||
const button = target.querySelector('button');
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const checkbox = target.querySelector('input[type=checkbox]');
|
||||
const textarea = target.querySelector('textarea');
|
||||
ok(input);
|
||||
ok(button);
|
||||
ok(checkbox);
|
||||
ok(textarea);
|
||||
|
||||
flushSync(() => {
|
||||
input.value = 'foo';
|
||||
checkbox.click();
|
||||
textarea.innerHTML = 'bar';
|
||||
button.click();
|
||||
});
|
||||
|
||||
assert.equal(input.value, 'foo');
|
||||
assert.equal(checkbox.checked, true);
|
||||
assert.equal(textarea.innerHTML, 'bar');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
let count = 0;
|
||||
let value = { value: "" };
|
||||
let checked = { value: false };
|
||||
</script>
|
||||
|
||||
<input type="text" value={value.value} />
|
||||
|
||||
<textarea value={value.value}></textarea>
|
||||
|
||||
<input type="checkbox" checked={checked.value} />
|
||||
|
||||
<button on:click={()=>count++}>{count}</button>
|
||||
@ -0,0 +1,23 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
async test({ assert, target, logs }) {
|
||||
let [btn1] = target.querySelectorAll('button');
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
btn1.click();
|
||||
});
|
||||
|
||||
assert.deepEqual(logs, ['recalculating']);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
<script context="module">
|
||||
let visible = $state(true);
|
||||
|
||||
function toggleVisibility() {
|
||||
visible = !visible;
|
||||
}
|
||||
|
||||
let unchangedState = $state("unchanged state");
|
||||
let derived = $derived.by(() => {
|
||||
console.log("recalculating");
|
||||
return unchangedState;
|
||||
});
|
||||
</script>
|
||||
|
||||
<button onclick={toggleVisibility}>Toggle Visibility</button>
|
||||
{#if visible}
|
||||
<p>{derived}</p>
|
||||
{/if}
|
||||
@ -0,0 +1,34 @@
|
||||
import { test, ok } from '../../test';
|
||||
import { flushSync } from 'svelte';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
|
||||
async test({ assert, target }) {
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const input = target.querySelector('input[type=text]');
|
||||
const button = target.querySelector('button');
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const checkbox = target.querySelector('input[type=checkbox]');
|
||||
const textarea = target.querySelector('textarea');
|
||||
ok(input);
|
||||
ok(button);
|
||||
ok(checkbox);
|
||||
ok(textarea);
|
||||
|
||||
flushSync(() => {
|
||||
input.value = 'foo';
|
||||
checkbox.click();
|
||||
textarea.innerHTML = 'bar';
|
||||
button.click();
|
||||
});
|
||||
|
||||
assert.equal(input.value, 'foo');
|
||||
assert.equal(checkbox.checked, true);
|
||||
assert.equal(textarea.innerHTML, 'bar');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
let count = $state(0);
|
||||
let value = $state({
|
||||
value: "",
|
||||
});
|
||||
let checked = $state({
|
||||
checked: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
<input type="text" {...value} />
|
||||
|
||||
<textarea {...value}></textarea>
|
||||
|
||||
<input type="checkbox" {...checked} />
|
||||
|
||||
<button onclick={()=>count++}>{count}</button>
|
||||
@ -0,0 +1,34 @@
|
||||
import { test, ok } from '../../test';
|
||||
import { flushSync } from 'svelte';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
|
||||
async test({ assert, target }) {
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const input = target.querySelector('input[type=text]');
|
||||
const button = target.querySelector('button');
|
||||
/**
|
||||
* @type {HTMLInputElement | null}
|
||||
*/
|
||||
const checkbox = target.querySelector('input[type=checkbox]');
|
||||
const textarea = target.querySelector('textarea');
|
||||
ok(input);
|
||||
ok(button);
|
||||
ok(checkbox);
|
||||
ok(textarea);
|
||||
|
||||
flushSync(() => {
|
||||
input.value = 'foo';
|
||||
checkbox.click();
|
||||
textarea.innerHTML = 'bar';
|
||||
button.click();
|
||||
});
|
||||
|
||||
assert.equal(input.value, 'foo');
|
||||
assert.equal(checkbox.checked, true);
|
||||
assert.equal(textarea.innerHTML, 'bar');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
let count = $state(0);
|
||||
let value = $state("");
|
||||
let checked = $state(false);
|
||||
</script>
|
||||
|
||||
<input type="text" {value} />
|
||||
|
||||
<textarea {value}></textarea>
|
||||
|
||||
<input type="checkbox" {checked} />
|
||||
|
||||
<button onclick={()=>count++}>{count}</button>
|
||||
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"code": "bind_invalid_name",
|
||||
"message": "`bind:clientWidth` is not a valid binding. Possible bindings for <svelte:document> are focused, fullscreenElement, visibilityState, this",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 17
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 39
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
let foo;
|
||||
</script>
|
||||
|
||||
<svelte:document bind:clientWidth={foo} />
|
||||
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"code": "bind_invalid_name",
|
||||
"message": "`bind:clientWidth` is not a valid binding. Possible bindings for <svelte:window> are focused, innerWidth, innerHeight, outerWidth, outerHeight, scrollX, scrollY, online, devicePixelRatio, this",
|
||||
"start": {
|
||||
"line": 5,
|
||||
"column": 15
|
||||
},
|
||||
"end": {
|
||||
"line": 5,
|
||||
"column": 37
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
let foo;
|
||||
</script>
|
||||
|
||||
<svelte:window bind:clientWidth={foo} />
|
||||
@ -1,4 +1,5 @@
|
||||
src/*
|
||||
dist/*
|
||||
dist/client/*
|
||||
dist/server/*
|
||||
!src/entry-client.ts
|
||||
!src/entry-server.ts
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import express from 'express';
|
||||
import { head, html } from './server/entry-server.js';
|
||||
|
||||
const rendered = fs
|
||||
.readFileSync(path.resolve('./dist/client/index.html'), 'utf-8')
|
||||
.replace(`<!--ssr-html-->`, html)
|
||||
.replace(`<!--ssr-head-->`, head);
|
||||
|
||||
express()
|
||||
.use('*', async (req, res) => {
|
||||
if (req.originalUrl !== '/') {
|
||||
res.sendFile(path.resolve('./dist/client' + req.originalUrl));
|
||||
return;
|
||||
}
|
||||
|
||||
res.status(200).set({ 'Content-Type': 'text/html' }).end(rendered);
|
||||
})
|
||||
.listen('3000');
|
||||
|
||||
console.log('listening on http://localhost:3000');
|
||||
Loading…
Reference in new issue