diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1481dd850..2c9922a086 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,10 @@
## Unreleased
+* Fix specificity of certain styles involving a child selector ([#4795](https://github.com/sveltejs/svelte/issues/4795))
+* Fix transitions that are parameterised with stores ([#5244](https://github.com/sveltejs/svelte/issues/5244))
* Fix scoping of styles involving child selector and `*` ([#5370](https://github.com/sveltejs/svelte/issues/5370))
+* Fix destructuring which reassigns stores ([#5388](https://github.com/sveltejs/svelte/issues/5388))
## 3.25.0
diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts
index ed2b10e404..078ecb8869 100644
--- a/src/compiler/compile/Component.ts
+++ b/src/compiler/compile/Component.ts
@@ -947,12 +947,6 @@ export default class Component {
const variable = component.var_lookup.get(name);
if (variable.export_name && variable.writable) {
- const insert = variable.subscribable
- ? get_insert(variable)
- : null;
-
- parent[key].splice(index + 1, 0, insert);
-
declarator.id = {
type: 'ObjectPattern',
properties: [{
@@ -973,7 +967,9 @@ export default class Component {
};
declarator.init = x`$$props`;
- } else if (variable.subscribable) {
+ }
+
+ if (variable.subscribable && declarator.init) {
const insert = get_insert(variable);
parent[key].splice(index + 1, 0, ...insert);
}
diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts
index e3e1fa96bb..d18a7e7ba6 100644
--- a/src/compiler/compile/css/Selector.ts
+++ b/src/compiler/compile/css/Selector.ts
@@ -65,9 +65,8 @@ export default class Selector {
transform(code: MagicString, attr: string, max_amount_class_specificity_increased: number) {
const amount_class_specificity_to_increase = max_amount_class_specificity_increased - this.blocks.filter(block => block.should_encapsulate).length;
- attr = attr.repeat(amount_class_specificity_to_increase + 1);
- function encapsulate_block(block: Block) {
+ function encapsulate_block(block: Block, attr: string) {
let i = block.selectors.length;
while (i--) {
@@ -89,15 +88,14 @@ export default class Selector {
}
}
- this.blocks.forEach((block) => {
+ this.blocks.forEach((block, index) => {
if (block.global) {
const selector = block.selectors[0];
const first = selector.children[0];
const last = selector.children[selector.children.length - 1];
code.remove(selector.start, first.start).remove(last.end, selector.end);
}
-
- if (block.should_encapsulate) encapsulate_block(block);
+ if (block.should_encapsulate) encapsulate_block(block, index === this.blocks.length - 1 ? attr.repeat(amount_class_specificity_to_increase + 1) : attr);
});
}
diff --git a/src/compiler/compile/nodes/Transition.ts b/src/compiler/compile/nodes/Transition.ts
index a680fde46e..983a6ee6c7 100644
--- a/src/compiler/compile/nodes/Transition.ts
+++ b/src/compiler/compile/nodes/Transition.ts
@@ -34,7 +34,7 @@ export default class Transition extends Node {
}
this.expression = info.expression
- ? new Expression(component, this, scope, info.expression, true)
+ ? new Expression(component, this, scope, info.expression)
: null;
}
}
diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts
index 6fc026de23..0990281d91 100644
--- a/src/compiler/compile/render_dom/Renderer.ts
+++ b/src/compiler/compile/render_dom/Renderer.ts
@@ -166,12 +166,14 @@ export default class Renderer {
return member;
}
- invalidate(name: string, value?) {
+ invalidate(name: string, value?, main_execution_context: boolean = false) {
const variable = this.component.var_lookup.get(name);
const member = this.context_lookup.get(name);
if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) {
- return x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
+ return main_execution_context
+ ? x`${`$$subscribe_${name}`}(${value || name})`
+ : x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`;
}
if (name[0] === '$' && name[1] !== '$') {
diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts
index 28e4f37e3f..c7d9759ccd 100644
--- a/src/compiler/compile/render_dom/invalidate.ts
+++ b/src/compiler/compile/render_dom/invalidate.ts
@@ -31,10 +31,9 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
function get_invalidated(variable: Var, node?: Expression) {
if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') {
- return node || x`${variable.name}`;
+ return node;
}
-
- return renderer.invalidate(variable.name);
+ return renderer.invalidate(variable.name, undefined, main_execution_context);
}
if (head) {
@@ -44,12 +43,15 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
return get_invalidated(head, node);
} else {
const is_store_value = head.name[0] === '$' && head.name[1] !== '$';
- const extra_args = tail.map(variable => get_invalidated(variable));
+ const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean);
const pass_value = (
- extra_args.length > 0 ||
- (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
- (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
+ !main_execution_context &&
+ (
+ extra_args.length > 0 ||
+ (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
+ (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
+ )
);
if (pass_value) {
@@ -63,7 +65,9 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
? x`@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})`
: !main_execution_context
? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`
- : node;
+ : extra_args.length
+ ? [node, ...extra_args]
+ : node;
if (head.subscribable && head.reassigned) {
const subscribe = `$$subscribe_${head.name}`;
diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts
index 2e35f0271f..f740560bcd 100644
--- a/src/compiler/compile/render_dom/wrappers/Element/index.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts
@@ -868,6 +868,10 @@ export default class ElementWrapper extends Wrapper {
block.chunks.destroy.push(b`if (detaching && ${outro_name}) ${outro_name}.end();`);
}
}
+
+ if ((intro && intro.expression && intro.expression.dependencies.size) || (outro && outro.expression && outro.expression.dependencies.size)) {
+ block.maintain_context = true;
+ }
}
add_animation(block: Block) {
diff --git a/test/css/samples/child-combinator/expected.css b/test/css/samples/child-combinator/expected.css
new file mode 100644
index 0000000000..5d50ae16d7
--- /dev/null
+++ b/test/css/samples/child-combinator/expected.css
@@ -0,0 +1 @@
+main.svelte-xyz button.svelte-xyz.svelte-xyz{background-color:red}main.svelte-xyz div.svelte-xyz>button.svelte-xyz{background-color:blue}
\ No newline at end of file
diff --git a/test/css/samples/child-combinator/input.svelte b/test/css/samples/child-combinator/input.svelte
new file mode 100644
index 0000000000..9d5d8d27e0
--- /dev/null
+++ b/test/css/samples/child-combinator/input.svelte
@@ -0,0 +1,14 @@
+
+