Repository: sveltejs/svelte (JavaScript)
Date: 2020-02-26 16:58:53+00:00
Task type: Bug Fix

Issue:
SyntaxError: missing formal parameter (Firefox)
**Describe the bug**

The svelte title is replaced by `500` and I have this error on the console:

```
SyntaxError: missing formal parameter
```

**Logs**
Please include browser console and server logs around the time this bug occurred.

**To Reproduce**
To help us help you, if you've found a bug please consider the following:

* Create a svelte template
* Require the tailwind default config (this produce the bug):
```javascript
const {
  colors, boxShadow, fontFamily, fontSize, opacity,
} = require('tailwindcss/defaultTheme');
```

You can also checkout this public MR: https://gitlab.com/nexylan/design/-/merge_requests/42

**Expected behavior**
Working without any error.

**Severity**
Happen on dev env only for a demo project, so not a big deal to me.

Could be problematic for other, especially with the `500` title issue.

**Additional context**

This happens only on v3.19.0 and v3.19.1, maybe a BC break?

I also tried a Tailwind downgrade to the old version I used before, the error still happen with Svelte 3.19.
SyntaxError: missing formal parameter (Firefox)
**Describe the bug**

The svelte title is replaced by `500` and I have this error on the console:

```
SyntaxError: missing formal parameter
```

**Logs**
Please include browser console and server logs around the time this bug occurred.

**To Reproduce**
To help us help you, if you've found a bug please consider the following:

* Create a svelte template
* Require the tailwind default config (this produce the bug):
```javascript
const {
  colors, boxShadow, fontFamily, fontSize, opacity,
} = require('tailwindcss/defaultTheme');
```

You can also checkout this public MR: https://gitlab.com/nexylan/design/-/merge_requests/42

**Expected behavior**
Working without any error.

**Severity**
Happen on dev env only for a demo project, so not a big deal to me.

Could be problematic for other, especially with the `500` title issue.

**Additional context**

This happens only on v3.19.0 and v3.19.1, maybe a BC break?

I also tried a Tailwind downgrade to the old version I used before, the error still happen with Svelte 3.19.


Issue discussion:
Part of this is definitely webpack doing something peculiar, but I think what Svelte's doing that might be wrong is including the unknown global `require` in the object returned by `$capture_state`. Webpack is then apparently doing something weird with the bare `require` when it's not immediately called on anything.

@rixo Do you have thoughts about making `$capture_state` not include unknown globals? That would seem to make sense to me.
@Conduitry How do you qualify "unknown" globals? Anyway, I think we should exclude all of them from `$capture_state`.

For HMR it's irrelevant, but I guess that'd be weird to end up with things like `window`, or `requestAnimationFrame`, or `require` in the inspect view of dev tools. There might, in some cases, be a micro interest in viewing user's own globals, but even that could be weird too, depending on the variable. And that would need some kind of white list, which makes it prohibitively complicated to implement IMO, considering these variables are very easy to inspect in the console, since they're global.

So yeah, I think we should definitely remove globals from `$capture_state`. It would also protect people from this Webpack bug. I'll send a PR for this.

@RedHatter Can you confirm that globals are not needed for dev tools? Or did I miss something?

@soullivaneuh I think you shouldn't be using `require` anymore in frontend code nowadays (and especially in a Svelte component)... Replace it with the following, and your bug will be fixed with 3.19.1 right away:

```js
import config from "../../tailwind.config.js";
```

(And for what it's worth, the whole client side component is crashed... What you get is just the SSR'd page.)
Yeah, excluding globals from `$capture_state` is fine and probably preferable.
Sorry, yeah, 'unknown' was a bit of a loaded term. I was really just asking about all variables that aren't declared (possibly implicitly) or imported in the component - and it sounds like there's agreement that these should be excluded when capturing the state. I don't think there should be a whitelist of globals that should still be included anyway in the captured state.
Part of this is definitely webpack doing something peculiar, but I think what Svelte's doing that might be wrong is including the unknown global `require` in the object returned by `$capture_state`. Webpack is then apparently doing something weird with the bare `require` when it's not immediately called on anything.

@rixo Do you have thoughts about making `$capture_state` not include unknown globals? That would seem to make sense to me.
@Conduitry How do you qualify "unknown" globals? Anyway, I think we should exclude all of them from `$capture_state`.

For HMR it's irrelevant, but I guess that'd be weird to end up with things like `window`, or `requestAnimationFrame`, or `require` in the inspect view of dev tools. There might, in some cases, be a micro interest in viewing user's own globals, but even that could be weird too, depending on the variable. And that would need some kind of white list, which makes it prohibitively complicated to implement IMO, considering these variables are very easy to inspect in the console, since they're global.

So yeah, I think we should definitely remove globals from `$capture_state`. It would also protect people from this Webpack bug. I'll send a PR for this.

@RedHatter Can you confirm that globals are not needed for dev tools? Or did I miss something?

@soullivaneuh I think you shouldn't be using `require` anymore in frontend code nowadays (and especially in a Svelte component)... Replace it with the following, and your bug will be fixed with 3.19.1 right away:

```js
import config from "../../tailwind.config.js";
```

(And for what it's worth, the whole client side component is crashed... What you get is just the SSR'd page.)
Yeah, excluding globals from `$capture_state` is fine and probably preferable.
Sorry, yeah, 'unknown' was a bit of a loaded term. I was really just asking about all variables that aren't declared (possibly implicitly) or imported in the component - and it sounds like there's agreement that these should be excluded when capturing the state. I don't think there should be a whitelist of globals that should still be included anyway in the captured state.

Solution patch:
diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts
--- a/src/compiler/compile/render_dom/index.ts
+++ b/src/compiler/compile/render_dom/index.ts
@@ -167,7 +167,7 @@ export default function dom(
 			`;
 		}
 
-		const capturable_vars = component.vars.filter(v => !v.internal && !v.name.startsWith('$$'));
+		const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$'));
 
 		if (capturable_vars.length > 0) {
 			capture_state = x`() => ({ ${capturable_vars.map(prop => p`${prop.name}`)} })`;


Test patch:
diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js
--- a/test/js/samples/loop-protect/expected.js
+++ b/test/js/samples/loop-protect/expected.js
@@ -108,7 +108,7 @@ function instance($$self, $$props, $$invalidate) {
 		});
 	}
 
-	$$self.$capture_state = () => ({ node, foo, console });
+	$$self.$capture_state = () => ({ node, foo });
 
 	$$self.$inject_state = $$props => {
 		if ("node" in $$props) $$invalidate(0, node = $$props.node);
@@ -153,4 +153,4 @@ class Component extends SvelteComponentDev {
 	}
 }
 
-export default Component;
\ No newline at end of file
+export default Component;