This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 20580 - Need to define behavior when multiple submissions happen more clearly
Summary: Need to define behavior when multiple submissions happen more clearly
Status: RESOLVED FIXED
Alias: None
Product: WHATWG
Classification: Unclassified
Component: HTML (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: Unsorted
Assignee: Ian 'Hixie' Hickson
QA Contact: contributor
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-01-06 17:37 UTC by contributor
Modified: 2013-06-19 21:37 UTC (History)
5 users (show)

See Also:


Attachments

Description contributor 2013-01-06 17:37:51 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html
Multipage: http://www.whatwg.org/C#form-submission-algorithm
Complete: http://www.whatwg.org/c#form-submission-algorithm

Comment:
Need to define behavior when multiple submissions happen more clearly

Posted from: 173.48.81.109 by bzbarsky@mit.edu
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20121217 Firefox/20.0
Comment 1 Boris Zbarsky 2013-01-06 17:40:35 UTC
Consider these testcases:

  <form action="whatever">
     <input type="submit" onclick="this.form.submit()">
  </form>

  <form action="whatever">
     <input type="submit"
            onclick="this.form.submit(); this.form.submit(); return false">
  </form>

Per current spec text it looks like both of these should invoke beforeunload twice, at first glance.  But that doesn't seem to be what UAs do in practice (though needs careful testing in various UAs).

I believe Gecko has a "pending submission" concept and will cancel earlier submission attempts when a later submission happens, if the earlier submission has not gotten far enough along yet, for what it's worth.  Not sure what other UAs do.
Comment 2 Boris Zbarsky 2013-01-06 17:41:19 UTC
Note also that the behavior of both of the comment 1 testcases is particularly interesting if the form has target="_blank".  Should two new windows be opened, or just one?
Comment 3 Ian 'Hixie' Hickson 2013-03-06 22:42:48 UTC
As far as I can tell the spec comprehensively describes everything that should happen here.

It might not match reality, but that's a different issue. For that, I need specific test cases, and to know which browser you'd like me to match.

Could you elaborate on what changes you would like for this bug?

See also bug 18854.
Comment 4 Boris Zbarsky 2013-03-06 22:54:59 UTC
I don't have a particular opinion on which browser you should match, but I'm pretty sure on the testcases in comment 1 the spec matches none of the browsers I tested.

What needs to happen for this bug is:

1)  Marking the spec section as fiction-so-far so implementors know that they
    can't rely on it at this point.
2)  Someone sitting down and figuring out what UAs actually do with form
    submission.
3)  Figuring out how to spec it.

I realize you might well not have time for this yourself, but that's where step 1 comes in: implementors who need to go reverse-engineer things anyway might be able to step up for #2 and #3.
Comment 5 Ian 'Hixie' Hickson 2013-03-08 21:39:23 UTC
#1 is a bit over the top, since 99% of the section is accurate as far as I can tell, the only part that's inaccurate is the exact timings. In fact, this section might be entirely accurate, with the problem only being in the navigation section.

   http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=2151

Gecko does fire the beforeunloads synchronously, but somehow it does it when you set the "action" attribute, which makes no sense to me??? Gecko also does not pause while displaying the beforeunload prompt. If you wait before dismissing the second one, you see the first page loading in the background.

Chrome only shows one beforeunload prompt, but it looks like what might be going on there is that it does the navigation synchronously, but then does the beforeunload async, in a task, which it cancels if it doesn't get time to run it before another navigation starts. (As a side note, Chrome does pause during the beforeunload prompt.)

Clearly both browsers do something to prevent multiple form.submit()s from taking effect, either directly or accidentally.

IE (9), however, does not. It does the navigation and beforeunload test synchronously, and just doesn't follow the original form submission if one of the submit()s works. (If you cancel the beforeunload, though, they throw an exception, which is rather novel.)

Per today's spec, the behaviour should be that you get three beforeunload prompts, and end at the 'document' URL from the native click. That's one prompt less than Gecko and IE's two prompts, but you end up at the same doc as Chrome and Gecko, so it seems unlikely to be a compat problem, and the page clearly asks for three submissions, so having three prompts makes sense from an authoring perspective.


It really is something to do with "action" that triggers Gecko. In this test, you can see it loading the first submission, before it loads the image — somehow, the final submit and the native click get ignored?

   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2155

In Chrome, the behaviour here is saner, with each subsequence navigation canceling the previous one, just one beforeunload, for the last navigation. In IE, the same applies, except that the "real" submission doesn't occur for some reason if you call submit() in the onsubmit handler.

Per today's spec, the behaviour here should be four prompts and ending up at the "?" URL. You end up at the "?" URL in Chrome, and both Gecko and IE end up at URLs that are unintuitive and different from each other, so the URL probably doesn't matter for compat. Gecko and IE both show multiple prompts, so the number of prompts probably doesn't matter for compat either.

Testing _blank:

   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2157

...shows browsers behaving consistently with the above, e.g. with Gecko opening three tabs and navigating the local browsing context.


In conclusion, it seems that multiple beforeunloads aren't unheard of. The timings varies dramatically from browser to browser. Even the exact page they land on seems to vary. They all don't make much sense, and there's definitely unintuitive behaviour going on. The spec isn't exactly like any browser today, but seems to plot a course between the various behaviours that is very likely compatible with content while being more intuitive for authors.

Are there known compat reasons for why the spec's current compromise between the browser behaviours is not tenable?
Comment 6 Boris Zbarsky 2013-03-12 02:30:48 UTC
I tried implementing the current spec in Gecko, and it failed on all sorts of websites that had submit() in an onclick on a submit input but didn't return false and expected only one submission and one beforeunload.  So in that simple situation there needs to be exactly one submission and one beforeunload as far as I can tell.  The fact that the current spec doesn't do that makes it pretty useless to me as an implementor, unfortunately.

Note that if you start mutating the form then pending submissions can get thrown out, which allows you to do more than on submission.  At least in in Gecko.  I would not be surprised if the exact mechanisms that are used in different browsers is different and responds differently to such mutations.  However I'm pretty sure that mutations during an onsubmit handler and during the click handler in question need to affect where the submission goes in the end...

I should also note that trying to test all the edge cases here with a simple omnibus testcase, especially one that involves modal dialogs and nested event loops, is not likely to produce ideal amounts of clarity.  :(
Comment 7 Boris Zbarsky 2013-03-12 02:31:48 UTC
Oh, and the beforeunload handlers I ran into did things like saving user data or otherwise communicating with the server, not actually prompting for whether to unload.
Comment 8 Ian 'Hixie' Hickson 2013-03-14 00:41:38 UTC
I had lots of different test cases, not all of them on the Live DOM viewer and not all of them archived (but e.g. for the saved Live DOM viewer ones, try save IDs from 2138 to 2157) — I just didn't mention them all here.

Do you happen to still have any of the URLs around of Web pages that broke? I'd love to study real world cases in various browsers.
Comment 9 Boris Zbarsky 2013-03-14 00:54:46 UTC
I don't offhand, sorry.  I should have saved them.  :(
Comment 10 Ian 'Hixie' Hickson 2013-04-22 19:22:24 UTC
OK, how about this. The submission is done synchronously like now, except that instead of synchronously invoking the "navigate" algorithm at the end, where we would do that we instead queue a task to do that, but if any such task has already been queued for this form, we first remove the previous one.

So essentially each form can have a "queued navigation" task, and once it fires it fires, but until it fires, if another gets queued, it clobbers the previous one.

This doesn't describe IE's behaviour, but it gets the simple case right (one submission for the first example in comment 1), and is closer for other browsers. It's close to what you describe as Gecko's actual implementation, without having the weird behaviour around setting attributes and the like.
Comment 11 Boris Zbarsky 2013-04-23 16:33:04 UTC
I think that makes sense to me.  Would like Mounir to double-check it...
Comment 12 Mounir Lamouri 2013-04-23 18:11:16 UTC
Sounds good to me but Jonas knows way more than me about form submission. CCing him in case of he has anything to say.
Comment 13 Jonas Sicking (Not reading bugmail) 2013-06-04 23:25:54 UTC
Man, you rewrite form submission once and then everyone thinks that you're an expert...

I only have two non-strong opinions.

1. I'm not a huge fan of queuing a task and then changing behavior when that task runs. It makes things a little bit racy. End-of-microtask checkpoint or some such wouldn't have that problem, but might have other disadvantages? Even better would be if we change behavior at the end of the click/submit event.

2. The only compatibility constraints that I remember is the fact that people do submissions during the event firing related to another submission. I don't recall exactly what behavior was expected, but that's definitely something we should ensure to test.
Comment 14 Ian 'Hixie' Hickson 2013-06-12 21:59:34 UTC
Based on http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2309 it looks like every browser does the same thing, which is, the first form submitted wins. Which luckily is consistent with comment 10's proposal, but I'm a little skeptical that all the browsers do the same thing here. That seems too good to be true.
Comment 15 Ian 'Hixie' Hickson 2013-06-19 21:35:43 UTC
Let me know if the new text isn't good enough!
Comment 16 contributor 2013-06-19 21:37:07 UTC
Checked in as WHATWG revision r7992.
Check-in comment: Make <form> submission more like reality.
http://html5.org/tools/web-apps-tracker?from=7991&to=7992