Skip to content

fix InvalidStateError exception #251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 22, 2020
Merged

fix InvalidStateError exception #251

merged 1 commit into from
May 22, 2020

Conversation

brokenalarms
Copy link
Contributor

@brokenalarms brokenalarms commented May 21, 2020

fix InvalidStateError exception

This commit fixes #244.

The xhr.responseText property cannot be accessed unless xhr.responseType is either 'text' or '',
otherwise it throws an error:

Uncaught InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest':
The value is only accessible if the object's 'responseType' is '' or 'text' (was 'json')

This will therefore happen in handleCoverageResponse whenever
a request returns falsy. This should never happen, but is occasionally
flaking and producing the above error.

This commit fixes a few likely culprits:

  • responseType = json was being set after xhr.send, which may cause a race condition
    https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response
  • the middleware called res.send with a CoverageMap may receive a non-serializable
    object, since istanbul CoverageMap provides a toJSON method, implying that
    the default method may not be serializable
  • removing now-unused PhantomJS code.
  • finally, introduces a check to only read from the 'responseText'
    property in a valid circumstance, and gives a more meaningful error otherwise.

@rwjblue
Copy link
Collaborator

rwjblue commented May 21, 2020

I guess the thing I'm curious about is why is the response type text or empty?

@brokenalarms
Copy link
Contributor Author

brokenalarms commented May 21, 2020

It won't be. It's just to guard against the case where xhr rejects or returns falsy by expressing the only satisfactory conditions on which xhr.responseText property should ever be read.

When this happens, and the content type is json (as it always is in the async request done stage), this will cause the xhr.responseText to be incorrectly read rather than just return the original falsy value of xhr.response.

@brokenalarms
Copy link
Contributor Author

Satisfying constraints of https://xhr.spec.whatwg.org/#the-responsetext-attribute
1 - this PR
2 - state is always done in this function
3 - already exists by falling back to text in the remaining valid scenarios.

Copy link
Collaborator

@rwjblue rwjblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely agree that avoiding the (IMHO bizarre) error RE: touching responseText would be better, but can you update this to add an else that throws an error RE: not being able to properly report coverage?

AFAICT this is a failure scenario, and we should error.

@rwjblue
Copy link
Collaborator

rwjblue commented May 21, 2020

After poking at this a bit with @brokenalarms, I think we should do a few things:

  1. Ensure that our middleware responds with the expected content type

https://github.com/kategengler/ember-cli-code-coverage/blob/d6e2262923e7caeeb383fb6ccdf7b46e227f5715/lib/attach-middleware.js#L54-L58

  1. Remove phantomjs related codepaths and comments (💀)

https://github.com/kategengler/ember-cli-code-coverage/blob/81b57078d362b16dafa0197756e9ff8938151996/lib/templates/test-body-footer.html#L2-L3

https://github.com/kategengler/ember-cli-code-coverage/blob/81b57078d362b16dafa0197756e9ff8938151996/lib/templates/test-body-footer.html#L56-L59

  1. Use a guard (similar to the one in this PR) to ensure we have the expected response type, and if we don't error

@brokenalarms
Copy link
Contributor Author

brokenalarms commented May 21, 2020

Theory is there's been a non-serializable object provided sometimes in map.getCoverageSummary() since istanbul provides additional toJSON method this infers that the getCoverageSummaryMap() alone may not always be serializable.

This commit fixes #244.

The xhr.responseText property cannot be accessed unless xhr.responseType is either 'text' or '',
otherwise it throws an error:

Uncaught InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest':
The value is only accessible if the object's 'responseType' is '' or 'text' (was 'json')

This will therefore happen in handleCoverageResponse whenever
a request returns falsy. This should never happen, but is occasionally
flaking and producing the above error.

This commit fixes a few likely culprits:
- responseType = `json` was being set after `xhr.send`, which may cause a race condition
  https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response
- the middleware called res.send with a CoverageMap may receive a non-serializable
  object, since istanbul CoverageMap provides a toJSON method, implying that
  the default method may not be serializable
- removing now-unused PhantomJS code.
- finally, introduces a check to only read from the 'responseText'
property in a valid circumstance, and gives a more meaningful error otherwise.
@RobbieTheWagner
Copy link
Collaborator

I defer to the wisdom of @rwjblue. @brokenalarms if you haven't already, can you adjust based on his feedback?

@brokenalarms
Copy link
Contributor Author

Have done, thanks!

Copy link
Collaborator

@rwjblue rwjblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me, thanks for working through it @brokenalarms!

@RobbieTheWagner RobbieTheWagner merged commit 8803463 into ember-cli-code-coverage:master May 22, 2020
@RobbieTheWagner
Copy link
Collaborator

Thanks for the PR @brokenalarms!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The value is only accessible if the object's 'responseType' is '' or 'text' (was 'json')
3 participants