Stylesheets and scripts behave differently when dynamically included in Combinator: dynamically generated script inclusions move to bottom

Topics: Core, Writing modules
Developer
Nov 21, 2012 at 9:10 PM

When you exclude a resource in Combinator it will be inserted among the bundled resources' links, e.g.:

<link href="/Media/Default/Combinator/Styles/-388152671-1.css?timestamp=129980049677367943" rel="stylesheet" type="text/css" />
<link href="/Themes/Piedone.PrettyGoodBaseTheme/Styles/Structure.css" rel="stylesheet" type="text/css" />
<link href="/Media/Default/Combinator/Styles/-388152671-3.css?timestamp=129980049678688018" rel="stylesheet" type="text/css" />
<link href="/Themes/OrchardHUN.Theme/Styles/Site.css" rel="stylesheet" type="text/css" />

Combinator's IResourceManager implementation's BuildRequiredResources() just outputs the list of resources, among them the ones linked to a bundle and ones linked to the original resource.

The same doesn't work for script's, however. There, although the mixed list of excluded scripts and bundles contains the resource objects in order (output from BuildRequiredResources()) too, original resources go to the top:

<script src="/Modules/Heikura.SyntaxHighlighter/Scripts/shAutoloader.js" type="text/javascript"></script>
<script src="/Themes/OrchardHUN.Theme/Scripts/NavigationFix.js" type="text/javascript"></script>
<meta content="Orchard" name="generator" />
<link href="/Themes/OrchardHUN.Theme/Images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<script src="/Media/Default/Combinator/Scripts/489417834-1.js?timestamp=129980049687388516" type="text/javascript"></script>
<script src="/Media/Default/Combinator/Scripts/489417834-3.js?timestamp=129980049688898602" type="text/javascript"></script>

(shAutoloader should be the second, Navigationfix the last resource)

I've discovered that the in the end the difference between how the bundles and original scripts are handled goes down to CoreShapes. What happens there for a bundle:

  1. Display.Script() is called on ln 395.
  2. Script() shape method is called on ln 344.
  3. ResourceManager.WriteResource() is called. The passed TextWriter object is empty first and in the method it's filled with just the code of the script tag ().
  4. The "result" variable on ln 400 contains the script tag.

What happens for scripts with the original urls:

  1. Display.Script() is called on ln 395.
  2. Script() shape method is NOT called.
  3. ResourceManager.WriteResource() is called. The passed TextWriter object contains the beginning of the html document (everything before the above script list) and the script tag is concatenated to it (that's how these scripts get to the top).
  4. The "result" variable on ln 400 is null.

The problem is I can't track the call chain because when Display.Script() is invoked Clay objects do something but you can't break into Clay behaviours. So I don't know what happens between step 2 and 3 so I also can't discover what the difference between the two kind of resources are that causes them to be handled differently.

I would very much appreciate any hints.

Developer
Nov 21, 2012 at 10:29 PM
Edited Nov 21, 2012 at 10:31 PM

I've found the difference in the execution path, but still not the solution: original scripts go through StaticFileBindingStrategy (what's BTW in StylesheetBindingStrategy.cs what's a bit misleading) while bundled ones through ShapeAttributeBindingStrategy. As the same is for stylesheets I don't know why they keep their order while scripts don't.

Developer
Nov 21, 2012 at 10:53 PM

I may have found what causes the difference: since the Script and Style shape methods' signature differs ResourceManager.WriteResource() is called with the same TextWriter instance with stylesheets and a different one for scripts (actually original scripts are called with the instance used by stylesheets, that's why they're are written where styles end).

When I change the Script shape's signature to the same one as Style's the correct order is kept, but they differ because of a reason.

Developer
Nov 22, 2012 at 12:01 AM

All right, so the solution apparently is to remove the shapes of the original resources from the current shape table.