Repository: sveltejs/svelte (JavaScript)
Date: 2020-09-15 10:10:59+00:00
Task type: Bug Fix

Issue:
No "unused selector" warning when unused child combinator with universal selector is present
**Describe the bug**
Svelte does not warn when there is an unused selector of the form `element > *` inside `<style>` tags. E.g.:

```css
article > * {
    font-size: 36px;
}
```

**Logs**

No logs.

**To Reproduce**

REPL:
https://svelte.dev/repl/6480b8f41e784418bdae55a163257e21?version=3.24.1

* Confirm that `article > *` does not raise warnings.
* Uncomment the `article *` selector to see the correctly raised warning.

**Expected behavior**
A warning should be raised.

**Stacktraces**
If you have a stack trace to include, we recommend putting inside a `<details>` block for the sake of the thread's readability:

<details>
  <summary>Stack trace</summary>

  Stack trace goes here...
</details>

**Information about your Svelte project:**
- All browsers

- Latest macOS

- 3.24.1

- Rollup

**Severity**
It took some time to realize this when trying to target elements that are inside the `@html` string. I then noticed that it is impossible in the first place without using `:global` but having a warning would be much much better.

**Additional context**
I can try fixing it myself.



Issue discussion:

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Svelte changelog
 
+## Unreleased
+
+* Fix scoping of styles involving child selector and `*` ([#5370](https://github.com/sveltejs/svelte/issues/5370))
+
 ## 3.25.0
 
 * Use `null` rather than `undefined` for coerced bound value of `<input type="number">` ([#1701](https://github.com/sveltejs/svelte/issues/1701))
diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts
--- a/src/compiler/compile/css/Selector.ts
+++ b/src/compiler/compile/css/Selector.ts
@@ -152,7 +152,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
 	if (!block) return false;
 
 	if (!node) {
-		return blocks.every(block => block.global);
+		return block.global && blocks.every(block => block.global);
 	}
 
 	switch (block_might_apply_to_node(block, node)) {
@@ -208,7 +208,7 @@ function apply_selector(blocks: Block[], node: Element, stack: Element[], to_enc
 	return true;
 }
 
-function block_might_apply_to_node(block, node): BlockAppliesToNode {
+function block_might_apply_to_node(block: Block, node: Element): BlockAppliesToNode {
 	let i = block.selectors.length;
 
 	while (i--) {


Test patch:
diff --git a/test/css/samples/unused-selector-child-combinator/_config.js b/test/css/samples/unused-selector-child-combinator/_config.js
new file mode 100644
--- /dev/null
+++ b/test/css/samples/unused-selector-child-combinator/_config.js
@@ -0,0 +1,45 @@
+export default {
+	warnings: [
+		{
+			code: "css-unused-selector",
+			message: 'Unused CSS selector "article > *"',
+			frame: `
+			1: <style>
+			2:   article > * {
+			     ^
+			3:     font-size: 36px;
+			4:   }`,
+			pos: 10,
+			start: { character: 10, column: 1, line: 2 },
+			end: { character: 21, column: 12, line: 2 }
+		},
+		{
+			code: "css-unused-selector",
+			message: 'Unused CSS selector "article *"',
+			frame: `
+			4:   }
+			5:
+			6:   article * {
+			     ^
+			7:     font-size: 36px;
+			8:   }`,
+			pos: 49,
+			start: { character: 49, column: 1, line: 6 },
+			end: { character: 58, column: 10, line: 6 }
+		},
+		{
+			code: "css-unused-selector",
+			message: 'Unused CSS selector ".article > *"',
+			frame: `
+			 8:   }
+			 9:
+			10:   .article > * {
+			      ^
+			11:     font-size: 48px;
+			12:   }`,
+			pos: 86,
+			start: { character: 86, column: 1, line: 10 },
+			end: { character: 98, column: 13, line: 10 }
+		}
+	]
+};
diff --git a/test/css/samples/unused-selector-child-combinator/expected.css b/test/css/samples/unused-selector-child-combinator/expected.css
new file mode 100644
--- /dev/null
+++ b/test/css/samples/unused-selector-child-combinator/expected.css
@@ -0,0 +1 @@
+div.svelte-xyz>.svelte-xyz{color:orange}
\ No newline at end of file
diff --git a/test/css/samples/unused-selector-child-combinator/input.svelte b/test/css/samples/unused-selector-child-combinator/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/css/samples/unused-selector-child-combinator/input.svelte
@@ -0,0 +1,23 @@
+<style>	
+	article > * {
+		font-size: 36px;
+  }
+
+	article * {
+		font-size: 36px;
+	}
+	
+	.article > * {
+		font-size: 48px;
+	}
+	
+	div > * {
+		color: orange;
+	}
+</style>
+
+<div>
+	<p>
+		Svelte REPLs are svelte.
+	</p>
+</div>
\ No newline at end of file