Re: [whatwg] defer on style, depends

2009-02-15 Thread Garrett Smith
On Fri, Feb 13, 2009 at 12:34 AM, Ian Hickson i...@hixie.ch wrote:

 On Mon, 9 Feb 2009, Boris Zbarsky wrote:
 Ian Hickson wrote:
  I'm not convinced either of these are really great solutions. I think it'd
  be better just to have the script itself only block when it hits
  CSS-dependent APIs (though I recognise that that is a much harder problem 
  in
  most rendering engines today).

 I'm not sure how you envision this working.  The run-to-completion
 semantics mean that while the script is working on the API call to
 return (which means that network events are being processed, etc), the
 following invariants need to be maintained (list very much not
 exhaustive):

 1)  No setTimeout timers fire.
 2)  No XMLHttpRequest state changes happen.
 3)  No image load events fire.
 4)  No stylesheet load events fire (for UAs that implement such an
 event on their link elements, as Gecko would like to do).
 5)  No user interaction with the page or other pages that can reach the
 given page is allowed.

 #5 makes it unlikely that a UA would want to go this route at all.  #4
 means that this approach would be incompatible with reasonable style
 load events... #1, #2, #3 all mean that networking needs to
 differentiate between the set of stylesheets we're waiting on and
 everything else.

 Yeah, fair enough.

 By the way, the spec doesn't yet require the blocking behavior. I couldn't
 work out how to do it. Could you elaborate on when exactly in the process
 the style sheet is waited on? Does it happen for all scripts? For example,
 if a script inserts a style sheet and then a script, does that script wait
 for the style sheet to load?


 On Mon, 9 Feb 2009, Garrett Smith wrote:

 If I put the script at the bottom of the page, and a linked stylesheet
 in the head, the script waits for the stylesheet.

 I want my page to load faster and this feature prevents it.

 Put the script in the head before the style sheet and use the defer
 attribute so that it runs the script as if it was at the end of the page.


  It seems pretty simple to me; if you want the style to be loaded when
  the script runs, put the style first. If you don't, put the script
  first and defer it (or mark it async). Why should this not be enough?

 The implementation might delayed the page from rendering when it sees
 the stylesheet.

 That's unrelated to scripts, though, right?

 If you don't want the script to block page load, then speak to your
 browser vendor. The spec doesn't require that.


 The script's defer attribute does not work in a majority of
 implementations. For such browsers, it makes sense to put the script
 lower on the page for performance reasons, not before the linked
 stylesheets. Moving the deferred script from the bottom of the page to
 the head, just before the stylesheet would mean that those scripts would
 load first. This would prevent the page content from loading until those
 scripts had loaded. This would hurt performance in the majority of
 browsers in use today.

 Sure, but then the feature you describe doesn't work in today's browsers
 either, so that seems like a wash.


 On Mon, 9 Feb 2009, Garrett Smith wrote:

 There are two/three issues.
 1) want to load stylesheets without having scripts block

 Put the scripts first.


Then the scripts block. I explained this and showed this in examples.

If the script is deferred, it will wait for the stylesheet.

 2) want to load stylesheets later, (infoPanel example)

 Put the styles later.

The script blocks the stylesheet.

 3) (2), but want to make sure the stylesheet is loaded before the script 
 runs.

 Put the styles first.

The stylesheet can be placed right before the script which depends on
it, right before closing body tag:

http://dhtmlkitchen.com/jstest/block/link-script-bottom.html

and the result will work in Firefox. However, that does not works
consistently in a wide enough range of current browsers. Particularly,
Webkit and Opera will alert('loaded') before getting the stylesheet.


 Example 1:
 headtitle/title
 link independent type=text/css  ...
 script.../script
 I want the browser to:
 1) load my stylesheet and then immediately begin to load script in parallel.

 Put the script first with a defer or async attribute.


I have already explained why this is going to make the page
functionally inconsistent and hard to maintain across a set of
browsers where some browsers have support for defer and others do not.

The deferred alert external script will run first in  browsers that
ignore defer. In browsers that do not ignore defer, (Firefox 3.1 pre)
it will run last, after the stylesheet is loaded. Boris explained that
current Gecko behavior is that any stylesheet load started by parsing
a style or link tag will increment a counter on the script loader
object for that document.

This also explains why putting deferred scripts first will hurt
performance in both cases.

Putting deferred scripts first is a really bad idea.


 Example 2
 

Re: [whatwg] defer on style, depends

2009-02-15 Thread Boris Zbarsky

Garrett Smith wrote:

Because you have scripts after your stylesheets, not just stylesheets.
 Really, controlled experiments are hard.  You have to hold all but one
variable constant.


OK, I modified the example:

http://localhost/jstest/block/link-img-noscript.html

The bottom script will not load ('load' as opposed to 'run') in
Firefox/3.0.6 until after 5 seconds.


Right.  Because you still have another script before it.


The result shows that example.js loads 5 seconds after the initial
page load. example.js waits for the stylesheet to load.


It waits for the first script to execute, which waits for the stylesheet 
to load.  That's not quite the same thing.



My concern is with the recomputation you mentioned. Can you elaborate
on that, or point me to a webpage that explains it?


Well, once a new stylesheet loads you have to redo rule matching for all 
nodes that might be affected in the document.  In practice, I believe 
current UAs will rerun the rule matching algorithm on all nodes in the 
document.



Question: What does IE do?


That's a really good question.  I don't have IE on hand to test with; do 
you?



Well, one option is to stop worrying about micromanaging the load order and
assume that speculative parsing will solve your problems will it?


Possibly. If the author could declare what a script depends on and let
the implementation determine what to load and when, would that be too
complicated?


Too complicated for whom?  The author or the implementation?

-Boris


Re: [whatwg] defer on style, depends

2009-02-15 Thread Boris Zbarsky

Ian Hickson wrote:

On Fri, 13 Feb 2009, Boris Zbarsky wrote:

The current Gecko behavior is that any stylesheet load started by parsing a
style or link tag will increment a counter on the document (well, on a
per-document script loader object, to be more precise). Completion of the load
will decrement the counter.  While the counter is nonzero, script execution
is blocked.  When it goes back to 0, the first pending script (if any) is run.
If this increments the counter again, no more scripts are run until the count
goes to 0 again.

So it doesn't matter how the script is created/inserted, but the only
stylesheets that block scripts are ones that the parser knows about.  So only
the ones present in the original source or added via document.write.  If you
createElement a link and insert it into the DOM, it won't block script
execution.  Also, link elements pointing to alternate style sheets don't
block script execution.


So in this:

   !DOCTYPE html
   ...
   script
document.write('link rel=stylesheet href=style');
document.write('scripta();\/script');
b();
   /script

...is the script paused after the second document.write() call, before a() 
and b() execute?


No.  What's paused is execution of new scripts, not of existing ones. 
So in this case, b() executes immediately, while a() executes after the 
stylesheet loads.


Here's a simple testcase to demonstrate that:

   !DOCTYPE html
   script
var res = ;
document.write('link rel=stylesheet href=data:text/css,');
document.write('scriptres+=a\/script');
res+=b;
   /script
   body onload=alert(res)/body

I realize that this does mean that the execution order of a() and b() is 
different if the link is written out as above


-Boris


Re: [whatwg] defer on style, depends

2009-02-15 Thread Garrett Smith
On Sun, Feb 15, 2009 at 9:54 AM, Boris Zbarsky bzbar...@mit.edu wrote:
 Garrett Smith wrote:

 Because you have scripts after your stylesheets, not just stylesheets.
  Really, controlled experiments are hard.  You have to hold all but one
 variable constant.

 OK, I modified the example:

 http://localhost/jstest/block/link-img-noscript.html

 The bottom script will not load ('load' as opposed to 'run') in
 Firefox/3.0.6 until after 5 seconds.

 Right.  Because you still have another script before it.


Yes, you are correct. It is the script that blocks the external script
from being requested; not the stylesheet. This has been changed in
3.1pre.

 The result shows that example.js loads 5 seconds after the initial
 page load. example.js waits for the stylesheet to load.

 It waits for the first script to execute, which waits for the stylesheet to
 load.  That's not quite the same thing.


Yes, thank you.

 My concern is with the recomputation you mentioned. Can you elaborate
 on that, or point me to a webpage that explains it?

 Well, once a new stylesheet loads you have to redo rule matching for all
 nodes that might be affected in the document.  In practice, I believe
 current UAs will rerun the rule matching algorithm on all nodes in the
 document.


I can see why rule matching would happen for all nodes in the document.

On what occasion(s) do(es) that algorithm run?

Aside: Could the CSS have a selector applied to it for sub-matches?
e.g. First find nodes in the document that match a selector value,
then match stylesheets rules that match the subset. So instead of:

.infoPanel table { }
.infoPanel table tr { }

it would be (pseudocode):
.infoPanel {
table {}
tr {}
}

Could such a strategy for rule-matching help performance, or would it
hinder performance or be too much work to maintain?

I know it is off topic, but the effect of rule matching would hurt performance.

 Question: What does IE do?

 That's a really good question.  I don't have IE on hand to test with; do
 you?


LOL. No, I have only my mac at home. I need a new laptop with windows.
Does anyone reading have windows?

 Well, one option is to stop worrying about micromanaging the load order
 and
 assume that speculative parsing will solve your problems will it?

 Possibly. If the author could declare what a script depends on and let
 the implementation determine what to load and when, would that be too
 complicated?

 Too complicated for whom?  The author or the implementation?


I see a few edge cases. For example:
  A script depends on something that is never loaded.
  A script depends on something that is added to the document later.
  A script depends on an alternate stylesheet.

Reading script depends=a.../script seems clear to me. Then
again, I stole the idea from ANT.

For the implementation, I do not actually know because I have not
worked on that code. What are your thoughts?

 -Boris


Garrett


Re: [whatwg] defer on style, depends

2009-02-15 Thread Boris Zbarsky

Garrett Smith wrote:

I can see why rule matching would happen for all nodes in the document.

On what occasion(s) do(es) that algorithm run?


Depends on the UA, probably.

For Gecko in particular, any time a stylesheet is added to or removed 
from the document, any time a rule is added to or removed from a 
stylesheet via the CSSOM, and any time a rule is changed via the CSSOM. 
 The one exception is inline style; changing that only performs style 
recomputation (which includes selector matching) on the subtree rooted 
at the node whose inline style has changed.


In general, the whole setup in Gecko is optimized around changes to 
nodes being common and changes to stylesheets being rare.


So far this is a good working assumption; if that ever changes we'll 
look into optimizing changes to stylesheets more.



Could such a strategy for rule-matching help performance, or would it
hinder performance or be too much work to maintain?


To a first approximation it'd have no effect on performance.


Too complicated for whom?  The author or the implementation?


For the implementation, I do not actually know because I have not
worked on that code. What are your thoughts?


I haven't thought about this enough to have any useful ones yet.

-Boris