Like MooTools jQuery tackled, or detective-style Colombo

the call Stack is jQuery/MooTools On the debt, Airi, I sometimes parse error functioning of the site into the network / browser interaction. This typically boils down to a simple analysis of the headers of the request response and playback of trivial conditions. But sometimes there are interesting cases.

It all began a cold evening in February. A client wrote about a strange problem under acceleration site: slideshow multiplied and blocked the behavior of the site, the page was unavailable. Two days after clarification of all details, I found out why Mootools and jQuery categorically cannot be used together. Confirmed in the idea that "alcohol is evil" and "eval is evil."

But about all under the order.

the

Find out the root of the troubles


At the moment in browsers there are a sufficient number of profiling tools (you could even say that this number is somewhat redundant), allowing to fix the problem, reproduce the error and resolve it. This, in the first place:
the
    the
  • Network panel in the developer tools: it displays all requests, legitimate transmitted by the browser, with all the headers and responses. If we are not talking about some traffic is encrypted and requires a standard information about the requests (headers, status, size), its more than enough.
  • the
  • Console (errors) in the developer tools. In the event of a problem can be viewed as the cause of the error and a stack of callbacks. And also to repeat the behavior of the browser when you run the code.
  • the
  • DOM tree and source code of the website. It is not always clear what the properties were set and which is dynamically applied to HTML elements. But you can always see the information "first hand" from your browser.

If it was easy tracing the error, then this article could be complete. But the problem was complicated and recursive. And the browser tab would crash a few seconds after the page has loaded, leaving in error console about this track:
call Stack
c.Request.Class.send @ mootools-core.js:182
i.extend.$owner @ mootools-core.js:50
Element.implement.load @ mootools-core.js:187
st.event.trigger @ jquery.js:2989
(anonymous function) @ jquery.js:3639
st.extend.each @ jquery.js:642
st.fn.st.each @ jquery.js:263
st.fn.extend.trigger @ jquery.js:3638
st.fn.(anonymous function) @ jquery.js:3662
st.fn.load @ jquery.js:7498
(anonymous function) @ jquery.bxslider.js:11
st.extend.each @ jquery.js:642
st.fn.st.each @ jquery.js:263
(anonymous function) @ jquery.bxslider.js:11
st.extend.each @ jquery.js:642
st.fn.st.each @ jquery.js:263
loadElements @ jquery.bxslider.js:11
setup @ jquery.bxslider.js:11
init @ jquery.bxslider.js:6
$.fn.bxSlider @ jquery.bxslider.js:52
(anonymous function) @ VM375:2
f @ jquery.js:1026
p.fireWith @ jquery.js:1138
st.extend.ready @ jquery.js:427
xt @ jquery.js:97

On the website it was displayed in a repeating slider (multiple arrows on the right and on the left is multiple copies of the slider, superimposed on each other due to an error):

Bug in slider bxslider

the

digression


It is worth saying that MooTools and jQuery came to the site in compressed form. However, jQuery walked map of source (map source), which greatly facilitated the search for the extreme (=to blame).

Map source — the most useful thing in debugging compressed code released for the third specification, reducing the volume of the card. If you hear about the map sources for the first time, we advise you to pay attention to it. But we move on.

the

Digging deeper


In any problem it is important to identify the minimum conditions, still cause problems (but without extra data), and these conditions consistently perform. As it turned out, a minimum condition for stable reproduction of the problem was embedded (inline) JavaScript code in the HTML page. The caching mechanisms in the browser and Internet providers can make it difficult to make simple conclusions, therefore, when working with public unencrypted HTML pages it is necessary to articulate several times to recheck the conditions to be confident in them for sure.
But why the inclusion of JavaScript code in HTML led to a recursive implementation in the browser? Google anything about such situations is not yet know. You need to help him.

the

Hypothesis: never enough


Hypothesis on the one hand, everything is clear: JavaScript inline code recursively, it is impossible to use it on this site. On the other hand: what exactly leads to a recursive implementation of the inline code?

Helps to understand the call stack (see listing above). Bxslider (Written while drinking Belgian ales and listening to jazz — Belgian ale for sure prevented the author to predict some non-standard scenarios) on each object (in our case the picture) caused the property to load, which was processed through jQuery like this:

event Handling jQuery
jQuery.event.triggered = type;
try {
elem[ type ]();
}  catch  ( e ) {
// IE<9 dies on focus/blur to hidden element (#1486,#12518)
// only reproducible on winXP IE8 native, not IE9 in IE8 mode
}

Like all well: jQuery calls the native method on the element as soon as with the rest of the wrapper finished. In this case, is img["load"](). That should lead to the completion of the load event from the image, it should rely in your browser cache, and everything should be happy. But this situation does not agree library MooTools:

Processing load MooTools
Element.Properties.load = {
set:  function  ( a ) {
var b = this.get("load").cancel();
b.setOptions(a);
return this;
},
get: function() {
var a = this.retrieve("load");
if ( !a ) {
a = new Request.HTML( {data: this, link: "cancel", update:this, method:"get"} );
this.store("load", a);
}
return a
}
};

MooTools method load has its own understanding. And in the absence of information about the object, the object is loaded using new Request.HTML. Seems okay too: now let us download the picture if it is information from MooTools (because the picture is already loaded in the browser cache, it's just an in-memory operation of the local user's computer). But jQuery calls this method when the image, for some reason forgets to pass parameters in the particular URL. Probably jQuery does not know that after it will still work MooTools, which these settings will be Oh as are necessary. And MooTools without any parameters loads the "empty" URL (the current page).

Also seems a valid scenario: when the page loads, the browser will download it another 5 times from the server (simple HTML document), if the slider is loaded 5 images (as on the website). If the page in the server cache, the performance is (almost) no impact (and resources on the network panel of the developer tools to find these "extra" calls, mixed with pictures and counters, too easy).

But the problem is that the default MooTools performs eval of all the scripts in the loaded HTML document. And it is worse: we can worry about code execution counters several times on the website. But if it starts to run the DOMReady handler, which loads the slider, which causes the loading of the images that load the HTML page on which turns the whole inline code, which triggers the handler for DOMReady... Well, you understand.

the

Summary


Do not use multiple JavaScript frameworks. Never (for Joomla! there is even a plugin, removing MooTools from the system). If you suddenly have the desire to read this article. The problem described was "on the surface" and were quickly identified. But possible situation when the joint behavior of the frameworks will depend on the network (delays and the progress of queries) and the browser used. And then to find the cause of the problem and its fix does not seem possible.

Use eval only in those cases where you control the executable code. If there is no control, no eval.

Alcohol is evil El evil. A sober lifestyle is everything.

Developer tools in browsers can really give you all the necessary information. You need to be able to use them.
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Monitoring PostgreSQL + php-fpm + nginx + disk using Zabbix

Templates ESKD and GOST 7.32 for Lyx 1.6.x

Customize your Google