From f13dcfeb4648806e424e14be73cadf2d4848c2ca Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 19 Jun 2013 11:01:04 -0700 Subject: [PATCH 01/14] document.readyState on IE 10 is busted on 'interactive', remove check in boot Documentation of readyState issue: https://github.com/mobify/mobifyjs/issues/136 --- src/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot.js b/src/boot.js index 4468524..3ec4897 100644 --- a/src/boot.js +++ b/src/boot.js @@ -28,7 +28,7 @@ function bootstrap() { }); }; -if (document.readyState === 'complete' || document.readyState === 'interactive') { +if (document.readyState === 'complete') { bootstrap(); } else { window.addEventListener('DOMContentLoaded', bootstrap); From 2fc7081f47e489e6dc37d19f09a4da092e889e11 Mon Sep 17 00:00:00 2001 From: "Scott J. Miles" Date: Wed, 19 Jun 2013 14:00:08 -0700 Subject: [PATCH 02/14] export `path` in HTMLImports, revise sourceMap tagging for eval'd scripts --- src/HTMLImports.js | 3 ++- src/Parser.js | 37 ++++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 5c9c418..013cac8 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -393,9 +393,10 @@ var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); // exports +scope.path = path; scope.xhr = xhr; scope.importer = importer; scope.getDocumentUrl = path.getDocumentUrl; scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; -})(window.HTMLImports); +})(HTMLImports); diff --git a/src/Parser.js b/src/Parser.js index 07700df..0163ebc 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -50,10 +50,25 @@ var importParser = { }, parseScript: function(scriptElt) { if (needsMainDocumentContext(scriptElt)) { - // evaluate now - var code = scriptElt.__resource || scriptElt.textContent; + // acquire code to execute + var code = (scriptElt.__resource || scriptElt.textContent).trim(); if (code) { - code += "\n//# sourceURL=" + (scriptElt.__nodeUrl || ('inline' + '[' + Math.floor((Math.random()+1)*1000) + ']')) + "\n"; + // calculate source map hint + var moniker = scriptElt.__nodeUrl; + if (!moniker) { + var moniker = scope.path.documentUrlFromNode(scriptElt); + // there could be more than one script this url + var tag = '[' + Math.floor((Math.random()+1)*1000) + ']'; + // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow + // this sort of thing + var matches = code.match(/Polymer\(['"]([^'"]*)/); + tag = matches && matches[1] || tag; + // tag the moniker + moniker += '/' + tag + '.js'; + } + // source map hint + code += "\n//# sourceURL=" + moniker + "\n"; + // evaluate the code eval.call(window, code); } } @@ -62,9 +77,9 @@ var importParser = { var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); -function isDocumentLink(inElt) { - return inElt.localName === 'link' - && inElt.getAttribute('rel') === IMPORT_LINK_TYPE; +function isDocumentLink(elt) { + return elt.localName === 'link' + && elt.getAttribute('rel') === IMPORT_LINK_TYPE; } function needsMainDocumentContext(node) { @@ -74,14 +89,14 @@ function needsMainDocumentContext(node) { && !isElementElementChild(node); } -function inMainDocument(inElt) { - return inElt.ownerDocument === document || +function inMainDocument(elt) { + return elt.ownerDocument === document || // TODO(sjmiles): ShadowDOMPolyfill intrusion - inElt.ownerDocument.impl === document; + elt.ownerDocument.impl === document; } -function isElementElementChild(inElt) { - return inElt.parentNode && inElt.parentNode.localName === 'element'; +function isElementElementChild(elt) { + return elt.parentNode && elt.parentNode.localName === 'element'; } // exports From 6f66a00ba6f02970d07c9deee922fa071307621d Mon Sep 17 00:00:00 2001 From: Yvonne Yip Date: Thu, 20 Jun 2013 15:06:49 -0700 Subject: [PATCH 03/14] test: update karma config --- conf/karma.conf.js | 170 ++++++++++++++++++++++----------------------- gruntfile.js | 2 +- package.json | 2 +- 3 files changed, 85 insertions(+), 89 deletions(-) diff --git a/conf/karma.conf.js b/conf/karma.conf.js index a204c98..8cdb5af 100644 --- a/conf/karma.conf.js +++ b/conf/karma.conf.js @@ -1,88 +1,84 @@ -// Sample Karma configuration file, that contain pretty much all the available options -// It's used for running client tests on Travis (http://travis-ci.org/#!/karma-runner/karma) -// Most of the options can be overriden by cli arguments (see karma --help) -// -// For all available config options and default values, see: -// https://github.com/karma-runner/karma/blob/stable/lib/config.js#L54 - - -// base path, that will be used to resolve files and exclude -basePath = '../'; - -// list of files / patterns to load in the browser -files = [ - 'tools/test/mocha-htmltest.js', - 'conf/mocha.conf.js', - 'node_modules/chai/chai.js', - 'test/js/*.js', - 'html-imports.js', - {pattern: 'tools/**/*.js', included: false}, - {pattern: 'src/*', included: false}, - {pattern: 'test/**/*', included: false} -]; - -// list of files to exclude -exclude = []; - -frameworks = ['mocha']; - -// use dots reporter, as travis terminal does not support escaping sequences -// possible values: 'dots', 'progress', 'junit', 'teamcity' -// CLI --reporters progress -reporters = ['progress']; - -// web server port -// CLI --port 9876 -port = 9876; - -// cli runner port -// CLI --runner-port 9100 -runnerPort = 9100; - -// enable / disable colors in the output (reporters and logs) -// CLI --colors --no-colors -colors = true; - -// level of logging -// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG -// CLI --log-level debug -logLevel = LOG_INFO; - -// enable / disable watching file and executing tests whenever any file changes -// CLI --auto-watch --no-auto-watch -autoWatch = true; - -// Start these browsers, currently available: -// - Chrome -// - ChromeCanary -// - Firefox -// - Opera -// - Safari (only Mac) -// - PhantomJS -// - IE (only Windows) -// CLI --browsers Chrome,Firefox,Safari -browsers = ['ChromeCanary']; - -// If browser does not capture in given timeout [ms], kill it -// CLI --capture-timeout 5000 -captureTimeout = 50000; - -// Auto run tests on start (when browsers are captured) and exit -// CLI --single-run --no-single-run -singleRun = true; - -// report which specs are slower than 500ms -// CLI --report-slower-than 500 -reportSlowerThan = 500; - -// compile coffee scripts -preprocessors = { +module.exports = function(karma) { + karma.configure({ + // base path, that will be used to resolve files and exclude + basePath: '../', + + // list of files / patterns to load in the browser + files: [ + 'tools/test/mocha-htmltest.js', + 'conf/mocha.conf.js', + 'node_modules/chai/chai.js', + 'test/js/*.js', + 'html-imports.js', + {pattern: 'tools/**/*.js', included: false}, + {pattern: 'src/*', included: false}, + {pattern: 'test/**/*', included: false} + ], + + // list of files to exclude + exclude: [], + + frameworks: ['mocha'], + + // use dots reporter, as travis terminal does not support escaping sequences + // possible values: 'dots', 'progress', 'junit', 'teamcity' + // CLI --reporters progress + reporters: ['progress'], + + // web server port + // CLI --port 9876 + port: 9876, + + // cli runner port + // CLI --runner-port 9100 + runnerPort: 9100, + + // enable / disable colors in the output (reporters and logs) + // CLI --colors --no-colors + colors: true, + + // level of logging + // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG + // CLI --log-level debug + logLevel: LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + // CLI --auto-watch --no-auto-watch + autoWatch: true, + + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + // CLI --browsers Chrome,Firefox,Safari + browsers: ['ChromeCanary'], + + // If browser does not capture in given timeout [ms], kill it + // CLI --capture-timeout 5000 + captureTimeout: 50000, + + // Auto run tests on start (when browsers are captured) and exit + // CLI --single-run --no-single-run + singleRun: true, + + // report which specs are slower than 500ms + // CLI --report-slower-than 500 + reportSlowerThan: 500, + + // compile coffee scripts + preprocessors: { + }, + + plugins: [ + 'karma-mocha', + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-script-launcher', + 'karma-crbot-reporter' + ] + }); }; - -plugins = [ - 'karma-mocha', - 'karma-chrome-launcher', - 'karma-firefox-launcher', - 'karma-script-launcher', - 'karma-crbot-reporter' -] diff --git a/gruntfile.js b/gruntfile.js index 45668fa..ca0ef4f 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -76,7 +76,7 @@ module.exports = function(grunt) { // plugins grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-yuidoc'); - grunt.loadNpmTasks('grunt-karma-0.9.1'); + grunt.loadNpmTasks('grunt-karma'); // tasks grunt.registerTask('default', ['uglify']); diff --git a/package.json b/package.json index 6a523d4..6240e88 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "grunt": "*", "grunt-contrib-uglify": "*", "grunt-contrib-yuidoc": "~0.4.0", - "grunt-karma-0.9.1": "~0.4.3", + "grunt-karma": "~0.5.0", "karma-mocha": "*", "karma-script-launcher": "*", "karma-crbot-reporter": "*" From e60d55770dbb59cacd2dcc914b937e3d5cd6e585 Mon Sep 17 00:00:00 2001 From: "Scott J. Miles" Date: Mon, 24 Jun 2013 00:51:36 -0600 Subject: [PATCH 04/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 17f5cb0..f8e661d 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Use the minified version (`html-imports.min.js`) if you need to load the file dy In imported documents, `href` and `src` attributes in HTML, and `url` properties in CSS files, are relative to the location of the imported document, not the main document. -The HTML Imports polyfill begins processing link tags when the `window.load` event fires. To know when loading is complete, listen for the `HTMLImportsLoaded` event on `document` or `window`. +The HTML Imports polyfill begins processing link tags when the `DOMContentLoaded` event fires. To know when loading is complete, listen for the `HTMLImportsLoaded` event on `document` or `window`. Example: From 1d58da61c00e511dbb0233accb9b252b0e127ce2 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Fri, 28 Jun 2013 11:33:18 -0700 Subject: [PATCH 05/14] correct scope function argument. --- src/HTMLImports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 013cac8..4bfac91 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -399,4 +399,4 @@ scope.importer = importer; scope.getDocumentUrl = path.getDocumentUrl; scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; -})(HTMLImports); +})(window.HTMLImports); From 2806add1a128f3b5ce91ff447642cce0b7e2cbb2 Mon Sep 17 00:00:00 2001 From: Arron Schaar Date: Fri, 28 Jun 2013 15:43:50 -0700 Subject: [PATCH 06/14] make script execution specific to js --- src/HTMLImports.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 4bfac91..637aefc 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -43,7 +43,9 @@ var importer = { 'link[rel=' + IMPORT_LINK_TYPE + ']', 'element link[rel=' + STYLE_LINK_TYPE + ']', 'template', - 'script[src]' + 'script[src]', + 'script:not([type])', + 'script[type="text/javascript"]' ].join(','), loader: function(inNext) { // construct a loader instance @@ -82,10 +84,10 @@ var importer = { nodes = Array.prototype.filter.call(nodes, function(n) { if (n.localName === 'template') { if (n.content) { - var l$ = n.content.querySelectorAll('link[rel=' + STYLE_LINK_TYPE + + var l$ = n.content.querySelectorAll('link[rel=' + STYLE_LINK_TYPE + ']'); if (l$.length) { - extra = extra.concat(Array.prototype.slice.call(l$, 0)); + extra = extra.concat(Array.prototype.slice.call(l$, 0)); } } return false; From 0f35bd21fab3e0e9b99b525581d1135f27787dd1 Mon Sep 17 00:00:00 2001 From: secretrobotron Date: Sat, 29 Jun 2013 23:21:38 -0300 Subject: [PATCH 07/14] block obviously non-js script tags from being parsed --- src/Parser.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Parser.js b/src/Parser.js index 0163ebc..2f00e05 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -15,7 +15,8 @@ var importParser = { 'link[rel=' + IMPORT_LINK_TYPE + ']', 'link[rel=stylesheet]', 'style', - 'script' + 'script:not([type])', + 'script[type="text/javascript"]' ], map: { link: 'parseLink', From 7b6d21c17913829427cd460777886599655ccd1f Mon Sep 17 00:00:00 2001 From: secretrobotron Date: Sat, 29 Jun 2013 23:34:37 -0300 Subject: [PATCH 08/14] more specific preloader selectors for script tags that actually have a src attribute --- src/HTMLImports.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 637aefc..408c125 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -43,9 +43,8 @@ var importer = { 'link[rel=' + IMPORT_LINK_TYPE + ']', 'element link[rel=' + STYLE_LINK_TYPE + ']', 'template', - 'script[src]', - 'script:not([type])', - 'script[type="text/javascript"]' + 'script[src]:not([type])', + 'script[src][type="text/javascript"]' ].join(','), loader: function(inNext) { // construct a loader instance From c11b6169bffd6eaceb2dec36fd77b546f8ab4a3e Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 3 Jul 2013 12:11:38 -0700 Subject: [PATCH 09/14] Fixes #22 --- src/HTMLImports.js | 27 ++++++++++++++++++-------- test/html/imports/template-import.html | 5 +++++ test/html/template-script.html | 23 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 test/html/imports/template-import.html create mode 100644 test/html/template-script.html diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 408c125..44896df 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -106,7 +106,7 @@ var importer = { // generate an HTMLDocument from data document = makeDocument(resource, url); // resolve resource paths relative to host document - path.resolvePathsInHTML(document.body); + path.resolvePathsInHTML(document); // cache document importer.documents[url] = document; // add nodes from this document to the loader queue @@ -148,17 +148,20 @@ function isScript(elt) { return elt.localName === 'script'; } -function makeDocument(inHTML, inUrl) { +function makeDocument(resource, url) { // create a new HTML document - var doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE); + var doc = resource; + if (!doc instanceof Document) { + doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE); + // install html + doc.body.innerHTML = resource; + } // cache the new document's source url - doc._URL = inUrl; + doc._URL = url; // establish a relative path via var base = doc.createElement('base'); base.setAttribute('href', document.baseURI); doc.head.appendChild(base); - // install html - doc.body.innerHTML = inHTML; // TODO(sorvell): MDV Polyfill intrusion: boostrap template polyfill if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) { HTMLTemplateElement.bootstrap(doc); @@ -219,7 +222,11 @@ Loader.prototype = { var receiveXhr = function(err, resource) { this.receive(url, elt, err, resource); }.bind(this); - xhr.load(url, receiveXhr); + if (isDocumentLink(elt)) { + xhr.loadDocument(url, receiveXhr); + } else { + xhr.load(url, receiveXhr); + } }, receive: function(inUrl, inElt, inErr, inResource) { if (!inErr) { @@ -256,7 +263,7 @@ var path = { return inNode.getAttribute("href") || inNode.getAttribute("src"); }, documentUrlFromNode: function(inNode) { - return path.getDocumentUrl(inNode.ownerDocument); + return path.getDocumentUrl(inNode.ownerDocument || inNode); }, getDocumentUrl: function(inDocument) { var url = inDocument && @@ -387,6 +394,10 @@ xhr = xhr || { } }); request.send(); + return request; + }, + loadDocument: function(url, next, nextContext) { + this.load(url, next, nextContext).responseType = 'document'; } }; diff --git a/test/html/imports/template-import.html b/test/html/imports/template-import.html new file mode 100644 index 0000000..9f34e4e --- /dev/null +++ b/test/html/imports/template-import.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/test/html/template-script.html b/test/html/template-script.html new file mode 100644 index 0000000..cbb7954 --- /dev/null +++ b/test/html/template-script.html @@ -0,0 +1,23 @@ + + + + template script test + + + + + + + + + From e521926d9803eac7014d8fca143cb4e5bf3dc635 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 3 Jul 2013 12:14:50 -0700 Subject: [PATCH 10/14] include template script test --- test/js/tests.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/js/tests.js b/test/js/tests.js index b216a89..081daa7 100644 --- a/test/js/tests.js +++ b/test/js/tests.js @@ -8,4 +8,5 @@ htmlSuite('HTMLImports', function() { htmlTest('html/HTMLImports.html'); htmlTest('html/parser.html'); htmlTest('html/style-links.html'); + htmlTest('html/template-script.html'); }); From fb2e4c25242cdbdc71ef4687e27799226f88cbfc Mon Sep 17 00:00:00 2001 From: Yvonne Yip Date: Wed, 3 Jul 2013 15:36:15 -0700 Subject: [PATCH 11/14] instanceof has lower precedence than ! --- src/HTMLImports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index 44896df..ae9bab9 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -151,7 +151,7 @@ function isScript(elt) { function makeDocument(resource, url) { // create a new HTML document var doc = resource; - if (!doc instanceof Document) { + if (!(doc instanceof Document)) { doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE); // install html doc.body.innerHTML = resource; From 5dff179ae10f01981e210114f75356b037f6dd8a Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 3 Jul 2013 15:42:53 -0700 Subject: [PATCH 12/14] remove test that fails on FF. Scripts from imports do not execute on FF due to https://www.w3.org/Bugs/Public/show_bug.cgi?id=11323 --- test/js/tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/js/tests.js b/test/js/tests.js index 081daa7..b216a89 100644 --- a/test/js/tests.js +++ b/test/js/tests.js @@ -8,5 +8,4 @@ htmlSuite('HTMLImports', function() { htmlTest('html/HTMLImports.html'); htmlTest('html/parser.html'); htmlTest('html/style-links.html'); - htmlTest('html/template-script.html'); }); From c0811c7c876455dd63c948cf56d4fc4902dd38f6 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 3 Jul 2013 17:16:22 -0700 Subject: [PATCH 13/14] Reverted fix for #22, blocked on https://code.google.com/p/chromium/issues/detail?id=257221 --- src/HTMLImports.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/HTMLImports.js b/src/HTMLImports.js index ae9bab9..db0239d 100644 --- a/src/HTMLImports.js +++ b/src/HTMLImports.js @@ -222,11 +222,20 @@ Loader.prototype = { var receiveXhr = function(err, resource) { this.receive(url, elt, err, resource); }.bind(this); + xhr.load(url, receiveXhr); + // TODO(sorvell): blocked on + // https://code.google.com/p/chromium/issues/detail?id=257221 + // xhr'ing for a document makes scripts in imports runnable; otherwise + // they are not; however, it requires that we have doctype=html in + // the import which is unacceptable. This is only needed on Chrome + // to avoid the bug above. + /* if (isDocumentLink(elt)) { xhr.loadDocument(url, receiveXhr); } else { xhr.load(url, receiveXhr); } + */ }, receive: function(inUrl, inElt, inErr, inResource) { if (!inErr) { From 69e86c01bde0e88e2a9d85fd5dec01f454edaf55 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 3 Jul 2013 13:06:33 -0700 Subject: [PATCH 14/14] create build manifest --- build.json | 5 +++++ gruntfile.js | 9 +++------ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 build.json diff --git a/build.json b/build.json new file mode 100644 index 0000000..d957ebb --- /dev/null +++ b/build.json @@ -0,0 +1,5 @@ +[ + "src/Parser.js", + "src/HTMLImports.js", + "src/boot.js" +] diff --git a/gruntfile.js b/gruntfile.js index ca0ef4f..f1e9236 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -4,9 +4,7 @@ * license that can be found in the LICENSE file. */ module.exports = function(grunt) { - HTMLComponents = [ - 'src/HTMLImports.js' - ]; + HTMLComponents = grunt.file.readJSON('build.json'); // karma setup var browsers; (function() { @@ -44,11 +42,10 @@ module.exports = function(grunt) { }, uglify: { HTMLComponents: { - /* options: { - sourceMap: 'html-components.min.source-map.js' + sourceMap: 'html-components.min.source-map.js', + banner: grunt.file.read('LICENSE') }, - */ files: { 'html-imports.min.js': HTMLComponents }