Bug 38180 - Remove unneeded custom code for WebSocket.send
Summary: Remove unneeded custom code for WebSocket.send
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore JavaScript (show other bugs)
Version: 528+ (Nightly build)
Hardware: Other OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-04-27 00:55 PDT by Adam Barth
Modified: 2010-06-18 02:31 PDT (History)
5 users (show)

See Also:


Attachments
Patch (3.21 KB, patch)
2010-04-27 00:56 PDT, Adam Barth
no flags Details | Formatted Diff | Diff
Patch (7.04 KB, patch)
2010-04-27 16:53 PDT, Adam Barth
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Adam Barth 2010-04-27 00:55:12 PDT
Remove unneeded custom code for WebSocket.send
Comment 1 Adam Barth 2010-04-27 00:56:00 PDT
Created attachment 54393 [details]
Patch
Comment 2 Eric Seidel (no email) 2010-04-27 00:57:37 PDT
Comment on attachment 54393 [details]
Patch

Seems like we should write a layout test to explain the badness?
Comment 3 Adam Barth 2010-04-27 01:01:55 PDT
It's not really part of our testing plan, but we could.
Comment 4 Alexey Proskuryakov 2010-04-27 10:13:42 PDT
-    if (exec->hadException())
-        return throwError(exec, SyntaxError, "bad message data.");

How is this going to be autogenerated?

> Seems like we should write a layout test to explain the badness?

I'm confused - this bug sounds like it shouldn't change behavior, how can one make a layout test for that?
Comment 5 Adam Barth 2010-04-27 10:22:47 PDT
The old code looks wrong.  (In reply to comment #4)
> -    if (exec->hadException())
> -        return throwError(exec, SyntaxError, "bad message data.");
> 
> How is this going to be autogenerated?

Is that code correct?  Why do we do that here but not everywhere else we convert arguments to strings?

> > Seems like we should write a layout test to explain the badness?
> 
> I'm confused - this bug sounds like it shouldn't change behavior, how can one
> make a layout test for that?

- if (args.size() < 1)

Why do we check args.size() here?  That's very rare in our bindings and usually reserved for when we need it for web compat.  Our general philosophy is that args that aren't given are treated as undefined.
Comment 6 Alexey Proskuryakov 2010-04-27 10:54:48 PDT
> Is that code correct?  Why do we do that here but not everywhere else we
> convert arguments to strings?

We do that sometimes. In particular, we do that elsewhere in WebSocket bindings code (e.g. constructWebSocket()).

> Why do we check args.size() here?  That's very rare in our bindings

Searching for "if (args.size()" reveals many cases where we check for the number of arguments.

I don't have good answers to those questions. It's not unthinkable that most of WebKit code is wrong in this respect. Given that IE and Firefox diverge a lot, and WebIDL is just a working draft, it's hard to even define"right" and "wrong".

Providing better error reporting and catching exceptions from argument conversion early both seem to be generally good things to do, although there's of course the question of how these affect performance.
Comment 7 Adam Barth 2010-04-27 11:16:31 PDT
(In reply to comment #6)
> > Is that code correct?  Why do we do that here but not everywhere else we
> > convert arguments to strings?
> 
> We do that sometimes. In particular, we do that elsewhere in WebSocket bindings
> code (e.g. constructWebSocket()).
[...]
> Providing better error reporting and catching exceptions from argument
> conversion early both seem to be generally good things to do, although there's
> of course the question of how these affect performance.

If that's the right things to do, then we should do it everywhere.  I don't know why we have special-case code here.

> > Why do we check args.size() here?  That's very rare in our bindings
> 
> Searching for "if (args.size()" reveals many cases where we check for the
> number of arguments.

Our project-wide policy is not to check args.size() unless we need to.  This violates the spec, but my understanding is that we do this to make writing JS wrapper functions easier for library developers.  In any case, we should be making these decisions on a project-wide basis (e.g., in the code generator) instead of having randomly different behavior in each location based on who happened to write the custom bindings code.

> I don't have good answers to those questions. It's not unthinkable that most of
> WebKit code is wrong in this respect. Given that IE and Firefox diverge a lot,
> and WebIDL is just a working draft, it's hard to even define"right" and
> "wrong".

Indeed.  However, consistency is a virtue.  As far as I can tell, this method is randomly custom for no reason.  It seems much better to have it work the same way as every other method.
Comment 8 Alexey Proskuryakov 2010-04-27 11:29:36 PDT
Comment on attachment 54393 [details]
Patch

> It seems much better to have it work the same way as every other method.

I don't have a big problem with this change in behavior per se. But I have two problems with this patch:
1. Since it's a behavior change, there should be tests.
2. The "every other method" explanation doesn't really hold water. As I mentioned, there are hundreds of cases where we do the same as the code you are changing does. Those may be a minority, but not a negligible minority.
Comment 9 Sam Weinig 2010-04-27 15:18:43 PDT
(In reply to comment #8)
> (From update of attachment 54393 [details])
> > It seems much better to have it work the same way as every other method.
> 
> I don't have a big problem with this change in behavior per se. But I have two
> problems with this patch:
> 1. Since it's a behavior change, there should be tests.
> 2. The "every other method" explanation doesn't really hold water. As I
> mentioned, there are hundreds of cases where we do the same as the code you are
> changing does. Those may be a minority, but not a negligible minority.

I have to agree with Alexey on this one and would add that we should aim to separate cleanup from functionality change.  And to reiterate, any functionality change here should be tested.
Comment 10 Eric Seidel (no email) 2010-04-27 15:24:31 PDT
Any time we convert a method from custom to autogen a few "bugs" get fixed automatically.

One of them is that

otherObject.function = Class.proto.function
otherObject.function()

starts to throw an error because the autogen bindings check to make sure "this" is of the right type, and so far I've not seen a single custom binding do so.

If we're going to bother to test such a thing, the test should simply walk the whole tree and test all classes at once.
Comment 11 Adam Barth 2010-04-27 16:22:45 PDT
> starts to throw an error because the autogen bindings check to make sure "this"
> is of the right type, and so far I've not seen a single custom binding do so.

I think that's checked before the custom implementation is called.
Comment 12 Adam Barth 2010-04-27 16:26:31 PDT
> I have to agree with Alexey on this one and would add that we should aim to
> separate cleanup from functionality change.

That's a noble aim, but more or less impossible.  The custom bindings are riddled with trivial mistakes.  It seems a fools errand to document that we don't have these specific mistakes.  There's are infinite sea of trivial mistakes we could have.

> And to reiterate, any functionality change here should be tested.

In that case, we should accept any new custom bindings code without testing all the trivial behaviors it has since every time we write custom bindings we introduce tons of subtle functionality changes.
Comment 13 Adam Barth 2010-04-27 16:35:59 PDT
> In that case, we should accept any new custom bindings code 

*shouldn't
Comment 14 Adam Barth 2010-04-27 16:48:31 PDT
Here's the a diff from the future.  Will explain in a minute.

--- /tmp/layout-test-results/websocket/tests/send-throw-expected.txt	2010-04-27 16:47:23.000000000 -0700
+++ /tmp/layout-test-results/websocket/tests/send-throw-actual.txt	2010-04-27 16:47:23.000000000 -0700
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 Connected.
-Caught exception: SyntaxError: bad message data.
+Caught exception: Pickles
 Closed.
 PASS successfullyParsed is true
Comment 15 Adam Barth 2010-04-27 16:53:48 PDT
Created attachment 54473 [details]
Patch
Comment 16 Adam Barth 2010-04-27 16:54:57 PDT
The diff in Comment #14 is the change in behavior from this patch.  I think the old behavior is really bogus because it magically catches and mutates the exception.
Comment 17 Adam Barth 2010-04-27 17:04:11 PDT
Comment on attachment 54473 [details]
Patch

There's another difference in behavior, which is whether the side-effects happen when toString throws, which I've filed https://bugs.webkit.org/show_bug.cgi?id=38230 about.
Comment 18 Alexey Proskuryakov 2010-04-27 19:19:02 PDT
> https://bugs.webkit.org/show_bug.cgi?id=38230 about

For WebSocket specifically, that would be a regression from this patch, right?

As mentioned in comment 6, if we're regression this behavior, it makes no sense to do that only for send() - constructWebSocket also has this check.

> I think the old behavior is really bogus because it magically catches and 
> mutates the exception.

What do WebIDL or other applicable specs say?
Comment 19 Sam Weinig 2010-04-27 21:08:09 PDT
(In reply to comment #12)
> > I have to agree with Alexey on this one and would add that we should aim to
> > separate cleanup from functionality change.
> 
> That's a noble aim, but more or less impossible.  The custom bindings are
> riddled with trivial mistakes.  It seems a fools errand to document that we
> don't have these specific mistakes.  There's are infinite sea of trivial
> mistakes we could have.

For my benefit, can you list some of them?

> 
> > And to reiterate, any functionality change here should be tested.
> 
> In that case, we should accept any new custom bindings code without testing all
> the trivial behaviors it has since every time we write custom bindings we
> introduce tons of subtle functionality changes.

We expect new code to be well tested, but we need to set a higher bar on changes to existing code since it is a change in existing behavior.  For this change in particular, it seems the correct way to go would be to remove the number of arguments check first (with a test as we would require if that was the only thing you wanted to do) and then auto-generate it.
Comment 20 Adam Barth 2010-04-28 09:08:33 PDT
(In reply to comment #18)
> > https://bugs.webkit.org/show_bug.cgi?id=38230 about
> 
> For WebSocket specifically, that would be a regression from this patch, right?

Yes it would.  However, the case is quite rare and we have this bug almost everywhere already.  I'd be happy to fix it in the code generator so that the fix can be applied to every non-custom binding.

> As mentioned in comment 6, if we're regression this behavior, it makes no sense
> to do that only for send() - constructWebSocket also has this check.

I don't understand this comment.  Is there a way to generate constructWebSocket automatically?  I haven't looked at it yet.

> > I think the old behavior is really bogus because it magically catches and 
> > mutates the exception.
> 
> What do WebIDL or other applicable specs say?

I'm not sure, but if WebIDL says we should mutate the exception, then we have many, many other parts of our bindings that are also out of spec.

My point is that autogenerating this code makes it work the same as the vast, vast majority of our bindings.  If there are bugs in the autogenerated code, then those bugs exist everywhere and should be fixed.  As far as I can tell, there's no reason why this specific API should have custom code that's randomly different than the rest of our code.  That's just entropy for the sake of entropy.  Autogenerating this code is a step forward even if we randomly respin a bunch of arbitrary subtleties in the API's behavior because we're making those subtleties match how the rest of the bindings work.

(In reply to comment #19)
> (In reply to comment #12)
> > > I have to agree with Alexey on this one and would add that we should aim to
> > > separate cleanup from functionality change.
> > 
> > That's a noble aim, but more or less impossible.  The custom bindings are
> > riddled with trivial mistakes.  It seems a fools errand to document that we
> > don't have these specific mistakes.  There's are infinite sea of trivial
> > mistakes we could have.
> 
> For my benefit, can you list some of them?

Here's a list off the top of my head:

1) The order in which arguments are coerced to various types can be observed use toString and valueOf.
2) What happens when each of the argument separately (or in combination) throw exceptions: Are the other arguments coerced?  Do any side effects happen?  Does the exception get swallowed?  Which exception do you get thrown?  What if the underlying operation generates an exception?
3) Relatedly, if the method operates on objects, when are the identities of those object frozen?  For example, if you mutate the DOM or the Frame hierarchy during coercion, do you get the objects from before the mutation or after the mutation?

Those are just the ones I can think of related into how and when you coerce arguments.  As we remove more custom code, I'm sure we'll find lost more exciting bugs.  For example, in NodeIterator, we saw that the custom code was computing DOM wrappers using the wrong global object.

The bindings are extremely high-touch regions of code because the web platform can poke at them very directly.  Essentially, the only way to ensure uniform behavior is to autogenerate them.  The custom bindings we have are a necessary evil in some places, but by and large just filled with trivial (and not so trivial) bugs.

> > > And to reiterate, any functionality change here should be tested.
> > 
> > In that case, we should accept any new custom bindings code without testing all
> > the trivial behaviors it has since every time we write custom bindings we
> > introduce tons of subtle functionality changes.
> 
> We expect new code to be well tested, but we need to set a higher bar on
> changes to existing code since it is a change in existing behavior.  For this
> change in particular, it seems the correct way to go would be to remove the
> number of arguments check first (with a test as we would require if that was
> the only thing you wanted to do) and then auto-generate it.

Well, the patch I posted keeps the argument check using the "RequiresAllArguments" IDL attribute.  We can remove that attribute later, if we like.
Comment 21 Darin Adler 2010-06-12 17:59:49 PDT
Comment on attachment 54473 [details]
Patch

> +        // FIXME: RequiresAllArguments is likely bogus here.

I think we should find a better way to keep track of these. I am not sure these “is likely bogus” comments are useful.

> +        [RequiresAllArguments] boolean send(in DOMString data)
> +            raises(DOMException);

I prefer the "all in one line" style for these.
Comment 22 Adam Barth 2010-06-18 01:38:52 PDT
(In reply to comment #21)
> (From update of attachment 54473 [details])
> > +        // FIXME: RequiresAllArguments is likely bogus here.
> 
> I think we should find a better way to keep track of these. I am not sure these “is likely bogus” comments are useful.

Yeah, I removed these comments in the other patches in this vein.

> > +        [RequiresAllArguments] boolean send(in DOMString data)
> > +            raises(DOMException);
> 
> I prefer the "all in one line" style for these.

Will do.
Comment 23 Adam Barth 2010-06-18 02:31:48 PDT
Committed r61390: <http://trac.webkit.org/changeset/61390>