mirror of https://github.com/sveltejs/svelte
commit
959abf6d6a
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
A transition's parameters are now evaluated when the transition is initialized.
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
feat: add `$state.frozen` rune
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
Fix issue with assigning prop values as defaults of other props
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
Fix interopability between backticks and templates
|
||||
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: support hydrating around `<noscript>`
|
||||
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
export function sanitize_template_string(str) {
|
||||
return str.replace(/(`|\${|\\)/g, '\\$1');
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
<!--ssr:0--><noscript>JavaScript is required for this site.</noscript>
|
||||
<h1>Hello!</h1><p>Count: 0</p><!--ssr:0-->
|
||||
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
let count = 0;
|
||||
onMount(() => count++);
|
||||
</script>
|
||||
|
||||
<noscript>JavaScript is required for this site.</noscript>
|
||||
|
||||
<h1>Hello!</h1><p>Count: {count}</p>
|
||||
@ -0,0 +1,44 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<p>1</p>
|
||||
<p>2</p>
|
||||
<p>3</p>
|
||||
<p>4</p>
|
||||
<p>5</p>
|
||||
<p>6</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>6</p>
|
||||
<p></p>
|
||||
<p></p>
|
||||
|
||||
<button>Click me!</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target, window }) {
|
||||
const button = target.querySelector('button');
|
||||
const clickEvent = new window.Event('click', { bubbles: true });
|
||||
await button?.dispatchEvent(clickEvent);
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>7</p>
|
||||
<p>8</p>
|
||||
<p>9</p>
|
||||
<p>10</p>
|
||||
<p>11</p>
|
||||
<p>12</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>12</p>
|
||||
<p>14</p>
|
||||
<p>15</p>
|
||||
|
||||
<button>Click me!</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,42 @@
|
||||
<script>
|
||||
import { get, writable } from 'svelte/store'
|
||||
|
||||
let bagOlStores = writable([1, 2, 3, writable(4), writable(5), writable(6)]);
|
||||
|
||||
let firstNonStore, secondNonStore, thirdNonStore, firstStore, secondStore, thirdStore;
|
||||
([firstNonStore, secondNonStore, thirdNonStore, firstStore, secondStore, thirdStore] = $bagOlStores);
|
||||
|
||||
function changeStores() {
|
||||
$bagOlStores = ([
|
||||
firstNonStore,
|
||||
secondNonStore,
|
||||
thirdNonStore,
|
||||
firstStore,
|
||||
$secondStore,
|
||||
thirdStore
|
||||
] = [
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
writable(10),
|
||||
11,
|
||||
writable(12),
|
||||
writable(14),
|
||||
writable(15)
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>{firstNonStore}</p>
|
||||
<p>{secondNonStore}</p>
|
||||
<p>{thirdNonStore}</p>
|
||||
<p>{$firstStore}</p>
|
||||
<p>{$secondStore}</p>
|
||||
<p>{$thirdStore}</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>{get($bagOlStores[5])}</p>
|
||||
<p>{get($bagOlStores[6])}</p>
|
||||
<p>{get($bagOlStores[7])}</p>
|
||||
|
||||
<button on:click={changeStores}>Click me!</button>
|
||||
@ -0,0 +1,44 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<p>1</p>
|
||||
<p>2</p>
|
||||
<p>3</p>
|
||||
<p>4</p>
|
||||
<p>5</p>
|
||||
<p>6</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>4</p>
|
||||
<p>5</p>
|
||||
<p>6</p>
|
||||
|
||||
<button>Click me!</button>
|
||||
`,
|
||||
|
||||
async test({ assert, target, window }) {
|
||||
const button = target.querySelector('button');
|
||||
const clickEvent = new window.Event('click', { bubbles: true });
|
||||
await button?.dispatchEvent(clickEvent);
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<p>7</p>
|
||||
<p>8</p>
|
||||
<p>9</p>
|
||||
<p>10</p>
|
||||
<p>11</p>
|
||||
<p>12</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>14</p>
|
||||
<p>13</p>
|
||||
<p>12</p>
|
||||
|
||||
<button>Click me!</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,48 @@
|
||||
<script>
|
||||
import { get, writable } from 'svelte/store'
|
||||
|
||||
let bagOlStores = writable({
|
||||
firstNonStore: 1,
|
||||
secondNonStore: 2,
|
||||
thirdNonStore: 3,
|
||||
firstStore: writable(4),
|
||||
secondStore: writable(5),
|
||||
thirdStore: writable(6)
|
||||
});
|
||||
|
||||
let { firstNonStore, secondNonStore, thirdNonStore, firstStore, secondStore, thirdStore } = $bagOlStores;
|
||||
|
||||
function changeStores() {
|
||||
$bagOlStores = ({
|
||||
thirdStore,
|
||||
$secondStore,
|
||||
$firstStore,
|
||||
firstNonStore,
|
||||
secondNonStore,
|
||||
thirdNonStore,
|
||||
} = {
|
||||
firstNonStore: 7,
|
||||
secondNonStore: 8,
|
||||
thirdNonStore: 9,
|
||||
$firstStore: 10,
|
||||
$secondStore: 11,
|
||||
firstStore: writable(14),
|
||||
secondStore: writable(13),
|
||||
thirdStore: writable(12)
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>{firstNonStore}</p>
|
||||
<p>{secondNonStore}</p>
|
||||
<p>{thirdNonStore}</p>
|
||||
<p>{$firstStore}</p>
|
||||
<p>{$secondStore}</p>
|
||||
<p>{$thirdStore}</p>
|
||||
|
||||
<h1>Bag'ol stores</h1>
|
||||
<p>{get($bagOlStores.firstStore)}</p>
|
||||
<p>{get($bagOlStores.secondStore)}</p>
|
||||
<p>{get($bagOlStores.thirdStore)}</p>
|
||||
|
||||
<button on:click={changeStores}>Click me!</button>
|
||||
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let z = 8;
|
||||
let { a, b = a, c = b * b, d = z * b + c } = $props();
|
||||
</script>
|
||||
|
||||
<p>{a}</p>
|
||||
<p>{b}</p>
|
||||
<p>{c}</p>
|
||||
<p>{d}</p>
|
||||
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<p>5</p><p>5</p><p>25</p><p>65</p>`
|
||||
});
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import Test from './Test.svelte'
|
||||
</script>
|
||||
|
||||
<Test a={5} />
|
||||
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: '<div>/ $clicks: 0 `tim$es` \\</div><div>$dollars `backticks` pyramid /\\</div>'
|
||||
});
|
||||
@ -0,0 +1,6 @@
|
||||
<div>
|
||||
/ $clicks: {0} `tim${"e"}s` \
|
||||
</div>
|
||||
<div>
|
||||
$dollars `backticks` pyramid /\
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
import { test } from '../../test';
|
||||
import { log } from './log.js';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
before_test() {
|
||||
log.length = 0;
|
||||
},
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>0</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>0</button>`);
|
||||
|
||||
assert.deepEqual(log, ['read only', 'read only']);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,2 @@
|
||||
/** @type {any[]} */
|
||||
export const log = [];
|
||||
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import { log } from './log.js';
|
||||
|
||||
class Counter {
|
||||
count = $state.frozen({ a: 0 });
|
||||
}
|
||||
const counter = new Counter();
|
||||
</script>
|
||||
|
||||
<button on:click={() => {
|
||||
try {
|
||||
counter.count.a++
|
||||
} catch (e) {
|
||||
log.push('read only')
|
||||
}
|
||||
}}>{counter.count.a}</button>
|
||||
@ -0,0 +1,15 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>1</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>2</button>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,8 @@
|
||||
<script>
|
||||
class Counter {
|
||||
count = $state.frozen(0);
|
||||
}
|
||||
const counter = new Counter();
|
||||
</script>
|
||||
|
||||
<button on:click={() => counter.count++}>{counter.count}</button>
|
||||
@ -0,0 +1,22 @@
|
||||
import { test } from '../../test';
|
||||
import { log } from './log.js';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
before_test() {
|
||||
log.length = 0;
|
||||
},
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>0</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>0</button>`);
|
||||
|
||||
assert.deepEqual(log, ['read only', 'read only']);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,2 @@
|
||||
/** @type {any[]} */
|
||||
export const log = [];
|
||||
@ -0,0 +1,27 @@
|
||||
<script>
|
||||
import { log } from './log.js';
|
||||
|
||||
class Counter {
|
||||
#count = $state.frozen();
|
||||
|
||||
constructor(initial_count) {
|
||||
this.#count = { a: initial_count };
|
||||
}
|
||||
|
||||
get count() {
|
||||
return this.#count;
|
||||
}
|
||||
set count(val) {
|
||||
this.#count = val;
|
||||
}
|
||||
}
|
||||
const counter = new Counter(0);
|
||||
</script>
|
||||
|
||||
<button on:click={() => {
|
||||
try {
|
||||
counter.count.a++
|
||||
} catch (e) {
|
||||
log.push('read only')
|
||||
}
|
||||
}}>{counter.count.a}</button>
|
||||
@ -0,0 +1,15 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<button>0</button>`,
|
||||
|
||||
async test({ assert, target }) {
|
||||
const btn = target.querySelector('button');
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>1</button>`);
|
||||
|
||||
await btn?.click();
|
||||
assert.htmlEqual(target.innerHTML, `<button>2</button>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,19 @@
|
||||
<script>
|
||||
class Counter {
|
||||
#count = $state.frozen(0);
|
||||
|
||||
constructor(initial_count) {
|
||||
this.#count = initial_count;
|
||||
}
|
||||
|
||||
get count() {
|
||||
return this.#count;
|
||||
}
|
||||
set count(val) {
|
||||
this.#count = val;
|
||||
}
|
||||
}
|
||||
const counter = new Counter(0);
|
||||
</script>
|
||||
|
||||
<button on:click={() => counter.count++}>{counter.count}</button>
|
||||
@ -0,0 +1,38 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<button>Update</button>
|
||||
|
||||
<p>0</p>
|
||||
<p>b</p>
|
||||
<p>true</p>
|
||||
<p>0</p>
|
||||
<p>10</p>
|
||||
<p>12</p>
|
||||
<p>15</p>
|
||||
<p>16</p>
|
||||
`,
|
||||
|
||||
async test({ assert, target, window }) {
|
||||
const button = target.querySelector('button');
|
||||
const clickEvent = new window.Event('click', { bubbles: true });
|
||||
await button?.dispatchEvent(clickEvent);
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>Update</button>
|
||||
|
||||
<p>5</p>
|
||||
<p>d</p>
|
||||
<p>false</p>
|
||||
<p>3</p>
|
||||
<p>100</p>
|
||||
<p>120</p>
|
||||
<p>25</p>
|
||||
<p>26</p>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,23 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state("b");
|
||||
let c = $state(true);
|
||||
let d = $state([]);
|
||||
let e = $state({ x: 10, y: 12 });
|
||||
let f = $state({ w: 15, v: 16 });
|
||||
|
||||
function change() {
|
||||
({ d, e, g: [f.w, f.v] } = { d: ([a, b, c] = [5, "d", false]), e: { x: 100, y: 120 }, g: [25, 26] });
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={change}>Update</button>
|
||||
|
||||
<p>{a}</p>
|
||||
<p>{b}</p>
|
||||
<p>{c}</p>
|
||||
<p>{d.length}</p>
|
||||
<p>{e.x}</p>
|
||||
<p>{e.y}</p>
|
||||
<p>{f.w}</p>
|
||||
<p>{f.v}</p>
|
||||
@ -0,0 +1,11 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
const [b1] = target.querySelectorAll('button');
|
||||
b1.click();
|
||||
await Promise.resolve();
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>0, 1</button>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,11 @@
|
||||
<script>
|
||||
let items = $state.frozen([0]);
|
||||
|
||||
const addItem = () => {
|
||||
items = [...items, items.length];
|
||||
};
|
||||
</script>
|
||||
|
||||
<button on:click={addItem}>
|
||||
{items.join(', ')}
|
||||
</button>
|
||||
@ -0,0 +1,17 @@
|
||||
import { test } from '../../test';
|
||||
import { log } from './log.js';
|
||||
|
||||
export default test({
|
||||
before_test() {
|
||||
log.length = 0;
|
||||
},
|
||||
|
||||
async test({ assert, target }) {
|
||||
const [b1, b2] = target.querySelectorAll('button');
|
||||
b1.click();
|
||||
b2.click();
|
||||
await Promise.resolve();
|
||||
|
||||
assert.deepEqual(log, [0, 1]);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,2 @@
|
||||
/** @type {any[]} */
|
||||
export const log = [];
|
||||
@ -0,0 +1,13 @@
|
||||
<script>
|
||||
import { log } from './log.js';
|
||||
|
||||
let x = $state.frozen(0);
|
||||
let y = $state.frozen(0);
|
||||
|
||||
$effect(() => {
|
||||
log.push(x);
|
||||
});
|
||||
</script>
|
||||
|
||||
<button on:click={() => x++}>{x}</button>
|
||||
<button on:click={() => y++}>{y}</button>
|
||||
@ -0,0 +1,12 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
test({ assert, component, target }) {
|
||||
const div = /** @type {HTMLDivElement & { foo?: number }} */ (target.querySelector('div'));
|
||||
|
||||
assert.equal(div.foo, undefined);
|
||||
component.foo = 2;
|
||||
component.visible = false;
|
||||
assert.equal(div.foo, 2);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
const { visible = true, foo = 1 } = $props();
|
||||
|
||||
function bar(node, params) {
|
||||
node.foo = params;
|
||||
return () => ({});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
<div transition:bar={foo}></div>
|
||||
{/if}
|
||||
Loading…
Reference in new issue