Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I stop Chrome from eating my global property?

Chrome on iOS appears to create an XMLHttpRequest object when you include an external JavaScript file. It seems to assign this object to a global variable with the identifier a, overwriting anything you may have already had in there.

Test case:

  • HTML file (test.html):

    <!-- ... -->
    <script>
        var a = 1; // Value is not important for this demonstration
    </script>
    <script src="test.js"></script>
    <!-- ... -->
    
  • External JavaScript file (test.js):

    setTimeout(function () {
        document.write(a); // [object XMLHttpRequest]
        a.onreadystatechange = function () {
            document.write(a.readyState); // Alternates between "1" and "4"
        };
    }, 100);
    

The XMLHttpRequest appears to repeatedly make a request (to somewhere... routing the device connection through a proxy and monitoring requests doesn't show up anything) and the onreadystatechange event handler is repeatedly executed.

Some more observations:

  • This only seems to happen some time after page load (hence the setTimeout)
  • When it does happen, there is also a window.__gchrome_CachedRequest property
  • __gchrome_CachedRequest === a
  • It doesn't seem to happen in older versions of iOS Chrome (not sure which version it first occurs in though)

Has anyone come across this before? Is there a way I can stop it from happening (Note... I cannot rename a)? If anyone knows why it does this I would love to find out.


Update

I've just noticed that this actually happens with inline scripts too, not just when you include an external script. I didn't notice this initially because I didn't have the setTimeout call in there. So it looks like it actually just always happens some time after page load.

like image 856
James Allardice Avatar asked Feb 27 '13 14:02

James Allardice


1 Answers

From the discussion we had in comments, it looks like Chrome is using a with statement to layer some of its own stuff over the top of window properties. It probably does this because those properties would not normally be overwritable. The delay is most likely down to how soon Chrome can inject its own script into the UIWebView (browsers on iOS are forced to use the underlying UIWebView object rather than their own engines) after a page starts loading.

If all this speculation is actually true, then there's simple solution, other than to access window.a instead of a or take the power back and use your own with statement:

with (window)
    eval(myScript);

Hardly a solution anyone would relish implementing, but might be your only option.

like image 77
Andy E Avatar answered Nov 19 '22 06:11

Andy E