From 434bdebe035c3045f955a3dd06af0d759e5b44d7 Mon Sep 17 00:00:00 2001 From: Kelvin Soh Date: Fri, 8 Sep 2023 00:05:29 +0800 Subject: [PATCH 1/3] fix: style directive not updating when style attribute is present and style directive is updated via an object prop --- .changeset/chilled-tigers-tie.md | 5 +++++ .../_config.js | 20 +++++++++++++++++++ .../main.svelte | 12 +++++++++++ 3 files changed, 37 insertions(+) create mode 100644 .changeset/chilled-tigers-tie.md create mode 100644 packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js create mode 100644 packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte diff --git a/.changeset/chilled-tigers-tie.md b/.changeset/chilled-tigers-tie.md new file mode 100644 index 000000000000..83e1f821e3b9 --- /dev/null +++ b/.changeset/chilled-tigers-tie.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: style directive not updating when style attribute is present and style is updated via an object prop diff --git a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js new file mode 100644 index 000000000000..b926ae6ad962 --- /dev/null +++ b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js @@ -0,0 +1,20 @@ +export default { + html: ` +

+ `, + + test({ assert, target, window, component }) { + const p = target.querySelector('p'); + const styles = window.getComputedStyle(p); + assert.equal(styles.backgroundColor, 'rgb(0, 128, 0)'); + assert.equal(styles.fontSize, '12px'); + + { + component.modify = true; + const p = target.querySelector('p'); + const styles = window.getComputedStyle(p); + assert.equal(styles.backgroundColor, 'rgb(0, 128, 0)'); + assert.equal(styles.fontSize, '50px'); + } + } +}; diff --git a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte new file mode 100644 index 000000000000..0a643bdf4832 --- /dev/null +++ b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte @@ -0,0 +1,12 @@ + + +

From 39015d447a59eca81e4255448ca9b18384f8e96d Mon Sep 17 00:00:00 2001 From: Kelvin Soh Date: Sun, 1 Oct 2023 22:56:31 +0800 Subject: [PATCH 2/3] fix: applying :global for +,~ combinator when slots are present --- .changeset/swift-falcons-fetch.md | 5 ++++ .../src/compiler/compile/css/Selector.js | 30 +++++++++++++------ .../_config.js | 25 ++++++++++++++++ .../expected.css | 1 + .../input.svelte | 12 ++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 .changeset/swift-falcons-fetch.md create mode 100644 packages/svelte/test/css/samples/siblings-combinator-global-slots/_config.js create mode 100644 packages/svelte/test/css/samples/siblings-combinator-global-slots/expected.css create mode 100644 packages/svelte/test/css/samples/siblings-combinator-global-slots/input.svelte diff --git a/.changeset/swift-falcons-fetch.md b/.changeset/swift-falcons-fetch.md new file mode 100644 index 000000000000..02ea10991959 --- /dev/null +++ b/.changeset/swift-falcons-fetch.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: applying :global for +,~ sibling combinator when slots are present diff --git a/packages/svelte/src/compiler/compile/css/Selector.js b/packages/svelte/src/compiler/compile/css/Selector.js index 7f26989bcb27..a1c58515d726 100644 --- a/packages/svelte/src/compiler/compile/css/Selector.js +++ b/packages/svelte/src/compiler/compile/css/Selector.js @@ -291,14 +291,17 @@ function apply_selector(blocks, node, to_encapsulate) { } return false; } else if (block.combinator.name === '+' || block.combinator.name === '~') { - const siblings = get_possible_element_siblings(node, block.combinator.name === '+'); + const [siblings, has_slot_sibling] = get_possible_element_siblings( + node, + block.combinator.name === '+' + ); let has_match = false; // NOTE: if we have :global(), we couldn't figure out what is selected within `:global` due to the // css-tree limitation that does not parse the inner selector of :global // so unless we are sure there will be no sibling to match, we will consider it as matched const has_global = blocks.some((block) => block.global); if (has_global) { - if (siblings.size === 0 && get_element_parent(node) !== null) { + if (siblings.size === 0 && get_element_parent(node) !== null && !has_slot_sibling) { return false; } to_encapsulate.push({ node, block }); @@ -542,13 +545,15 @@ function get_element_parent(node) { *

Heading 1

*

Heading 2

* @param {import('../nodes/interfaces.js').INode} node - * @returns {import('../nodes/interfaces.js').INode} + * @returns {[import('../nodes/interfaces.js').INode, boolean]} */ function find_previous_sibling(node) { /** @type {import('../nodes/interfaces.js').INode} */ let current_node = node; + let has_slot_sibling = false; do { if (current_node.type === 'Slot') { + has_slot_sibling = true; const slot_children = current_node.children; if (slot_children.length > 0) { current_node = slot_children.slice(-1)[0]; // go to its last child first @@ -560,13 +565,13 @@ function find_previous_sibling(node) { } current_node = current_node.prev; } while (current_node && current_node.type === 'Slot'); - return current_node; + return [current_node, has_slot_sibling]; } /** * @param {import('../nodes/interfaces.js').INode} node * @param {boolean} adjacent_only - * @returns {Map} + * @returns {[Map, boolean]} */ function get_possible_element_siblings(node, adjacent_only) { /** @type {Map} */ @@ -574,7 +579,10 @@ function get_possible_element_siblings(node, adjacent_only) { /** @type {import('../nodes/interfaces.js').INode} */ let prev = node; - while ((prev = find_previous_sibling(prev))) { + let has_slot_sibling = false; + let slot_sibling_found = false; + while (([prev, slot_sibling_found] = find_previous_sibling(prev)) && prev) { + has_slot_sibling = has_slot_sibling || slot_sibling_found; if (prev.type === 'Element') { if ( !prev.attributes.find( @@ -590,7 +598,7 @@ function get_possible_element_siblings(node, adjacent_only) { const possible_last_child = get_possible_last_child(prev, adjacent_only); add_to_map(possible_last_child, result); if (adjacent_only && has_definite_elements(possible_last_child)) { - return result; + return [result, has_slot_sibling]; } } } @@ -605,7 +613,11 @@ function get_possible_element_siblings(node, adjacent_only) { parent.type === 'ElseBlock' || parent.type === 'AwaitBlock') ) { - const possible_siblings = get_possible_element_siblings(parent, adjacent_only); + const [possible_siblings, slot_sibling_found] = get_possible_element_siblings( + parent, + adjacent_only + ); + has_slot_sibling = has_slot_sibling || slot_sibling_found; add_to_map(possible_siblings, result); if (parent.type === 'EachBlock') { // first child of each block can select the last child of each block as previous sibling @@ -623,7 +635,7 @@ function get_possible_element_siblings(node, adjacent_only) { } } } - return result; + return [result, has_slot_sibling]; } /** diff --git a/packages/svelte/test/css/samples/siblings-combinator-global-slots/_config.js b/packages/svelte/test/css/samples/siblings-combinator-global-slots/_config.js new file mode 100644 index 000000000000..6744b032874e --- /dev/null +++ b/packages/svelte/test/css/samples/siblings-combinator-global-slots/_config.js @@ -0,0 +1,25 @@ +export default { + warnings: [ + { + code: 'css-unused-selector', + message: 'Unused CSS selector ":global(input) ~ p"', + pos: 160, + start: { + character: 160, + column: 1, + line: 11 + }, + end: { + character: 178, + column: 19, + line: 11 + }, + frame: ` 9: :global(input) ~ span { color: red; } + 10: /* no match */ + 11: :global(input) ~ p { color: red; } + ^ + 12: + ` + } + ] +}; diff --git a/packages/svelte/test/css/samples/siblings-combinator-global-slots/expected.css b/packages/svelte/test/css/samples/siblings-combinator-global-slots/expected.css new file mode 100644 index 000000000000..9b583715eda1 --- /dev/null +++ b/packages/svelte/test/css/samples/siblings-combinator-global-slots/expected.css @@ -0,0 +1 @@ +input+span.svelte-xyz{color:red}input~span.svelte-xyz{color:red} \ No newline at end of file diff --git a/packages/svelte/test/css/samples/siblings-combinator-global-slots/input.svelte b/packages/svelte/test/css/samples/siblings-combinator-global-slots/input.svelte new file mode 100644 index 000000000000..35edb26e58d4 --- /dev/null +++ b/packages/svelte/test/css/samples/siblings-combinator-global-slots/input.svelte @@ -0,0 +1,12 @@ +
+ + Hello +
+ + From 067f18f17507778cf1945f9376fc569692f4f9c8 Mon Sep 17 00:00:00 2001 From: Kelvin Soh Date: Sun, 1 Oct 2023 23:14:26 +0800 Subject: [PATCH 3/3] Revert "fix: style directive not updating when style attribute is present and style directive is updated via an object prop" This reverts commit 434bdebe035c3045f955a3dd06af0d759e5b44d7. --- .changeset/chilled-tigers-tie.md | 5 ----- .../_config.js | 20 ------------------- .../main.svelte | 12 ----------- 3 files changed, 37 deletions(-) delete mode 100644 .changeset/chilled-tigers-tie.md delete mode 100644 packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js delete mode 100644 packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte diff --git a/.changeset/chilled-tigers-tie.md b/.changeset/chilled-tigers-tie.md deleted file mode 100644 index 83e1f821e3b9..000000000000 --- a/.changeset/chilled-tigers-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: style directive not updating when style attribute is present and style is updated via an object prop diff --git a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js deleted file mode 100644 index b926ae6ad962..000000000000 --- a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/_config.js +++ /dev/null @@ -1,20 +0,0 @@ -export default { - html: ` -

- `, - - test({ assert, target, window, component }) { - const p = target.querySelector('p'); - const styles = window.getComputedStyle(p); - assert.equal(styles.backgroundColor, 'rgb(0, 128, 0)'); - assert.equal(styles.fontSize, '12px'); - - { - component.modify = true; - const p = target.querySelector('p'); - const styles = window.getComputedStyle(p); - assert.equal(styles.backgroundColor, 'rgb(0, 128, 0)'); - assert.equal(styles.fontSize, '50px'); - } - } -}; diff --git a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte b/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte deleted file mode 100644 index 0a643bdf4832..000000000000 --- a/packages/svelte/test/runtime-browser/samples/inline-style-directive-update-object-property/main.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - -