Skip to content
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

Change exceptions to extend Error. #184

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

markdoliner-doma
Copy link

@markdoliner-doma markdoliner-doma commented Jun 1, 2020

This changes exception classes generated for --target thrift-server so that they extend ErrorThriftLike instead of ThriftLike. There's a corresponding thrift-server change to add the ErrorThriftLike class.

As mentioned in the GitHub issue, this is useful because it causes Thrift exceptions to have stack traces and because some frameworks expect exceptions to derive from Error. The GitHub issue mentions graphql-js. Jest's toThrow() function would also benefit from this. Here's an example:

await expect(thriftClient.someFunction()).rejects.toThrow()

toThrow doesn't identify Thrift exceptions as exceptions because they don't derive from Error and so it will return false in such cases. Part of the blame could fall on Jest, because perhaps toThrow should return true for any rejected promise regardless of the type of object being throw, but I think some of the blame still falls on Thrift.

A downside of extending Error is that there's a naming collision when developers define fields named name, message, stack, etc in their Thrift exceptions (because these are defined by the super class). I think this is an acceptable tradeoff. FYI tsc complains if someone defines a field that differs from the super class. For example, if someone has a Thrift exception with 1: required i32 message (because message must be a string) or 1: optional string message (because message is required).

I tried to avoid the naming collisions by manually adding Error to the exception class's prototype chain. It might avoid the tsc compile errors when there's a naming collision but it doesn't really eliminate the problem of same-named properties being used for two different things. And so I think manually changing the prototype chain is a bad solution.

The code generator could possibly try to detect naming collisions between fields in user-defined exceptions and Error, but it doesn't seem super important to me. One difficulty is that different JavaScript implementations set different properties on Error. It would be hard for the code generator to warn about all of them. But message and name are obvious things to warn about.

I didn't change the code generated for --target apache. Those classes also don't derive from Error. As mentioned in #178 the Apache thrift generator has exception types inheriting from thrift.TException. I think it would be great for our code generator to do the same when using --target apache, but it seemed like a different enough change that it didn't make sense to do it as part of this commit.

Remaining work:

  • Update README.md to mention that end-users need to require the new version of thrift-server which includes ErrorThriftLike.

This changes exception classes generated for `--target thrift-server` so that they extend `ErrorThriftLike` instead of `ThriftLike`. There's a corresponding `thrift-server` change to add the `ErrorThriftLike` class.

As mentioned in [the GitHub issue](creditkarma#178), this is useful because it causes Thrift exceptions to have stack traces and because some frameworks expect exceptions to derive from Error. The GitHub issue mentions graphql-js. Jest's `toThrow()` function would also benefit from this. Here's an example:

```
await expect(thriftClient.someFunction()).rejects.toThrow()
```

`toThrow` doesn't identify Thrift exceptions as exceptions because they don't derive from Error and so it will return false in such cases. Part of the blame could fall on Jest, because perhaps `toThrow` should return true for any rejected promise regardless of the type of object being throw, but I think some of the blame still falls on Thrift.

A downside of extending Error is that there's a naming collision when developers define fields named `name`, `message`, `stack`, etc in their Thrift exceptions (because these are defined by the super class). I think this is an acceptable tradeoff. FYI `tsc` complains if someone defines a field that differs from the super class. For example, if someone has a Thrift exception with `1: required i32 message` (because message must be a string) or `1: optional string message` (because message is required).

I tried to avoid the naming collisions by manually adding Error to the exception class's prototype chain. It might avoid the tsc compile errors when there's a naming collision but it doesn't really eliminate the problem of same-named fields being used for two different things. And so I think manually changing the prototype chain is a bad solution.

Remaining work:
- Fix tests.
- Update README.md to mention that end-users need to require the new version of thrift-server which includes `ErrorThriftLike`.
- Update README.me to mention the naming collision limitation.
- `tsc` complains for naming collisions, and that's fine. Maybe the Thrift compiler should check for and report on collisions? Would probably be a friendly user experience. One challenge is [different JS implementations define different properties on their Error class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Instance_properties).
- I didn't change the code generated for `--target apache`. It looks like those classes also don't derive from Error. They probably should.
@markdoliner-doma
Copy link
Author

I can clean this up a little (fix tests, update documentation as needed, etc), but wanted to get feedback from Credit Karma folks to make sure I'm heading in the right direction before spending more time on it.

markdoliner-doma added a commit to StatesTitle/thrift-typescript that referenced this pull request Sep 1, 2020
…to_extend_Error

I'm merging this change into the all_states_title_changes branch. For the full PR description see [the PR for merging this change into Credit Karma's master branch](creditkarma#184).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant