Skip to content

Use toString check rather than instanceof check.#3

Merged
paf31 merged 1 commit into
purescript:masterfrom
joneshf:master
Sep 4, 2014
Merged

Use toString check rather than instanceof check.#3
paf31 merged 1 commit into
purescript:masterfrom
joneshf:master

Conversation

@joneshf

@joneshf joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member

Re: discussion in #1 Should fix wonky js context things.

This seems to provide the semantics of what the type specifies, since throwing if we didn't immediately get an Error actually introduces back an Exception effect. which catchException is supposed to remove.

@paf31

paf31 commented Sep 2, 2014

Copy link
Copy Markdown
Contributor

Seems like the issue with this is that I can define my own Error type and throw it, and it could be just as type-unsafe. My vote would be to do what you suggested and wrap everything that isn't instanceof Error in a constructor and pass it to the continuation.

@joneshf

joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member Author

Well, if it's a user defined type, the toString call will give back '[object Object]' so it would fail the first check and be wrapped into a Error and handled.

That sort of raises the question, what do you do for user defined Error. Maybe we should have more than one check in here:

  1. instanceof - to handle built-in Error hierarchy and user defined in the same context
  2. toString - to handle built-in Error hierarchy in a different context (iframe, NodeWebKit, etc)
  3. check for the only standardized properties name and message - to handle user defined in different context

In any other case, just wrap in an Error and handle it.

@joneshf

joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member Author

Also, since I'm not fully confident in js's prototypal semantics, It'd be great to hear some feedback from others like @michaelficarra

@paf31

paf31 commented Sep 2, 2014

Copy link
Copy Markdown
Contributor

I'd like to keep this as simple as possible. Why not just if something is an instanceof Error, we pass it to the continuation unchanged, and if not, we wrap its .toString() in an Error and pass that?

Comment thread src/Control/Monad/Eff/Exception.purs Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

{}.toString.call(e) === '[object Error]'

is more idiomatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess that wouldn't match TypeError and the like though?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, nevermind, nor would the slice.

@joneshf

joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member Author

I agree, the simpler the better. Unfortunately, I think that the ugliness of js will either show up in this library or with users of the library.

If we stringify and wrap things that fail the instanceof check in an Error and you're handling an exception from a different context (iframe or something like node's vm), you end up with a few issues: the name of the error is lost, you have to parse the string to get the actual message, and, as you mentioned, the stack is not correct (even if it's non-standard). There might be more here, but those are the ones that come to mind.

The name bit might be less important if we provide finer control over Error subtypes
The message part means you have to parse out the Error: in order to get to it, not that big a deal, but something to be awareof.
The stack part is non-standard so it really shouldn't be a concern, but I think most common engines implement it anyway.

I think we actually lose a bit of expressivity by just wrapping anything that doesn't pass the instanceof check, since we wouldn't be able to properly handle an exception from a different context as we would lose some information in the toString call.

I might be overthinking it. Or, more likely, underthinking it. Or, maybe it's more unsafe to have these separate checks. But it feels like someone is going to get the ugliness of this, and mitigating it to the library sounds like the better way.

@joneshf

joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member Author

Actually, I guess since the toString would prefix the name of the Error to the message the first two points don't really matter much.

Hmm, I think I'm actually okay with this.

@joneshf

joneshf commented Sep 2, 2014

Copy link
Copy Markdown
Member Author

Alright, let me know of any other changes.

Comment thread src/Control/Monad/Eff/Exception.purs Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why did you remove the cross-realm support? I think that is useful for people working in a browser environment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I agree entirely that this is very useful for these different scenarios. I think to be robust, we should handle more cases (at least the three mentioned here). But, it also seems like you're not losing much information if you parse the message returned. You lose the stack, but that's non-standard anyway. Maybe it's more important to support that as well?

My thoughts on this whole situation is that I'd rather not have to deal with js semantics at all and especially not exceptions. At this point, if something is thrown somewhere, it's more than likely something that could have been caught on the ps side if it were implemented there. So, until more things are implemented there, I'm fine with dealing with partially implemented solutions. I don't actually care enough what catchException does so long as I can handle it. It might not be pretty or robust, but so long as it's not a runtime error I can deal with it. And, if partially solving this at the moment is what it takes to get this merged, I'd rather that. I'm surely not the only one who has (or will) run into this issue, and I'd rather there be some fix than none at all.

Not mad, not angry, not trying to be condescending or snarky or anything like that, just wanting to explain my thoughts over the internet :).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Oh, and if you have a different or better way to do this, please, relay the info or submit a pr or whatever.

As I said, I don't really care what happens here, so long as it's not a runtime error I can't do anything about.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think it's worth the slightly less clear (but common and idiomatic) {}.toString call. If there was a downside to doing it the right way, I'd be 100% on your side, but it doesn't hurt anything in this case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

But then, don't we miss out on a user/library defined Error type? Since {}.toString.call(myError) === '[object Object]'. Or is there a way to make this work as well?

Again, I'm indifferent either way, because at least we've not got a runtime error now. But, I don't think this can be a simple one case check. There's multiple ways to construct an error that should be caught here, and we should have cases for each if we're going to do it right.

@paf31 thoughts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I really only care to handle the Error type, and to wrap other things. If we can handle Errors from other domains, that's a plus in my book.

I'll let you both decide :)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alright, so @michaelficarra what say you?

Just the one {}.toString.call(e).slice(8, -1) === 'Error' check, or also an instance check so we catch user/lib defined Error's as well?

@joneshf

joneshf commented Sep 3, 2014

Copy link
Copy Markdown
Member Author

Alright, can we call this good? or more changes?

@paf31

paf31 commented Sep 3, 2014

Copy link
Copy Markdown
Contributor

Yeah, looks good to me. :shipit:

@michaelficarra

Copy link
Copy Markdown

Just the one {}.toString.call(e) ... check, or also an instance check so we catch user/lib defined Error's as well?

👍, do both. That should achieve cross-realm support as well as Error subclass support.

Use `toString` check AND `instanceof` check.
@joneshf

joneshf commented Sep 4, 2014

Copy link
Copy Markdown
Member Author

Okay. Good all around? @paf31 @michaelficarra ?

@paf31

paf31 commented Sep 4, 2014

Copy link
Copy Markdown
Contributor

🏁

@michaelficarra

Copy link
Copy Markdown

💝 Perfect.

@joneshf

joneshf commented Sep 4, 2014

Copy link
Copy Markdown
Member Author

How about over here 😉

paf31 added a commit that referenced this pull request Sep 4, 2014
Use `toString` check rather than `instanceof` check.
@paf31 paf31 merged commit 4db7688 into purescript:master Sep 4, 2014
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.

4 participants