<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>19713</bug_id>
          
          <creation_ts>2012-10-26 05:46:47 +0000</creation_ts>
          <short_desc>Processing of event handler return value is ambiguous</short_desc>
          <delta_ts>2013-10-14 14:41:53 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WHATWG</product>
          <component>HTML</component>
          <version>unspecified</version>
          <rep_platform>Other</rep_platform>
          <op_sys>other</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc>http://www.whatwg.org/specs/web-apps/current-work/#events</bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P3</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>Unsorted</target_milestone>
          <dependson>23489</dependson>
          
          <everconfirmed>1</everconfirmed>
          <reporter>contributor</reporter>
          <assigned_to name="Ian &apos;Hixie&apos; Hickson">ian</assigned_to>
          <cc>bzbarsky</cc>
    
    <cc>ian</cc>
    
    <cc>mike</cc>
          
          <qa_contact>contributor</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>77128</commentid>
    <comment_count>0</comment_count>
    <who name="">contributor</who>
    <bug_when>2012-10-26 05:46:47 +0000</bug_when>
    <thetext>Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html
Multipage: http://www.whatwg.org/C#events
Complete: http://www.whatwg.org/c#events

Comment:
Processing of event handler return value is ambiguous

Posted from: 173.48.30.113 by bzbarsky@mit.edu
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/19.0 Firefox/19.0</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>77129</commentid>
    <comment_count>1</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2012-10-26 05:55:21 +0000</bug_when>
    <thetext>For example, this part:

  If the event type is mouseover
    If return value is a boolean with the value true, then cancel the event.

This doesn&apos;t really define what &quot;is a boolean&quot; is.  So it&apos;s not clear what should happen if the return value is the string &quot;something&quot;.

I would suggest relying on WebIDL here.  In particular, make the IDL look somewhat like this:

  [TreatNonCallableAsNull]
  callback EventHandlerNonNull = boolean (Event event);
  typedef EventHandlerNonNull? EventHandler;

  [TreatNonCallableAsNull]
  callback BeforeUnloadEventHandlerNonNull = DOMString? (Event event);
  typedef BeforeUnloadEventHandlerNonNull? BeforeUnloadEventHandler;

and define the onbeforeunload attribute as taking a BeforeUnloadEventHandler.  Then the processing model can say:

  If the event type is mouseover
    If return value is true, then cancel the event.
  If the Event object E is a BeforeUnloadEvent object
    If return value is not null and the Event object E&apos;s returnValue
    attribute&apos;s value is the empty string, then set the returnValue attribute&apos;s
    value to return value.
  Otherwise
    If return value is false, then cancel the event.

That should be completely unambiguous in weird cases like the onbeforeunload handler returning { toString: function() { return &quot;hey, look at that&quot; } }, which brings up a dialog in browsers but arguably shouldn&apos;t per current spec&apos;s &quot;if the value is a string&quot; bit.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>77765</commentid>
    <comment_count>2</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2012-11-02 17:28:50 +0000</bug_when>
    <thetext>So the proposal in comment 1 doesn&apos;t work as-is because no return value would get treated as &quot;false&quot; for EventHandlerNonNull.

We could do &quot;boolean?&quot; as the return type, and say that a non-null false is needed.  That would still mean that returning &quot;0&quot; cancels the event; not sure whether that&apos;s desirable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>77766</commentid>
    <comment_count>3</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2012-11-02 17:33:41 +0000</bug_when>
    <thetext>But even if we decide that we can&apos;t have 0 preventing default, we should clearly define what &quot;is a boolean&quot; actually means here... in non-ECMAScript terms.  :(</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>77770</commentid>
    <comment_count>4</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2012-11-02 19:22:39 +0000</bug_when>
    <thetext>Based on https://bugzilla.mozilla.org/show_bug.cgi?id=345521 sounds like we really don&apos;t want 0 to prevent default, unfortunately.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>77780</commentid>
    <comment_count>5</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2012-11-02 21:39:23 +0000</bug_when>
    <thetext>&quot;Is a JavaScript boolean with the value false&quot;?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>78809</commentid>
    <comment_count>6</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2012-11-26 04:53:58 +0000</bug_when>
    <thetext>The return value is a WebIDL value...

It may be that the best we can do here is keep using IDL &quot;any&quot; and just make sure that this is &quot;boolean&quot; in the WebIDL sense, and rely on http://dev.w3.org/2006/webapi/WebIDL/#es-any to do the right thing for us.

I still think beforeunload should have DOMString? as return value, though.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>82663</commentid>
    <comment_count>7</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-02-06 23:38:10 +0000</bug_when>
    <thetext>bz: Using special WebIDL callbacks for beforeunload doesn&apos;t work because BeforeUnloadEvent objects can be fired for any event name, not just &apos;beforeunload&apos;.

But I&apos;ve tried to fix it... let me know (and reopen) if it&apos;s still problematic.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>82664</commentid>
    <comment_count>8</comment_count>
    <who name="">contributor</who>
    <bug_when>2013-02-06 23:38:21 +0000</bug_when>
    <thetext>Checked in as WHATWG revision r7702.
Check-in comment: Be more explicit about what this means.
http://html5.org/tools/web-apps-tracker?from=7701&amp;to=7702</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>82761</commentid>
    <comment_count>9</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-02-08 16:58:58 +0000</bug_when>
    <thetext>&gt; because BeforeUnloadEvent objects can be fired for any event name, not just
&gt; &apos;beforeunload&apos;.

I don&apos;t follow this.  Can you explain?

As far as I can tell the spec as currently written doesn&apos;t match implementations very well (not that interop for beforeunload is all that great).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>85125</commentid>
    <comment_count>10</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-03-28 20:28:34 +0000</bug_when>
    <thetext>What do you think the spec _should_ say?

The options I see are:

1. only have this magic behaviour for the beforeunload events fired as part of the &quot;prompt to unload a document&quot; algorithm,

2. have this magic behaviour for all BeforeUnloadEvent events

3. have this magic behaviour for all BeforeUnloadEvent events named &apos;beforeunload&apos;

Is there a fourth option I&apos;m missing?

Option 1 seems bad because it means the event dispatch mechanism has a dependency on the otherwise unrelated unload logic.

Option 3, as far as I can tell, needs a few more cycles to do something less useful than option 2.

That leaves option 2, which is what the spec says.

I agree that interop here isn&apos;t so hot, which is why I haven&apos;t really attempted to precisely match any UA, but obviously if there&apos;s a compat need, or if there&apos;s more interop than I realise, or if there&apos;s a fourth better option, or something, then we should change this.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>85135</commentid>
    <comment_count>11</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-03-29 00:09:38 +0000</bug_when>
    <thetext>&gt; What do you think the spec _should_ say?

What Gecko implements at this point is as follows:

1)  onbeforeunload has the type BeforeUnloadEventHandler on window/body/frameset,
    defined like so:

   callback BeforeUnloadEventHandlerNonNull = DOMString? (Event event);
   typedef BeforeUnloadEventHandlerNonNull? BeforeUnloadEventHandler;

2)  When invoking a BeforeUnloadEventHandlerNonNull, if the return value is not
    null call preventDefault() on the event object.  Then if the event is a
    BeforeUnloadEvent and its returnValue is empty, set its returnValue
    to the return value of the handler.

In particular, if the handler returns the number 42, or { toString: function() { return &quot;hey there&quot;; } } , we will show a prompt whereas current spec will not, as far as I can tell.  Furthermore, returning non-null from the handler will call preventDefault on the event, whereas the spec doesn&apos;t do that.  Those seem to be the main web-page detectable differences between what the spec says and Gecko does.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87234</commentid>
    <comment_count>12</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-05-04 00:31:07 +0000</bug_when>
    <thetext>So that would be:

4. have &apos;beforeunload&apos; events&apos; return values be coerced to DOMString or null (unlike other events which aren&apos;t coerced at all), cancel if it&apos;s null, and if it&apos;s also a BeforeUnloadEvent event, additionally set the event object&apos;s returnValue based on the returned string if it&apos;s not null.

Is that right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87235</commentid>
    <comment_count>13</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-05-04 01:17:31 +0000</bug_when>
    <thetext>That&apos;s what Gecko implements right now, I believe, yes.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>88909</commentid>
    <comment_count>14</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-06-07 20:58:14 +0000</bug_when>
    <thetext>Thanks for your patience with me on this, as always.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>88910</commentid>
    <comment_count>15</comment_count>
    <who name="">contributor</who>
    <bug_when>2013-06-07 21:01:16 +0000</bug_when>
    <thetext>Checked in as WHATWG revision r7933.
Check-in comment: Bring onbeforeunload handling closer to compatibility with the Web
http://html5.org/tools/web-apps-tracker?from=7932&amp;to=7933</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>