← Back to team overview

launchpad-dev team mailing list archive

Re: YUI "issue" under Windmill

 

On 11/15/2010 06:39 PM, Maris Fogels wrote:
> On 11/13/2010 10:10 AM, Paul Hummer wrote:
>> On 11/13/2010 06:42 AM, Ian Booth wrote:
>>> Hi
>>>
>>> Well, not really an issue but a problem I had getting stuff to work. I 
>>> recently wrote some YUI javascript and it all worked fine when running 
>>> Launchpad but the Windmill tests would fail. But the failure was 
>>> intermittent. Since everything worked outside Windmill (and sometimes
>>> under Windmill too)  I really struggled to find out what was wrong. But I
>>> think I finally found what I needed to do to fix it.
>>>
>>> My javascript was written to be executed onload so I added some stuff to 
>>> base-layout-macros.pt:
>>>
>>> <script id="base-layout-load-scripts" type="text/javascript"> 
>>> LPS.use('lp.app.links', function(Y) { Y.on('load', function(e) { 
>>> Y.lp.app.links.check_valid_lp_links(); }, window); }); </script>
>> It's probably better for you if you structure this code like this:
>>
>> LPS.use('lp.app.links', function(Y) { Y.config.win.on('domready',
>> function(e) { Y.lp.app.links.check_valid_lp_links(); }); });
>>
>> We shouldn't be referencing window or document in our code.  We should be 
>> using Y.config.win and Y.config.doc.
>>
> I have not seen the domready hook written this way before.  Is it new since
> YUI 3.2?
>
> It was my understanding that Y.on('load') and Y.on('domready') did everything to
> hook the events up for you, so you do not have to touch the Window or Document
> objects yourself.  (Doing it yourself is also more typing :)

Yeah, I've generally been trying to stay away from doing Y.on.  In this
case it probably doesn't matter, but it's a habit I've gotten into for
everything, so it's how I wrote it here.  It's preferable to do your
event bindings on the node or nodelist (be careful here) in general.

>>> My javascript was like so:
>>>
>>> YUI.add('lp.app.links', function(Y) {
>>>
>>> Y.lp.app.links.check_valid_lp_links = function() { //code here }; },
>>> "0.1", {"requires": [ "base", "node", "io", "dom", "json" ]});
>>>
>>> Can anyone see what makes the above fail under Windmill but work fine
>>> every time when running Launchpad? By fail, I mean that what happens is
>>> that the call to check_valid_lp_links() in the onload just never happens.
>>>
>>> Well, in case anyone else is new to YUI like me, I had to add this line of 
>>> code to the top of the javascript:
>>>
>>> var namespace = Y.namespace('lp.app.links');
>>>
>>> Or at least doing the above made the Windmill tests run reliably every
>>> time I subsequently ran them.
>>>
>>> Why? Nothing in the javascript uses the namespace variable at all. It's as 
>>> if the Y.namespace('lp.app.links') call has some magic side effect that 
>>> Makes Stuff Work (tm).
>>>
>>> Can someone enlighten me? I wasted far too much time trying to track this 
>>> down and would like to know the answer.
>> Y.namespace indeed does some (kinda icky) magic for namespacing.  I'm 
>> starting to wonder if we really need to namespace as much as we are. There's 
>> a pretty large performance hit to it, and as long as we don't YUI.use('*')
>> or something, we should be okay with a more relaxed namespacing.  If we
>> didn't use periods as our namespacing character, we wouldn't need it at all.
> The namespacing was a decision we made two years ago when we first started
> writing JavaScript, and we did not know how much JavaScript we would end up with.

Yeah, we've done the best we can up until this point, and I think it's
important that we continue to improve.  As I recall, I proposed we made
the namespacing deeper, and based on the lp.<app> pattern, which I now
realize probably wasn't the greatest idea.  What I fear is that we'll
just continue to c-n-p code that we were only 28% sure of in the first
place.  :)

> We thought we were at risk of pulling from two apps on the same page, or
> silently stomping on another app's functions.  For example, merge proposals and
> bugs might both define a Y.add_comment() function - woe to the one who
> accidentally pulls both modules onto the same page.  Setting the public API as
> Y.bugs.add_comment() and Y.code.add_comment() keeps things safe.
>
> The assumption was that *simple* namespacing is inexpensive, difficult to add
> later, and will save you at least one late-night hair-pulling debug session.

Yeah, this is a lie.  Namespacing in javascript is a lie in general,
because ECMAScript keeps a scope chain, not a namespace.  The more
periods you have in your variable, the slower the access is going to be,
and so our "namespacing" is actually causing things to be slower
(although it's probably not the immediate performance focus).

> Now that our JavaScript code base has settled, we can ask if namespace clashes
> have been a practical problem or concern for us.  If not, then go for it, and
> pull everything down to Y.  We can always keep namespaces around to be applied
> on an as-needed basis.
>
> I am surprised to hear that Y.namespace() has expensive magic behind it.  I
> expected it to use simple, presumably fast, object literal creation and
> attribute lookups.  Two years ago (when we started writing this stuff) building
> a namespace system was tedious boilerplate, nothing more.  YUI's namespacing was
> as good or better than most others.

It's not Y.namespace that has any "magic" per se, but rather the way
javascript keeps track of scope.

Cheers,
Paul



Follow ups

References