Move import-href into plugin, so Gerrit does not have to provide it Change-Id: I437c0474b4364cbdce92e3395a7a030daa406f8a
diff --git a/README.md b/README.md index c85c098..96d3063 100644 --- a/README.md +++ b/README.md
@@ -18,7 +18,7 @@ You will need `polymer-bridges` which is a submodule you can clone from: https://gerrit-review.googlesource.com/admin/repos/polymer-bridges -As polymer 3 no longer support `Polymer.importHref` anymore, Gerrit still supports through a custom implementation, the implementation is copied here for testing purpose (`test/import-href.js`). +As polymer 3 no longer support `Polymer.importHref` anymore, this plugin still supports it through a custom implementation in `gr-editor.js`. ## Test plugin on Gerrit @@ -28,4 +28,4 @@ If your plugin is already enabled, then you can block it and then inject the compiled local verison. -See more about how to use dev helper extension to help you test here: https://gerrit.googlesource.com/gerrit-fe-dev-helper/+/master \ No newline at end of file +See more about how to use dev helper extension to help you test here: https://gerrit.googlesource.com/gerrit-fe-dev-helper/+/master
diff --git a/gr-editor/gr-editor.js b/gr-editor/gr-editor.js index d7297ad..4f1c175 100644 --- a/gr-editor/gr-editor.js +++ b/gr-editor/gr-editor.js
@@ -15,6 +15,86 @@ * limitations under the License. */ +// Run a callback when HTMLImports are ready or immediately if +// this api is not available. +function whenImportsReady(cb) { + if (window.HTMLImports) { + HTMLImports.whenReady(cb); + } else { + cb(); + } +} + +/** + * Convenience method for importing an HTML document imperatively. Mostly copied + * from polymer/lib/utils/import-href.html. + * + * This method creates a new `<link rel="import">` element with + * the provided URL and appends it to the document to start loading. + * In the `onload` callback, the `import` property of the `link` + * element will contain the imported document contents. + * + * @param {string} href URL to document to load. + * @param {?function(!Event):void=} onload Callback to notify when an import successfully + * loaded. + * @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import + * unsuccessfully loaded. + */ +function importHref(href, onload, onerror) { + let link = + /** @type {HTMLLinkElement} */ + (document.head.querySelector('link[href="' + href + '"][import-href]')); + if (!link) { + link = /** @type {HTMLLinkElement} */ (document.createElement('link')); + link.rel = 'import'; + link.href = href; + link.setAttribute('import-href', ''); + } + // NOTE: the link may now be in 3 states: (1) pending insertion, + // (2) inflight, (3) already loaded. In each case, we need to add + // event listeners to process callbacks. + const cleanup = function() { + link.removeEventListener('load', loadListener); + link.removeEventListener('error', errorListener); + }; + const loadListener = function(event) { + cleanup(); + // In case of a successful load, cache the load event on the link so + // that it can be used to short-circuit this method in the future when + // it is called with the same href param. + link.__dynamicImportLoaded = true; + if (onload) { + whenImportsReady(() => { + onload(event); + }); + } + }; + const errorListener = function(event) { + cleanup(); + // In case of an error, remove the link from the document so that it + // will be automatically created again the next time `importHref` is + // called. + if (link.parentNode) { + link.parentNode.removeChild(link); + } + if (onerror) { + whenImportsReady(() => { + onerror(event); + }); + } + }; + link.addEventListener('load', loadListener); + link.addEventListener('error', errorListener); + if (link.parentNode == null) { + document.head.appendChild(link); + // if the link already loaded, dispatch a fake load event + // so that listeners are called and get a proper event argument. + } else if (link.__dynamicImportLoaded) { + link.dispatchEvent(new Event('load')); + } + return link; +} + // we need to be on codemirror 5.33.0+ to get the support for // text/x-php in CodeMirror.findModeByMIME const LANGUAGE_MAP = { @@ -87,7 +167,7 @@ const codemirrorElementFile = '/static/codemirror-element.html'; const url = this.plugin.url(codemirrorElementFile); return new Promise((resolve, reject) => { - Polymer.importHref(url, resolve, reject); + importHref(url, resolve, reject); }); } @@ -159,9 +239,8 @@ customElements.define(GrEditor.is, GrEditor); -// Install the plugin if (window.Gerrit) { Gerrit.install(plugin => { plugin.registerCustomComponent('editor', 'gr-editor', {replace: true}); }); -} \ No newline at end of file +}
diff --git a/gr-editor/gr-editor_test.html b/gr-editor/gr-editor_test.html index 586d703..fcbcb5f 100644 --- a/gr-editor/gr-editor_test.html +++ b/gr-editor/gr-editor_test.html
@@ -31,6 +31,7 @@ <script type="module"> import '../test/common-test-setup.js'; import './gr-editor.js'; +import {importHref} from './gr-editor.js'; suite('gr-editor tests', () => { let element; let sandbox; @@ -41,7 +42,7 @@ stub('gr-editor', { _importCodeMirror() { return new Promise((resolve, reject) => { - Polymer.importHref('./codemirror-element.html', resolve, reject); + importHref('./codemirror-element.html', resolve, reject); }); }, });
diff --git a/test/common-test-setup.js b/test/common-test-setup.js index a0f1f1b..1158af4 100644 --- a/test/common-test-setup.js +++ b/test/common-test-setup.js
@@ -57,6 +57,3 @@ import 'polymer-bridges/polymer/polymer-legacy_bridge.js'; import '@polymer/iron-test-helpers/iron-test-helpers.js'; -import {importHref} from './import-href.js'; - -window.Polymer.importHref = importHref;
diff --git a/test/import-href.js b/test/import-href.js deleted file mode 100644 index 80ae389..0000000 --- a/test/import-href.js +++ /dev/null
@@ -1,109 +0,0 @@ -/** - * @license - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This file is a replacement for the -// polymer-bridges/polymer/lib/utils/import-href.html file. The html -// file contains code inside <script>...</script> and can't be imported -// in es6 modules. - -// run a callback when HTMLImports are ready or immediately if -// this api is not available. -function whenImportsReady(cb) { - if (window.HTMLImports) { - HTMLImports.whenReady(cb); - } else { - cb(); - } -} - -/** - * Convenience method for importing an HTML document imperatively. - * - * This method creates a new `<link rel="import">` element with - * the provided URL and appends it to the document to start loading. - * In the `onload` callback, the `import` property of the `link` - * element will contain the imported document contents. - * - * @memberof Polymer - * @param {string} href URL to document to load. - * @param {?function(!Event):void=} onload Callback to notify when an import successfully - * loaded. - * @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import - * unsuccessfully loaded. - * @param {boolean=} optAsync True if the import should be loaded `async`. - * Defaults to `false`. - * @return {!HTMLLinkElement} The link element for the URL to be loaded. - */ -export function importHref(href, onload, onerror, optAsync) { - let link = - /** @type {HTMLLinkElement} */ - (document.head.querySelector('link[href="' + href + '"][import-href]')); - if (!link) { - link = /** @type {HTMLLinkElement} */ (document.createElement("link")); - link.rel = "import"; - link.href = href; - link.setAttribute("import-href", ""); - } - // always ensure link has `async` attribute if user specified one, - // even if it was previously not async. This is considered less confusing. - if (optAsync) { - link.setAttribute("async", ""); - } - // NOTE: the link may now be in 3 states: (1) pending insertion, - // (2) inflight, (3) already loaded. In each case, we need to add - // event listeners to process callbacks. - const cleanup = function () { - link.removeEventListener("load", loadListener); - link.removeEventListener("error", errorListener); - }; - const loadListener = function (event) { - cleanup(); - // In case of a successful load, cache the load event on the link so - // that it can be used to short-circuit this method in the future when - // it is called with the same href param. - link.__dynamicImportLoaded = true; - if (onload) { - whenImportsReady(() => { - onload(event); - }); - } - }; - const errorListener = function (event) { - cleanup(); - // In case of an error, remove the link from the document so that it - // will be automatically created again the next time `importHref` is - // called. - if (link.parentNode) { - link.parentNode.removeChild(link); - } - if (onerror) { - whenImportsReady(() => { - onerror(event); - }); - } - }; - link.addEventListener("load", loadListener); - link.addEventListener("error", errorListener); - if (link.parentNode == null) { - document.head.appendChild(link); - // if the link already loaded, dispatch a fake load event - // so that listeners are called and get a proper event argument. - } else if (link.__dynamicImportLoaded) { - link.dispatchEvent(new Event("load")); - } - return link; -}