Merge branch 'safari-borking' into add-more-hydration-mismatch

pull/12755/head
Rich Harris 2 years ago
commit 67bfcfde52

@ -0,0 +1,5 @@
---
'svelte': patch
---
perf: speed up $.exclude_from_object

@ -0,0 +1,5 @@
---
'svelte': patch
---
chore: publish package provenance info

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: skip `is_standalone` optimisation for dynamic components

@ -53,6 +53,7 @@
"bright-snakes-sing",
"brown-geckos-fry",
"brown-houses-obey",
"brown-insects-float",
"brown-months-fry",
"brown-spoons-boil",
"calm-buses-clap",
@ -193,6 +194,7 @@
"fluffy-colts-grin",
"fluffy-dolls-share",
"fluffy-humans-worry",
"fluffy-kings-complain",
"fluffy-ravens-juggle",
"forty-bikes-buy",
"forty-comics-invent",
@ -266,6 +268,7 @@
"happy-moles-live",
"happy-suits-film",
"healthy-ants-film",
"healthy-dancers-play",
"healthy-mangos-brush",
"healthy-planes-vanish",
"healthy-zebras-accept",
@ -416,8 +419,10 @@
"nervous-turkeys-end",
"new-boats-wait",
"new-brooms-grin",
"new-cooks-roll",
"new-rabbits-flow",
"nice-avocados-move",
"nice-bottles-greet",
"nice-jobs-breathe",
"nine-cooks-join",
"ninety-days-visit",
@ -436,6 +441,7 @@
"old-oranges-compete",
"olive-apples-lick",
"olive-cobras-wonder",
"olive-forks-grin",
"olive-kangaroos-brake",
"olive-mice-fix",
"olive-moons-act",
@ -569,6 +575,7 @@
"silver-mice-double",
"silver-points-approve",
"silver-sheep-knock",
"six-apes-peel",
"six-bears-trade",
"six-boats-shave",
"six-chicken-kneel",
@ -762,6 +769,7 @@
"wicked-hairs-cheer",
"wicked-wasps-allow",
"wicked-ways-reply",
"wicked-years-drive",
"wild-cows-chew",
"wild-foxes-wonder",
"wild-moose-compare",

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: order of arguments for `push_element` in `svelte:element`

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure event handlers referencing $host are not hoisted

@ -0,0 +1,5 @@
---
'svelte': patch
---
feat: simplify derived object destructuring

@ -12,6 +12,7 @@ jobs:
if: github.repository == 'sveltejs/svelte'
permissions:
contents: write # to create release (changesets/action)
id-token: write # OpenID Connect token needed for provenance
pull-requests: write # to create pull request (changesets/action)
name: Release
runs-on: ubuntu-latest

@ -1,5 +1,29 @@
# svelte
## 5.0.0-next.212
### Patch Changes
- perf: speed up $.exclude_from_object ([#12783](https://github.com/sveltejs/svelte/pull/12783))
- chore: publish package provenance info ([#12779](https://github.com/sveltejs/svelte/pull/12779))
- feat: simplify derived object destructuring ([#12781](https://github.com/sveltejs/svelte/pull/12781))
## 5.0.0-next.211
### Patch Changes
- fix: improve prop binding warning validation for stores ([#12745](https://github.com/sveltejs/svelte/pull/12745))
- chore: add error for derived self referencing ([#12746](https://github.com/sveltejs/svelte/pull/12746))
- fix: skip `is_standalone` optimisation for dynamic components ([#12767](https://github.com/sveltejs/svelte/pull/12767))
- fix: ensure unowned deriveds correctly update ([#12747](https://github.com/sveltejs/svelte/pull/12747))
- fix: order of arguments for `push_element` in `svelte:element` ([#12763](https://github.com/sveltejs/svelte/pull/12763))
## 5.0.0-next.210
### Patch Changes

@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.0.0-next.210",
"version": "5.0.0-next.212",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
@ -154,5 +154,8 @@
"project": [
"src/**"
]
},
"publishConfig": {
"provenance": true
}
}

@ -155,8 +155,8 @@ function get_delegated_event(event_name, handler, context) {
const visited_references = new Set();
const scope = target_function.metadata.scope;
for (const [reference] of scope.references) {
// Bail out if the arguments keyword is used
if (reference === 'arguments') return unhoisted;
// Bail out if the arguments keyword is used or $host is referenced
if (reference === 'arguments' || reference === '$host') return unhoisted;
// Bail out if references a store subscription
if (scope.get(`$${reference}`)?.kind === 'store_sub') return unhoisted;

@ -171,39 +171,29 @@ export function VariableDeclaration(node, context) {
)
);
} else {
const bindings = context.state.scope.get_bindings(declarator);
const object_id = context.state.scope.generate('derived_object');
const values_id = context.state.scope.generate('derived_values');
declarations.push(
b.declarator(
b.id(object_id),
b.call('$.derived', rune === '$derived.by' ? value : b.thunk(value))
)
);
declarations.push(
b.declarator(
b.id(values_id),
b.call(
'$.derived',
b.thunk(
b.block([
b.let(declarator.id, b.call('$.get', b.id(object_id))),
b.return(b.array(bindings.map((binding) => binding.node)))
])
)
)
)
);
const bindings = extract_paths(declarator.id);
const init = /** @type {CallExpression} */ (declarator.init);
/** @type {Identifier} */
let id;
let rhs = value;
if (init.arguments[0].type === 'Identifier') {
id = init.arguments[0];
} else {
id = b.id(context.state.scope.generate('$$d'));
rhs = b.call('$.get', id);
declarations.push(
b.declarator(id, b.call('$.derived', rune === '$derived.by' ? value : b.thunk(value)))
);
}
for (let i = 0; i < bindings.length; i++) {
const binding = bindings[i];
declarations.push(
b.declarator(
binding.node,
b.call(
'$.derived',
b.thunk(b.member(b.call('$.get', b.id(values_id)), b.literal(i), true))
)
)
b.declarator(binding.node, b.call('$.derived', b.thunk(binding.expression(rhs))))
);
}
}

@ -1,7 +1,8 @@
/** @import { Location } from 'locate-character' */
/** @import { BlockStatement, Expression } from 'estree' */
/** @import { SvelteElement } from '#compiler' */
/** @import { ComponentContext } from '../types.js' */
import { dev } from '../../../../state.js';
import { dev, locator } from '../../../../state.js';
import * as b from '../../../../utils/builders.js';
import { determine_namespace_for_children } from '../../utils.js';
import { build_element_attributes } from './shared/element.js';
@ -36,7 +37,18 @@ export function SvelteElement(node, context) {
build_element_attributes(node, { ...context, state });
if (dev) {
context.state.template.push(b.stmt(b.call('$.push_element', tag, b.id('$$payload'))));
const location = /** @type {Location} */ (locator(node.start));
context.state.template.push(
b.stmt(
b.call(
'$.push_element',
b.id('$$payload'),
tag,
b.literal(location.line),
b.literal(location.column)
)
)
);
}
const attributes = b.block([...state.init, ...build_template(state.template)]);

@ -283,6 +283,7 @@ export function clean_nodes(
((first.type === 'RenderTag' && !first.metadata.dynamic) ||
(first.type === 'Component' &&
!state.options.hmr &&
!first.metadata.dynamic &&
!first.attributes.some(
(attribute) => attribute.type === 'Attribute' && attribute.name.startsWith('--')
))),

@ -276,15 +276,19 @@ function _extract_paths(assignments = [], param, expression, update_expression,
const rest_expression = (object) => {
/** @type {ESTree.Expression[]} */
const props = [];
for (const p of param.properties) {
if (p.type === 'Property' && p.key.type !== 'PrivateIdentifier') {
if (p.key.type === 'Identifier' && !p.computed) {
props.push(b.literal(p.key.name));
} else if (p.key.type === 'Literal') {
props.push(b.literal(String(p.key.value)));
} else {
props.push(p.key);
props.push(b.call('String', p.key));
}
}
}
return b.call('$.exclude_from_object', expression(object), b.array(props));
};

@ -991,12 +991,16 @@ export function update_pre(signal, d = 1) {
* @returns {Record<string, unknown>}
*/
export function exclude_from_object(obj, keys) {
obj = { ...obj };
let key;
for (key of keys) {
delete obj[key];
/** @type {Record<string, unknown>} */
var result = {};
for (var key in obj) {
if (!keys.includes(key)) {
result[key] = obj[key];
}
}
return obj;
return result;
}
/**

@ -6,5 +6,5 @@
* https://svelte.dev/docs/svelte-compiler#svelte-version
* @type {string}
*/
export const VERSION = '5.0.0-next.210';
export const VERSION = '5.0.0-next.212';
export const PUBLIC_VERSION = '5';

@ -0,0 +1 @@
<!--[--><h1>call +636-555-3226 now</h1><!--]-->

@ -0,0 +1 @@
<!--[--><h1>call <a href="tel:+636-555-3226">+636-555-3226</a> now</h1><!--]-->

@ -0,0 +1,5 @@
<script>
const message = `call +636-555-3226 now`;
</script>
<h1>{message}</h1>

@ -0,0 +1,2 @@
<!-- unrelated comment -->
<!--[--><!--[-->hello<!--]--><!--]-->

@ -113,11 +113,10 @@ const { test, run } = suite<HydrationTest>(async (config, cwd) => {
throw new Error(`Unexpected errors: ${errors.join('\n')}`);
}
if (!override) {
const expected = read(`${cwd}/_expected.html`) ?? rendered.html;
flushSync();
assert.equal(target.innerHTML.trim(), expected.trim());
}
flushSync();
const expected = read(`${cwd}/_expected.html`) ?? rendered.html;
assert.equal(target.innerHTML.trim(), expected.trim());
if (rendered.head) {
const expected = read(`${cwd}/_expected_head.html`) ?? rendered.head;

@ -14,11 +14,13 @@ export default test({
await tick();
el.shadowRoot.querySelector('button').click();
assert.deepEqual(events, ['greeting', 'hello']);
el.shadowRoot.querySelectorAll('button')[0].click();
el.shadowRoot.querySelectorAll('button')[1].click();
assert.deepEqual(events, ['greeting', 'hello', 'greeting', 'welcome']);
el.removeEventListener('greeting', handle_evt);
el.shadowRoot.querySelector('button').click();
assert.deepEqual(events, ['greeting', 'hello']);
el.shadowRoot.querySelectorAll('button')[0].click();
el.shadowRoot.querySelectorAll('button')[1].click();
assert.deepEqual(events, ['greeting', 'hello', 'greeting', 'welcome']);
}
});

@ -4,6 +4,11 @@
function greet(greeting) {
$host().dispatchEvent(new CustomEvent('greeting', { detail: greeting }))
}
function welcome() {
$host().dispatchEvent(new CustomEvent('greeting', { detail: 'welcome' }))
}
</script>
<button onclick={() => greet('hello')}>say hello</button>
<button onclick={welcome}>say welcome</button>

@ -9,18 +9,21 @@ export default test({
quote: 'q1',
'wrong-quote': 'wq1',
16: '16',
17: '17',
class: 'class'
},
{
quote: 'q2',
'wrong-quote': 'wq2',
16: 'sixteen',
17: 'seventeen',
class: 'glass'
},
{
quote: 'q3',
'wrong-quote': 'wq3',
16: 'seize',
17: 'dix-sept',
class: 'mass'
}
]
@ -28,19 +31,19 @@ export default test({
},
html: `
<p class="class">Quote: q1, Wrong Quote: wq1, 16: 16</p>
<p class="glass">Quote: q2, Wrong Quote: wq2, 16: sixteen</p>
<p class="mass">Quote: q3, Wrong Quote: wq3, 16: seize</p>
<p class="class">Quote: q1, Wrong Quote: wq1, 16: 16, 17: 17</p>
<p class="glass">Quote: q2, Wrong Quote: wq2, 16: sixteen, 17: seventeen</p>
<p class="mass">Quote: q3, Wrong Quote: wq3, 16: seize, 17: dix-sept</p>
`,
test({ assert, component, target }) {
component.objectsArray = [
{ quote: 'new-quote', 'wrong-quote': 'wq4', 16: 'ten+six', role: 'role' }
{ quote: 'new-quote', 'wrong-quote': 'wq4', 16: 'ten+six', 17: 'ten+seven', role: 'role' }
];
assert.htmlEqual(
target.innerHTML,
`
<p role="role">Quote: new-quote, Wrong Quote: wq4, 16: ten+six</p>
<p role="role">Quote: new-quote, Wrong Quote: wq4, 16: ten+six, 17: ten+seven</p>
`
);
}

@ -2,6 +2,6 @@
export let objectsArray;
</script>
{#each objectsArray as { "quote": quotedProp, "wrong-quote": wrongQuote, 16: sixteen, ...props } }
<p {...props}>Quote: {quotedProp}, Wrong Quote: {wrongQuote}, 16: {sixteen}</p>
{#each objectsArray as { "quote": quotedProp, "wrong-quote": wrongQuote, 16: sixteen, [10 + 7]: seventeen, ...props }}
<p {...props}>Quote: {quotedProp}, Wrong Quote: {wrongQuote}, 16: {sixteen}, 17: {seventeen}</p>
{/each}

@ -1,5 +1,5 @@
import { test } from '../../test';
export default test({
html: `true 1 2 baz`
html: `true 1 2 baz 1 2 3`
});

@ -1,6 +1,9 @@
<script>
let stuff = $state({ foo: true, bar: [1, 2, {baz: 'baz'}] });
let { foo, bar: [a, b, { baz }]} = $derived(stuff);
let stuff2 = $state([1, 2, 3]);
let [d, e, f] = $derived(stuff2);
</script>
{foo} {a} {b} {baz}
{foo} {a} {b} {baz} {d} {e} {f}

@ -0,0 +1,5 @@
<script>
let { id } = $props();
</script>
<span>{id}</span>

@ -0,0 +1,16 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button>flip</button> <span>0</span><span>1</span><span>2</span>`,
async test({ assert, target }) {
const button = target.querySelector('button');
flushSync(() => button?.click());
assert.htmlEqual(
target.innerHTML,
`<button>flip</button> <span>2</span><span>1</span><span>0</span>`
);
}
});

@ -0,0 +1,13 @@
<script>
import Row from './Row.svelte';
const items = $state([{ id: 0 }, { id: 1 }, { id: 2 }]);
const Table = { Row };
</script>
<button onclick={() => items.reverse()}> flip </button>
{#each items as item (item.id)}
<Table.Row id={item.id} />
{/each}

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
compileOptions: {
dev: true
}
});

@ -0,0 +1 @@
<!--[--><!----><p ><!----><p ><!----></p><!----><!----></p><!----><!--]-->

@ -0,0 +1 @@
<script>console.error("node_invalid_placement_ssr: `<p>` (packages/svelte/tests/server-side-rendering/samples/invalid-nested-svelte-element/main.svelte:1:0) cannot contain `<p>` (packages/svelte/tests/server-side-rendering/samples/invalid-nested-svelte-element/main.svelte:2:1)\n\nThis can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.")</script>

@ -0,0 +1,3 @@
<svelte:element this={'p'}>
<svelte:element this={'p'}></svelte:element>
</svelte:element>

@ -8,7 +8,10 @@
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"><!--ssr-body--></div>
<!-- prettier-ignore -->
<div id="root">
<!--[--><h1>call <a href="tel:+636-555-3226">+636-555-3226</a> now</h1><!--]-->
</div>
<script type="module">
import { mount, hydrate, unmount } from 'svelte';

Loading…
Cancel
Save