[Bug] For a query param initialized as an array, visiting a URL with an unexpected value results in a crash
- Dominant language
- TypeScript
- Stars
- 22.6k
- Forks
- 4.2k
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 15
Description
# 🐞 Describe the Bug
When a property configured to back a query param is initialized as an array, Ember crashes when the query param exists and is not a JSON representation of an array.
This should not be the case. As the URL field is accessible for the user to type anything into it, no input should cause the app to crash gracelessly.
To make it worse, it seems to be impossible to work around it with public API. I had to resort to private API like this:
```js
// This method is private API
deserializeQueryParam(value, urlKey, defaultValueType) {
try {
return super.deserializeQueryParam(value, urlKey, defaultValueType);
} catch (error) {
if (error instanceof SyntaxError && urlKey === 'items' && value.slice(0, 2) !== '["') {
// Silence cases where `items` are:
// * an empty string
// * a single quoteless id
let newValue = value === '' ? '[]' : `["${value}"]`;
return super.deserializeQueryParam(newValue, urlKey, defaultValueType);
} else {
throw error;
}
}
}
```
On top of that, I found it impossible to update the URL with the expected query param! This is due to a combination of reasons:
* The crash happens before the `beforeModel` hook, so I still need to override the private `deserializeQueryParam`.
* I cannot do a redirect in `deserializeQueryParam` because it does not have access to `transition.to.queryParams`.
* In `beforeModel`, I can do a `replaceWith()` and I do have access to `transition.to.queryParams`, but those are raw strings, whereas `replaceWith` expects them to be values of properties on controllers.
* I cannot convert string query params to controller values, because `deserializeQueryParam` expects a `defaultValueType` argument which can only be accessed through `_queryParamsFor` which is also private! 😡
# 🔬 Minimal Reproduction
1. Define a query param like this:
```js
export default class IndexController extends Controller {
queryParams = ['items'];
items = [];
}
```
2. Visit any of these URLs:
* http://localhost:4200/?items
* http://localhost:4200/?items=
* http://localhost:4200/?items=foo
* http://localhost:4200/?items=42
# 🚀 Demo
I have discovered that the exact error is different depending on the case and assembled a demo that covers all the differences:
Demo: https://main--splendid-twilight-1e584c.netlify.app/
Source : https://github.com/lolmaus/ember-app-query-param-array-error

# 🌍 Environment
- Ember: 4.11.0
Contributor guide
Assessment
This issue has not been assessed yet.