Repository: Polymer/vulcanize (js)

Issue:
Vulcanize is looking for scripts in the wrong place
I have a polymer element that includes a script, in my example it includes requirejs.

    <link rel="import" href="../polymer/polymer.html"/>
    <script src="../requirejs/require.js"></script>

With inlineScripts: true the vulcanize process now expects the require.js file relative to the location of the vulcanized file rather than the polymer file.

    ERROR finding resources/components/requirejs/require.js

I'm expecting the file to be somewhere else -> resources/external/bower/requirejs

This just showed up in 1.14.1.  We are looking into locking down our version to 1.14.0 to fix our build pipeline.



Pull request description:
Make sure scripts moved to body have the right path
Fixes #297

Patch:
diff --git a/lib/vulcan.js b/lib/vulcan.js
index 0e4f77b..7840893 100644
--- a/lib/vulcan.js
+++ b/lib/vulcan.js
@@ -241,15 +241,11 @@ Vulcan.prototype = {
           // only examine elements between this and the next import
           var start = flatHead.indexOf(thisImport) + 1;
           var end = flatHead.indexOf(importNodes[i + 1]);
-          if (end === -1) {
-            end = flatHead.length;
-          }
-          for (var headidx = start, el; headidx < end; headidx++) {
-            el = flatHead[headidx];
-            // if the element is a script, move it to bodyFragment
-            if (matchers.JS(el)) {
-              dom5.append(bodyFragment, el);
-            }
+          var container = this.findElementsToMoveToBody(flatHead, start, end);
+          // repath nodes moving to bodyFragment
+          if (container.childNodes.length) {
+            this.pathResolver.resolvePaths(container, tree.href, mainDocUrl);
+            dom5.append(bodyFragment, container);
           }
         }
       }
@@ -257,6 +253,25 @@ Vulcan.prototype = {
     return doc;
   },
 
+  /**
+   * Return a document fragment with elements that need to be moved to <body> to
+   * preserve order of execution of scripts
+   */
+  findElementsToMoveToBody: function(flatHead, startIndex, endIndex) {
+    if (endIndex === -1) {
+      endIndex = flatHead.length;
+    }
+    var container = dom5.constructors.fragment();
+    for (var headidx = startIndex, el; headidx < endIndex; headidx++) {
+      el = flatHead[headidx];
+      // if the element is a script, move it to bodyFragment
+      if (matchers.JS(el)) {
+        dom5.append(container, el);
+      }
+    }
+    return container;
+  },
+
   prepend: function prepend(parent, node) {
     if (parent.childNodes.length) {
       dom5.insertBefore(parent, parent.childNodes[0], node);


Test patch:
diff --git a/test/html/order/first-import.html b/test/html/order/first-import.html
index dc106e1..85980eb 100644
--- a/test/html/order/first-import.html
+++ b/test/html/order/first-import.html
@@ -1,3 +1,4 @@
-<script id="first-import-script">console.log('first-import-script')</script>
+<link rel="import" href="second-import.html">
+<script id="first-import-first-script" src="first-import/first-script.js"></script>
 <div></div>
-<script id="second-import-script">console.log('second-import-script')</script>
+<script id="first-import-second-script" src="first-import/second-script.js"></script>
diff --git a/test/html/order/first-import/first-script.js b/test/html/order/first-import/first-script.js
new file mode 100644
index 0000000..32aadde
--- /dev/null
+++ b/test/html/order/first-import/first-script.js
@@ -0,0 +1,1 @@
+console.log('first-import-first-script');
diff --git a/test/html/order/first-import/second-script.js b/test/html/order/first-import/second-script.js
new file mode 100644
index 0000000..675ec7d
--- /dev/null
+++ b/test/html/order/first-import/second-script.js
@@ -0,0 +1,1 @@
+console.log('first-import-second-script');
diff --git a/test/html/order/second-import.html b/test/html/order/second-import.html
new file mode 100644
index 0000000..6e55ec5
--- /dev/null
+++ b/test/html/order/second-import.html
@@ -0,0 +1,5 @@
+<script
+id="second-import-first-script" src="second-import/first-script.js"></script>
+<div></div>
+<script
+id="second-import-second-script" src="second-import/second-script.js"></script>
diff --git a/test/html/order/second-import/first-script.js b/test/html/order/second-import/first-script.js
new file mode 100644
index 0000000..ce33125
--- /dev/null
+++ b/test/html/order/second-import/first-script.js
@@ -0,0 +1,1 @@
+console.log('second-import-first-script');
diff --git a/test/html/order/second-import/second-script.js b/test/html/order/second-import/second-script.js
new file mode 100644
index 0000000..d0c1068
--- /dev/null
+++ b/test/html/order/second-import/second-script.js
@@ -0,0 +1,1 @@
+console.log('second-import-second-script');
diff --git a/test/test.js b/test/test.js
index 581a77c..a33a87a 100644
--- a/test/test.js
+++ b/test/test.js
@@ -384,24 +384,40 @@ suite('Vulcan', function() {
     });
 
     test('Imports and scripts are ordered correctly', function(done) {
-      var expected = [
+      var expectedOrder = [
         'first-script',
-        'first-import-script',
-        'second-import-script',
+        'second-import-first-script',
+        'second-import-second-script',
+        'first-import-first-script',
+        'first-import-second-script',
         'second-script',
         'third-script'
       ];
 
+      var expectedSrc = [
+        'order/first-script.js',
+        'order/second-import/first-script.js',
+        'order/second-import/second-script.js',
+        'order/first-import/first-script.js',
+        'order/first-import/second-script.js',
+        'order/second-script.js',
+        'order/third-script.js'
+      ];
+
       var scriptMatcher = preds.hasTagName('script');
 
       var callback = function(err, doc) {
         if (err) {
           return done(err);
         }
-        var scripts = dom5.queryAll(doc, scriptMatcher).map(function(s) {
-          return dom5.getAttribute(s, 'id');
+        var scripts = dom5.queryAll(doc, scriptMatcher);
+        var actualOrder = [], actualSrc = [];
+        scripts.forEach(function(s) {
+          actualOrder.push(dom5.getAttribute(s, 'id'));
+          actualSrc.push(dom5.getAttribute(s, 'src'));
         });
-        assert.deepEqual(scripts, expected);
+        assert.deepEqual(actualOrder, expectedOrder, 'order is not as expected');
+        assert.deepEqual(actualSrc, expectedSrc, 'srcs are not preserved correctly');
         done();
       };