Repository: sveltejs/svelte (JavaScript)
Date: 2019-08-04 01:20:13+00:00
Task type: Bug Fix

Issue:
Variable called `$` allowed by compiler and produces invalid output
```svelte
<script>
	$;
</script>
```

Variables called simply `$` are currently allowed and are assumed to be subscriptions to a variable with the empty string as the name, which results in syntactically incorrect output. The simplest solution would probably be to disallow this at parse time.


Issue discussion:

Solution patch:
diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts
--- a/src/compiler/compile/Component.ts
+++ b/src/compiler/compile/Component.ts
@@ -662,7 +662,7 @@ export default class Component {
 			this.node_for_declaration.set(name, node);
 		});
 
-		globals.forEach((_node, name) => {
+		globals.forEach((node, name) => {
 			if (this.var_lookup.has(name)) return;
 
 			if (this.injected_reactive_declaration_vars.has(name)) {
@@ -679,6 +679,13 @@ export default class Component {
 					injected: true
 				});
 			} else if (name[0] === '$') {
+				if (name === '$' || name[1] === '$') {
+					this.error(node, {
+						code: 'illegal-global',
+						message: `${name} is an illegal variable name`
+					});
+				}
+
 				this.add_var({
 					name,
 					injected: true,
@@ -1235,10 +1242,18 @@ export default class Component {
 
 	warn_if_undefined(name: string, node, template_scope: TemplateScope) {
 		if (name[0] === '$') {
-			name = name.slice(1);
+			if (name === '$' || name[1] === '$' && name !== '$$props') {
+				this.error(node, {
+					code: 'illegal-global',
+					message: `${name} is an illegal variable name`
+				});
+			}
+
 			this.has_reactive_assignments = true; // TODO does this belong here?
 
-			if (name[0] === '$') return; // $$props
+			if (name === '$$props') return;
+
+			name = name.slice(1);
 		}
 
 		if (this.var_lookup.has(name) && !this.var_lookup.get(name).global) return;


Test patch:
diff --git a/test/validator/samples/dollar-dollar-global-in-markup/errors.json b/test/validator/samples/dollar-dollar-global-in-markup/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-dollar-global-in-markup/errors.json
@@ -0,0 +1,15 @@
+[{
+	"code": "illegal-global",
+	"message": "$$billsyall is an illegal variable name",
+	"pos": 1,
+	"start": {
+		"line": 1,
+		"column": 1,
+		"character": 1
+	},
+	"end": {
+		"line": 1,
+		"column": 12,
+		"character": 12
+	}
+}]
\ No newline at end of file
diff --git a/test/validator/samples/dollar-dollar-global-in-markup/input.svelte b/test/validator/samples/dollar-dollar-global-in-markup/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-dollar-global-in-markup/input.svelte
@@ -0,0 +1 @@
+{$$billsyall}
\ No newline at end of file
diff --git a/test/validator/samples/dollar-dollar-global-in-script/errors.json b/test/validator/samples/dollar-dollar-global-in-script/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-dollar-global-in-script/errors.json
@@ -0,0 +1,15 @@
+[{
+	"code": "illegal-global",
+	"message": "$$billsyall is an illegal variable name",
+	"pos": 10,
+	"start": {
+		"line": 2,
+		"column": 1,
+		"character": 10
+	},
+	"end": {
+		"line": 2,
+		"column": 12,
+		"character": 21
+	}
+}]
\ No newline at end of file
diff --git a/test/validator/samples/dollar-dollar-global-in-script/input.svelte b/test/validator/samples/dollar-dollar-global-in-script/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-dollar-global-in-script/input.svelte
@@ -0,0 +1,3 @@
+<script>
+	$$billsyall;
+</script>
\ No newline at end of file
diff --git a/test/validator/samples/dollar-global-in-markup/errors.json b/test/validator/samples/dollar-global-in-markup/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-global-in-markup/errors.json
@@ -0,0 +1,15 @@
+[{
+	"code": "illegal-global",
+	"message": "$ is an illegal variable name",
+	"pos": 1,
+	"start": {
+		"line": 1,
+		"column": 1,
+		"character": 1
+	},
+	"end": {
+		"line": 1,
+		"column": 2,
+		"character": 2
+	}
+}]
\ No newline at end of file
diff --git a/test/validator/samples/dollar-global-in-markup/input.svelte b/test/validator/samples/dollar-global-in-markup/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-global-in-markup/input.svelte
@@ -0,0 +1 @@
+{$}
\ No newline at end of file
diff --git a/test/validator/samples/dollar-global-in-script/errors.json b/test/validator/samples/dollar-global-in-script/errors.json
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-global-in-script/errors.json
@@ -0,0 +1,15 @@
+[{
+	"code": "illegal-global",
+	"message": "$ is an illegal variable name",
+	"pos": 10,
+	"start": {
+		"line": 2,
+		"column": 1,
+		"character": 10
+	},
+	"end": {
+		"line": 2,
+		"column": 2,
+		"character": 11
+	}
+}]
\ No newline at end of file
diff --git a/test/validator/samples/dollar-global-in-script/input.svelte b/test/validator/samples/dollar-global-in-script/input.svelte
new file mode 100644
--- /dev/null
+++ b/test/validator/samples/dollar-global-in-script/input.svelte
@@ -0,0 +1,3 @@
+<script>
+	$;
+</script>
\ No newline at end of file