From d7b5141a1ad55a2b9563c74a3ff4ebace263cea1 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 6 Mar 2017 14:08:54 -0800 Subject: [PATCH] Make sure ce-es5 bundle fires WebComponentsReady Don't rely on HTMLImports Also, minify bundles with babili --- entrypoints/webcomponents-ce-es5-index.js | 5 +- gulpfile.js | 33 +- package.json | 2 + webcomponents-ce-es5.js | 255 +----- webcomponents-hi-ce-es5.js | 979 +--------------------- 5 files changed, 39 insertions(+), 1235 deletions(-) diff --git a/entrypoints/webcomponents-ce-es5-index.js b/entrypoints/webcomponents-ce-es5-index.js index 7760a41..457536a 100644 --- a/entrypoints/webcomponents-ce-es5-index.js +++ b/entrypoints/webcomponents-ce-es5-index.js @@ -16,5 +16,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN import '../bower_components/custom-elements/src/native-shim.js' -import '../src/post-polyfill.js' import '../src/unresolved.js' + +requestAnimationFrame(() => { + window.dispatchEvent(new CustomEvent('WebComponentsReady')); +}); diff --git a/gulpfile.js b/gulpfile.js index 3765282..6005b2d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -23,8 +23,9 @@ const del = require('del'); const bower = require('bower'); const runseq = require('run-sequence'); const closure = require('google-closure-compiler').gulp(); +const babel = require('rollup-plugin-babel'); -function debugify(sourceName, fileName, needsContext) { +function debugify(sourceName, fileName, extraRollupOptions) { if (!fileName) fileName = sourceName; @@ -34,11 +35,7 @@ function debugify(sourceName, fileName, needsContext) { moduleName: 'webcomponentsjs' }; - // The es6-promise polyfill needs to set the correct context. - // See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined - if (needsContext) { - options.context = 'window'; - } + Object.assign(options, extraRollupOptions); return rollup(options) .pipe(source(`${sourceName}-index.js`), 'entrypoints') @@ -120,7 +117,10 @@ gulp.task('debugify-hi-sd-ce', () => { }); gulp.task('debugify-hi-sd-ce-pf', () => { - return debugify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite', true) + // The es6-promise polyfill needs to set the correct context. + // See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined + const extraOptions = {context: 'window'}; + return debugify('webcomponents-hi-sd-ce-pf', 'webcomponents-lite', extraOptions) }); gulp.task('debugify-sd-ce', () => { @@ -147,12 +147,27 @@ gulp.task('closurify-sd-ce', () => { return closurify('webcomponents-sd-ce') }); +function singleLicenseComment() { + let hasLicense = false; + return (comment) => { + if (hasLicense) { + return false; + } + return hasLicense = /@license/.test(comment); + } +} + +const babelOptions = { + presets: 'babili', + shouldPrintComment: singleLicenseComment() +}; + gulp.task('debugify-ce-es5', () => { - return debugify('webcomponents-ce-es5'); + return debugify('webcomponents-ce-es5', '', {plugins: [babel(babelOptions)]}); }); gulp.task('debugify-hi-ce-es5', () => { - return debugify('webcomponents-hi-ce-es5'); + return debugify('webcomponents-hi-ce-es5', '', {plugins: [babel(babelOptions)]}); }) gulp.task('refresh-bower', () => { diff --git a/package.json b/package.json index 3824d62..9603314 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ }, "homepage": "http://webcomponents.org", "devDependencies": { + "babel-preset-babili": "0.0.12", "bower": "^1.8.0", "del": "^2.2.2", "eslint": "^3.16.1", @@ -28,6 +29,7 @@ "gulp": "^3.8.8", "gulp-rename": "^1.2.2", "gulp-sourcemaps": "^2.4.1", + "rollup-plugin-babel": "^2.7.1", "rollup-stream": "^1.14.0", "run-sequence": "^1.2.2", "vinyl-buffer": "^1.0.0", diff --git a/webcomponents-ce-es5.js b/webcomponents-ce-es5.js index 9f04716..5c8f4b7 100644 --- a/webcomponents-ce-es5.js +++ b/webcomponents-ce-es5.js @@ -1,254 +1,9 @@ (function () { 'use strict'; -/** - * @license - * Copyright (c) 2016 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ +(()=>{'use strict';if(!window.customElements)return;const a=window.HTMLElement,b=window.customElements.define,c=window.customElements.get,d=new Map,e=new Map;let f=!1,g=!1;window.HTMLElement=function(){if(!f){const h=d.get(this.constructor),i=c.call(window.customElements,h);g=!0;const j=new i;return j}f=!1;},window.HTMLElement.prototype=a.prototype,window.customElements.define=(h,i)=>{const j=i.prototype,k=class extends a{constructor(){super(),Object.setPrototypeOf(this,j),g||(f=!0,i.call(this)),g=!1;}},l=k.prototype;k.observedAttributes=i.observedAttributes,l.connectedCallback=j.connectedCallback,l.disconnectedCallback=j.disconnectedCallback,l.attributeChangedCallback=j.attributeChangedCallback,l.adoptedCallback=j.adoptedCallback,d.set(i,h),e.set(h,i),b.call(window.customElements,h,k);},window.customElements.get=(h)=>e.get(h);})(); -/** - * This shim allows elements written in, or compiled to, ES5 to work on native - * implementations of Custom Elements. - * - * ES5-style classes don't work with native Custom Elements because the - * HTMLElement constructor uses the value of `new.target` to look up the custom - * element definition for the currently called constructor. `new.target` is only - * set when `new` is called and is only propagated via super() calls. super() - * is not emulatable in ES5. The pattern of `SuperClass.call(this)`` only works - * when extending other ES5-style classes, and does not propagate `new.target`. - * - * This shim allows the native HTMLElement constructor to work by generating and - * registering a stand-in class instead of the users custom element class. This - * stand-in class's constructor has an actual call to super(). - * `customElements.define()` and `customElements.get()` are both overridden to - * hide this stand-in class from users. - * - * In order to create instance of the user-defined class, rather than the stand - * in, the stand-in's constructor swizzles its instances prototype and invokes - * the user-defined constructor. When the user-defined constructor is called - * directly it creates an instance of the stand-in class to get a real extension - * of HTMLElement and returns that. - * - * There are two important constructors: A patched HTMLElement constructor, and - * the StandInElement constructor. They both will be called to create an element - * but which is called first depends on whether the browser creates the element - * or the user-defined constructor is called directly. The variables - * `browserConstruction` and `userConstruction` control the flow between the - * two constructors. - * - * This shim should be better than forcing the polyfill because: - * 1. It's smaller - * 2. All reaction timings are the same as native (mostly synchronous) - * 3. All reaction triggering DOM operations are automatically supported - * - * There are some restrictions and requirements on ES5 constructors: - * 1. All constructors in a inheritance hierarchy must be ES5-style, so that - * they can be called with Function.call(). This effectively means that the - * whole application must be compiled to ES5. - * 2. Constructors must return the value of the emulated super() call. Like - * `return SuperClass.call(this)` - * 3. The `this` reference should not be used before the emulated super() call - * just like `this` is illegal to use before super() in ES6. - * 4. Constructors should not create other custom elements before the emulated - * super() call. This is the same restriction as with native custom - * elements. - * - * Compiling valid class-based custom elements to ES5 will satisfy these - * requirements with the latest version of popular transpilers. - */ -(() => { - 'use strict'; - - // Do nothing if `customElements` does not exist. - if (!window.customElements) return; - - const NativeHTMLElement = window.HTMLElement; - const nativeDefine = window.customElements.define; - const nativeGet = window.customElements.get; - - /** - * Map of user-provided constructors to tag names. - * - * @type {Map} - */ - const tagnameByConstructor = new Map(); - - /** - * Map of tag names to user-provided constructors. - * - * @type {Map} - */ - const constructorByTagname = new Map(); - - - /** - * Whether the constructors are being called by a browser process, ie parsing - * or createElement. - */ - let browserConstruction = false; - - /** - * Whether the constructors are being called by a user-space process, ie - * calling an element constructor. - */ - let userConstruction = false; - - window.HTMLElement = function() { - if (!browserConstruction) { - const tagname = tagnameByConstructor.get(this.constructor); - const fakeClass = nativeGet.call(window.customElements, tagname); - - // Make sure that the fake constructor doesn't call back to this constructor - userConstruction = true; - const instance = new (fakeClass)(); - return instance; - } - // Else do nothing. This will be reached by ES5-style classes doing - // HTMLElement.call() during initialization - browserConstruction = false; - }; - // By setting the patched HTMLElement's prototype property to the native - // HTMLElement's prototype we make sure that: - // document.createElement('a') instanceof HTMLElement - // works because instanceof uses HTMLElement.prototype, which is on the - // ptototype chain of built-in elements. - window.HTMLElement.prototype = NativeHTMLElement.prototype; - - window.customElements.define = (tagname, elementClass) => { - const elementProto = elementClass.prototype; - const StandInElement = class extends NativeHTMLElement { - constructor() { - // Call the native HTMLElement constructor, this gives us the - // under-construction instance as `this`: - super(); - - // The prototype will be wrong up because the browser used our fake - // class, so fix it: - Object.setPrototypeOf(this, elementProto); - - if (!userConstruction) { - // Make sure that user-defined constructor bottom's out to a do-nothing - // HTMLElement() call - browserConstruction = true; - // Call the user-defined constructor on our instance: - elementClass.call(this); - } - userConstruction = false; - } - }; - const standInProto = StandInElement.prototype; - StandInElement.observedAttributes = elementClass.observedAttributes; - standInProto.connectedCallback = elementProto.connectedCallback; - standInProto.disconnectedCallback = elementProto.disconnectedCallback; - standInProto.attributeChangedCallback = elementProto.attributeChangedCallback; - standInProto.adoptedCallback = elementProto.adoptedCallback; - - tagnameByConstructor.set(elementClass, tagname); - constructorByTagname.set(tagname, elementClass); - nativeDefine.call(window.customElements, tagname, StandInElement); - }; - - window.customElements.get = (tagname) => constructorByTagname.get(tagname); - -})(); - -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ - -(function() { - - 'use strict'; - - var customElements = window['customElements']; - var HTMLImports = window['HTMLImports']; - - if (customElements && customElements['polyfillWrapFlushCallback']) { - // Here we ensure that the public `HTMLImports.whenReady` - // always comes *after* custom elements have upgraded. - var flushCallback; - var runAndClearCallback = function runAndClearCallback() { - if (flushCallback) { - var cb = flushCallback; - flushCallback = null; - cb(); - return true; - } - }; - var origWhenReady = HTMLImports['whenReady']; - customElements['polyfillWrapFlushCallback'](function(cb) { - flushCallback = cb; - origWhenReady(runAndClearCallback); - }); - - HTMLImports['whenReady'] = function(cb) { - origWhenReady(function() { - // custom element code may add dynamic imports - // to match processing of native custom elements before - // domContentLoaded, we wait for these imports to resolve first. - if (runAndClearCallback()) { - HTMLImports['whenReady'](cb); - } else { - cb(); - } - }); - }; - - } - - HTMLImports['whenReady'](function() { - requestAnimationFrame(function() { - window.dispatchEvent(new CustomEvent('WebComponentsReady')); - }); - }); - -})(); - -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ - -(function() { - 'use strict'; - // It's desireable to provide a default stylesheet - // that's convenient for styling unresolved elements, but - // it's cumbersome to have to include this manually in every page. - // It would make sense to put inside some HTMLImport but - // the HTMLImports polyfill does not allow loading of stylesheets - // that block rendering. Therefore this injection is tolerated here. - // - // NOTE: position: relative fixes IE's failure to inherit opacity - // when a child is not statically positioned. - var style = document.createElement('style'); - style.textContent = '' - + 'body {' - + 'transition: opacity ease-in 0.2s;' - + ' } \n' - + 'body[unresolved] {' - + 'opacity: 0; display: block; overflow: hidden; position: relative;' - + ' } \n' - ; - var head = document.querySelector('head'); - head.insertBefore(style, head.firstChild); - -})(); +(function(){'use strict';var a=document.createElement('style');a.textContent='body {transition: opacity ease-in 0.2s; } \\nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \\n';var b=document.querySelector('head');b.insertBefore(a,b.firstChild);})(); /** @license @@ -258,10 +13,6 @@ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ -/* - * Polyfills loaded: Custom Elements ES5 Shim - * Used in: Chrome - */ +*/requestAnimationFrame(()=>{window.dispatchEvent(new CustomEvent('WebComponentsReady'));}); }()); diff --git a/webcomponents-hi-ce-es5.js b/webcomponents-hi-ce-es5.js index f840580..4d15ac1 100644 --- a/webcomponents-hi-ce-es5.js +++ b/webcomponents-hi-ce-es5.js @@ -1,983 +1,16 @@ (function () { 'use strict'; -/** - * @license - * Copyright (c) 2016 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ +(()=>{'use strict';if(!window.customElements)return;const a=window.HTMLElement,b=window.customElements.define,c=window.customElements.get,d=new Map,e=new Map;let f=!1,g=!1;window.HTMLElement=function(){if(!f){const h=d.get(this.constructor),i=c.call(window.customElements,h);g=!0;const j=new i;return j}f=!1;},window.HTMLElement.prototype=a.prototype,window.customElements.define=(h,i)=>{const j=i.prototype,k=class extends a{constructor(){super(),Object.setPrototypeOf(this,j),g||(f=!0,i.call(this)),g=!1;}},l=k.prototype;k.observedAttributes=i.observedAttributes,l.connectedCallback=j.connectedCallback,l.disconnectedCallback=j.disconnectedCallback,l.attributeChangedCallback=j.attributeChangedCallback,l.adoptedCallback=j.adoptedCallback,d.set(i,h),e.set(h,i),b.call(window.customElements,h,k);},window.customElements.get=(h)=>e.get(h);})(); -/** - * This shim allows elements written in, or compiled to, ES5 to work on native - * implementations of Custom Elements. - * - * ES5-style classes don't work with native Custom Elements because the - * HTMLElement constructor uses the value of `new.target` to look up the custom - * element definition for the currently called constructor. `new.target` is only - * set when `new` is called and is only propagated via super() calls. super() - * is not emulatable in ES5. The pattern of `SuperClass.call(this)`` only works - * when extending other ES5-style classes, and does not propagate `new.target`. - * - * This shim allows the native HTMLElement constructor to work by generating and - * registering a stand-in class instead of the users custom element class. This - * stand-in class's constructor has an actual call to super(). - * `customElements.define()` and `customElements.get()` are both overridden to - * hide this stand-in class from users. - * - * In order to create instance of the user-defined class, rather than the stand - * in, the stand-in's constructor swizzles its instances prototype and invokes - * the user-defined constructor. When the user-defined constructor is called - * directly it creates an instance of the stand-in class to get a real extension - * of HTMLElement and returns that. - * - * There are two important constructors: A patched HTMLElement constructor, and - * the StandInElement constructor. They both will be called to create an element - * but which is called first depends on whether the browser creates the element - * or the user-defined constructor is called directly. The variables - * `browserConstruction` and `userConstruction` control the flow between the - * two constructors. - * - * This shim should be better than forcing the polyfill because: - * 1. It's smaller - * 2. All reaction timings are the same as native (mostly synchronous) - * 3. All reaction triggering DOM operations are automatically supported - * - * There are some restrictions and requirements on ES5 constructors: - * 1. All constructors in a inheritance hierarchy must be ES5-style, so that - * they can be called with Function.call(). This effectively means that the - * whole application must be compiled to ES5. - * 2. Constructors must return the value of the emulated super() call. Like - * `return SuperClass.call(this)` - * 3. The `this` reference should not be used before the emulated super() call - * just like `this` is illegal to use before super() in ES6. - * 4. Constructors should not create other custom elements before the emulated - * super() call. This is the same restriction as with native custom - * elements. - * - * Compiling valid class-based custom elements to ES5 will satisfy these - * requirements with the latest version of popular transpilers. - */ -(() => { - 'use strict'; - - // Do nothing if `customElements` does not exist. - if (!window.customElements) return; - - const NativeHTMLElement = window.HTMLElement; - const nativeDefine = window.customElements.define; - const nativeGet = window.customElements.get; - - /** - * Map of user-provided constructors to tag names. - * - * @type {Map} - */ - const tagnameByConstructor = new Map(); - - /** - * Map of tag names to user-provided constructors. - * - * @type {Map} - */ - const constructorByTagname = new Map(); - - - /** - * Whether the constructors are being called by a browser process, ie parsing - * or createElement. - */ - let browserConstruction = false; - - /** - * Whether the constructors are being called by a user-space process, ie - * calling an element constructor. - */ - let userConstruction = false; - - window.HTMLElement = function() { - if (!browserConstruction) { - const tagname = tagnameByConstructor.get(this.constructor); - const fakeClass = nativeGet.call(window.customElements, tagname); - - // Make sure that the fake constructor doesn't call back to this constructor - userConstruction = true; - const instance = new (fakeClass)(); - return instance; - } - // Else do nothing. This will be reached by ES5-style classes doing - // HTMLElement.call() during initialization - browserConstruction = false; - }; - // By setting the patched HTMLElement's prototype property to the native - // HTMLElement's prototype we make sure that: - // document.createElement('a') instanceof HTMLElement - // works because instanceof uses HTMLElement.prototype, which is on the - // ptototype chain of built-in elements. - window.HTMLElement.prototype = NativeHTMLElement.prototype; - - window.customElements.define = (tagname, elementClass) => { - const elementProto = elementClass.prototype; - const StandInElement = class extends NativeHTMLElement { - constructor() { - // Call the native HTMLElement constructor, this gives us the - // under-construction instance as `this`: - super(); - - // The prototype will be wrong up because the browser used our fake - // class, so fix it: - Object.setPrototypeOf(this, elementProto); - - if (!userConstruction) { - // Make sure that user-defined constructor bottom's out to a do-nothing - // HTMLElement() call - browserConstruction = true; - // Call the user-defined constructor on our instance: - elementClass.call(this); - } - userConstruction = false; - } - }; - const standInProto = StandInElement.prototype; - StandInElement.observedAttributes = elementClass.observedAttributes; - standInProto.connectedCallback = elementProto.connectedCallback; - standInProto.disconnectedCallback = elementProto.disconnectedCallback; - standInProto.attributeChangedCallback = elementProto.attributeChangedCallback; - standInProto.adoptedCallback = elementProto.adoptedCallback; - - tagnameByConstructor.set(elementClass, tagname); - constructorByTagname.set(tagname, elementClass); - nativeDefine.call(window.customElements, tagname, StandInElement); - }; - - window.customElements.get = (tagname) => constructorByTagname.get(tagname); - -})(); - -/** - * @license - * Copyright (c) 2016 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt - */ -(scope => { - - /********************* base setup *********************/ - const useNative = Boolean('import' in document.createElement('link')); - - // Polyfill `currentScript` for browsers without it. - let currentScript = null; - if ('currentScript' in document === false) { - Object.defineProperty(document, 'currentScript', { - get() { - return currentScript || - // NOTE: only works when called in synchronously executing code. - // readyState should check if `loading` but IE10 is - // interactive when scripts run so we cheat. This is not needed by - // html-imports polyfill but helps generally polyfill `currentScript`. - (document.readyState !== 'complete' ? - document.scripts[document.scripts.length - 1] : null); - }, - configurable: true - }); - } - - /********************* path fixup *********************/ - const ABS_URL_TEST = /(^\/)|(^#)|(^[\w-\d]*:)/; - const CSS_URL_REGEXP = /(url\()([^)]*)(\))/g; - const CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g; - const STYLESHEET_REGEXP = /(]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g; - - // path fixup: style elements in imports must be made relative to the main - // document. We fixup url's in url() and @import. - const Path = { - - fixUrls(element, base) { - if (element.href) { - element.setAttribute('href', - Path.replaceAttrUrl(element.getAttribute('href'), base)); - } - if (element.src) { - element.setAttribute('src', - Path.replaceAttrUrl(element.getAttribute('src'), base)); - } - if (element.localName === 'style') { - const r = Path.replaceUrls(element.textContent, base, CSS_URL_REGEXP); - element.textContent = Path.replaceUrls(r, base, CSS_IMPORT_REGEXP); - } - }, - - replaceUrls(text, linkUrl, regexp) { - return text.replace(regexp, (m, pre, url, post) => { - let urlPath = url.replace(/["']/g, ''); - if (linkUrl) { - urlPath = Path.resolveUrl(urlPath, linkUrl); - } - return pre + '\'' + urlPath + '\'' + post; - }); - }, - - replaceAttrUrl(text, linkUrl) { - if (text && ABS_URL_TEST.test(text)) { - return text; - } else { - return Path.resolveUrl(text, linkUrl); - } - }, - - resolveUrl(url, base) { - // Lazy feature detection. - if (Path.__workingURL === undefined) { - Path.__workingURL = false; - try { - const u = new URL('b', 'http://a'); - u.pathname = 'c%20d'; - Path.__workingURL = (u.href === 'http://a/c%20d'); - } catch (e) {} - } - - if (Path.__workingURL) { - return (new URL(url, base)).href; - } - - // Fallback to creating an anchor into a disconnected document. - let doc = Path.__tempDoc; - if (!doc) { - doc = document.implementation.createHTMLDocument('temp'); - Path.__tempDoc = doc; - doc.__base = doc.createElement('base'); - doc.head.appendChild(doc.__base); - doc.__anchor = doc.createElement('a'); - } - doc.__base.href = base; - doc.__anchor.href = url; - return doc.__anchor.href || url; - } - }; - - /********************* Xhr processor *********************/ - const Xhr = { - - async: true, - - /** - * @param {!string} url - * @param {!function(!string, string=)} success - * @param {!function(!string)} fail - */ - load(url, success, fail) { - if (!url) { - fail('error: href must be specified'); - } else if (url.match(/^data:/)) { - // Handle Data URI Scheme - const pieces = url.split(','); - const header = pieces[0]; - let resource = pieces[1]; - if (header.indexOf(';base64') > -1) { - resource = atob(resource); - } else { - resource = decodeURIComponent(resource); - } - success(resource); - } else { - const request = new XMLHttpRequest(); - request.open('GET', url, Xhr.async); - request.onload = () => { - // Servers redirecting an import can add a Location header to help us - // polyfill correctly. Handle relative and full paths. - let redirectedUrl = request.getResponseHeader('Location'); - if (redirectedUrl && redirectedUrl.indexOf('/') === 0) { - // In IE location.origin might not work - // https://connect.microsoft.com/IE/feedback/details/1763802/location-origin-is-undefined-in-ie-11-on-windows-10-but-works-on-windows-7 - const origin = (location.origin || location.protocol + '//' + location.host); - redirectedUrl = origin + redirectedUrl; - } - const resource = /** @type {string} */ (request.response || request.responseText); - if (request.status === 304 || request.status === 0 || - request.status >= 200 && request.status < 300) { - success(resource, redirectedUrl); - } else { - fail(resource); - } - }; - request.send(); - } - } - }; - - /********************* importer *********************/ - - const isIE = /Trident/.test(navigator.userAgent) || - /Edge\/\d./i.test(navigator.userAgent); - - const importSelector = 'link[rel=import]'; - - // Used to disable loading of resources. - const importDisableType = 'import-disable'; - - const disabledLinkSelector = `link[rel=stylesheet][href][type=${importDisableType}]`; - - const importDependenciesSelector = `${importSelector}, ${disabledLinkSelector}, +((a)=>{const b=!!('import'in document.createElement('link'));let c=null;!1=='currentScript'in document&&Object.defineProperty(document,'currentScript',{get(){return c||('complete'===document.readyState?null:document.scripts[document.scripts.length-1])},configurable:!0});const d=/(^\/)|(^#)|(^[\w-\d]*:)/,f=/(url\()([^)]*)(\))/g,g=/(@import[\s]+(?!url\())([^;]*)(;)/g,h=/(]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g,k={fixUrls(J,K){if(J.href&&J.setAttribute('href',k.replaceAttrUrl(J.getAttribute('href'),K)),J.src&&J.setAttribute('src',k.replaceAttrUrl(J.getAttribute('src'),K)),'style'===J.localName){const L=k.replaceUrls(J.textContent,K,f);J.textContent=k.replaceUrls(L,K,g);}},replaceUrls(J,K,L){return J.replace(L,(M,N,O,P)=>{let Q=O.replace(/["']/g,'');return K&&(Q=k.resolveUrl(Q,K)),N+'\''+Q+'\''+P})},replaceAttrUrl(J,K){return J&&d.test(J)?J:k.resolveUrl(J,K)},resolveUrl(J,K){if(void 0===k.__workingURL){k.__workingURL=!1;try{const M=new URL('b','http://a');M.pathname='c%20d',k.__workingURL='http://a/c%20d'===M.href;}catch(M){}}if(k.__workingURL)return new URL(J,K).href;let L=k.__tempDoc;return L||(L=document.implementation.createHTMLDocument('temp'),k.__tempDoc=L,L.__base=L.createElement('base'),L.head.appendChild(L.__base),L.__anchor=L.createElement('a')),L.__base.href=K,L.__anchor.href=J,L.__anchor.href||J}},o={async:!0,load(J,K,L){if(!J)L('error: href must be specified');else if(J.match(/^data:/)){const M=J.split(','),N=M[0];let O=M[1];O=-1{let N=M.getResponseHeader('Location');if(N&&0===N.indexOf('/')){const P=location.origin||location.protocol+'//'+location.host;N=P+N;}const O=M.response||M.responseText;304===M.status||0===M.status||200<=M.status&&300>M.status?K(O,N):L(O);},M.send();}}},p=/Trident/.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent),q='link[rel=import]',t='import-disable',v=`link[rel=stylesheet][href][type=${t}]`,w=`${q}, ${v}, style:not([type]), link[rel=stylesheet][href]:not([type]), script:not([type]), script[type="application/javascript"], - script[type="text/javascript"]`; + script[type="text/javascript"]`,x='import-dependency',y=`${q}:not(${x})`,z=`script[${x}]`,A=`style[${x}], + link[rel=stylesheet][${x}]`;const C=(J)=>{return J.nodeType===Node.ELEMENT_NODE&&'link'===J.localName&&'import'===J.rel},D=(J,K)=>{if(J.__loaded)K&&K();else if('script'===J.localName&&!J.src)J.__loaded=!0,K&&K();else{const L=(M)=>{J.removeEventListener(M.type,L),J.__loaded=!0,K&&K();};J.addEventListener('load',L),p&&'style'===J.localName||J.addEventListener('error',L);}},E=(J)=>{F(()=>G(()=>J&&J()));},F=(J)=>{if('loading'!==document.readyState)J();else{const K=()=>{'loading'!==document.readyState&&(document.removeEventListener('readystatechange',K),J());};document.addEventListener('readystatechange',K);}},G=(J)=>{let K=document.querySelectorAll(y),L=K.length;if(!L)return void J();for(let O,M=0,N=K.length;M{0==--L&&J();});},H=(J)=>{if(b)return J.ownerDocument===document?null:J.ownerDocument;let K=J.__importDoc;if(!K&&J.parentNode){if(K=J.parentNode,'function'==typeof K.closest)K=K.closest(q);else for(;!C(K)&&(K=K.parentNode););J.__importDoc=K;}return K},I=(J,K)=>{if('function'==typeof window.CustomEvent)return new CustomEvent(J,K);const L=document.createEvent('CustomEvent');return L.initCustomEvent(J,!!K.bubbles,!!K.cancelable,K.detail),L};if(b){const J=document.querySelectorAll(q);for(let N,L=0,M=J.length;L{const M=L.target;C(M)&&(M.__loaded=!0);};document.addEventListener('load',K,!0),document.addEventListener('error',K,!0);}else new class{constructor(){this.documents={},this.inflight=0,this.dynamicImportsMO=new MutationObserver((J)=>this.handleMutations(J)),F(()=>{this.dynamicImportsMO.observe(document.head,{childList:!0,subtree:!0}),this.loadImports(document);});}loadImports(J){const K=J.querySelectorAll(q);for(let L=0,M=K.length;L{const N=this.makeDocument(L,M||K);this.documents[K]=N,this.inflight--,this.loadImports(N),this.processImportsIfLoadingDone();},()=>{this.documents[K]=null,this.inflight--,this.processImportsIfLoadingDone();});}makeDocument(J,K){if(!J)return document.createDocumentFragment();p&&(J=J.replace(h,(Q,R,S)=>{return-1===Q.indexOf('type=')?`${R} type=${t} ${S}`:Q}));let L;const M=document.createElement('template');if(M.innerHTML=J,M.content)L=M.content;else for(L=document.createDocumentFragment();M.firstChild;)L.appendChild(M.firstChild);const N=L.querySelector('base');N&&(K=k.replaceAttrUrl(N.getAttribute('href'),K),N.removeAttribute('href'));const O=L.querySelectorAll(w);let P=0;for(let S,Q=0,R=O.length;Q{K&&J&&(this.dynamicImportsMO.observe(document.head,{childList:!0,subtree:!0}),this.fireEvents());};this.waitForStyles(()=>{K=!0,L();}),this.runScripts(()=>{J=!0,L();});}flatten(J){const K=J.querySelectorAll(q);for(let N,L=0,M=K.length;LN.href,configurable:!0,enumerable:!0}),this.flatten(O),N.appendChild(O));}}runScripts(J){const K=document.querySelectorAll(z),L=K.length,M=(N)=>{if(N{c=null,M(N+1);});}else J();};M(0);}waitForStyles(J){const K=document.querySelectorAll(A);let L=K.length;if(!L)return void J();const M=p&&!!document.querySelector(v);for(let P,N=0,O=K.length;N{P.removeAttribute(x),0==--L&&J();}),M&&P.parentNode!==document.head){const Q=document.createElement(P.localName);Q.__appliedElement=P,Q.setAttribute('type','import-placeholder'),P.parentNode.insertBefore(Q,P.nextSibling);let R=H(P);for(;R&&H(R);)R=H(R);R.parentNode!==document.head&&(R=null),document.head.insertBefore(P,R),P.removeAttribute('type');}}fireEvents(){const J=document.querySelectorAll(q);for(let L,K=J.length-1;0<=K&&(L=J[K]);K--)this.fireEventIfNeeded(L);}fireEventIfNeeded(J){if(!J.__loaded){J.__loaded=!0,J.import&&(J.import.readyState='complete');const K=J.import?'load':'error';J.dispatchEvent(I(K,{bubbles:!1,cancelable:!1,detail:void 0}));}}handleMutations(J){for(let K=0;Kdocument.dispatchEvent(I('HTMLImportsLoaded',{cancelable:!0,bubbles:!0,detail:void 0}))),a.useNative=b,a.whenReady=E,a.importForElement=H;})(window.HTMLImports=window.HTMLImports||{}); - const importDependencyAttr = 'import-dependency'; +(function(){'use strict';var a=window.customElements,b=window.HTMLImports;if(a&&a.polyfillWrapFlushCallback){var c,d=function(){if(c){var g=c;return c=null,g(),!0}},e=b.whenReady;a.polyfillWrapFlushCallback(function(f){c=f,e(d);}),b.whenReady=function(f){e(function(){d()?b.whenReady(f):f();});};}b.whenReady(function(){requestAnimationFrame(function(){window.dispatchEvent(new CustomEvent('WebComponentsReady'));});});})(); - const rootImportSelector = `${importSelector}:not(${importDependencyAttr})`; - - const pendingScriptsSelector = `script[${importDependencyAttr}]`; - - const pendingStylesSelector = `style[${importDependencyAttr}], - link[rel=stylesheet][${importDependencyAttr}]`; - - /** - * Importer will: - * - load any linked import documents (with deduping) - * - whenever an import is loaded, prompt the parser to try to parse - * - observe imported documents for new elements (these are handled via the - * dynamic importer) - */ - class Importer { - constructor() { - this.documents = {}; - // Used to keep track of pending loads, so that flattening and firing of - // events can be done when all resources are ready. - this.inflight = 0; - this.dynamicImportsMO = new MutationObserver(m => this.handleMutations(m)); - // 1. Load imports contents - // 2. Assign them to first import links on the document - // 3. Wait for import styles & scripts to be done loading/running - // 4. Fire load/error events - whenDocumentReady(() => { - // Observe changes on . - this.dynamicImportsMO.observe(document.head, { - childList: true, - subtree: true - }); - this.loadImports(document); - }); - } - - /** - * @param {!(HTMLDocument|DocumentFragment|Element)} doc - */ - loadImports(doc) { - const links = /** @type {!NodeList} */ - (doc.querySelectorAll(importSelector)); - for (let i = 0, l = links.length; i < l; i++) { - this.loadImport(links[i]); - } - } - - /** - * @param {!HTMLLinkElement} link - */ - loadImport(link) { - const url = link.href; - // This resource is already being handled by another import. - if (this.documents[url] !== undefined) { - // If import is already loaded, we can safely associate it to the link - // and fire the load/error event. - const imp = this.documents[url]; - if (imp && imp['__loaded']) { - link.import = imp; - this.fireEventIfNeeded(link); - } - return; - } - this.inflight++; - // Mark it as pending to notify others this url is being loaded. - this.documents[url] = 'pending'; - Xhr.load(url, (resource, redirectedUrl) => { - const doc = this.makeDocument(resource, redirectedUrl || url); - this.documents[url] = doc; - this.inflight--; - // Load subtree. - this.loadImports(doc); - this.processImportsIfLoadingDone(); - }, () => { - // If load fails, handle error. - this.documents[url] = null; - this.inflight--; - this.processImportsIfLoadingDone(); - }); - } - - /** - * Creates a new document containing resource and normalizes urls accordingly. - * @param {string=} resource - * @param {string=} url - * @return {!DocumentFragment} - */ - makeDocument(resource, url) { - if (!resource) { - return document.createDocumentFragment(); - } - - if (isIE) { - // should be appended to . Not doing so - // in IE/Edge breaks the cascading order. We disable the loading by - // setting the type before setting innerHTML to avoid loading - // resources twice. - resource = resource.replace(STYLESHEET_REGEXP, (match, p1, p2) => { - if (match.indexOf('type=') === -1) { - return `${p1} type=${importDisableType} ${p2}`; - } - return match; - }); - } - - let content; - const template = /** @type {!HTMLTemplateElement} */ - (document.createElement('template')); - template.innerHTML = resource; - if (template.content) { - // This creates issues in Safari10 when used with shadydom (see #12). - content = template.content; - } else { - //