From 11c7cd5495903c42398b2a0e87520a6fbf55a638 Mon Sep 17 00:00:00 2001 From: Vaibhav Rai Date: Mon, 22 Apr 2024 17:16:42 +0530 Subject: [PATCH 01/18] Feat: Add read-only binding focused (#11271) * Feat: Add readonly binding focused * prettier * simplify test * revert * simplify implementation * changeset --------- Co-authored-by: Rich Harris Co-authored-by: Rich Harris --- .changeset/thick-swans-type.md | 5 +++++ .../3-transform/client/visitors/template.js | 4 +++- .../svelte/src/compiler/phases/bindings.js | 1 + .../client/dom/elements/bindings/universal.js | 12 ++++++++++++ packages/svelte/src/internal/client/index.js | 6 +++++- .../samples/binding-focused/_config.js | 19 +++++++++++++++++++ .../samples/binding-focused/main.svelte | 7 +++++++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 .changeset/thick-swans-type.md create mode 100644 packages/svelte/tests/runtime-legacy/samples/binding-focused/_config.js create mode 100644 packages/svelte/tests/runtime-legacy/samples/binding-focused/main.svelte diff --git a/.changeset/thick-swans-type.md b/.changeset/thick-swans-type.md new file mode 100644 index 0000000000..430cdbdc5b --- /dev/null +++ b/.changeset/thick-swans-type.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +feat: add read-only `bind:focused` diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index fa711c324f..e9d3b519c7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -2727,7 +2727,9 @@ export const template_visitors = { case 'checked': call_expr = b.call(`$.bind_checked`, state.node, getter, setter); break; - + case 'focused': + call_expr = b.call(`$.bind_focused`, state.node, setter); + break; case 'group': { /** @type {import('estree').CallExpression[]} */ const indexes = []; diff --git a/packages/svelte/src/compiler/phases/bindings.js b/packages/svelte/src/compiler/phases/bindings.js index e3fdd7eb8c..9a6f1c316b 100644 --- a/packages/svelte/src/compiler/phases/bindings.js +++ b/packages/svelte/src/compiler/phases/bindings.js @@ -21,6 +21,7 @@ export const binding_properties = { event: 'durationchange', omit_in_ssr: true }, + focused: {}, paused: { valid_elements: ['audio', 'video'], omit_in_ssr: true diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/universal.js b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js index 8c40c04da5..f42f67d594 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/universal.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/universal.js @@ -1,4 +1,5 @@ import { render_effect } from '../../../reactivity/effects.js'; +import { listen } from './shared.js'; /** * @param {'innerHTML' | 'textContent' | 'innerText'} property @@ -67,3 +68,14 @@ export function bind_property(property, event_name, type, element, get_value, up } }); } + +/** + * @param {HTMLElement} element + * @param {(value: unknown) => void} update + * @returns {void} + */ +export function bind_focused(element, update) { + listen(element, ['focus', 'blur'], () => { + update(element === document.activeElement); + }); +} diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 2362698ab1..6e6488c001 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -44,7 +44,11 @@ export { bind_prop } from './dom/elements/bindings/props.js'; export { bind_select_value, init_select, select_option } from './dom/elements/bindings/select.js'; export { bind_element_size, bind_resize_observer } from './dom/elements/bindings/size.js'; export { bind_this } from './dom/elements/bindings/this.js'; -export { bind_content_editable, bind_property } from './dom/elements/bindings/universal.js'; +export { + bind_content_editable, + bind_property, + bind_focused +} from './dom/elements/bindings/universal.js'; export { bind_window_scroll, bind_window_size } from './dom/elements/bindings/window.js'; export { once, diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-focused/_config.js b/packages/svelte/tests/runtime-legacy/samples/binding-focused/_config.js new file mode 100644 index 0000000000..02f2574f34 --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/binding-focused/_config.js @@ -0,0 +1,19 @@ +import { flushSync } from 'svelte'; + +import { test } from '../../test'; + +export default test({ + async test({ assert, component, target, window }) { + const [in1, in2] = target.querySelectorAll('input'); + + flushSync(() => in1.focus()); + assert.equal(window.document.activeElement, in1); + assert.equal(component.a, true); + assert.equal(component.b, false); + + flushSync(() => in2.focus()); + assert.equal(window.document.activeElement, in2); + assert.equal(component.a, false); + assert.equal(component.b, true); + } +}); diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-focused/main.svelte b/packages/svelte/tests/runtime-legacy/samples/binding-focused/main.svelte new file mode 100644 index 0000000000..7ba892393d --- /dev/null +++ b/packages/svelte/tests/runtime-legacy/samples/binding-focused/main.svelte @@ -0,0 +1,7 @@ + + + + From 9721d5641b48e4247c87132695f1ca2f2119e0d8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 07:48:50 -0400 Subject: [PATCH 02/18] feat: implement `:global {...}` CSS blocks (#11276) * feat: implement `:global {...}` CSS blocks * tests for compiler errors * regenerate types * lint --- .changeset/small-apples-eat.md | 5 +++ packages/svelte/src/compiler/errors.js | 9 ++++ .../src/compiler/phases/1-parse/read/style.js | 6 +-- .../phases/2-analyze/css/css-analyze.js | 44 +++++++++++++++++++ .../phases/2-analyze/css/css-prune.js | 8 +++- .../compiler/phases/2-analyze/css/css-warn.js | 7 +++ .../compiler/phases/3-transform/css/index.js | 26 ++++++++++- packages/svelte/src/compiler/types/css.d.ts | 1 + .../css-global-block-combinator/_config.js | 9 ++++ .../main.svelte | 2 +- .../css-global-block-declaration/_config.js | 9 ++++ .../css-global-block-declaration/main.svelte | 5 +++ .../css-global-block-modifier/_config.js | 9 ++++ .../css-global-block-modifier/main.svelte | 3 ++ .../css-global-block-multiple/_config.js | 9 ++++ .../css-global-block-multiple/main.svelte | 3 ++ .../css-global-without-selector/_config.js | 9 ---- .../tests/css/samples/global-block/_config.js | 21 +++++++++ .../css/samples/global-block/expected.css | 17 +++++++ .../css/samples/global-block/input.svelte | 21 +++++++++ packages/svelte/types/index.d.ts | 1 + 21 files changed, 208 insertions(+), 16 deletions(-) create mode 100644 .changeset/small-apples-eat.md create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/_config.js rename packages/svelte/tests/compiler-errors/samples/{css-global-without-selector => css-global-block-combinator}/main.svelte (50%) create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/main.svelte create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/main.svelte create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/main.svelte delete mode 100644 packages/svelte/tests/compiler-errors/samples/css-global-without-selector/_config.js create mode 100644 packages/svelte/tests/css/samples/global-block/_config.js create mode 100644 packages/svelte/tests/css/samples/global-block/expected.css create mode 100644 packages/svelte/tests/css/samples/global-block/input.svelte diff --git a/.changeset/small-apples-eat.md b/.changeset/small-apples-eat.md new file mode 100644 index 0000000000..baa6396bb6 --- /dev/null +++ b/.changeset/small-apples-eat.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +feat: implement `:global {...}` CSS blocks diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index ab0a17497e..71bc353336 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -103,6 +103,15 @@ const css = { /** @param {string} message */ 'css-parse-error': (message) => message, 'invalid-css-empty-declaration': () => `Declaration cannot be empty`, + 'invalid-css-global-block-list': () => + `A :global {...} block cannot be part of a selector list with more than one item`, + 'invalid-css-global-block-modifier': () => + `A :global {...} block cannot modify an existing selector`, + /** @param {string} name */ + 'invalid-css-global-block-combinator': (name) => + `A :global {...} block cannot follow a ${name} combinator`, + 'invalid-css-global-block-declaration': () => + `A :global {...} block can only contain rules, not declarations`, 'invalid-css-global-placement': () => `:global(...) can be at the start or end of a selector sequence, but not in the middle`, 'invalid-css-global-selector': () => `:global(...) must contain exactly one selector`, diff --git a/packages/svelte/src/compiler/phases/1-parse/read/style.js b/packages/svelte/src/compiler/phases/1-parse/read/style.js index ef64a97953..8ec00daff1 100644 --- a/packages/svelte/src/compiler/phases/1-parse/read/style.js +++ b/packages/svelte/src/compiler/phases/1-parse/read/style.js @@ -3,7 +3,6 @@ import { error } from '../../../errors.js'; const REGEX_MATCHER = /^[~^$*|]?=/; const REGEX_CLOSING_BRACKET = /[\s\]]/; const REGEX_ATTRIBUTE_FLAGS = /^[a-zA-Z]+/; // only `i` and `s` are valid today, but make it future-proof -const REGEX_COMBINATOR_WHITESPACE = /^\s*(\+|~|>|\|\|)\s*/; const REGEX_COMBINATOR = /^(\+|~|>|\|\|)/; const REGEX_PERCENTAGE = /^\d+(\.\d+)?%/; const REGEX_NTH_OF = @@ -116,7 +115,8 @@ function read_rule(parser) { end: parser.index, metadata: { parent_rule: null, - has_local_selectors: false + has_local_selectors: false, + is_global_block: false } }; } @@ -252,8 +252,6 @@ function read_selector(parser, inside_pseudo_class = false) { if (parser.eat('(')) { args = read_selector_list(parser, true); parser.eat(')', true); - } else if (name === 'global') { - error(parser.index, 'invalid-css-global-selector'); } relative_selector.selectors.push({ diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js index 7b6cbff0ae..38a62b9ca7 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js @@ -69,6 +69,17 @@ const analysis_visitors = { Rule(node, context) { node.metadata.parent_rule = context.state.rule; + // `:global {...}` or `div :global {...}` + node.metadata.is_global_block = node.prelude.children.some((selector) => { + const last = selector.children[selector.children.length - 1]; + + const s = last.selectors[last.selectors.length - 1]; + + if (s.type === 'PseudoClassSelector' && s.name === 'global' && s.args === null) { + return true; + } + }); + context.next({ ...context.state, rule: node @@ -84,6 +95,39 @@ const analysis_visitors = { /** @type {Visitors} */ const validation_visitors = { + Rule(node, context) { + if (node.metadata.is_global_block) { + if (node.prelude.children.length > 1) { + error(node.prelude, 'invalid-css-global-block-list'); + } + + const complex_selector = node.prelude.children[0]; + const relative_selector = complex_selector.children[complex_selector.children.length - 1]; + + if (relative_selector.selectors.length > 1) { + error( + relative_selector.selectors[relative_selector.selectors.length - 1], + 'invalid-css-global-block-modifier' + ); + } + + if (relative_selector.combinator && relative_selector.combinator.name !== ' ') { + error( + relative_selector, + 'invalid-css-global-block-combinator', + relative_selector.combinator.name + ); + } + + const declaration = node.block.children.find((child) => child.type === 'Declaration'); + + if (declaration) { + error(declaration, 'invalid-css-global-block-declaration'); + } + } + + context.next(); + }, ComplexSelector(node, context) { // ensure `:global(...)` is not used in the middle of a selector { diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js index a5010c543a..1726a4fab1 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js @@ -1,7 +1,6 @@ import { walk } from 'zimmerframe'; import { get_possible_values } from './utils.js'; import { regex_ends_with_whitespace, regex_starts_with_whitespace } from '../../patterns.js'; -import { error } from '../../../errors.js'; /** * @typedef {{ @@ -60,6 +59,13 @@ export function prune(stylesheet, element) { /** @type {import('zimmerframe').Visitors} */ const visitors = { + Rule(node, context) { + if (node.metadata.is_global_block) { + context.visit(node.prelude); + } else { + context.next(); + } + }, ComplexSelector(node, context) { const selectors = truncate(node); const inner = selectors[selectors.length - 1]; diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-warn.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-warn.js index 8d7fef873f..3aa2382205 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-warn.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-warn.js @@ -30,5 +30,12 @@ const visitors = { } context.next(); + }, + Rule(node, context) { + if (node.metadata.is_global_block) { + context.visit(node.prelude); + } else { + context.next(); + } } }; diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index a71d77b2aa..cb54841657 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -116,7 +116,7 @@ const visitors = { } } }, - Rule(node, { state, next }) { + Rule(node, { state, next, visit }) { // keep empty rules in dev, because it's convenient to // see them in devtools if (!state.dev && is_empty(node)) { @@ -134,6 +134,26 @@ const visitors = { return; } + if (node.metadata.is_global_block) { + const selector = node.prelude.children[0]; + + if (selector.children.length === 1) { + // `:global {...}` + state.code.prependRight(node.start, '/* '); + state.code.appendLeft(node.block.start + 1, '*/'); + + state.code.prependRight(node.block.end - 1, '/*'); + state.code.appendLeft(node.block.end, '*/'); + + // don't recurse into selector or body + return; + } + + // don't recurse into body + visit(node.prelude); + return; + } + next(); }, SelectorList(node, { state, next, path }) { @@ -275,6 +295,10 @@ const visitors = { /** @param {import('#compiler').Css.Rule} rule */ function is_empty(rule) { + if (rule.metadata.is_global_block) { + return rule.block.children.length === 0; + } + for (const child of rule.block.children) { if (child.type === 'Declaration') { return false; diff --git a/packages/svelte/src/compiler/types/css.d.ts b/packages/svelte/src/compiler/types/css.d.ts index 4bce904425..ee323ad6d1 100644 --- a/packages/svelte/src/compiler/types/css.d.ts +++ b/packages/svelte/src/compiler/types/css.d.ts @@ -33,6 +33,7 @@ export namespace Css { metadata: { parent_rule: null | Rule; has_local_selectors: boolean; + is_global_block: boolean; }; } diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/_config.js new file mode 100644 index 0000000000..6a11aa63ec --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'invalid-css-global-block-combinator', + message: 'A :global {...} block cannot follow a > combinator', + position: [12, 21] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-without-selector/main.svelte b/packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/main.svelte similarity index 50% rename from packages/svelte/tests/compiler-errors/samples/css-global-without-selector/main.svelte rename to packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/main.svelte index a626136cfc..b3b6ebe6ac 100644 --- a/packages/svelte/tests/compiler-errors/samples/css-global-without-selector/main.svelte +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-combinator/main.svelte @@ -1,3 +1,3 @@ diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/_config.js new file mode 100644 index 0000000000..7b637ca42e --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'invalid-css-global-block-declaration', + message: 'A :global {...} block can only contain rules, not declarations', + position: [24, 34] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/main.svelte b/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/main.svelte new file mode 100644 index 0000000000..6a1891ca29 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-declaration/main.svelte @@ -0,0 +1,5 @@ + diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/_config.js new file mode 100644 index 0000000000..9e7cac667f --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'invalid-css-global-block-modifier', + message: 'A :global {...} block cannot modify an existing selector', + position: [14, 21] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/main.svelte b/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/main.svelte new file mode 100644 index 0000000000..7d274e3894 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-modifier/main.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/_config.js new file mode 100644 index 0000000000..8021a9c677 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'invalid-css-global-block-list', + message: 'A :global {...} block cannot be part of a selector list with more than one item', + position: [9, 31] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/main.svelte b/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/main.svelte new file mode 100644 index 0000000000..75178bc664 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/css-global-block-multiple/main.svelte @@ -0,0 +1,3 @@ + diff --git a/packages/svelte/tests/compiler-errors/samples/css-global-without-selector/_config.js b/packages/svelte/tests/compiler-errors/samples/css-global-without-selector/_config.js deleted file mode 100644 index 549ad3ebe2..0000000000 --- a/packages/svelte/tests/compiler-errors/samples/css-global-without-selector/_config.js +++ /dev/null @@ -1,9 +0,0 @@ -import { test } from '../../test'; - -export default test({ - error: { - code: 'invalid-css-global-selector', - message: ':global(...) must contain exactly one selector', - position: [16, 16] - } -}); diff --git a/packages/svelte/tests/css/samples/global-block/_config.js b/packages/svelte/tests/css/samples/global-block/_config.js new file mode 100644 index 0000000000..53b9ee318f --- /dev/null +++ b/packages/svelte/tests/css/samples/global-block/_config.js @@ -0,0 +1,21 @@ +import { test } from '../../test'; + +export default test({ + warnings: [ + { + filename: 'SvelteComponent.svelte', + code: 'css-unused-selector', + message: 'Unused CSS selector ".unused :global"', + start: { + line: 16, + column: 1, + character: 128 + }, + end: { + line: 16, + column: 16, + character: 143 + } + } + ] +}); diff --git a/packages/svelte/tests/css/samples/global-block/expected.css b/packages/svelte/tests/css/samples/global-block/expected.css new file mode 100644 index 0000000000..8bf0f0e596 --- /dev/null +++ b/packages/svelte/tests/css/samples/global-block/expected.css @@ -0,0 +1,17 @@ + /* :global {*/ + .x { + color: green; + } + /*}*/ + + div.svelte-xyz { + .y { + color: green; + } + } + + /* (unused) .unused :global { + .z { + color: red; + } + }*/ diff --git a/packages/svelte/tests/css/samples/global-block/input.svelte b/packages/svelte/tests/css/samples/global-block/input.svelte new file mode 100644 index 0000000000..d05a6b7edc --- /dev/null +++ b/packages/svelte/tests/css/samples/global-block/input.svelte @@ -0,0 +1,21 @@ +
{@html whatever}
+ + diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 900bee5a76..401b569a61 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -1122,6 +1122,7 @@ declare module 'svelte/compiler' { metadata: { parent_rule: null | Rule; has_local_selectors: boolean; + is_global_block: boolean; }; } From 521d124267080a1e70ba40f5e36aec648c52d99d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 07:51:55 -0400 Subject: [PATCH 03/18] fix: allow events to continue propagating following an error (#11263) * fix: allow events to continue propagating following an error * test * appease eslint --- .changeset/light-penguins-invent.md | 5 ++ .../internal/client/dom/elements/events.js | 56 ++++++++++--------- .../event-propagation-with-error/_config.js | 15 +++++ .../event-propagation-with-error/main.svelte | 19 +++++++ 4 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 .changeset/light-penguins-invent.md create mode 100644 packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/main.svelte diff --git a/.changeset/light-penguins-invent.md b/.changeset/light-penguins-invent.md new file mode 100644 index 0000000000..2610fddf06 --- /dev/null +++ b/.changeset/light-penguins-invent.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: allow events to continue propagating following an error diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index 330bcc2661..536b1c0442 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -122,36 +122,42 @@ export function handle_event_propagation(handler_element, event) { } }); - while (current_target !== null) { + /** @param {Element} current_target */ + function next(current_target) { /** @type {null | Element} */ var parent_element = current_target.parentNode || /** @type {any} */ (current_target).host || null; - var internal_prop_name = '__' + event_name; - // @ts-ignore - var delegated = current_target[internal_prop_name]; - - if (delegated !== undefined && !(/** @type {any} */ (current_target).disabled)) { - if (is_array(delegated)) { - var [fn, ...data] = delegated; - fn.apply(current_target, [event, ...data]); - } else { - delegated.call(current_target, event); - } - } - if ( - event.cancelBubble || - parent_element === handler_element || - current_target === handler_element - ) { - break; + try { + // @ts-expect-error + var delegated = current_target['__' + event_name]; + + if (delegated !== undefined && !(/** @type {any} */ (current_target).disabled)) { + if (is_array(delegated)) { + var [fn, ...data] = delegated; + fn.apply(current_target, [event, ...data]); + } else { + delegated.call(current_target, event); + } + } + } finally { + if ( + !event.cancelBubble && + parent_element !== handler_element && + parent_element !== null && + current_target !== handler_element + ) { + next(parent_element); + } } - - current_target = parent_element; } - // @ts-expect-error is used above - event.__root = handler_element; - // @ts-expect-error is used above - current_target = handler_element; + try { + next(current_target); + } finally { + // @ts-expect-error is used above + event.__root = handler_element; + // @ts-expect-error is used above + current_target = handler_element; + } } diff --git a/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/_config.js b/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/_config.js new file mode 100644 index 0000000000..d12f42f863 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/_config.js @@ -0,0 +1,15 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + html: `
`, + + async test({ assert, target }) { + const button1 = target.querySelector('button'); + + flushSync(() => button1?.click()); + assert.htmlEqual(target.innerHTML, `
`); + }, + + runtime_error: 'nope' +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/main.svelte new file mode 100644 index 0000000000..4bab336347 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-propagation-with-error/main.svelte @@ -0,0 +1,19 @@ + + +
+ +
From 5ef1fdf7cc2575efb07b2d1504d1c8e247942476 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 07:52:40 -0400 Subject: [PATCH 04/18] fix: run render functions for dynamic void elements (#11258) * fix: run render functions for dynamic void elements * Update packages/svelte/src/internal/client/dom/blocks/svelte-element.js --- .changeset/fifty-masks-give.md | 5 +++++ .../internal/client/dom/blocks/svelte-element.js | 14 ++++++-------- .../samples/action-void-element/_config.js | 11 +++++++++++ .../samples/action-void-element/main.svelte | 9 +++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 .changeset/fifty-masks-give.md create mode 100644 packages/svelte/tests/runtime-runes/samples/action-void-element/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/action-void-element/main.svelte diff --git a/.changeset/fifty-masks-give.md b/.changeset/fifty-masks-give.md new file mode 100644 index 0000000000..c555a7a34b --- /dev/null +++ b/.changeset/fifty-masks-give.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: run render functions for dynamic void elements diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js index bb660209e1..1972ee4cb7 100644 --- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js +++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js @@ -40,7 +40,7 @@ function swap_block_dom(effect, from, to) { * @param {Comment} anchor * @param {() => string} get_tag * @param {boolean} is_svg - * @param {undefined | ((element: Element, anchor: Node) => void)} render_fn, + * @param {undefined | ((element: Element, anchor: Node | null) => void)} render_fn, * @param {undefined | (() => string)} get_namespace * @returns {void} */ @@ -115,13 +115,11 @@ export function element(anchor, get_tag, is_svg, render_fn, get_namespace) { ? element.firstChild && hydrate_anchor(/** @type {Comment} */ (element.firstChild)) : element.appendChild(empty()); - if (child_anchor) { - // `child_anchor` can be undefined if this is a void element with children, - // i.e. `...`. This is - // user error, but we warn on it elsewhere (in dev) so here we just - // silently ignore it - render_fn(element, child_anchor); - } + // `child_anchor` is undefined if this is a void element, but we still + // need to call `render_fn` in order to run actions etc. If the element + // contains children, it's a user error (which is warned on elsewhere) + // and the DOM will be silently discarded + render_fn(element, child_anchor); } anchor.before(element); diff --git a/packages/svelte/tests/runtime-runes/samples/action-void-element/_config.js b/packages/svelte/tests/runtime-runes/samples/action-void-element/_config.js new file mode 100644 index 0000000000..3ebd8d126a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/action-void-element/_config.js @@ -0,0 +1,11 @@ +import { test } from '../../test'; + +export default test({ + html: ``, + + async test({ assert, target }) { + const inputs = target.querySelectorAll('input'); + assert.equal(inputs[0].value, 'set from action'); + assert.equal(inputs[1].value, 'set from action'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/action-void-element/main.svelte b/packages/svelte/tests/runtime-runes/samples/action-void-element/main.svelte new file mode 100644 index 0000000000..e9a833d6ac --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/action-void-element/main.svelte @@ -0,0 +1,9 @@ + + + + From 47ba488cf22a6d3353fe1b550cbfbf96755bbeb6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 07:53:38 -0400 Subject: [PATCH 05/18] fix: only destroy snippets when they have changed (#11267) * fix: only destroy snippets when they have changed * tidy up * changeset * oops * tidy up --- .changeset/shiny-mayflies-clean.md | 5 ++++ .../src/internal/client/dom/blocks/if.js | 16 +++++------- .../src/internal/client/dom/blocks/snippet.js | 18 ++++++++----- .../client/dom/elements/transitions.js | 26 ++++++++++++------- .../src/internal/client/reactivity/effects.js | 9 ++++--- 5 files changed, 47 insertions(+), 27 deletions(-) create mode 100644 .changeset/shiny-mayflies-clean.md diff --git a/.changeset/shiny-mayflies-clean.md b/.changeset/shiny-mayflies-clean.md new file mode 100644 index 0000000000..3adaa3dec8 --- /dev/null +++ b/.changeset/shiny-mayflies-clean.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: only destroy snippets when they have changed diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index c432943c1a..80ed8c09f4 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -20,15 +20,17 @@ export function if_block( elseif = false ) { /** @type {import('#client').Effect | null} */ - let consequent_effect = null; + var consequent_effect = null; /** @type {import('#client').Effect | null} */ - let alternate_effect = null; + var alternate_effect = null; /** @type {boolean | null} */ - let condition = null; + var condition = null; - const effect = block(() => { + var flags = elseif ? EFFECT_TRANSPARENT : 0; + + block(() => { if (condition === (condition = !!get_condition())) return; /** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */ @@ -76,9 +78,5 @@ export function if_block( // continue in hydration mode set_hydrating(true); } - }); - - if (elseif) { - effect.f |= EFFECT_TRANSPARENT; - } + }, flags); } diff --git a/packages/svelte/src/internal/client/dom/blocks/snippet.js b/packages/svelte/src/internal/client/dom/blocks/snippet.js index e885440910..c5097ee2c3 100644 --- a/packages/svelte/src/internal/client/dom/blocks/snippet.js +++ b/packages/svelte/src/internal/client/dom/blocks/snippet.js @@ -1,5 +1,5 @@ import { EFFECT_TRANSPARENT } from '../../constants.js'; -import { branch, render_effect } from '../../reactivity/effects.js'; +import { branch, block, destroy_effect } from '../../reactivity/effects.js'; /** * @template {(node: import('#client').TemplateNode, ...args: any[]) => import('#client').Dom} SnippetFn @@ -12,13 +12,19 @@ export function snippet(get_snippet, node, ...args) { /** @type {SnippetFn | null | undefined} */ var snippet; - var effect = render_effect(() => { + /** @type {import('#client').Effect | null} */ + var snippet_effect; + + block(() => { if (snippet === (snippet = get_snippet())) return; - if (snippet) { - branch(() => /** @type {SnippetFn} */ (snippet)(node, ...args)); + if (snippet_effect) { + destroy_effect(snippet_effect); + snippet_effect = null; } - }); - effect.f |= EFFECT_TRANSPARENT; + if (snippet) { + snippet_effect = branch(() => /** @type {SnippetFn} */ (snippet)(node, ...args)); + } + }, EFFECT_TRANSPARENT); } diff --git a/packages/svelte/src/internal/client/dom/elements/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js index a9f55d940f..3551a093da 100644 --- a/packages/svelte/src/internal/client/dom/elements/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -7,7 +7,7 @@ import { should_intro } from '../../render.js'; import { is_function } from '../../utils.js'; import { current_each_item } from '../blocks/each.js'; import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../constants.js'; -import { BLOCK_EFFECT, EFFECT_RAN } from '../../constants.js'; +import { BLOCK_EFFECT, EFFECT_RAN, EFFECT_TRANSPARENT } from '../../constants.js'; /** * @template T @@ -241,18 +241,26 @@ export function transition(flags, element, get_fn, get_params) { (e.transitions ??= []).push(transition); - // if this is a local transition, we only want to run it if the parent (block) effect's - // parent (branch) effect is where the state change happened. we can determine that by - // looking at whether the branch effect is currently initializing + // if this is a local transition, we only want to run it if the parent (branch) effect's + // parent (block) effect is where the state change happened. we can determine that by + // looking at whether the block effect is currently initializing if (is_intro && should_intro) { - var parent = /** @type {import('#client').Effect} */ (e.parent); + let run = is_global; - // e.g snippets are implemented as render effects — keep going until we find the parent block - while ((parent.f & BLOCK_EFFECT) === 0 && parent.parent) { - parent = parent.parent; + if (!run) { + var block = /** @type {import('#client').Effect | null} */ (e.parent); + + // skip over transparent blocks (e.g. snippets, else-if blocks) + while (block && (block.f & EFFECT_TRANSPARENT) !== 0) { + while ((block = block.parent)) { + if ((block.f & BLOCK_EFFECT) !== 0) break; + } + } + + run = !block || (block.f & EFFECT_RAN) !== 0; } - if (is_global || (parent.f & EFFECT_RAN) !== 0) { + if (run) { effect(() => { untrack(() => transition.in()); }); diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 3b0b97ade5..515d13136e 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -230,9 +230,12 @@ export function render_effect(fn) { return create_effect(RENDER_EFFECT, fn, true); } -/** @param {(() => void)} fn */ -export function block(fn) { - return create_effect(RENDER_EFFECT | BLOCK_EFFECT, fn, true); +/** + * @param {(() => void)} fn + * @param {number} flags + */ +export function block(fn, flags = 0) { + return create_effect(RENDER_EFFECT | BLOCK_EFFECT | flags, fn, true); } /** @param {(() => void)} fn */ From fd5f5bb85d5bf304030e4173bea6e4098168b33b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 07:54:09 -0400 Subject: [PATCH 06/18] monkey-patch console.log and console.warn for all tests (#11265) * monkey-patch console.log and console.warn for all tests * update legacy tests * various * tests passing * tidy up * tidy up * tidier output --- .../samples/ignore-mismatched-href/_config.js | 6 +- packages/svelte/tests/hydration/test.ts | 11 ++- packages/svelte/tests/runtime-browser/test.ts | 1 - .../samples/binding-this-multiple/_config.js | 8 +-- .../samples/binding-this-multiple/main.svelte | 3 +- .../samples/component-nested-deep/_config.js | 4 +- .../Nested.svelte | 8 +-- .../_config.js | 11 +-- .../main.svelte | 5 +- .../Nested.svelte | 8 +-- .../_config.js | 7 +- .../main.svelte | 5 +- .../Inner.svelte | 7 +- .../Nested.svelte | 5 +- .../_config.js | 7 +- .../main.svelte | 3 +- .../samples/destroy-twice/_config.js | 7 +- .../empty-component-destroy/Empty.svelte | 2 +- .../empty-component-destroy/_config.js | 22 +----- .../empty-component-destroy/main.svelte | 2 +- .../event-handler-mutation-scope/_config.js | 6 +- .../event-handler-mutation-scope/main.svelte | 3 +- .../Child.svelte | 9 ++- .../lifecycle-render-afterUpdate2/_config.js | 9 +-- .../lifecycle-render-afterUpdate2/log.js | 2 - .../Child.svelte | 3 +- .../lifecycle-render-beforeUpdate/_config.js | 10 +-- .../lifecycle-render-beforeUpdate/main.svelte | 4 +- .../_config.js | 11 +-- .../reactive-assignment-prevent-loop/log.js | 2 - .../main.svelte | 6 +- .../svelte/tests/runtime-legacy/shared.ts | 68 +++++++++++++------ .../samples/action-context/_config.js | 13 ++-- .../samples/action-context/log.js | 2 - .../samples/action-context/main.svelte | 6 +- .../samples/action-state-arg-deep/Task.svelte | 4 +- .../samples/action-state-arg-deep/_config.js | 11 +-- .../samples/action-state-arg-deep/log.js | 2 - .../Child.svelte | 3 +- .../before-update-in-legacy-child/_config.js | 7 +- .../before-update-in-legacy-child/logs.js | 2 - .../samples/bind-this-proxy/_config.js | 9 +-- .../samples/bind-this-proxy/log.js | 2 - .../samples/bind-this-proxy/main.svelte | 3 +- .../class-frozen-state-object/_config.js | 9 +-- .../samples/class-frozen-state-object/log.js | 2 - .../class-frozen-state-object/main.svelte | 4 +- .../_config.js | 9 +-- .../class-private-frozen-state-object/log.js | 2 - .../main.svelte | 4 +- .../class-state-derived-unowned/_config.js | 15 ++-- .../class-state-derived-unowned/log.js | 2 - .../class-state-derived-unowned/main.svelte | 8 +-- .../class-state-init-eager-2/_config.js | 9 +-- .../samples/class-state-init-eager-2/log.js | 2 - .../class-state-init-eager-2/main.svelte | 4 +- .../class-state-init-eager-3/_config.js | 9 +-- .../samples/class-state-init-eager-3/log.js | 2 - .../class-state-init-eager-3/main.svelte | 4 +- .../samples/class-state-init-eager/_config.js | 9 +-- .../samples/class-state-init-eager/log.js | 2 - .../class-state-init-eager/main.svelte | 4 +- .../samples/derived-destructure/_config.js | 19 ++---- .../samples/derived-destructure/log.js | 2 - .../samples/derived-destructure/main.svelte | 8 +-- .../samples/derived-fn-destructure/_config.js | 10 +-- .../samples/derived-fn-destructure/log.js | 2 - .../derived-fn-destructure/main.svelte | 4 +- .../samples/derived-stale-value/_config.js | 9 +-- .../samples/derived-stale-value/log.js | 2 - .../samples/derived-stale-value/main.svelte | 4 +- .../destructure-derived-event/_config.js | 9 +-- .../samples/destructure-derived-event/log.js | 2 - .../destructure-derived-event/main.svelte | 4 +- .../samples/dynamic-transition/_config.js | 13 ++-- .../samples/dynamic-transition/log.js | 2 - .../samples/dynamic-transition/main.svelte | 6 +- .../samples/effect-cleanup/_config.js | 9 +-- .../samples/effect-cleanup/log.js | 2 - .../samples/effect-cleanup/main.svelte | 8 +-- .../samples/effect-order-2/_config.js | 9 +-- .../samples/effect-order-2/log.js | 2 - .../samples/effect-order-2/main.svelte | 7 +- .../samples/effect-order/_config.js | 9 +-- .../runtime-runes/samples/effect-order/log.js | 2 - .../samples/effect-order/main.svelte | 6 +- .../samples/effect-root-2/_config.js | 13 ++-- .../samples/effect-root-2/log.js | 2 - .../samples/effect-root-2/main.svelte | 6 +- .../samples/effect-root/_config.js | 13 ++-- .../runtime-runes/samples/effect-root/log.js | 2 - .../samples/effect-root/main.svelte | 8 +-- .../runtime-runes/samples/effect/_config.js | 9 +-- .../tests/runtime-runes/samples/effect/log.js | 2 - .../runtime-runes/samples/effect/main.svelte | 4 +- .../samples/effects-order/_config.js | 9 +-- .../samples/effects-order/log.js | 2 - .../samples/effects-order/main.svelte | 6 +- .../event-attribute-delegation-2/_config.js | 9 +-- .../event-attribute-delegation-2/log.js | 2 - .../event-attribute-delegation-2/main.svelte | 7 +- .../event-attribute-delegation-3/_config.js | 9 +-- .../event-attribute-delegation-3/log.js | 2 - .../event-attribute-delegation-3/main.svelte | 9 ++- .../event-attribute-delegation-4/_config.js | 13 ++-- .../event-attribute-delegation-4/log.js | 2 - .../event-attribute-delegation-4/main.svelte | 9 ++- .../event-attribute-delegation-4/sub.svelte | 10 +-- .../event-attribute-delegation-5/_config.js | 9 +-- .../event-attribute-delegation-5/log.js | 2 - .../event-attribute-delegation-5/main.svelte | 10 +-- .../event-attribute-delegation-6/_config.js | 9 +-- .../event-attribute-delegation-6/log.js | 2 - .../event-attribute-delegation-6/main.svelte | 4 +- .../event-attribute-delegation-7/_config.js | 9 +-- .../event-attribute-delegation-7/log.js | 2 - .../event-attribute-delegation-7/main.svelte | 8 +-- .../event-attribute-delegation/_config.js | 9 +-- .../samples/event-attribute-delegation/log.js | 2 - .../event-attribute-delegation/main.svelte | 9 ++- .../samples/event-prop-reference/_config.js | 9 +-- .../samples/event-prop-reference/log.js | 2 - .../samples/event-prop-reference/main.svelte | 4 +- .../samples/inspect-derived-2/_config.js | 24 +------ .../samples/inspect-multiple/_config.js | 24 +------ .../samples/inspect-nested-state/_config.js | 24 +------ .../samples/inspect-new-property/_config.js | 24 +------ .../samples/inspect-trace/_config.js | 28 ++------ .../runtime-runes/samples/inspect/_config.js | 24 +------ .../Item.svelte | 10 ++- .../_config.js | 13 ++-- .../log.js | 2 - .../main.svelte | 9 ++- .../Item.svelte | 8 +-- .../_config.js | 13 ++-- .../log.js | 2 - .../main.svelte | 5 +- .../Item.svelte | 10 ++- .../_config.js | 13 ++-- .../log.js | 2 - .../main.svelte | 9 ++- .../_config.js | 13 ++-- .../log.js | 2 - .../main.svelte | 11 +-- .../Item.svelte | 8 +-- .../_config.js | 13 ++-- .../log.js | 2 - .../main.svelte | 7 +- .../samples/nested-effect-conflict/_config.js | 9 +-- .../samples/nested-effect-conflict/log.js | 2 - .../nested-effect-conflict/main.svelte | 21 +++--- .../samples/nested-script-tag/_config.js | 23 +------ .../_config.js | 16 +---- .../samples/nullish-operator/_config.js | 9 +-- .../samples/nullish-operator/log.js | 2 - .../samples/nullish-operator/main.svelte | 6 +- .../samples/pre-effect-ordering/_config.js | 9 +-- .../samples/pre-effect-ordering/log.js | 2 - .../samples/pre-effect-ordering/main.svelte | 8 +-- .../samples/pre-effect/_config.js | 9 +-- .../runtime-runes/samples/pre-effect/log.js | 2 - .../samples/pre-effect/main.svelte | 4 +- .../samples/props-derived-2/Item.svelte | 4 +- .../samples/props-derived-2/_config.js | 11 +-- .../samples/props-derived-2/log.js | 2 - .../samples/props-equality/main.svelte | 2 +- .../samples/readonly-state/_config.js | 9 +-- .../samples/readonly-state/log.js | 2 - .../samples/readonly-state/main.svelte | 4 +- .../samples/snippet-reactive-args/_config.js | 15 ++-- .../snippet-reactive-args/inner.svelte | 4 +- .../samples/snippet-reactive-args/main.svelte | 4 +- .../store-subscribe-effect-init/_config.js | 13 ++-- .../store-subscribe-effect-init/log.js | 2 - .../store-subscribe-effect-init/main.svelte | 3 +- .../text-multiple-call-expression/_config.js | 9 +-- .../text-multiple-call-expression/log.js | 2 - .../text-multiple-call-expression/main.svelte | 6 +- 178 files changed, 404 insertions(+), 927 deletions(-) delete mode 100644 packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/log.js delete mode 100644 packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/action-context/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/logs.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/bind-this-proxy/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-private-frozen-state-object/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-state-derived-unowned/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-state-init-eager-3/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/class-state-init-eager/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/derived-destructure/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/derived-stale-value/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/destructure-derived-event/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/dynamic-transition/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect-cleanup/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect-order-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect-order/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect-root-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect-root/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effect/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/effects-order/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/event-prop-reference/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/nullish-operator/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/pre-effect-ordering/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/pre-effect/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/props-derived-2/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/readonly-state/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/store-subscribe-effect-init/log.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/log.js diff --git a/packages/svelte/tests/hydration/samples/ignore-mismatched-href/_config.js b/packages/svelte/tests/hydration/samples/ignore-mismatched-href/_config.js index ce81251e5e..5ebdbb2680 100644 --- a/packages/svelte/tests/hydration/samples/ignore-mismatched-href/_config.js +++ b/packages/svelte/tests/hydration/samples/ignore-mismatched-href/_config.js @@ -11,5 +11,9 @@ export default test({ test(assert, target) { assert.equal(target.querySelector('a')?.getAttribute('href'), '/bar'); - } + }, + + errors: [ + 'Detected a href attribute value change during hydration. This will not be repaired during hydration, the href value that came from the server will be used. Related element:' + ] }); diff --git a/packages/svelte/tests/hydration/test.ts b/packages/svelte/tests/hydration/test.ts index 6884504718..9002f56d51 100644 --- a/packages/svelte/tests/hydration/test.ts +++ b/packages/svelte/tests/hydration/test.ts @@ -32,6 +32,7 @@ interface HydrationTest extends BaseTest { ) => void | Promise; before_test?: () => void; after_test?: () => void; + errors?: any[]; } function read(path: string): string | void { @@ -65,6 +66,7 @@ const { test, run } = suite(async (config, cwd) => { const snapshot = config.snapshot ? config.snapshot(target) : {}; const error = console.error; + const errors: any[] = []; let got_hydration_error = false; console.error = (message: any) => { if (typeof message === 'string' && message.startsWith('ERR_SVELTE_HYDRATION_MISMATCH')) { @@ -73,7 +75,7 @@ const { test, run } = suite(async (config, cwd) => { error(message); } } else { - error(message); + errors.push(message); } }; @@ -85,12 +87,19 @@ const { test, run } = suite(async (config, cwd) => { }); console.error = error; + if (config.expect_hydration_error) { assert.ok(got_hydration_error, 'Expected hydration error'); } else { assert.ok(!got_hydration_error, 'Unexpected hydration error'); } + if (config.errors) { + assert.deepEqual(errors, config.errors); + } else if (errors.length) { + throw new Error(`Unexpected errors: ${errors.join('\n')}`); + } + const expected = read(`${cwd}/_expected.html`) ?? rendered.html; assert_html_equal(target.innerHTML, expected); diff --git a/packages/svelte/tests/runtime-browser/test.ts b/packages/svelte/tests/runtime-browser/test.ts index b2df361aa5..d58f7e78cd 100644 --- a/packages/svelte/tests/runtime-browser/test.ts +++ b/packages/svelte/tests/runtime-browser/test.ts @@ -14,7 +14,6 @@ let browser: import('@playwright/test').Browser; beforeAll(async () => { browser = await chromium.launch(); - console.log('[runtime-browser] Launched browser'); }, 20000); afterAll(async () => { diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/_config.js b/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/_config.js index 07356ad6fd..88b0ff31e3 100644 --- a/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/_config.js @@ -2,11 +2,11 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ - test({ assert, component, target }) { + test({ assert, target, logs }) { const [b1, b2, b3] = target.querySelectorAll('button'); const first_h1 = target.querySelector('h1'); - assert.deepEqual(component.log, [undefined, first_h1]); + assert.deepEqual(logs, [undefined, first_h1]); flushSync(() => { b3.click(); @@ -14,12 +14,12 @@ export default test({ const third_h1 = target.querySelector('h1'); - assert.deepEqual(component.log, [undefined, first_h1, third_h1]); + assert.deepEqual(logs, [undefined, first_h1, third_h1]); flushSync(() => { b1.click(); }); - assert.deepEqual(component.log, [undefined, first_h1, third_h1, target.querySelector('h1')]); + assert.deepEqual(logs, [undefined, first_h1, third_h1, target.querySelector('h1')]); } }); diff --git a/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/main.svelte b/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/main.svelte index bde2158c51..2fb062c2ee 100644 --- a/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/binding-this-multiple/main.svelte @@ -1,9 +1,8 @@
diff --git a/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js index e61d8d7b38..da6b9c0442 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/component-nested-deep/_config.js @@ -4,5 +4,7 @@ import { unmount } from 'svelte'; export default test({ test({ component }) { unmount(component.l1); - } + }, + + warnings: ['Tried to unmount a component that was not mounted.'] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/Nested.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/Nested.svelte index fab3ae1890..d6e214a926 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/Nested.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/Nested.svelte @@ -1,14 +1,14 @@ {#each items as item (item)} {#each keys as key (key)} setKey(key, value, item)} /> {/each} -{/each} \ No newline at end of file +{/each} diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/_config.js index 4633776a1f..563efe099a 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/_config.js @@ -7,25 +7,26 @@ export default test({ `, - async test({ assert, target, window, component }) { + + async test({ assert, target, window, logs }) { const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button'); const click = new window.MouseEvent('click', { bubbles: true }); await btn1.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a-c, c)']); + assert.deepEqual(logs, ['setKey(a, value-a-c, c)']); await btn2.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a-c, c)', 'setKey(b, value-b-c, c)']); + assert.deepEqual(logs, ['setKey(a, value-a-c, c)', 'setKey(b, value-b-c, c)']); await btn3.dispatchEvent(click); - assert.deepEqual(component.log, [ + assert.deepEqual(logs, [ 'setKey(a, value-a-c, c)', 'setKey(b, value-b-c, c)', 'setKey(a, value-a-d, d)' ]); await btn4.dispatchEvent(click); - assert.deepEqual(component.log, [ + assert.deepEqual(logs, [ 'setKey(a, value-a-c, c)', 'setKey(b, value-b-c, c)', 'setKey(a, value-a-d, d)', diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/main.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/main.svelte index 7feb55aaf6..187b4167d5 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each-nested/main.svelte @@ -1,8 +1,7 @@ - + - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/Nested.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/Nested.svelte index a29ffe0376..f356bca079 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/Nested.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/Nested.svelte @@ -1,11 +1,11 @@ {#each keys as key (key)} setKey(key, value)} /> -{/each} \ No newline at end of file +{/each} diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/_config.js index 008089edc3..7a3eec4eeb 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/_config.js @@ -5,14 +5,15 @@ export default test({ `, - async test({ assert, target, window, component }) { + + async test({ assert, target, window, logs }) { const [btn1, btn2] = target.querySelectorAll('button'); const click = new window.MouseEvent('click', { bubbles: true }); await btn1.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a)']); + assert.deepEqual(logs, ['setKey(a, value-a)']); await btn2.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a)', 'setKey(b, value-b)']); + assert.deepEqual(logs, ['setKey(a, value-a)', 'setKey(b, value-b)']); } }); diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/main.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/main.svelte index 7dc17b4c95..777ad5a0ee 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-each/main.svelte @@ -1,8 +1,7 @@ - + - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Inner.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Inner.svelte index 6beaabbb68..41673867d2 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Inner.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Inner.svelte @@ -1,9 +1,8 @@ - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Nested.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Nested.svelte index 97c44c5145..4e63d7f3fc 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Nested.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/Nested.svelte @@ -1,8 +1,7 @@ - + set(key, value)} /> - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/_config.js b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/_config.js index 008089edc3..7a3eec4eeb 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/_config.js @@ -5,14 +5,15 @@ export default test({ `, - async test({ assert, target, window, component }) { + + async test({ assert, target, window, logs }) { const [btn1, btn2] = target.querySelectorAll('button'); const click = new window.MouseEvent('click', { bubbles: true }); await btn1.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a)']); + assert.deepEqual(logs, ['setKey(a, value-a)']); await btn2.dispatchEvent(click); - assert.deepEqual(component.log, ['setKey(a, value-a)', 'setKey(b, value-b)']); + assert.deepEqual(logs, ['setKey(a, value-a)', 'setKey(b, value-b)']); } }); diff --git a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/main.svelte b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/main.svelte index a061f73b3a..777ad5a0ee 100644 --- a/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/component-slot-context-props-let/main.svelte @@ -1,8 +1,7 @@ - + diff --git a/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js b/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js index 4fe9fbaf45..bfdf090cbd 100644 --- a/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/destroy-twice/_config.js @@ -5,5 +5,10 @@ export default test({ test({ component }) { unmount(component); unmount(component); - } + }, + + warnings: [ + 'Tried to unmount a component that was not mounted.', + 'Tried to unmount a component that was not mounted.' + ] }); diff --git a/packages/svelte/tests/runtime-legacy/samples/empty-component-destroy/Empty.svelte b/packages/svelte/tests/runtime-legacy/samples/empty-component-destroy/Empty.svelte index 616839ee0e..1708640d08 100644 --- a/packages/svelte/tests/runtime-legacy/samples/empty-component-destroy/Empty.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/empty-component-destroy/Empty.svelte @@ -1,6 +1,6 @@ - + diff --git a/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/_config.js b/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/_config.js index 96e5edba1f..825ffc73ef 100644 --- a/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/_config.js @@ -2,7 +2,7 @@ import { flushSync } from 'svelte'; import { ok, test } from '../../test'; export default test({ - test({ assert, component, target, window }) { + test({ assert, logs, target }) { const button = target.querySelector('button'); ok(button); @@ -10,12 +10,12 @@ export default test({ button.click(); }); - assert.deepEqual(component.log, ['1 - 1']); + assert.deepEqual(logs, ['1 - 1']); flushSync(() => { button.click(); }); - assert.deepEqual(component.log, ['1 - 1', '2 - 2']); + assert.deepEqual(logs, ['1 - 1', '2 - 2']); } }); diff --git a/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/main.svelte b/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/main.svelte index b7b9f3da0c..4ef9bf62bc 100644 --- a/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/event-handler-mutation-scope/main.svelte @@ -1,5 +1,4 @@ diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/Child.svelte b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/Child.svelte index 29a201e16c..50fb461cb3 100644 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/Child.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/Child.svelte @@ -1,24 +1,23 @@ diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/_config.js b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/_config.js index 4050d2ef03..1309ef8a24 100644 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; -import { log } from './log.js'; import { test, ok } from '../../test'; export default test({ - before_test: () => { - log.length = 0; - }, - - test({ assert, target }) { + test({ assert, target, logs }) { const [button1, button2] = target.querySelectorAll('button'); ok(button1); ok(button2); @@ -18,7 +13,7 @@ export default test({ button2.click(); flushSync(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'before', 'before 0, 0', 'after', diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/log.js b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/log.js deleted file mode 100644 index a119176880..0000000000 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-afterUpdate2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {string[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/Child.svelte b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/Child.svelte index af01095d95..0c43f7cc29 100644 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/Child.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/Child.svelte @@ -1,7 +1,6 @@

welcome, dan

diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/_config.js b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/_config.js index a723026b8d..98eb7716fb 100644 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/_config.js @@ -2,11 +2,11 @@ import { test } from '../../test'; import { flushSync } from 'svelte'; export default test({ - async test({ assert, target, component }) { + async test({ assert, target, logs }) { const input = /** @type {HTMLInputElement} */ (target.querySelector('input')); assert.equal(input?.value, 'rich'); - assert.deepEqual(component.log, []); + assert.deepEqual(logs, []); const inputEvent = new window.InputEvent('input'); input.value = 'dan'; @@ -14,15 +14,15 @@ export default test({ flushSync(); - assert.deepEqual(component.log, ['name in child: dan']); + assert.deepEqual(logs, ['name in child: dan']); - component.log.length = 0; + logs.length = 0; input.value = 'da'; await input.dispatchEvent(inputEvent); flushSync(); - assert.deepEqual(component.log, []); + assert.deepEqual(logs, []); } }); diff --git a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/main.svelte b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/main.svelte index 0793bb45d0..d63945bbc7 100644 --- a/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/lifecycle-render-beforeUpdate/main.svelte @@ -2,8 +2,6 @@ import { beforeUpdate } from 'svelte'; import Child from './Child.svelte'; - export let log = []; - let name = 'rich'; let allowed = false; @@ -16,5 +14,5 @@ {#if allowed} - + {/if} diff --git a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/_config.js b/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/_config.js index 35619e3a0a..7c15475384 100644 --- a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/_config.js @@ -1,21 +1,16 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ html: '', - before_test() { - log.length = 0; - }, - - test({ assert, target }) { - assert.deepEqual(log, [2, 1]); + test({ assert, target, logs }) { + assert.deepEqual(logs, [2, 1]); const button = target.querySelector('button'); flushSync(() => button?.click()); - assert.deepEqual(log, [2, 1, 2, 1]); + assert.deepEqual(logs, [2, 1, 2, 1]); assert.htmlEqual(target.innerHTML, ''); } diff --git a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/log.js b/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/main.svelte b/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/main.svelte index c65c992b0c..50b91246ff 100644 --- a/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/reactive-assignment-prevent-loop/main.svelte @@ -1,6 +1,4 @@ diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index a0d00ec1c5..039cf64eb0 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -1,7 +1,6 @@ import * as fs from 'node:fs'; import { setImmediate } from 'node:timers/promises'; import glob from 'tiny-glob/sync.js'; -import * as $ from 'svelte/internal/client'; import { createClassComponent } from 'svelte/legacy'; import { flushSync } from 'svelte'; import { render } from 'svelte/server'; @@ -56,6 +55,8 @@ export interface RuntimeTest = Record void | Promise; test_ssr?: (args: { assert: Assert }) => void | Promise; accessors?: boolean; @@ -151,6 +152,36 @@ async function run_test_variant( ) { let unintended_error = false; + // eslint-disable-next-line no-console + const { log, warn } = console; + + let logs: string[] = []; + let warnings: string[] = []; + + { + // use some crude static analysis to determine if logs/warnings are intercepted. + // we do this instead of using getters on the `test` parameters so that we can + // squelch logs in SSR tests while printing temporary logs in other cases + let str = config.test?.toString() ?? ''; + let n = 0; + let i = 0; + while (i < str.length) { + if (str[i] === '(') n++; + if (str[i] === ')' && --n === 0) break; + i++; + } + + if (str.slice(0, i).includes('logs')) { + // eslint-disable-next-line no-console + console.log = (...args) => logs.push(...args); + } + + if (str.slice(0, i).includes('warnings') || config.warnings) { + // eslint-disable-next-line no-console + console.warn = (...args) => warnings.push(...args); + } + } + try { unhandled_rejection = null; @@ -237,15 +268,9 @@ async function run_test_variant( }); } } else { - config.before_test?.(); + logs.length = warnings.length = 0; - const warnings: string[] = []; - // eslint-disable-next-line no-console - const warn = console.warn; - // eslint-disable-next-line no-console - console.warn = (warning) => { - warnings.push(warning); - }; + config.before_test?.(); // eslint-disable-next-line no-console const error = console.error; @@ -266,8 +291,6 @@ async function run_test_variant( hydrate: variant === 'hydrate' }); - // eslint-disable-next-line no-console - console.warn = warn; // eslint-disable-next-line no-console console.error = error; @@ -276,13 +299,6 @@ async function run_test_variant( assert.fail('Expected a runtime error'); } - if (config.warnings) { - assert.deepEqual(warnings, config.warnings); - } else if (warnings.length) { - unintended_error = true; - assert.fail('Received unexpected warnings'); - } - if (config.html) { flushSync(); assert_html_equal_with_options(target.innerHTML, config.html, { @@ -309,7 +325,9 @@ async function run_test_variant( snapshot, window, raf, - compileOptions + compileOptions, + logs, + warnings }); } @@ -319,6 +337,15 @@ async function run_test_variant( } } finally { instance.$destroy(); + + if (config.warnings) { + assert.deepEqual(warnings, config.warnings); + } else if (warnings.length && console.warn === warn) { + unintended_error = true; + warn.apply(console, warnings); + assert.fail('Received unexpected warnings'); + } + assert_html_equal( target.innerHTML, '', @@ -341,6 +368,9 @@ async function run_test_variant( throw err; } } finally { + console.log = log; + console.warn = warn; + config.after_test?.(); // Free up the microtask queue diff --git a/packages/svelte/tests/runtime-runes/samples/action-context/_config.js b/packages/svelte/tests/runtime-runes/samples/action-context/_config.js index 87e9842d9a..b23e88901a 100644 --- a/packages/svelte/tests/runtime-runes/samples/action-context/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/action-context/_config.js @@ -1,22 +1,17 @@ import { ok, test } from '../../test'; -import { flushSync, tick } from 'svelte'; -import { log } from './log.js'; +import { flushSync } from 'svelte'; export default test({ html: ``, - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); ok(btn); flushSync(() => btn.click()); - assert.deepEqual(log, ['update', 0, 1]); + assert.deepEqual(logs, ['update', 0, 1]); flushSync(() => btn.click()); - assert.deepEqual(log, ['update', 0, 1, 'destroy', 1]); + assert.deepEqual(logs, ['update', 0, 1, 'destroy', 1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/action-context/log.js b/packages/svelte/tests/runtime-runes/samples/action-context/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/action-context/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/action-context/main.svelte b/packages/svelte/tests/runtime-runes/samples/action-context/main.svelte index ef8f7894cc..fe3e317038 100644 --- a/packages/svelte/tests/runtime-runes/samples/action-context/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/action-context/main.svelte @@ -1,6 +1,4 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/_config.js b/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/_config.js index c263855bec..3bf9aa66d6 100644 --- a/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/_config.js @@ -1,15 +1,10 @@ import { test } from '../../test'; -import { flushSync, tick } from 'svelte'; -import { log } from './log.js'; +import { flushSync } from 'svelte'; export default test({ - before_test() { - log.length = 0; - }, - html: `
{"text":"initial"}
`, - async test({ assert, target }) { + async test({ assert, target, logs }) { const [btn1, btn2] = target.querySelectorAll('button'); flushSync(() => { @@ -30,7 +25,7 @@ export default test({ `
{"text":"updated"}
` ); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'action $effect: ', { buttonClicked: 0 }, 'action $effect: ', diff --git a/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/log.js b/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/action-state-arg-deep/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/Child.svelte b/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/Child.svelte index 9841295830..2a2dea8220 100644 --- a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/Child.svelte +++ b/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/Child.svelte @@ -2,11 +2,10 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/_config.js b/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/_config.js index aa42c2a2d6..8d4d63254d 100644 --- a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/_config.js @@ -1,20 +1,15 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { logs } from './logs.js'; export default test({ html: ``, - test({ assert, target }) { + test({ assert, target, logs }) { const btn = target.querySelector('button'); flushSync(() => btn?.click()); assert.htmlEqual(target.innerHTML, ``); assert.deepEqual(logs, ['changed', 'changed']); - }, - - after_test() { - logs.length = 0; } }); diff --git a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/logs.js b/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/logs.js deleted file mode 100644 index 8c8a1318cb..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/before-update-in-legacy-child/logs.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const logs = []; diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/_config.js b/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/_config.js index e075b5a588..c07f8d05a4 100644 --- a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/_config.js @@ -1,15 +1,10 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test: () => { - log.length = 0; - }, - html: `
Hello\nworld
`, - async test({ assert, target }) { + async test({ assert, target, logs }) { const [btn1] = target.querySelectorAll('button'); flushSync(() => { @@ -24,6 +19,6 @@ export default test({ assert.htmlEqual(target.innerHTML, `
Hello\nworld
`); - assert.deepEqual(log, [{ a: {} }, null, { a: {} }]); + assert.deepEqual(logs, [{ a: {} }, null, { a: {} }]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/log.js b/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/main.svelte b/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/main.svelte index adc67f46ae..6c24d5588a 100644 --- a/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/bind-this-proxy/main.svelte @@ -1,12 +1,11 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/_config.js b/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/_config.js index 6ad9dff351..79a0d13bdd 100644 --- a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/_config.js @@ -1,14 +1,9 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ html: ``, - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); await btn?.click(); @@ -17,6 +12,6 @@ export default test({ await btn?.click(); assert.htmlEqual(target.innerHTML, ``); - assert.deepEqual(log, ['read only', 'read only']); + assert.deepEqual(logs, ['read only', 'read only']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/log.js b/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/main.svelte b/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/main.svelte index e381961fe9..bdadbeee82 100644 --- a/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/class-frozen-state-object/main.svelte @@ -1,6 +1,4 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/_config.js b/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/_config.js index e11107a95c..6d49c0436f 100644 --- a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/_config.js @@ -1,14 +1,9 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ html: ``, - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); await btn?.click(); @@ -17,6 +12,6 @@ export default test({ await btn?.click(); assert.htmlEqual(target.innerHTML, ``); - assert.deepEqual(log, [undefined]); + assert.deepEqual(logs, [undefined]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/log.js b/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/main.svelte index 5a0d7b0de2..6409795767 100644 --- a/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/class-state-init-eager-2/main.svelte @@ -1,8 +1,6 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/_config.js b/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/_config.js index 1b6357656a..71c7e40ed5 100644 --- a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/_config.js @@ -1,19 +1,15 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - + mode: ['server'], html: ``, - async test({ assert, target, window }) { + async test({ assert, target, window, logs }) { const btn = target.querySelector('button'); const clickEvent = new window.Event('click', { bubbles: true }); await btn?.dispatchEvent(clickEvent); assert.htmlEqual(target.innerHTML, ``); - assert.deepEqual(log, ['create_derived']); + assert.deepEqual(logs, ['create_derived']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/log.js b/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/main.svelte b/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/main.svelte index 520765469b..bdedef7197 100644 --- a/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/derived-fn-destructure/main.svelte @@ -1,9 +1,7 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/_config.js b/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/_config.js index 0645ff4a16..6ad462cddb 100644 --- a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/_config.js @@ -1,15 +1,10 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target, window }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); await btn?.click(); - assert.deepEqual(log, ['works!']); + assert.deepEqual(logs, ['works!']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/log.js b/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/main.svelte b/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/main.svelte index d4f149eb81..4ad48eaec6 100644 --- a/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/destructure-derived-event/main.svelte @@ -1,9 +1,7 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/_config.js b/packages/svelte/tests/runtime-runes/samples/dynamic-transition/_config.js index 43c0bd7f86..91524c275e 100644 --- a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-transition/_config.js @@ -1,31 +1,26 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); flushSync(() => { b1.click(); }); - assert.deepEqual(log, ['transition 2']); + assert.deepEqual(logs, ['transition 2']); flushSync(() => { b2.click(); }); - assert.deepEqual(log, ['transition 2']); + assert.deepEqual(logs, ['transition 2']); flushSync(() => { b1.click(); }); - assert.deepEqual(log, ['transition 2', 'transition 1']); + assert.deepEqual(logs, ['transition 2', 'transition 1']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/log.js b/packages/svelte/tests/runtime-runes/samples/dynamic-transition/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/main.svelte b/packages/svelte/tests/runtime-runes/samples/dynamic-transition/main.svelte index 8355a20d71..c075c42c5d 100644 --- a/packages/svelte/tests/runtime-runes/samples/dynamic-transition/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/dynamic-transition/main.svelte @@ -1,8 +1,6 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/effect-order-2/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-order-2/_config.js index 302026493f..110bd622a8 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-order-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-order-2/_config.js @@ -1,13 +1,8 @@ import { test } from '../../test'; import { flushSync } from 'svelte'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); flushSync(() => { b1.click(); @@ -15,7 +10,7 @@ export default test({ flushSync(() => { b1.click(); }); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ { a: 1 }, { b: 1 }, { c: 1 }, diff --git a/packages/svelte/tests/runtime-runes/samples/effect-order-2/log.js b/packages/svelte/tests/runtime-runes/samples/effect-order-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/effect-order-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/effect-order-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/effect-order-2/main.svelte index fb9e9a6c53..7995527d44 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-order-2/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/effect-order-2/main.svelte @@ -1,19 +1,18 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-2/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-root-2/_config.js index f6d99a0f5d..4c7aeb1ad1 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-root-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-root-2/_config.js @@ -1,31 +1,26 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); flushSync(() => { b1.click(); }); - assert.deepEqual(log, [0]); + assert.deepEqual(logs, [0]); flushSync(() => { b2.click(); }); - assert.deepEqual(log, [0, 'cleanup']); + assert.deepEqual(logs, [0, 'cleanup']); flushSync(() => { b1.click(); }); - assert.deepEqual(log, [0, 'cleanup']); + assert.deepEqual(logs, [0, 'cleanup']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-2/log.js b/packages/svelte/tests/runtime-runes/samples/effect-root-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/effect-root-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/effect-root-2/main.svelte index 591975ce54..756053b03a 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-root-2/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/effect-root-2/main.svelte @@ -1,11 +1,9 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-root/_config.js index 1a2afc898f..fe2a8bb499 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-root/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-root/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2, b3] = target.querySelectorAll('button'); flushSync(() => { @@ -15,19 +10,19 @@ export default test({ b2.click(); }); - assert.deepEqual(log, [0, 1]); + assert.deepEqual(logs, [0, 1]); flushSync(() => { b3.click(); }); - assert.deepEqual(log, [0, 1, 'cleanup 1', 'cleanup 2']); + assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']); flushSync(() => { b1.click(); b2.click(); }); - assert.deepEqual(log, [0, 1, 'cleanup 1', 'cleanup 2']); + assert.deepEqual(logs, [0, 1, 'cleanup 1', 'cleanup 2']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root/log.js b/packages/svelte/tests/runtime-runes/samples/effect-root/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/effect-root/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/effect-root/main.svelte b/packages/svelte/tests/runtime-runes/samples/effect-root/main.svelte index f7e8275aae..65abb24374 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-root/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/effect-root/main.svelte @@ -1,22 +1,20 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/effects-order/_config.js b/packages/svelte/tests/runtime-runes/samples/effects-order/_config.js index 25b05af207..e4ca2d72a6 100644 --- a/packages/svelte/tests/runtime-runes/samples/effects-order/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effects-order/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.deepEqual(log, ['first0', 'second0', 'first1', 'second1']); + assert.deepEqual(logs, ['first0', 'second0', 'first1', 'second1']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/effects-order/log.js b/packages/svelte/tests/runtime-runes/samples/effects-order/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/effects-order/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/effects-order/main.svelte b/packages/svelte/tests/runtime-runes/samples/effects-order/main.svelte index 5d8973be35..1fb1c44e8e 100644 --- a/packages/svelte/tests/runtime-runes/samples/effects-order/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/effects-order/main.svelte @@ -1,15 +1,13 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js index 262240f5f3..b8cfb1e584 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); flushSync(() => { @@ -15,6 +10,6 @@ export default test({ }); await Promise.resolve(); - assert.deepEqual(log, ['clicked button']); + assert.deepEqual(logs, ['clicked button']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte index dc5fdd214e..2a18005538 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-2/main.svelte @@ -1,8 +1,5 @@ - -
{ log.push('clicked div') }}> -
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js index 262240f5f3..b8cfb1e584 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); flushSync(() => { @@ -15,6 +10,6 @@ export default test({ }); await Promise.resolve(); - assert.deepEqual(log, ['clicked button']); + assert.deepEqual(logs, ['clicked button']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte index 4cead08260..d39bdf42c3 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-3/main.svelte @@ -1,11 +1,10 @@ -
log.push('clicked container')} onkeydown={() => {}}> -
{ log.push('clicked div 1') }}> -
{ log.push('clicked div 2') }}> -
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/_config.js index 9830e74646..d253b9b6fc 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [btn1, btn2] = target.querySelectorAll('button'); btn1?.click(); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'button main', 'div main 1', 'div main 2', @@ -21,10 +16,10 @@ export default test({ 'window sub' ]); - log.length = 0; + logs.length = 0; btn2?.click(); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'button sub', 'document main', 'document sub', diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/main.svelte index 9fa1484907..9697540e18 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/main.svelte @@ -1,13 +1,12 @@ - - + + -
log.push('div main 1')} on:click={() => log.push('div main 2')}> - +
console.log('div main 1')} on:click={() => console.log('div main 2')}> +
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/sub.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/sub.svelte index c6c900b8b4..a7dd74a4c5 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/sub.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-4/sub.svelte @@ -1,8 +1,4 @@ - + console.log('window sub')} /> + console.log('document sub')} /> - log.push('window sub')} /> - log.push('document sub')} /> - - + diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/_config.js index fcbb0dbe2a..6fa7b732bf 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); btn?.click(); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'button onclick', 'button on:click', 'inner div on:click', diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/main.svelte index 438ecf5dc3..6df18bff43 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-5/main.svelte @@ -1,9 +1,5 @@ - - -
log.push('outer div onclick')}> -
log.push('inner div on:click')}> - +
console.log('outer div onclick')}> +
console.log('inner div on:click')}> +
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/_config.js index bc16bf031f..af62498171 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/_config.js @@ -1,16 +1,11 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); btn?.click(); await Promise.resolve(); - assert.deepEqual(log, ['method']); + assert.deepEqual(logs, ['method']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/main.svelte index 0a365990ec..d1696a04c1 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-6/main.svelte @@ -1,9 +1,7 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js index 69f1788171..3d3377b125 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/_config.js @@ -1,16 +1,11 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const btn = target.querySelector('button'); btn?.click(); await Promise.resolve(); - assert.deepEqual(log, ['div onclickcapture', 'button onclick']); + assert.deepEqual(logs, ['div onclickcapture', 'button onclick']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte index b79cc9008f..55f1608e77 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation-7/main.svelte @@ -1,7 +1,3 @@ - - -
log.push('div onclickcapture')}> - +
console.log('div onclickcapture')}> +
diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js index b1f5931a1e..bbe67d1bed 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); flushSync(() => { @@ -15,7 +10,7 @@ export default test({ }); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'clicked button', 'clicked div 2', 'clicked div 1', diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte index 8d3ac9fcc0..d1f767288a 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-delegation/main.svelte @@ -1,11 +1,10 @@ -
log.push('clicked container')} onkeydown={() => {}}> -
{ log.push('clicked div 1') }}> -
{ log.push('clicked div 2') }}> -
diff --git a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/_config.js b/packages/svelte/tests/runtime-runes/samples/event-prop-reference/_config.js index 3b801f6b7b..4d387569ee 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/event-prop-reference/_config.js @@ -1,21 +1,16 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - get props() { return { item: { name: 'Dominic' } }; }, - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); b1?.click(); await Promise.resolve(); - assert.deepEqual(log, ['Dominic']); + assert.deepEqual(logs, ['Dominic']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/log.js b/packages/svelte/tests/runtime-runes/samples/event-prop-reference/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-prop-reference/main.svelte index 697338d97b..258ef6046c 100644 --- a/packages/svelte/tests/runtime-runes/samples/event-prop-reference/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/event-prop-reference/main.svelte @@ -1,10 +1,8 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-derived-2/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-derived-2/_config.js index 0e6cf85884..9474397f7f 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-derived-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-derived-2/_config.js @@ -1,30 +1,12 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { + + async test({ assert, target, logs }) { const button = target.querySelector('button'); flushSync(() => { @@ -32,7 +14,7 @@ export default test({ }); assert.htmlEqual(target.innerHTML, `\n1`); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'init', { data: { diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-multiple/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-multiple/_config.js index be3c1988bd..fc9a0cda9a 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-multiple/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-multiple/_config.js @@ -1,34 +1,16 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { + + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.deepEqual(log, ['init', 0, 0, 'update', 1, 0, 'update', 1, 1]); + assert.deepEqual(logs, ['init', 0, 0, 'update', 1, 0, 'update', 1, 1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-nested-state/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-nested-state/_config.js index 32c9e98296..e4d9fb5013 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-nested-state/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-nested-state/_config.js @@ -1,34 +1,16 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { + + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); b1.click(); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'init', { x: { count: 0 } }, [{ count: 0 }], diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-new-property/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-new-property/_config.js index 5e5150bf0d..a85972a0f9 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-new-property/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-new-property/_config.js @@ -1,33 +1,15 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { + + async test({ assert, target, logs }) { const [btn] = target.querySelectorAll('button'); btn.click(); await Promise.resolve(); - assert.deepEqual(log, ['init', {}, 'init', [], 'update', { x: 'hello' }, 'update', ['hello']]); + assert.deepEqual(logs, ['init', {}, 'init', [], 'update', { x: 'hello' }, 'update', ['hello']]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect-trace/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect-trace/_config.js index 43b0915426..7bb71adafb 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect-trace/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect-trace/_config.js @@ -1,37 +1,19 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { - assert.deepEqual(log, []); + + async test({ assert, target, logs }) { + assert.deepEqual(logs, []); const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.ok(log[0].stack.startsWith('Error:') && log[0].stack.includes('HTMLButtonElement.')); - assert.deepEqual(log[1], 1); + assert.ok(logs[0].stack.startsWith('Error:') && logs[0].stack.includes('HTMLButtonElement.')); + assert.deepEqual(logs[1], 1); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/inspect/_config.js b/packages/svelte/tests/runtime-runes/samples/inspect/_config.js index 1f63249e31..09a921abee 100644 --- a/packages/svelte/tests/runtime-runes/samples/inspect/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/inspect/_config.js @@ -1,34 +1,16 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ compileOptions: { dev: true }, - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert, target }) { + + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.deepEqual(log, ['init', 0, 'update', 1]); + assert.deepEqual(logs, ['init', 0, 'update', 1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/Item.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/Item.svelte index 5375195617..f427b849e3 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/Item.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/Item.svelte @@ -1,23 +1,21 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js index 2667fff13c..b0271da3f1 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ get props() { return { n: 0 }; }, - before_test() { - log.length = 0; - }, - - async test({ assert, component }) { - assert.deepEqual(log, [ + async test({ assert, component, logs }) { + assert.deepEqual(logs, [ 'parent: $effect.pre 0', 'parent: $effect.pre (2) 0', 'parent: render 0', @@ -30,11 +25,11 @@ export default test({ 'parent: $effect 0' ]); - log.length = 0; + logs.length = 0; component.n += 1; - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'parent: $effect.pre 1', 'parent: $effect.pre (2) 1', 'parent: render 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/log.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/main.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/main.svelte index cc21df4f1b..e5dd43494c 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-2/main.svelte @@ -1,24 +1,23 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/Item.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/Item.svelte index 8719c578f9..de1573539e 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/Item.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/Item.svelte @@ -1,19 +1,17 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js index e528189597..04cfa4b0d5 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ get props() { return { n: 0 }; }, - before_test() { - log.length = 0; - }, - - async test({ assert, component }) { - assert.deepEqual(log, [ + async test({ assert, component, logs }) { + assert.deepEqual(logs, [ 'parent: render 0', '1: $effect.pre 0', '1: render 0', @@ -25,11 +20,11 @@ export default test({ 'parent: $effect 0' ]); - log.length = 0; + logs.length = 0; component.n += 1; - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'parent: render 1', '1: $effect.pre 1', '1: render 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/log.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/main.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/main.svelte index 57d85095d5..a029b9f18a 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-3/main.svelte @@ -1,16 +1,15 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/Item.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/Item.svelte index 2e9dc09c7a..cffeaf41b5 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/Item.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/Item.svelte @@ -1,23 +1,21 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js index 62a4b85546..d0e27957c5 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ get props() { return { n: 0 }; }, - before_test() { - log.length = 0; - }, - - async test({ assert, component }) { - assert.deepEqual(log, [ + async test({ assert, component, logs }) { + assert.deepEqual(logs, [ 'parent: $effect.pre 0', 'parent: nested $effect.pre 0', 'parent: render 0', @@ -30,11 +25,11 @@ export default test({ 'parent: $effect 0' ]); - log.length = 0; + logs.length = 0; component.n += 1; - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'parent: $effect.pre 1', 'parent: nested $effect.pre 1', 'parent: render 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/log.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/main.svelte index d9b83f837c..91cce1937b 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-4/main.svelte @@ -1,24 +1,23 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js index bc62b4f2c9..54212a580a 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/_config.js @@ -1,21 +1,16 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ get props() { return { n: 0 }; }, - before_test() { - log.length = 0; - }, - - async test({ assert, component }) { - assert.deepEqual(log, ['$effect.pre 0', 'another $effect.pre 1', 'render n0', 'render i1']); + async test({ assert, component, logs }) { + assert.deepEqual(logs, ['$effect.pre 0', 'another $effect.pre 1', 'render n0', 'render i1']); - log.length = 0; + logs.length = 0; component.n += 1; - assert.deepEqual(log, ['$effect.pre 1', 'another $effect.pre 2', 'render n1', 'render i2']); + assert.deepEqual(logs, ['$effect.pre 1', 'another $effect.pre 2', 'render n1', 'render i2']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/log.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/main.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/main.svelte index ecbd9321bf..a648f04865 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children-5/main.svelte @@ -1,17 +1,20 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/Item.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/Item.svelte index 8719c578f9..de1573539e 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/Item.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/Item.svelte @@ -1,19 +1,17 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js index 0c7118df75..affe03c344 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ get props() { return { n: 0 }; }, - before_test() { - log.length = 0; - }, - - async test({ assert, component }) { - assert.deepEqual(log, [ + async test({ assert, component, logs }) { + assert.deepEqual(logs, [ 'parent: $effect.pre 0', 'parent: render 0', '1: $effect.pre 0', @@ -26,11 +21,11 @@ export default test({ 'parent: $effect 0' ]); - log.length = 0; + logs.length = 0; component.n += 1; - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'parent: $effect.pre 1', 'parent: render 1', '1: $effect.pre 1', diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/log.js b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/main.svelte b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/main.svelte index 9cfa2b834c..f3918be07c 100644 --- a/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/lifecycle-render-order-for-children/main.svelte @@ -1,20 +1,19 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js index 6de94097f2..a8c16b7008 100644 --- a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js @@ -1,13 +1,8 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1] = target.querySelectorAll('button'); flushSync(() => { @@ -15,7 +10,7 @@ export default test({ }); await Promise.resolve(); - assert.deepEqual(log, [ + assert.deepEqual(logs, [ 'top level', 'inner', 0, diff --git a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/log.js b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/main.svelte b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/main.svelte index a7c6625dc1..47c98e5499 100644 --- a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/main.svelte @@ -1,18 +1,17 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/nested-script-tag/_config.js b/packages/svelte/tests/runtime-runes/samples/nested-script-tag/_config.js index 051f54889d..843805993f 100644 --- a/packages/svelte/tests/runtime-runes/samples/nested-script-tag/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/nested-script-tag/_config.js @@ -1,28 +1,9 @@ import { test } from '../../test'; -/** - * @type {any[]} - */ -let log; -/** - * @type {typeof console.log}} - */ -let original_log; - export default test({ mode: ['client'], - before_test() { - log = []; - original_log = console.log; - console.log = (...v) => { - log.push(...v); - }; - }, - after_test() { - console.log = original_log; - }, - async test({ assert }) { - assert.deepEqual(log, ['init']); + async test({ assert, logs }) { + assert.deepEqual(logs, ['init']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js index b4e2084871..6fc699efb6 100644 --- a/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js @@ -1,15 +1,9 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -/** @type {typeof console.warn} */ -let warn; - /** @type {typeof console.trace} */ let trace; -/** @type {any[]} */ -let warnings = []; - export default test({ html: ``, @@ -18,24 +12,16 @@ export default test({ }, before_test: () => { - warn = console.warn; trace = console.trace; - console.warn = (...args) => { - warnings.push(...args); - }; - console.trace = () => {}; }, after_test: () => { - console.warn = warn; console.trace = trace; - - warnings = []; }, - async test({ assert, target }) { + async test({ assert, target, warnings }) { const [btn1, btn2] = target.querySelectorAll('button'); flushSync(() => btn1.click()); diff --git a/packages/svelte/tests/runtime-runes/samples/nullish-operator/_config.js b/packages/svelte/tests/runtime-runes/samples/nullish-operator/_config.js index 11e729c3c7..940af7980e 100644 --- a/packages/svelte/tests/runtime-runes/samples/nullish-operator/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/nullish-operator/_config.js @@ -1,14 +1,9 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert }) { + async test({ assert, logs }) { await Promise.resolve(); await Promise.resolve(); - assert.deepEqual(log, ['a1: ', true, 'b1: ', true]); + assert.deepEqual(logs, ['a1: ', true, 'b1: ', true]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/nullish-operator/log.js b/packages/svelte/tests/runtime-runes/samples/nullish-operator/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/nullish-operator/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/nullish-operator/main.svelte b/packages/svelte/tests/runtime-runes/samples/nullish-operator/main.svelte index a98c4b4f39..801d568ffb 100644 --- a/packages/svelte/tests/runtime-runes/samples/nullish-operator/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/nullish-operator/main.svelte @@ -1,15 +1,13 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/pre-effect/_config.js b/packages/svelte/tests/runtime-runes/samples/pre-effect/_config.js index 1e6333bdeb..384356dc07 100644 --- a/packages/svelte/tests/runtime-runes/samples/pre-effect/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/pre-effect/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.deepEqual(log, [0, 1]); + assert.deepEqual(logs, [0, 1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/pre-effect/log.js b/packages/svelte/tests/runtime-runes/samples/pre-effect/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/pre-effect/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/pre-effect/main.svelte b/packages/svelte/tests/runtime-runes/samples/pre-effect/main.svelte index 5245340373..18f2610f6d 100644 --- a/packages/svelte/tests/runtime-runes/samples/pre-effect/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/pre-effect/main.svelte @@ -1,11 +1,9 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/props-derived-2/Item.svelte b/packages/svelte/tests/runtime-runes/samples/props-derived-2/Item.svelte index 1c2c6e7182..7d5e6cea08 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-derived-2/Item.svelte +++ b/packages/svelte/tests/runtime-runes/samples/props-derived-2/Item.svelte @@ -1,9 +1,7 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/props-derived-2/_config.js b/packages/svelte/tests/runtime-runes/samples/props-derived-2/_config.js index 32b526c9a8..d1518559b8 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-derived-2/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props-derived-2/_config.js @@ -1,19 +1,14 @@ import { test } from '../../test'; import { flushSync } from 'svelte'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { - log.length = 0; + async test({ assert, target, logs }) { + logs.length = 0; const input = /** @type {HTMLInputElement} */ (target.querySelector('input')); input.value = '1'; flushSync(() => input.dispatchEvent(new window.Event('input'))); - assert.deepEqual(log, ['active changed', false, 'active changed', true]); + assert.deepEqual(logs, ['active changed', false, 'active changed', true]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/props-derived-2/log.js b/packages/svelte/tests/runtime-runes/samples/props-derived-2/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/props-derived-2/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/props-equality/main.svelte b/packages/svelte/tests/runtime-runes/samples/props-equality/main.svelte index 7c7ee0c31e..9594cc406c 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-equality/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/props-equality/main.svelte @@ -11,7 +11,7 @@ {/each} {#each items as item (item.name)} - {console.log('hello'); item.name = item.name + '+'}} /> + item.name = item.name + '+'} /> {/each} {#each items as item} diff --git a/packages/svelte/tests/runtime-runes/samples/readonly-state/_config.js b/packages/svelte/tests/runtime-runes/samples/readonly-state/_config.js index 1e6333bdeb..384356dc07 100644 --- a/packages/svelte/tests/runtime-runes/samples/readonly-state/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/readonly-state/_config.js @@ -1,17 +1,12 @@ import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, - - async test({ assert, target }) { + async test({ assert, target, logs }) { const [b1, b2] = target.querySelectorAll('button'); b1.click(); b2.click(); await Promise.resolve(); - assert.deepEqual(log, [0, 1]); + assert.deepEqual(logs, [0, 1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/readonly-state/log.js b/packages/svelte/tests/runtime-runes/samples/readonly-state/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/readonly-state/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/readonly-state/main.svelte b/packages/svelte/tests/runtime-runes/samples/readonly-state/main.svelte index 1dde3104be..e92a479c93 100644 --- a/packages/svelte/tests/runtime-runes/samples/readonly-state/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/readonly-state/main.svelte @@ -1,11 +1,9 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/_config.js b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/_config.js index ffb50aaa53..01c8db2143 100644 --- a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/_config.js @@ -6,13 +6,8 @@ export default test({ `, - props: { - get log() { - return []; - } - }, - async test({ assert, target, component }) { + async test({ assert, target, logs }) { const [toggle, increment] = target.querySelectorAll('button'); await increment?.click(); @@ -24,7 +19,7 @@ export default test({ ` ); - assert.deepEqual(component.log, []); + assert.deepEqual(logs, []); await toggle?.click(); assert.htmlEqual( @@ -35,7 +30,7 @@ export default test({ ` ); - assert.deepEqual(component.log, [1]); + assert.deepEqual(logs, [1]); await increment?.click(); assert.htmlEqual( @@ -46,7 +41,7 @@ export default test({ ` ); - assert.deepEqual(component.log, [1]); + assert.deepEqual(logs, [1]); await toggle?.click(); assert.htmlEqual( @@ -57,6 +52,6 @@ export default test({ ` ); - assert.deepEqual(component.log, [1]); + assert.deepEqual(logs, [1]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/inner.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/inner.svelte index bbe3a61043..3980b77408 100644 --- a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/inner.svelte +++ b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/inner.svelte @@ -1,6 +1,6 @@

component: {count}

diff --git a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/main.svelte b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/main.svelte index 682fca22dc..90e04b45a5 100644 --- a/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/snippet-reactive-args/main.svelte @@ -1,8 +1,6 @@ diff --git a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/_config.js b/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/_config.js index d10b5e0790..064eca9aa3 100644 --- a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/_config.js @@ -1,13 +1,10 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; -import { log } from './log.js'; export default test({ - before_test() { - log.length = 0; - }, + async test({ assert, target, logs }) { + assert.deepEqual(logs, ['x', 'y']); - async test({ assert, target }) { const [b1, b2] = target.querySelectorAll('button'); flushSync(() => { @@ -18,6 +15,6 @@ export default test({ b2.click(); }); - assert.deepEqual(log, ['x', 'y', 'x', 'y']); + assert.deepEqual(logs, ['x', 'y', 'x', 'y']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/log.js b/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/log.js deleted file mode 100644 index d3df521f4d..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/log.js +++ /dev/null @@ -1,2 +0,0 @@ -/** @type {any[]} */ -export const log = []; diff --git a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/main.svelte b/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/main.svelte index 83ed148e44..a44130d944 100644 --- a/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/text-multiple-call-expression/main.svelte @@ -1,16 +1,14 @@ From dcfa5036173316a48a67c4e90d2688c0aa60dbbb Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 22 Apr 2024 08:11:47 -0400 Subject: [PATCH 07/18] fix: use type arguments when extending Map/Set (#10820) * use type arguments when extending Map/Set * changeset --- .changeset/silent-hats-stare.md | 5 +++++ packages/svelte/src/reactivity/map.js | 1 + packages/svelte/src/reactivity/set.js | 1 + packages/svelte/types/index.d.ts | 24 ++---------------------- 4 files changed, 9 insertions(+), 22 deletions(-) create mode 100644 .changeset/silent-hats-stare.md diff --git a/.changeset/silent-hats-stare.md b/.changeset/silent-hats-stare.md new file mode 100644 index 0000000000..3294f491ce --- /dev/null +++ b/.changeset/silent-hats-stare.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: add type arguments to Map and Set diff --git a/packages/svelte/src/reactivity/map.js b/packages/svelte/src/reactivity/map.js index b2b3ab605b..59fcfc1cf0 100644 --- a/packages/svelte/src/reactivity/map.js +++ b/packages/svelte/src/reactivity/map.js @@ -7,6 +7,7 @@ import { map } from './utils.js'; /** * @template K * @template V + * @extends {Map} */ export class ReactiveMap extends Map { /** @type {Map>} */ diff --git a/packages/svelte/src/reactivity/set.js b/packages/svelte/src/reactivity/set.js index 1855090cdf..7466885366 100644 --- a/packages/svelte/src/reactivity/set.js +++ b/packages/svelte/src/reactivity/set.js @@ -10,6 +10,7 @@ var inited = false; /** * @template T + * @extends {Set} */ export class ReactiveSet extends Set { /** @type {Map>} */ diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 401b569a61..d70e59d5eb 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -1985,38 +1985,18 @@ declare module 'svelte/reactivity' { constructor(...values: any[]); #private; } - class ReactiveSet extends Set { + class ReactiveSet extends Set { constructor(value?: Iterable | null | undefined); - has(value: T): boolean; - add(value: T): this; - - delete(value: T): boolean; - keys(): IterableIterator; - values(): IterableIterator; - entries(): IterableIterator<[T, T]>; - [Symbol.iterator](): IterableIterator; #private; } - class ReactiveMap extends Map { + class ReactiveMap extends Map { constructor(value?: Iterable | null | undefined); - has(key: K): boolean; - - forEach(callbackfn: (value: V, key: K, map: Map) => void, this_arg?: any): void; - - get(key: K): V | undefined; - set(key: K, value: V): this; - - delete(key: K): boolean; - keys(): IterableIterator; - values(): IterableIterator; - entries(): IterableIterator<[K, V]>; - [Symbol.iterator](): IterableIterator<[K, V]>; #private; } class ReactiveURL extends URL { From 0bb49b12d2a3eebaf1ab850295d8ddaa802d9f10 Mon Sep 17 00:00:00 2001 From: Yuichiro Yamashita Date: Mon, 22 Apr 2024 21:22:17 +0900 Subject: [PATCH 08/18] fix: resolve type definition error in `svelte/compiler` (#11283) * fix generated type * add changeset --- .changeset/lucky-colts-remember.md | 5 +++++ packages/svelte/src/compiler/index.js | 8 +++----- packages/svelte/types/index.d.ts | 4 +--- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 .changeset/lucky-colts-remember.md diff --git a/.changeset/lucky-colts-remember.md b/.changeset/lucky-colts-remember.md new file mode 100644 index 0000000000..0708829e01 --- /dev/null +++ b/.changeset/lucky-colts-remember.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: resolve type definition error in `svelte/compiler` diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js index a35f47adbc..eee35bf2a8 100644 --- a/packages/svelte/src/compiler/index.js +++ b/packages/svelte/src/compiler/index.js @@ -1,5 +1,5 @@ import { getLocator } from 'locate-character'; -import { walk } from 'zimmerframe'; +import { walk as zimmerframe_walk } from 'zimmerframe'; import { CompileError } from './errors.js'; import { convert } from './legacy.js'; import { parse as parse_acorn } from './phases/1-parse/acorn.js'; @@ -133,7 +133,7 @@ export function parse(source, options = {}) { function to_public_ast(source, ast, modern) { if (modern) { // remove things that we don't want to treat as public API - return walk(ast, null, { + return zimmerframe_walk(ast, null, { _(node, { next }) { // @ts-ignore delete node.parent; @@ -151,14 +151,12 @@ function to_public_ast(source, ast, modern) { * @deprecated Replace this with `import { walk } from 'estree-walker'` * @returns {never} */ -function _walk() { +export function walk() { throw new Error( `'svelte/compiler' no longer exports a \`walk\` utility — please import it directly from 'estree-walker' instead` ); } -export { _walk as walk }; - export { CompileError } from './errors.js'; export { VERSION } from '../version.js'; diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index d70e59d5eb..633a910991 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -507,7 +507,7 @@ declare module 'svelte/compiler' { /** * @deprecated Replace this with `import { walk } from 'estree-walker'` * */ - function walk(): never; + export function walk(): never; /** The return value of `compile` from `svelte/compiler` */ interface CompileResult { /** The compiled JavaScript */ @@ -1763,8 +1763,6 @@ declare module 'svelte/compiler' { style?: Preprocessor; script?: Preprocessor; } - - export { walk }; } declare module 'svelte/easing' { From 05ac8f4322a124fb4d8d064297f8aa47ca47b9a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 08:30:06 -0400 Subject: [PATCH 09/18] Version Packages (next) (#11260) Co-authored-by: github-actions[bot] --- .changeset/pre.json | 8 ++++++++ packages/svelte/CHANGELOG.md | 20 ++++++++++++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 250b24d1b8..6a3cec722e 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -106,6 +106,7 @@ "few-clouds-shop", "few-mugs-fail", "few-teachers-know", + "fifty-masks-give", "fifty-rice-wait", "fifty-steaks-float", "five-tigers-search", @@ -197,6 +198,7 @@ "light-badgers-glow", "light-days-clean", "light-humans-hang", + "light-penguins-invent", "light-pens-watch", "little-pans-jog", "long-buckets-lay", @@ -211,6 +213,7 @@ "lovely-houses-own", "lovely-items-turn", "lovely-rules-eat", + "lucky-colts-remember", "lucky-schools-hang", "lucky-toes-begin", "many-rockets-give", @@ -303,6 +306,7 @@ "selfish-socks-smile", "selfish-spies-help", "selfish-tools-hide", + "serious-crabs-punch", "serious-gorillas-eat", "serious-kids-deliver", "serious-needles-joke", @@ -320,12 +324,14 @@ "sharp-kids-happen", "sharp-tomatoes-learn", "shiny-baboons-play", + "shiny-mayflies-clean", "shiny-rats-heal", "shiny-shrimps-march", "short-buses-camp", "short-countries-rush", "shy-fishes-drive", "silent-apes-report", + "silent-hats-stare", "silly-laws-happen", "silly-lies-film", "silly-ways-wash", @@ -341,6 +347,7 @@ "slow-kids-sparkle", "slow-plums-chew", "slow-wombats-reply", + "small-apples-eat", "small-papayas-laugh", "small-sheep-type", "small-spiders-fail", @@ -404,6 +411,7 @@ "thick-cycles-rule", "thick-pans-tell", "thick-shirts-deliver", + "thick-swans-type", "thin-foxes-lick", "thirty-flowers-sit", "thirty-ghosts-fix", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 45415364f3..a5a654eedb 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,25 @@ # svelte +## 5.0.0-next.111 + +### Patch Changes + +- fix: run render functions for dynamic void elements ([#11258](https://github.com/sveltejs/svelte/pull/11258)) + +- fix: allow events to continue propagating following an error ([#11263](https://github.com/sveltejs/svelte/pull/11263)) + +- fix: resolve type definition error in `svelte/compiler` ([#11283](https://github.com/sveltejs/svelte/pull/11283)) + +- feat: include `script` and `svelte:options` attributes in ast ([#11241](https://github.com/sveltejs/svelte/pull/11241)) + +- fix: only destroy snippets when they have changed ([#11267](https://github.com/sveltejs/svelte/pull/11267)) + +- fix: add type arguments to Map and Set ([#10820](https://github.com/sveltejs/svelte/pull/10820)) + +- feat: implement `:global {...}` CSS blocks ([#11276](https://github.com/sveltejs/svelte/pull/11276)) + +- feat: add read-only `bind:focused` ([#11271](https://github.com/sveltejs/svelte/pull/11271)) + ## 5.0.0-next.110 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 43d86f4d9d..709d74dd35 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.0.0-next.110", + "version": "5.0.0-next.111", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 0056ca8180..b13963eb4d 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -6,5 +6,5 @@ * https://svelte.dev/docs/svelte-compiler#svelte-version * @type {string} */ -export const VERSION = '5.0.0-next.110'; +export const VERSION = '5.0.0-next.111'; export const PUBLIC_VERSION = '5'; From fe6e4e2b05b8099d27483b7b5f14c1d757c934d3 Mon Sep 17 00:00:00 2001 From: Craig Jennings <1683368+craig-jennings@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:16:02 -0500 Subject: [PATCH 10/18] fix: avoid hoisting error by using 'let' instead of 'var' (#11291) Fixes #11284 --- .changeset/plenty-starfishes-dress.md | 5 +++++ .../src/internal/client/dom/elements/attributes.js | 7 ++++--- .../samples/event-attribute-after-spread/_config.js | 13 +++++++++++++ .../event-attribute-after-spread/main.svelte | 7 +++++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 .changeset/plenty-starfishes-dress.md create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/main.svelte diff --git a/.changeset/plenty-starfishes-dress.md b/.changeset/plenty-starfishes-dress.md new file mode 100644 index 0000000000..38b2201e9e --- /dev/null +++ b/.changeset/plenty-starfishes-dress.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: avoid hoisting error by using 'let' instead of 'var' diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 67e336744f..58519d9baa 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -111,7 +111,8 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha var events = []; for (key in next) { - var value = next[key]; + // let instead of var because referenced in a closure + let value = next[key]; if (value === prev?.[key]) continue; var prefix = key[0] + key[1]; // this is faster than key.slice(0, 2) @@ -119,8 +120,8 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha if (prefix === 'on') { /** @type {{ capture?: true }} */ - var opts = {}; - var event_name = key.slice(2); + const opts = {}; + let event_name = key.slice(2); var delegated = DelegatedEvents.includes(event_name); if ( diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/_config.js b/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/_config.js new file mode 100644 index 0000000000..09975947e6 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/_config.js @@ -0,0 +1,13 @@ +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const input = target.querySelector('input'); + + input?.dispatchEvent(new Event('input', { bubbles: true })); + + await Promise.resolve(); + + assert.htmlEqual(target.innerHTML, 'true '); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/main.svelte new file mode 100644 index 0000000000..c854071f3e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-attribute-after-spread/main.svelte @@ -0,0 +1,7 @@ + + +{changed} + (changed = true)} class="hello" /> From e3c85897374a76812191464e7eca869e0aec3082 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:46:28 -0400 Subject: [PATCH 11/18] Version Packages (next) (#11292) Co-authored-by: github-actions[bot] --- .changeset/pre.json | 1 + packages/svelte/CHANGELOG.md | 6 ++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 6a3cec722e..91b0d77715 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -262,6 +262,7 @@ "orange-yaks-protect", "pink-bikes-agree", "pink-mayflies-tie", + "plenty-starfishes-dress", "polite-dolphins-care", "polite-pumpkins-guess", "polite-ravens-study", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index a5a654eedb..109238e281 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,11 @@ # svelte +## 5.0.0-next.112 + +### Patch Changes + +- fix: avoid hoisting error by using 'let' instead of 'var' ([#11291](https://github.com/sveltejs/svelte/pull/11291)) + ## 5.0.0-next.111 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 709d74dd35..f8bee6890b 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.0.0-next.111", + "version": "5.0.0-next.112", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index b13963eb4d..d17a9f204e 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -6,5 +6,5 @@ * https://svelte.dev/docs/svelte-compiler#svelte-version * @type {string} */ -export const VERSION = '5.0.0-next.111'; +export const VERSION = '5.0.0-next.112'; export const PUBLIC_VERSION = '5'; From 2d378bb76284d19ec843482086cf5d631ba238a7 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:29:02 +0200 Subject: [PATCH 12/18] breaking: disallow binding to component exports in runes mode (#11238) * breaking: disallow binding to component exports in runes mode Svelte 4 allowed you to have `export const foo = ..` in component A and then do ``. This is confusing because it's not clear whether the binding is for a property or an export, and we have to sanitize rest props from the export bindings. This PR therefore introduces a breaking change in runes mode: You cannot bind to these exports anymore. Instead use `` and then do `a.foo` - makes things easier to reason about. * Update sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md Co-authored-by: Rich Harris * tweak messages * fix tests * use component.name * oops --------- Co-authored-by: Rich Harris --- .changeset/beige-seas-share.md | 5 +++++ .../3-transform/client/transform-client.js | 14 ++++++++++-- .../client/visitors/javascript-runes.js | 3 ++- .../3-transform/server/transform-server.js | 22 ++----------------- .../svelte/src/internal/client/validate.js | 22 ++++++++++++++----- .../samples/export-binding/Counter.svelte | 12 ---------- .../samples/export-binding/_config.js | 15 ++++--------- .../export-binding/counter/index.svelte | 8 +++++++ .../samples/export-binding/main.svelte | 4 ++-- .../props-not-bindable-spread/_config.js | 5 +++-- .../samples/props-not-bindable/_config.js | 5 +++-- .../03-appendix/02-breaking-changes.md | 4 ++-- 12 files changed, 59 insertions(+), 60 deletions(-) create mode 100644 .changeset/beige-seas-share.md delete mode 100644 packages/svelte/tests/runtime-runes/samples/export-binding/Counter.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/export-binding/counter/index.svelte diff --git a/.changeset/beige-seas-share.md b/.changeset/beige-seas-share.md new file mode 100644 index 0000000000..3758385c55 --- /dev/null +++ b/.changeset/beige-seas-share.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +breaking: disallow binding to component exports in runes mode diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index f1de213a9b..70f981d3e6 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -255,14 +255,24 @@ export function client_component(source, analysis, options) { ); if (analysis.runes && options.dev) { - const bindable = analysis.exports.map(({ name, alias }) => b.literal(alias ?? name)); + const exports = analysis.exports.map(({ name, alias }) => b.literal(alias ?? name)); + /** @type {import('estree').Literal[]} */ + const bindable = []; for (const [name, binding] of properties) { if (binding.kind === 'bindable_prop') { bindable.push(b.literal(binding.prop_alias ?? name)); } } instance.body.unshift( - b.stmt(b.call('$.validate_prop_bindings', b.id('$$props'), b.array(bindable))) + b.stmt( + b.call( + '$.validate_prop_bindings', + b.id('$$props'), + b.array(bindable), + b.array(exports), + b.id(`${analysis.name}`) + ) + ) ); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js index 7646ae78b7..5c5b177917 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/javascript-runes.js @@ -222,7 +222,8 @@ export const javascript_visitors_runes = { if (rune === '$props') { assert.equal(declarator.id.type, 'ObjectPattern'); - const seen = state.analysis.exports.map(({ name, alias }) => alias ?? name); + /** @type {string[]} */ + const seen = []; for (const property of declarator.id.properties) { if (property.type === 'Property') { diff --git a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js index d5402351c7..4f631b8c70 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/transform-server.js @@ -692,8 +692,7 @@ const javascript_visitors_runes = { } if (rune === '$props') { - // remove $bindable() from props declaration and handle rest props - let uses_rest_props = false; + // remove $bindable() from props declaration const id = walk(declarator.id, null, { AssignmentPattern(node) { if ( @@ -705,26 +704,9 @@ const javascript_visitors_runes = { : b.id('undefined'); return b.assignment_pattern(node.left, right); } - }, - RestElement(node, { path }) { - if (path.at(-1) === declarator.id) { - uses_rest_props = true; - } } }); - - const exports = /** @type {import('../../types').ComponentAnalysis} */ ( - state.analysis - ).exports.map(({ name, alias }) => b.literal(alias ?? name)); - - declarations.push( - b.declarator( - id, - uses_rest_props && exports.length > 0 - ? b.call('$.rest_props', b.id('$$props'), b.array(exports)) - : b.id('$$props') - ) - ); + declarations.push(b.declarator(id, b.id('$$props'))); continue; } diff --git a/packages/svelte/src/internal/client/validate.js b/packages/svelte/src/internal/client/validate.js index add59ebe82..b2dfee7ab1 100644 --- a/packages/svelte/src/internal/client/validate.js +++ b/packages/svelte/src/internal/client/validate.js @@ -85,16 +85,26 @@ export function loop_guard(timeout) { /** * @param {Record} $$props * @param {string[]} bindable + * @param {string[]} exports + * @param {Function & { filename: string }} component */ -export function validate_prop_bindings($$props, bindable) { +export function validate_prop_bindings($$props, bindable, exports, component) { for (const key in $$props) { - if (!bindable.includes(key)) { - var setter = get_descriptor($$props, key)?.set; + var setter = get_descriptor($$props, key)?.set; + var name = component.name; - if (setter) { + if (setter) { + if (exports.includes(key)) { throw new Error( - `Cannot use bind:${key} on this component because the property was not declared as bindable. ` + - `To mark a property as bindable, use the $bindable() rune like this: \`let { ${key} = $bindable() } = $props()\`` + `Component ${component.filename} has an export named ${key} that a consumer component is trying to access using bind:${key}, which is disallowed. ` + + `Instead, use bind:this (e.g. <${name} bind:this={component} />) ` + + `and then access the property on the bound component instance (e.g. component.${key}).` + ); + } + if (!bindable.includes(key)) { + throw new Error( + `A component is binding to property ${key} of ${name}.svelte (i.e. <${name} bind:${key} />). This is disallowed because the property was not declared as bindable inside ${component.filename}. ` + + `To mark a property as bindable, use the $bindable() rune in ${name}.svelte like this: \`let { ${key} = $bindable() } = $props()\`` ); } } diff --git a/packages/svelte/tests/runtime-runes/samples/export-binding/Counter.svelte b/packages/svelte/tests/runtime-runes/samples/export-binding/Counter.svelte deleted file mode 100644 index 94c822f31f..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/export-binding/Counter.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - -{Object.keys(rest).length} - -{count} diff --git a/packages/svelte/tests/runtime-runes/samples/export-binding/_config.js b/packages/svelte/tests/runtime-runes/samples/export-binding/_config.js index aa41757bd1..0f64998059 100644 --- a/packages/svelte/tests/runtime-runes/samples/export-binding/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/export-binding/_config.js @@ -2,16 +2,9 @@ import { test } from '../../test'; export default test({ compileOptions: { - dev: true // to ensure we don't throw a false-positive "cannot bind to this" error + dev: true // to ensure we we catch the error }, - html: `0 0 `, - - async test({ assert, target }) { - const btn = target.querySelector('button'); - - btn?.click(); - await Promise.resolve(); - - assert.htmlEqual(target.innerHTML, `0 1 `); - } + error: + 'Component .../export-binding/counter/index.svelte has an export named increment that a consumer component is trying to access using bind:increment, which is disallowed. ' + + 'Instead, use bind:this (e.g. ) and then access the property on the bound component instance (e.g. component.increment).' }); diff --git a/packages/svelte/tests/runtime-runes/samples/export-binding/counter/index.svelte b/packages/svelte/tests/runtime-runes/samples/export-binding/counter/index.svelte new file mode 100644 index 0000000000..14e0de961b --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/export-binding/counter/index.svelte @@ -0,0 +1,8 @@ + + +{count} diff --git a/packages/svelte/tests/runtime-runes/samples/export-binding/main.svelte b/packages/svelte/tests/runtime-runes/samples/export-binding/main.svelte index 89f0aff9a0..4ad1684701 100644 --- a/packages/svelte/tests/runtime-runes/samples/export-binding/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/export-binding/main.svelte @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/packages/svelte/tests/runtime-runes/samples/props-not-bindable-spread/_config.js b/packages/svelte/tests/runtime-runes/samples/props-not-bindable-spread/_config.js index 4c3fdf5bd9..fc6b46d488 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-not-bindable-spread/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props-not-bindable-spread/_config.js @@ -5,7 +5,8 @@ export default test({ dev: true }, error: - 'Cannot use bind:count on this component because the property was not declared as bindable. ' + - 'To mark a property as bindable, use the $bindable() rune like this: `let { count = $bindable() } = $props()`', + 'A component is binding to property count of Counter.svelte (i.e. ). This is disallowed because the property was ' + + 'not declared as bindable inside .../samples/props-not-bindable-spread/Counter.svelte. To mark a property as bindable, use the $bindable() rune ' + + 'in Counter.svelte like this: `let { count = $bindable() } = $props()`', html: `0` }); diff --git a/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js index 4c3fdf5bd9..b3dcc7f23e 100644 --- a/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js @@ -5,7 +5,8 @@ export default test({ dev: true }, error: - 'Cannot use bind:count on this component because the property was not declared as bindable. ' + - 'To mark a property as bindable, use the $bindable() rune like this: `let { count = $bindable() } = $props()`', + 'A component is binding to property count of Counter.svelte (i.e. ). This is disallowed because the property was ' + + 'not declared as bindable inside .../samples/props-not-bindable/Counter.svelte. To mark a property as bindable, use the $bindable() rune ' + + 'in Counter.svelte like this: `let { count = $bindable() } = $props()`', html: `0` }); diff --git a/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md b/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md index 25547f72ab..43a5c7134c 100644 --- a/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md +++ b/sites/svelte-5-preview/src/routes/docs/content/03-appendix/02-breaking-changes.md @@ -121,9 +121,9 @@ Content inside component tags becomes a [snippet prop](/docs/snippets) called `c Some breaking changes only apply once your component is in runes mode. -### Bindings to component exports don't show up in rest props +### Bindings to component exports are not allowed -In runes mode, bindings to component exports don't show up in rest props. For example, `rest` in `let { foo, bar, ...rest } = $props();` would not contain `baz` if `baz` was defined as `export const baz = ...;` inside the component. In Svelte 4 syntax, the equivalent to `rest` would be `$$restProps`, which contains these component exports. +Exports from runes mode components cannot be bound to directly. For example, having `export const foo = ...` in component `A` and then doing `` causes an error. Use `bind:this` instead — `` — and access the export as `a.foo`. This change makes things easier to reason about, as it enforces a clear separation between props and exports. ### Bindings need to be explicitly defined using `$bindable()` From 3866887f3787a61c044448a7557a7f89489b293b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 09:56:58 -0400 Subject: [PATCH 13/18] Version Packages (next) (#11296) Co-authored-by: github-actions[bot] --- .changeset/pre.json | 1 + packages/svelte/CHANGELOG.md | 6 ++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 91b0d77715..300038c872 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -19,6 +19,7 @@ "beige-flies-wash", "beige-mirrors-listen", "beige-rabbits-shave", + "beige-seas-share", "big-cars-serve", "big-eggs-flash", "big-eyes-carry", diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 109238e281..0e57787e43 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,11 @@ # svelte +## 5.0.0-next.113 + +### Patch Changes + +- breaking: disallow binding to component exports in runes mode ([#11238](https://github.com/sveltejs/svelte/pull/11238)) + ## 5.0.0-next.112 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index f8bee6890b..11b8c7a46c 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.0.0-next.112", + "version": "5.0.0-next.113", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index d17a9f204e..81de554c27 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -6,5 +6,5 @@ * https://svelte.dev/docs/svelte-compiler#svelte-version * @type {string} */ -export const VERSION = '5.0.0-next.112'; +export const VERSION = '5.0.0-next.113'; export const PUBLIC_VERSION = '5'; From 73490bbb8e3c0640ac72151d7e9aa8b5bf6604d6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 23 Apr 2024 10:39:37 -0400 Subject: [PATCH 14/18] chore: markdown errors (#11294) * rename errors.js to errors-tmp.js * start porting errors * generate markdown files for more errors * convert parse errors * convert css errors * convert special_element errors * convert runes errors * convert element errors * more * more * more * more * more * more * fix some tests * fix some tests * more tests * remove unused error * prettierignore * weird * ugh * lint --- .prettierignore | 2 + eslint.config.js | 5 +- .../messages/compile-errors/attributes.md | 59 + .../messages/compile-errors/bindings.md | 35 + .../compile-errors/compiler_options.md | 7 + .../messages/compile-errors/components.md | 3 + .../messages/compile-errors/const_tag.md | 3 + .../svelte/messages/compile-errors/css.md | 51 + .../messages/compile-errors/elements.md | 27 + .../compile-errors/legacy_reactivity.md | 3 + .../svelte/messages/compile-errors/parse.md | 147 ++ .../svelte/messages/compile-errors/runes.md | 95 + .../svelte/messages/compile-errors/slots.md | 31 + .../compile-errors/special_elements.md | 99 + .../messages/compile-errors/variables.md | 19 + .../svelte/scripts/process-messages/index.js | 213 ++ .../templates/compile-errors.js | 74 + packages/svelte/src/compiler/errors.js | 1849 ++++++++++++----- .../src/compiler/phases/1-parse/index.js | 22 +- .../compiler/phases/1-parse/read/context.js | 10 +- .../phases/1-parse/read/expression.js | 4 +- .../compiler/phases/1-parse/read/options.js | 91 +- .../compiler/phases/1-parse/read/script.js | 8 +- .../src/compiler/phases/1-parse/read/style.js | 22 +- .../compiler/phases/1-parse/state/element.js | 74 +- .../src/compiler/phases/1-parse/state/tag.js | 30 +- .../phases/2-analyze/css/css-analyze.js | 27 +- .../src/compiler/phases/2-analyze/index.js | 22 +- .../compiler/phases/2-analyze/validation.js | 267 +-- .../3-transform/client/transform-client.js | 27 +- .../phases/3-transform/client/utils.js | 3 +- .../3-transform/client/visitors/template.js | 7 +- .../3-transform/server/transform-server.js | 18 +- packages/svelte/src/compiler/phases/scope.js | 12 +- packages/svelte/src/compiler/utils/assert.js | 6 +- .../svelte/src/compiler/validate-options.js | 9 +- .../samples/attribute-empty/_config.js | 2 +- .../_config.js | 2 +- .../attribute-sequence-expression/_config.js | 2 +- .../attribute-unique-binding/_config.js | 2 +- .../attribute-unique-shorthand/_config.js | 2 +- .../samples/attribute-unique/_config.js | 2 +- .../samples/catch-before-closing/_config.js | 2 +- .../samples/catch-without-await/_config.js | 2 +- .../class-state-field-static/_config.js | 5 +- .../samples/comment-unclosed/_config.js | 4 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../_config.js | 2 +- .../component-slot-duplicate-error/_config.js | 2 +- .../component-slot-nested-error-2/_config.js | 2 +- .../component-slot-nested-error-3/_config.js | 2 +- .../component-slot-nested-error/_config.js | 2 +- .../css-global-block-combinator/_config.js | 2 +- .../css-global-block-declaration/_config.js | 2 +- .../css-global-block-modifier/_config.js | 2 +- .../css-global-block-multiple/_config.js | 2 +- .../compiler-errors/samples/css/_config.js | 2 +- .../dollar-binding-declaration/_config.js | 2 +- .../dollar-binding-global-js/_config.js | 4 +- .../samples/dollar-binding-global/_config.js | 4 +- .../samples/dollar-binding-import/_config.js | 2 +- .../_config.js | 4 +- .../samples/else-before-closing-2/_config.js | 2 +- .../samples/else-before-closing-3/_config.js | 2 +- .../samples/else-before-closing/_config.js | 2 +- .../else-if-before-closing-2/_config.js | 2 +- .../samples/else-if-before-closing/_config.js | 2 +- .../samples/else-if-without-if/_config.js | 2 +- .../empty-attribute-shorthand/_config.js | 2 +- .../empty-classname-binding/_config.js | 2 +- .../samples/empty-directive-name/_config.js | 2 +- .../samples/export-derived-state/_config.js | 2 +- .../samples/export-state-module/_config.js | 2 +- .../samples/export-state/_config.js | 2 +- .../samples/illegal-expression/_config.js | 2 +- .../invalid-snippet-binding/_config.js | 2 +- .../invalid-snippet-mutation/_config.js | 2 +- .../legacy-no-const-assignment/_config.js | 4 +- .../samples/legacy-no-const-update/_config.js | 4 +- .../samples/multiple-styles/_config.js | 4 +- .../samples/options-children/_config.js | 2 +- .../raw-mustaches-whitespace/_config.js | 2 +- .../render-tag-invalid-call/_config.js | 2 +- .../runes-before-after-update/_config.js | 2 +- .../samples/runes-duplicate-props/_config.js | 4 +- .../samples/runes-export-let/_config.js | 2 +- .../runes-export-named-state/_config.js | 2 +- .../runes-invalid-each-binding/_config.js | 4 +- .../runes-invalid-each-mutation/_config.js | 4 +- .../runes-no-const-assignment/_config.js | 4 +- .../samples/runes-no-const-update/_config.js | 4 +- .../runes-no-derived-assignment/_config.js | 4 +- .../runes-no-derived-binding/_config.js | 4 +- .../_config.js | 4 +- .../_config.js | 4 +- .../runes-no-derived-update/_config.js | 4 +- .../samples/runes-no-rune-each/_config.js | 4 +- .../runes-prop-export-conflict/_config.js | 2 +- .../runes-wrong-bindable-args/_config.js | 4 +- .../runes-wrong-bindable-placement/_config.js | 4 +- .../runes-wrong-derived-args/_config.js | 4 +- .../runes-wrong-derived-placement/_config.js | 5 +- .../runes-wrong-effect-args/_config.js | 4 +- .../runes-wrong-effect-placement/_config.js | 4 +- .../runes-wrong-host-placement/_config.js | 4 +- .../samples/runes-wrong-props-args/_config.js | 4 +- .../runes-wrong-props-placement/_config.js | 4 +- .../samples/runes-wrong-state-args/_config.js | 4 +- .../runes-wrong-state-placement/_config.js | 4 +- .../_config.js | 4 +- .../samples/script-unclosed-eof/_config.js | 2 +- .../samples/script-unclosed/_config.js | 4 +- .../samples/self-reference/_config.js | 4 +- .../_config.js | 4 +- .../snippet-children-conflict/_config.js | 2 +- .../store-autosub-context-module/_config.js | 4 +- .../samples/store-contextual/_config.js | 2 +- .../store-global-disallowed/_config.js | 4 +- .../_config.js | 2 +- .../samples/store-shadow-scope-2/_config.js | 2 +- .../samples/store-shadow-scope-3/_config.js | 2 +- .../samples/store-shadow-scope/_config.js | 2 +- .../_config.js | 2 +- .../samples/style-unclosed-eof/_config.js | 2 +- .../samples/style-unclosed/_config.js | 2 +- .../samples/svelte-selfdestructive/_config.js | 4 +- .../samples/then-before-closing/_config.js | 2 +- .../samples/then-without-await/_config.js | 2 +- .../_config.js | 2 +- .../unexpected-end-of-input-b/_config.js | 2 +- .../unexpected-end-of-input-c/_config.js | 2 +- .../unexpected-end-of-input-d/_config.js | 2 +- .../unexpected-end-of-input/_config.js | 4 +- .../_config.js | 2 +- .../_config.js | 2 +- .../samples/unmatched-closing-tag/_config.js | 2 +- .../samples/void-closing/_config.js | 2 +- .../samples/window-children/_config.js | 2 +- .../samples/window-duplicate/_config.js | 2 +- .../samples/window-inside-block/_config.js | 2 +- .../samples/window-inside-element/_config.js | 2 +- .../samples/action-on-component/errors.json | 2 +- .../samples/animation-duplicate/errors.json | 2 +- .../samples/animation-not-in-each/errors.json | 4 +- .../animation-not-in-keyed-each/errors.json | 4 +- .../animation-on-component/errors.json | 2 +- .../samples/animation-siblings/errors.json | 4 +- .../samples/assignment-to-const-2/errors.json | 4 +- .../samples/assignment-to-const-3/errors.json | 4 +- .../samples/assignment-to-const-4/errors.json | 4 +- .../samples/assignment-to-const-5/errors.json | 4 +- .../samples/assignment-to-const-7/errors.json | 4 +- .../samples/assignment-to-const/errors.json | 4 +- .../attribute-expected-equals/errors.json | 2 +- .../attribute-invalid-name-2/errors.json | 2 +- .../attribute-invalid-name-3/errors.json | 2 +- .../attribute-invalid-name-4/errors.json | 2 +- .../attribute-invalid-name-5/errors.json | 2 +- .../attribute-invalid-name/errors.json | 2 +- .../samples/binding-await-catch/errors.json | 14 +- .../samples/binding-await-then-2/errors.json | 14 +- .../samples/binding-await-then/errors.json | 14 +- .../samples/binding-const/errors.json | 4 +- .../binding-dimensions-svg/errors.json | 4 +- .../samples/binding-input-checked/errors.json | 4 +- .../binding-input-type-boolean/errors.json | 2 +- .../errors.json | 4 +- .../binding-invalid-on-element-2/errors.json | 4 +- .../binding-invalid-on-element/errors.json | 4 +- .../binding-invalid-value-global/errors.json | 2 +- .../samples/binding-invalid-value/errors.json | 2 +- .../samples/binding-invalid/errors.json | 4 +- .../validator/samples/binding-let/errors.json | 4 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 12 +- .../errors.json | 4 +- .../errors.json | 2 +- .../component-slot-dynamic/errors.json | 2 +- .../errors.json | 12 +- .../component-slotted-each-block/errors.json | 2 +- .../component-slotted-if-block/errors.json | 2 +- .../samples/const-tag-conflict-1/errors.json | 14 +- .../samples/const-tag-conflict-2/errors.json | 14 +- .../samples/const-tag-placement-1/errors.json | 12 +- .../samples/const-tag-placement-2/errors.json | 12 +- .../samples/const-tag-readonly-1/errors.json | 14 +- .../samples/const-tag-readonly-2/errors.json | 14 +- .../contenteditable-dynamic/errors.json | 2 +- .../contenteditable-missing/errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../css-invalid-global-placement/errors.json | 2 +- .../css-invalid-global-selector-2/errors.json | 2 +- .../css-invalid-global-selector-3/errors.json | 2 +- .../css-invalid-global-selector-4/errors.json | 2 +- .../css-invalid-global-selector-5/errors.json | 2 +- .../css-invalid-global-selector-6/errors.json | 2 +- .../errors.json | 2 +- .../css-invalid-global-selector/errors.json | 2 +- .../errors.json | 2 +- .../samples/css-mismatched-quotes/errors.json | 2 +- .../samples/debug-invalid-args/errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../samples/default-export/errors.json | 2 +- .../directive-non-expression/errors.json | 2 +- .../errors.json | 4 +- .../errors.json | 4 +- .../dollar-global-in-markup/errors.json | 4 +- .../dollar-global-in-script/errors.json | 4 +- .../dynamic-element-invalid-tag/errors.json | 2 +- .../dynamic-element-missing-tag/errors.json | 4 +- .../samples/dynamic-element-this/errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../each-block-invalid-context/errors.json | 2 +- .../samples/event-attribute/errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../event-modifiers-invalid/errors.json | 2 +- .../html-block-in-attribute/errors.json | 12 +- .../html-block-in-textarea/errors.json | 12 +- .../illegal-variable-declaration/errors.json | 4 +- .../invalid-empty-css-declaration/errors.json | 2 +- .../invalid-node-placement-2/errors.json | 2 +- .../invalid-node-placement/errors.json | 2 +- .../samples/let-directive/errors.json | 14 +- .../logic-block-in-attribute/errors.json | 12 +- .../logic-block-in-textarea/errors.json | 12 +- .../errors.json | 4 +- .../errors.json | 4 +- .../samples/namespace-invalid/errors.json | 4 +- .../samples/namespace-non-literal/errors.json | 4 +- .../reactive-declaration-cyclical/errors.json | 12 +- .../script-invalid-context/errors.json | 2 +- .../slot-attribute-invalid/errors.json | 2 +- .../errors.json | 2 +- .../svelte-fragment-placement-2/errors.json | 14 +- .../svelte-fragment-placement/errors.json | 14 +- .../svelte-head-attributes/errors.json | 14 +- .../validator/samples/tag-invalid/errors.json | 4 +- .../samples/tag-non-string/errors.json | 2 +- .../textarea-value-children/errors.json | 4 +- .../samples/title-no-attributes/errors.json | 4 +- .../samples/title-no-children/errors.json | 4 +- .../errors.json | 4 +- .../transition-duplicate-in/errors.json | 4 +- .../errors.json | 4 +- .../transition-duplicate-out/errors.json | 4 +- .../errors.json | 4 +- .../errors.json | 4 +- .../errors.json | 4 +- .../transition-on-component/errors.json | 2 +- .../errors.json | 4 +- .../window-binding-invalid/errors.json | 4 +- 267 files changed, 3027 insertions(+), 1198 deletions(-) create mode 100644 packages/svelte/messages/compile-errors/attributes.md create mode 100644 packages/svelte/messages/compile-errors/bindings.md create mode 100644 packages/svelte/messages/compile-errors/compiler_options.md create mode 100644 packages/svelte/messages/compile-errors/components.md create mode 100644 packages/svelte/messages/compile-errors/const_tag.md create mode 100644 packages/svelte/messages/compile-errors/css.md create mode 100644 packages/svelte/messages/compile-errors/elements.md create mode 100644 packages/svelte/messages/compile-errors/legacy_reactivity.md create mode 100644 packages/svelte/messages/compile-errors/parse.md create mode 100644 packages/svelte/messages/compile-errors/runes.md create mode 100644 packages/svelte/messages/compile-errors/slots.md create mode 100644 packages/svelte/messages/compile-errors/special_elements.md create mode 100644 packages/svelte/messages/compile-errors/variables.md create mode 100644 packages/svelte/scripts/process-messages/index.js create mode 100644 packages/svelte/scripts/process-messages/templates/compile-errors.js diff --git a/.prettierignore b/.prettierignore index 48d37dc02f..77bdd29cf3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,8 @@ packages/**/dist/*.js packages/**/build/*.js packages/**/npm/**/* packages/**/config/*.js +packages/svelte/messages/**/*.md +packages/svelte/src/compiler/errors.js packages/svelte/tests/**/*.svelte packages/svelte/tests/**/_expected* packages/svelte/tests/**/_actual* diff --git a/eslint.config.js b/eslint.config.js index 75fcc7fa06..a86f724d34 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -33,13 +33,16 @@ export default [ ignores: [ '**/*.d.ts', '**/tests', + 'packages/svelte/scripts/process-messages/templates/*.js', + 'packages/svelte/src/compiler/errors.js', 'packages/svelte/compiler/index.js', // documentation can contain invalid examples 'documentation', // contains a fork of the REPL which doesn't adhere to eslint rules 'sites/svelte-5-preview/**', // wasn't checked previously, reenable at some point - 'sites/svelte.dev/**' + 'sites/svelte.dev/**', + 'tmp/**' ] } ]; diff --git a/packages/svelte/messages/compile-errors/attributes.md b/packages/svelte/messages/compile-errors/attributes.md new file mode 100644 index 0000000000..9501080ee0 --- /dev/null +++ b/packages/svelte/messages/compile-errors/attributes.md @@ -0,0 +1,59 @@ +## empty_attribute_shorthand + +Attribute shorthand cannot be empty + +## duplicate_attribute + +Attributes need to be unique + +## invalid_event_attribute_value + +Event attribute must be a JavaScript expression, not a string + +## invalid_attribute_name + +'%name%' is not a valid attribute name + +## animation_invalid_placement + +An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block + +## animation_missing_key + +An element that uses the `animate:` directive must be the only child of a keyed `{#each ...}` block. Did you forget to add a key to your each block? + +## animation_duplicate + +An element can only have one 'animate' directive + +## invalid_event_modifier + +Valid event modifiers are %list% + +## invalid_component_event_modifier + +Event modifiers other than 'once' can only be used on DOM elements + +## invalid_event_modifier_combination + +The '%modifier1%' and '%modifier2%' modifiers cannot be used together + +## transition_duplicate + +Cannot use multiple `%type%:` directives on a single element + +## transition_conflict + +Cannot use `%type%:` alongside existing `%existing%:` directive + +## invalid_let_directive_placement + +`let:` directive at invalid position + +## invalid_style_directive_modifier + +Invalid 'style:' modifier. Valid modifiers are: 'important' + +## invalid_sequence_expression + +Sequence expressions are not allowed as attribute/directive values in runes mode, unless wrapped in parentheses diff --git a/packages/svelte/messages/compile-errors/bindings.md b/packages/svelte/messages/compile-errors/bindings.md new file mode 100644 index 0000000000..5e88c5890a --- /dev/null +++ b/packages/svelte/messages/compile-errors/bindings.md @@ -0,0 +1,35 @@ +## invalid_binding_expression + +Can only bind to an Identifier or MemberExpression + +## invalid_binding_value + +Can only bind to state or props + +## bind_invalid_target + +`bind:%name%` can only be used with %elements% + +## bind_invalid + +`bind:%name%` is not a valid binding + +## bind_invalid_detailed + +`bind:%name%` is not a valid binding. %explanation% + +## invalid_type_attribute + +'type' attribute must be a static text value if input uses two-way binding + +## invalid_multiple_attribute + +'multiple' attribute must be static if select uses two-way binding + +## missing_contenteditable_attribute + +'contenteditable' attribute is required for textContent, innerHTML and innerText two-way bindings + +## dynamic_contenteditable_attribute + +'contenteditable' attribute cannot be dynamic if element uses two-way binding diff --git a/packages/svelte/messages/compile-errors/compiler_options.md b/packages/svelte/messages/compile-errors/compiler_options.md new file mode 100644 index 0000000000..761d74c72a --- /dev/null +++ b/packages/svelte/messages/compile-errors/compiler_options.md @@ -0,0 +1,7 @@ +## invalid_compiler_option + +Invalid compiler option: %msg% + +## removed_compiler_option + +Invalid compiler option: %msg% \ No newline at end of file diff --git a/packages/svelte/messages/compile-errors/components.md b/packages/svelte/messages/compile-errors/components.md new file mode 100644 index 0000000000..88a31a81c6 --- /dev/null +++ b/packages/svelte/messages/compile-errors/components.md @@ -0,0 +1,3 @@ +## invalid_component_directive + +This type of directive is not valid on components \ No newline at end of file diff --git a/packages/svelte/messages/compile-errors/const_tag.md b/packages/svelte/messages/compile-errors/const_tag.md new file mode 100644 index 0000000000..de8a8ca909 --- /dev/null +++ b/packages/svelte/messages/compile-errors/const_tag.md @@ -0,0 +1,3 @@ +## invalid_const_placement + +{@const} must be the immediate child of {#snippet}, {#if}, {:else if}, {:else}, {#each}, {:then}, {:catch}, or \ No newline at end of file diff --git a/packages/svelte/messages/compile-errors/css.md b/packages/svelte/messages/compile-errors/css.md new file mode 100644 index 0000000000..33331cfac6 --- /dev/null +++ b/packages/svelte/messages/compile-errors/css.md @@ -0,0 +1,51 @@ +## invalid_css_empty_declaration + +Declaration cannot be empty + +## invalid_css_global_block_list + +A :global {...} block cannot be part of a selector list with more than one item + +## invalid_css_global_block_modifier + +A :global {...} block cannot modify an existing selector + +## invalid_css_global_block_combinator + +A :global {...} block cannot follow a %name% combinator + +## invalid_css_global_block_declaration + +A :global {...} block can only contain rules, not declarations + +## invalid_css_global_placement + +:global(...) can be at the start or end of a selector sequence, but not in the middle + +## invalid_css_global_selector + +:global(...) must contain exactly one selector + +## invalid_css_global_selector_list + +:global(...) must not contain type or universal selectors when used in a compound selector + +## invalid_css_type_selector_placement + +:global(...) must not be followed with a type selector + +## invalid_css_selector + +Invalid selector + +## invalid_css_identifier + +Expected a valid CSS identifier + +## invalid_nesting_selector + +Nesting selectors can only be used inside a rule + +## invalid_css_declaration + +Declaration cannot be empty diff --git a/packages/svelte/messages/compile-errors/elements.md b/packages/svelte/messages/compile-errors/elements.md new file mode 100644 index 0000000000..466a26a7ac --- /dev/null +++ b/packages/svelte/messages/compile-errors/elements.md @@ -0,0 +1,27 @@ +## invalid_textarea_content + +A `