Bug 143836 - Incorrect behavior when patching window.setTimeout
Summary: Incorrect behavior when patching window.setTimeout
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-04-16 11:55 PDT by Matthew Manela
Modified: 2015-04-20 11:53 PDT (History)
4 users (show)

See Also:


Attachments
File which demonstrates the issue (1.46 KB, text/html)
2015-04-16 11:55 PDT, Matthew Manela
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Manela 2015-04-16 11:55:21 PDT
Created attachment 250935 [details]
File which demonstrates the issue

This is a demonstration of a really strange issue in Webkit (and PhantomJS which uses Webkit). The issue involves what happens when you monkey patch the window.setTimeout method in Javascript. The issue was discovered when debugging test failures that were using sinonJS (which monkey patches setTimeout). I worked through that issue and distilled the minimum repro out of it.

I validated this issue does not occur in Chrome 41, Firefox 36 and IE 11. As far as I can tell it only repros in Webkit based browsers (like Phantomjs).

Short Repro

1: Define a method (check) which references window.setTimeout

2: Call this method two times, then patch setTimeout to be a custom method and then call check again.

CODE:

function check() {
    console.log("window.setTimeout = " + window.setTimeout);
}
check();
check();
window.setTimeout = function() { console.log ("Patched"); }
check();
OUTPUT:

window.setTimeout = function setTimeout() {
    [native code]
}

window.setTimeout = function setTimeout() {
    [native code]
}

window.setTimeout = function setTimeout() {
    [native code]
}
3: Then call to check the third time will not output the contents of the monkey patched function. It will still contain the native one. THe odd thing is if you call the check() method only once (or not at all) before your patched setTimeout then it will output the expected value. For example:

CODE:

function check() {
    console.log("window.setTimeout = " + window.setTimeout);
}
check();
window.setTimeout = function() { console.log ("Patched"); }
check();
OUTPUT:

window.setTimeout = function setTimeout() {
    [native code]
}

window.setTimeout = function () { console.log("PATCHED"); }
Comment 1 Alexey Proskuryakov 2015-04-16 17:21:37 PDT
I cannot reproduce this in Safari 7.1.5, nor in a current WebKit build.
Comment 2 Matthew Manela 2015-04-17 06:46:51 PDT
Thanks for the comment. I reproed this on windows using PhantomJS which is build on top of QtWebKit. I checked what version of Webkit that is using and it said the following in QtWebKit:


"""
   This is a snapshot of WebKit. It is based on the upstream trunk subversion
revision 153112

You can browse the base of this snapshot at

    http://trac.webkit.org/browser/trunk?rev=153112

Additional patches may have been applied on top and files not required by the
Qt port may have been removed.
"""
Comment 3 Matthew Manela 2015-04-19 17:04:51 PDT
Also, I hit this issue on Windows. Could there be an OS specific bug?
Comment 4 Zack Weinberg 2015-04-20 11:15:56 PDT
Over at https://github.com/ariya/phantomjs/issues/13158 we are able to reproduce the problem in both Midori and PhantomJS, but only on Windows.