New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 666205 link

Starred by 15 users

Issue metadata

Status: WontFix
Owner: ----
Closed: Feb 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Mac
Pri: 2
Type: Feature

Blocking:
issue 125507



Sign in to add a comment

onblur event is going to infinite loop.

Reported by alagar...@modeln.com, Nov 17 2016

Issue description

UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36

Steps to reproduce the problem:
1. validating data provided in box.
2. error alert came. 
3. On click ok. we want to get focus on box again. but again alert appears and making infinite loop.

What is the expected behavior?
Once we click on ok button of alert. we should get the focus on box.

What went wrong?
On click ok in alert msg. we want to get focus on box again. but again alert appears and making infinite loop.

Did this work before? N/A 

Chrome version: 54.0.2840.99  Channel: stable
OS Version: 6.1 (Windows 7, Windows Server 2008 R2)
Flash Version: Shockwave Flash 23.0 r0

my method is below which is working properly on other browser.
function validateLastQty(box, prevQty) {
  if(!isValidNum(box)) return false;
  var valueEntered = matrixParseNumber(box.value);
  if (prevQty*1 + 1 > valueEntered) {
    var msg = "The value entered (" + valueEntered + ") must be bigger than " + matrixAddCommas(prevQty*1 + 1);
    showSoftError(msg);
    alert(msg);
    box.focus();
    return false;
  }
  return true;
}
 
I found some discussion about this in below link, that me help you people to short out the issue.

https://groups.google.com/a/chromium.org/forum/#!topic/chromium-discuss/2LqXp2DMIIs

Comment 2 Deleted

Labels: Needs-Bisect
Status: Untriaged (was: Unconfirmed)
Attaching a case with the behavior. WARNING: THIS LOCKS UP THE ENTIRE BROWSER!

Run it in a chromium build or some place that's easy to identify and kill the process.

The discussion linked to in comment #1 implies that this change was introduced somewhere in the M52 timeframe. If it's possible to bisect, that would be great, but note the WARNING above.
cr666205.html
251 bytes View Download

Comment 4 by tkent@chromium.org, Nov 18 2016

Components: -Blink>DOM>Events Blink>Focus Blink>WindowDialog
Cc: jmukthavaram@chromium.org
Components: Blink>JavaScript
Labels: -Type-Bug -Pri-2 -Needs-Bisect M-54 hasbisect OS-Linux OS-Mac Pri-1 Type-Bug-Regression
Owner: a...@chromium.org
Status: Assigned (was: Untriaged)
Able to reproduce this issue on windows 10, Mac 10.11.4,Linux Ubuntu 14.04 with Chrome stable version-53.0.2785.143 and Canary.

Manual Bisect:

Bad Build—54.0.2840.99

Good Build—53.0.2744.0

Unable to provide the tool bisect as good & bad builds are from different milestones, hence providing manual change log from Omahaproxy:

Manual Change log-
https://chromium.googlesource.com/chromium/src/+log/53.0.2744.0..54.0.2840.0?pretty=fuller&n=10000

Review-Url: 

https://codereview.chromium.org/2252913003

avi@ assigning to you, as you were listed as one of the reviewers for this CL.

Kindly take a look and please help us to reassign this issue to a right owner if not with respect to this change.

Thanks.!

Comment 6 by a...@chromium.org, Nov 18 2016

schenney, that is not a proper reduction. The original poster's function has an out that allows the defocus. Your reduction always re-focuses and forces an infinite loop no matter what.

I'm attaching a better repro. It wants you to type "hello" into the text box.

What seems to be happening is that calling focus() on the text field is triggering the onblur property, which is weird. Let me find someone in Blink to take a look at this.
cr666205.html
292 bytes View Download

Comment 7 by a...@chromium.org, Nov 18 2016

Actually, schenney, I was wrong. That is a proper reduction; on Chrome it spews dialogs incessantly whereas in other browsers it doesn't.

Comment 8 by a...@chromium.org, Nov 18 2016

Cc: a...@chromium.org
Owner: kochi@chromium.org
kochi, you've fixed quite a few Blink focus issues. Can you take a look at this?
This is currently being exploited in the wild by tech support scammers.

Comment 10 by kochi@chromium.org, Nov 21 2016

Status: Started (was: Assigned)
Taking a look.

Comment 11 by kochi@chromium.org, Nov 21 2016

I think I can reproduce the issue using attached html in c#3 or c#6,
and understand what the issue is.

However the dialog shows a "Prevent this page from creating additional dialogs"
checkbox and if I check on the box I can escape from the infinite loop,
though this is not a proper solution for this anyway.
So I am not sure I am experiencing "WARNING: THIS LOCKS UP THE ENTIRE BROWSER!"
correctly - (at my first impression on reading comments, I thought you can never
escape from the infinite loop.)

Comment 12 by kochi@chromium.org, Nov 21 2016

On the other hand, I checked other browsers on mac,
on Safari 10: shows the same dialog, without "Prevent this page..." checkbox
and fall into an infinite loop. Only way to escape from it (as far as I found)
is to focus on URL bar and type other URL.
on Firefox 50.0, shows the dialog, and click on "OK" button - then the dialog
closes, but focus is gone somewhere not in the original input box, and clicking
on input box doesn't restore the focus.

So to me, neither one of these browsers (Chrome, Safari, Firefox) is working
as expected.

Comment 13 by kochi@chromium.org, Nov 24 2016

Apparently, avi's CL in https://codereview.chromium.org/2252913003
shouldn't be a suspect, as it is mac-only.

I tried bisect myself, and got the range 394784(good)...394794(bad).

Tried running the sample attached to c#6, type "hel" and click outside
the input.  The alert popup shows, and clicking the OK button should
return the focus to the input field.

Bad revisions will infinitely repeat the alert dialogs.

The above range pointed me to
https://chromium.googlesource.com/chromium/src/+log/ae9b7a05e087905774fb29807281fa771711ff3b..a4df8ada22f3d15ad7153a369c780795797dfa1d
which does not seem to contain any suspicious change.

I'll try again.

Comment 14 by kochi@chromium.org, Nov 24 2016

Cc: changwan@chromium.org
Another bisect got the range of 394879...394885,
https://chromium.googlesource.com/chromium/src/+/6ed4d4373c5ce4743850df50f94b867240472033
among which https://codereview.chromium.org/1931793002 looks suspicious.

Reverting it seems not trivial as it is 6 months ago.

Adding changwan@.

Changwan, if you are familiar with the change and can try reverting it
would fix the repro case in c#6, could you own this?
Cc: aelias@chromium.org
Hmm... Not sure if reverting the change is the best course of action here.
I wonder why we get onblur event when alert() dialog gets dismissed.

box.focus() gets the box to be focused first, then it ends up calling onblur somehow...

Comment 16 by kochi@chromium.org, Nov 24 2016

I wanted to check if reverting the CL changes the issue exposure or not, and I didn't
intend to revert the CL to fix this issue.

I can look into what is happening in Blink internally next week, and at this point I'm not sure
the chromium-side only change https://codereview.chromium.org/1931793002 is the
real cause.
I haven't tried reverting it, but I think it has likely caused the changed behavior here.

Previously, box.focus() was called in the background in a nested loop while alert() is being shown to the user - alert()'s dismissal moved focus back to the document and to the box.

Now box.focus() is called after alert() gets dismissed. If alert()'s dismissal moved focus back to document/body and not to the box, then I think this infinite loop can happen.

Comment 18 by kochi@chromium.org, Nov 28 2016

Looks like https://codereview.chromium.org/2532853002 (partially
revert the changwan's CL to restor DoNotNotifyWebKitOfModalLoop() et al.)
fixes this issue (and probably breaks something else).

I'll take further look.

Comment 19 by kochi@chromium.org, Nov 29 2016

For comment#12 about Safari - https://bugs.webkit.org/show_bug.cgi?id=18315
looks like a still-open bug.

Comment 20 by kochi@chromium.org, Nov 30 2016

Here's my observation on Linux about the sequences before and after the change.

The sequence of old behavior (good one) is:

1. Renderer: window.alert() is called
2. Browser: shows popup dialog
3. Browser: sends InputMsg_SetFocus(false)
4. Renderer: receives InputMsg_setFocus(false) and handle it
5. User: Clicks "OK" button on the dialog
6. Renderer: script continues, box.focus() is called
7. Browser: sends InputMsg_SetFocus(true)

And after changwan's CL landed the sequence (bad one) is:

a. Renderer: window.alert() is called
b. Browser: shows popup dialog
c. Browser: sends InputMsg_SetFocus(false)
   => The message is blocked, renderer is not pumping
d. User: Clicks "OK" button on the dialog
e. Renderer: script continues, box.focus() is called
f. Browser: sends InputMsg_SetFocus(true)
g. Renderer: receives InputMsg_setFocus(*false*) and handle it

(The big difference is step c. and g.)

While window.alert() dialog is shown, the sync message to show the popup
was still pumping the messages and handle them, but now it is completely
blocked until dialog is dismissed.
So now it receives InputMsg_SetFocus(false) to blur the page focus, after
the dialog is dismissed - then onblur handler is called.

Hmm... Is it possible to handle InputMsg_SetFocus(true) before we resume on the script? Dismissal signal is also propagated from browser to renderer, anyways. Can we propagate dismissal and focus change at the same time?

Alex, what do you think about this?

Comment 22 by kochi@chromium.org, Nov 30 2016

I guess once the sync message (to show alert dialog) returns,
Blink continues the execution of the script - thus the box.focus() is
executed immediately after dialog is dismissed, then deferred messages
are handled.

Comment 23 by kochi@chromium.org, Nov 30 2016

Now I think this boils down to the following question:

Does window.alert() and other modal dialog really blur focus from the
originating window?
- if yes, shall we dispatch onblur synchronously when window.alert() is
  executed? (How can we?)
- if no, shall we ignore / treat specially from the window deactivation
  message from browser process?  Can all messages delivered while popup
  is open be drained?

Probably this is a gray area in terms of standard specifications, therefore
interoperability is not guaranteed if window.alert() is used within focus
or blur handlers, but anyway...

Comment 24 Deleted

Comment 25 by tkent@chromium.org, Nov 30 2016

I checked Edge behavior, and alert() didn't dispatch focus-related events in Edge.
Found some relevant discussion at WebKit bugzilla:
https://bugs.webkit.org/show_bug.cgi?id=33962

- In comment 2 (old browsers behavior)
  > Firefox 3.5.7 executes the 'onblur' handler when the modal dialog appears.
  > IE8 executes the 'onblur' handler when the modal dialog appears.
  > Safari 4.0.4 on Windows does not execute the 'onblur' handler at all.
  > WebKit ToT executes the 'onblur' handler while the dialog is up and
  > fires the timer while the dialog is up.
- In comment 12
  > window.alert(), window.pause(), and window.prompt() all require
  > the user agent to 'pause' which is defined at
  > http://dev.w3.org/html5/spec/Overview.html#pause
- In comment 15
  > Note that Firefox will fire an image onload event behind
  > a modal dialog when the image load finishes.
- In comment 16
  > Firing events on a page that is already in a modal UI means
  > more JS reentrancy. Very few JS developers are prepared to
  > handle reentrancy, that's a good reason to 'freeze' the page
  > behind the modal UI.
- In comment 18
  > I believe that's a bug in Firefox.  JavaScript is supposed to
  > run to completion without any interleaving threads.

I'll research more about other browser/platform behaviors on
window.alert()/tab switch/app switch.
Re #26, comment 12 is the reason why we had to introduce the alert() behavior change.

Thanks for looking into this!
The link in #26 is now https://html.spec.whatwg.org/#pause (reference for pause in the whatwg spec).
So, in the pre-M52 world, since there was a nested message loop still running JS,  it needed to do onBlur at the beginning and onFocus when the message was cleared, to avoid the page still being weirdly interactable while the alert box was up.  After M52, this should no longer be needed since the Blink main thread is blocked, and conversely it's even actively harmful since the asynchronously posted blur event can arrive after a JS focus call.

So I think we should just try and delete this blur/focus code; I think it's obsolete and hopefully it shouldn't cause any new bug to do so (the only thing to watch out for is an overhang of MouseMove spam, we should make sure that's coalesced properly).
Blocking: 125507

Comment 31 by tkent@chromium.org, Jan 20 2017

 Issue 682557  has been merged into this issue.

Comment 32 by tkent@chromium.org, Jan 20 2017

Components: -Blink>JavaScript
Any code snippet for  the fix?
I'm trying getting the error in google chrome version 52+, in JSF on blur event. 
Kindly do the needful
Cc: dcheng@chromium.org
+dcheng, feel free to comment on this.

Comment 35 Deleted

Are there any fix planned for this bug by Google chrome in the subsequent versions?
Kindly suggest any workarounds for this bug.

Comment 37 by kochi@chromium.org, Feb 20 2017

Fix work in progress: https://codereview.chromium.org/2702243002/

Comment 38 by kochi@chromium.org, Feb 21 2017

With this test JSbin (see focus/blur on window when popup happens):
http://jsbin.com/yorori/1/edit?html,console,output

On IE, Edge and Firefox, "blur" event dispatched to window upon popup appearance.
On Safari and Chrome, "blur" event dispatched to window *after* popup closes.

So not sending a "blur" event isn't a solution here, considering interoperability.
The patch on c#37 removed sending blur on popup window, but I have to give up the idea.
(Also, a few browser tests that depend on blur event to be sent failed.)

So with nested message loop disabled for Chrome, Blink could dispatch "blur" event
before asking browser process to show popup window (the order is somewhat speculative,
but from JS point of view it is synchronous) to match Firefox / Edge / IE behavior.

aelias@, do you see any issue/other ideas?

OK, I see the events are automatically generated by OS-level focus change.  I had assumed there was some explicit code for alert() that we could delete, but it's not so simple.

> So with nested message loop disabled for Chrome, Blink could dispatch "blur" event
before asking browser process to show popup window (the order is somewhat speculative,
but from JS point of view it is synchronous) to match Firefox / Edge / IE behavior.

This idea is fundamentally incompatible with the current model where the renderer main thread is fully blocked waiting for the alert() result.  JS can't receive the blur() event in that interval, as the JS code that called alert() is still holding onto the thread.

We definitely shouldn't reintroduce a nested message loop for this.  One alternative idea is to reimplement alert() in terms of ES7 async await.  This would also elegantly address related developer complaint  http://crbug.com/639150 .  Then JS would actually release the message loop while the alert box is up, and the code after the alert() call would implicitly be packaged into a closure.  The effect would be similar to creating an HTML fixed-position box that provides a promise for the button result, and await its result with ES7 await.

This would be something of a project that probably would call for a Blink intent to ship and coordination with other browser vendors, but I'd support you if you have the cycles to take it on.

In the short term though, given that you've found the current behavior is interoperable with Safari, I don't think we should introduce any weird compromise behavior.  Developers who really care about this problem can themselves switch to a custom ES7 await-based polyfill instead of using alert().

Comment 40 by kochi@chromium.org, Feb 22 2017

Cc: kochi@chromium.org
Labels: -Pri-1 -Type-Bug-Regression Pri-2 Type-Feature
Owner: ----
Status: Available (was: Started)
Thanks aelias@ for the excellent summary!

I totally agree on the last paragraph (... the current behavior is
interoperable with Safari, ... (we should not) introduce any compromise
behavior).

And yeah, dispatching blur at window.alert() could well be broken,
like blur event calls window.alert() etc. etc.

I do not have much cycle at this moment on this issue, so changing the
status to "Available" so anyone who has interest in this can take, and
as this is not really a regression, changed the type to "Feature",
and lowered priority.

Comment 41 by a...@chromium.org, Feb 22 2017

Hi, I'm Avi.

I'm working on making alert dialogs less awful, and one of my key constraints is that alert() and friends block the JavaScript event loop. I didn't realize that reimplementing it with async await was an option. It's beyond my abilities, but that certainly does open up lots of possibilities. If we could also move sync XHR as well, we could be rid of engine blocking events and that could be a huge win for complexity, allowing us to simplify things.

I would love to see this happen, though I'm not sure who to talk to to try to make it so.

Comment 42 by phistuck@gmail.com, Feb 22 2017

#41 - I hardly believe that making alert() asynchronous would be web compatible.

Comment 43 by a...@chromium.org, Feb 22 2017

#41 - I have no idea if it would be. I didn't think it was a possibility. Re comment #39, maybe? aelias@, can you clarify? 
Cc: ca...@igalia.com
I think it might well be web-compatible because async await is indistinguishable from running a nested message loop for most practical purposes.  In both cases, JS events are fired in the interval while the alert() call is running, then execution continues on the next line after alert() returns.

According to dcheng@ at https://groups.google.com/a/chromium.org/forum/#!topic/scheduler-dev/FaWVXvggvWA, sync XHR also involves a nested message loop so we could consider it for that as well.

There may be some deeper problems I don't realize, but prima facie it doesn't seem insane.  dcheng@ and caitp@, any thoughts on this?
Cc: adamk@chromium.org
Status: WontFix (was: Available)
According to adamk@ from V8 team, my async await idea is totally impossible because that primitive is not powerful/dynamic enough.  The outer function that await is inside needs to be marked "async" at compile time in order to create some global tables.  There is no way to do it at the time that alert() executes (which could be something like an exec of a string).

So I don't think there's anything we can do better here unfortunately, WontFixing this.

Comment 46 by kochi@chromium.org, Mar 24 2017

Cc: kavvaru@chromium.org
 Issue 700847  has been merged into this issue.

Comment 47 by kochi@chromium.org, Jul 21 2017

Cc: msrchandra@chromium.org kkaluri@chromium.org
 Issue 703407  has been merged into this issue.
Is this issue going to have it's status changed from WontFix?

My comments on this issue were made on  Issue 703407 . 

We need to know if you will fix this bug or if we need to direct Users to a different browser that doesn't crash on expected browser behavior. 

A JavaScript .focus() to a form field should not cause the onblur event to occur by the browser. The onblur attribute is supposed to fire the moment that the form element loses focus, not when it gains focus by User interaction or by JavaScript.

Comment 49 by kochi@chromium.org, Jul 26 2017

As I'm told from avi@ is that "The intended escape hatch for infinite dialogs
is closing the tab.", so if you got into infinite loop situation, you have to
close the tab, and is expected behavior on Chrome.
Frankly, this is unacceptable.  I mean.. sure.. closing the tab is a reasonable catch-all for unexpected infinite loops, but this is standard javascript for handling  alerting the user to a bad entry in a text box.

Are you actually asking people to switch browsers if they have problems fat fingering text boxes?

I don't see why you can't revert this to operate the way it did before it was broken.
Found this chrome bug this morning working on app that uses an onblur to validate a date field via a native browser alert.  I end up in an infinite alert loop I have to kill the tab to get out of.  Here's a simple workaround for those in the same boat.

Simply store the input value, clear the input field, focus the input field and restore the input value.

var temp = datefield.value;
datefield.value = '';
setTimeout(function () {
    datefield.focus();
    datefield.value = temp;
}, 0);

It isn't a perfect fix as if the blur event fires again (either outside the input field or browser), the alert fires again. This fix lets the user correct the input value (the input is focused at this point with the old value) to a correct value so the alert doesn't fire on the next blur.
Components: Blink>HTML>Focus
Components: -Blink>Focus

Comment 54 by tkent@chromium.org, Feb 16 2018

Cc: bokan@chromium.org
 Issue 812043  has been merged into this issue.

Comment 55 by tkent@chromium.org, May 31 2018

 Issue 847843  has been merged into this issue.

Sign in to add a comment