Last modified: 2012-04-25 01:16:16 UTC
I am trying to build modular client-side code for my extension with ResourceLoader. When there were less chains of modules, I was able to sort out my JS prototypes. Now I am having trouble with many modules. An attempt of loading module causes the following error in Chrome console: Uncaught RangeError: Maximum call stack size exceeded without providing any info, which module causes it. No code line, no stack trace is available. Is it possible to maintain separate virtual call stack of module dependencies in ResourceLoader to limit the recursion in ResourceLoader gracefully with more explanative diagnostic message? I cannot even get with console.log() at the start of each module, it doesn't get there (RangeError happens before my console.log() prints). I hope to get advice from ResourceLoader / JS guru, if possible. Maybe the correct way to debug the dependence chains (I've checked them few times, yet the recursion is still infinite).
(In reply to comment #0) > module causes the following error in Chrome console: > > Uncaught RangeError: Maximum call stack size exceeded > > without providing any info, which module causes it. No code line, no stack > trace is available. What do you mean there is no info? In Chrome exceptions thrown always have the stack trace under the collapsible triangle and the file/line-number are available on the right hand side (clicking it will take you to the file and line position directly). If you go to the Scripts tab you can even pause it (click || twice to make it purple, which will make it pause on exceptions so that you can get to the problem line in context while it is executing). If all you can see is "load.php" and the file is unreadable, make sure you enable debug mode by either appending "debug=true" in the query parameter of the URL or by setting $wgResourceLoaderDebug = true;[1] on the server. -- Krinkle [1] [[mw:Manual:$wgResourceLoaderDebug]]
Of course I have $wgResourceLoaderDebug = true; in LocalSettings.php. There is no file / line number on right hand side in my case. I use Chrome debugger regularly and know where it should usually be displayed (I had enough of errors in my own code). You are right, there is a stack trace, however it has only: jQuery.extend.inArray recurse recurse recurse recurse recurse recurse recurse recurse recurse recurse recurse .... lots of times. I probably should check ResourceLoader client-side code and add console.log somewhere in it.
It is funny that latest Chrome does not provide the line but here at work really old IE8 did: LOG: start map.view LOG: start marker.view LOG: start common Out of stack space load.php?debug=true&lang=ru&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=20111213T184703Z, line 495 character 3 LOG: start map.view LOG: start marker.view LOG: start common Out of stack space load.php?debug=true&lang=ru&modules=jquery%2Cmediawiki&only=scripts&skin=vector&version=20111213T184703Z, line 9446 character 6 /** * Recursively resolves dependencies and detects circular references */ function recurse( module, resolved, unresolved ) { if ( registry[module] === undefined ) { throw new Error( 'Unknown dependency: ' + module ); } // Resolves dynamic loader function and replaces it with its own results if ( $.isFunction( registry[module].dependencies ) ) { registry[module].dependencies = registry[module].dependencies(); // Ensures the module's dependencies are always in an array if ( typeof registry[module].dependencies !== 'object' ) { registry[module].dependencies = [registry[module].dependencies]; } } // Tracks down dependencies for ( var n = 0; n < registry[module].dependencies.length; n++ ) { if ( $.inArray( registry[module].dependencies[n], resolved ) === -1 ) { if ( $.inArray( registry[module].dependencies[n], unresolved ) !== -1 ) { throw new Error( 'Circular reference detected: ' + module + ' -> ' + registry[module].dependencies[n] ); } recurse( registry[module].dependencies[n], resolved, unresolved ); } } resolved[resolved.length] = module; unresolved.splice( $.inArray( module, unresolved ), 1 ); } It is infinite recursion loop, just as I have thought. It should be possible to detect such rings and provide diagnostic message.
Created attachment 10390 [details] Detect zero length circular references of ResourceLoader dependencies 1.18wmf1 didn't check for trivial circular references (zero length of ring). Don't know whether that is fixed in the trunk. It is for 1.18wmf1. Sorry for not being able to provide patch to trunk, with current move to git it became a little bit more difficult to me. With this patch, I detected and fixed the circular reference in my PHP module definitions code immediately.
Thanks for the patch, Dmitriy! Sorry for the trouble -- please feel free to come into the #mediawiki IRC channel on Freenode anytime and ask for help with Git problems.
Thanks, Sumana! Contributing from depressive place in the poor country is not easy. I do not have enough of free time and not much of savings. Because of that, I have to save my time, so I rarely come to IRC. IRC is known to be a time-eater and time-waster. I prefer the mailing lists and boards. I hope I'll find some more time to develop my extensions further and also I'll consider moving from svn to git.
(In reply to comment #4) > Created attachment 10390 [details] > Detect zero length circular references of ResourceLoader dependencies > > 1.18wmf1 didn't check for trivial circular references (zero length of ring). > Don't know whether that is fixed in the trunk. > This is working for me in master. I made mediawiki.user depend on itself, and got a circular reference exception. We did refactor this code a bit recently (in 1.19wmf1 IIRC), so maybe that's what fixed it. Marking as FIXED because this isn't broken in master any more.