Skip to content

Commit

Permalink
Merge pull request #5172 from Polymer/5163-kschaaf-import-meta
Browse files Browse the repository at this point in the history
Add importMeta getter to derive importPath from modules. Fixes #5163
  • Loading branch information
kevinpschaaf authored Apr 3, 2018
2 parents 53dd08d + c8c9e24 commit 689ff72
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
33 changes: 27 additions & 6 deletions lib/mixins/element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -398,24 +398,46 @@

/**
* Path matching the url from which the element was imported.
*
* This path is used to resolve url's in template style cssText.
* The `importPath` property is also set on element instances and can be
* used to create bindings relative to the import path.
* Defaults to the path matching the url containing a `dom-module` element
* matching this element's static `is` property.
* For elements defined in ES modules, users should implement `importMeta`
* and this getter will return `import.meta.url`'s path. For elements
* defined in HTML imports, this getter will return the path to the
* document containing a `dom-module` element matching this element's
* static `is` property.
*
* Note, this path should contain a trailing `/`.
*
* @return {string} The import path for this element class
*/
static get importPath() {
if (!this.hasOwnProperty(JSCompiler_renameProperty('_importPath', this))) {
const meta = this.importMeta;
if (meta) {
this._importPath = Polymer.ResolveUrl.pathFromUrl(meta.url);
} else {
const module = Polymer.DomModule && Polymer.DomModule.import(/** @type {PolymerElementConstructor} */ (this).is);
this._importPath = module ? module.assetpath : '' ||
Object.getPrototypeOf(/** @type {PolymerElementConstructor}*/ (this).prototype).constructor.importPath;
this._importPath = (module && module.assetpath) ||
Object.getPrototypeOf(/** @type {PolymerElementConstructor}*/ (this).prototype).constructor.importPath;
}
}
return this._importPath;
}

/**
* When an element definition is being loaded from an ES module, users
* may override this getter to return the `import.meta` object from that
* module, which will be used to derive the `importPath` for the element.
* When implementing `importMeta`, users should not implement `importPath`.
*
* @return {!Object} The `import.meta` object for the element's module
*/
static get importMeta() {
return null;
}

constructor() {
super();
/** @type {HTMLTemplateElement} */
Expand Down Expand Up @@ -447,14 +469,13 @@
_initializeProperties() {
Polymer.telemetry.instanceCount++;
this.constructor.finalize();
const importPath = this.constructor.importPath;
// note: finalize template when we have access to `localName` to
// avoid dependence on `is` for polyfilling styling.
this.constructor._finalizeTemplate(/** @type {!HTMLElement} */(this).localName);
super._initializeProperties();
// set path defaults
this.rootPath = Polymer.rootPath;
this.importPath = importPath;
this.importPath = this.constructor.importPath;
// apply property defaults...
let p$ = propertyDefaults(this.constructor);
if (!p$) {
Expand Down
14 changes: 9 additions & 5 deletions test/unit/resolveurl.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@
<script>
suite('ResolveUrl', function() {

test('Urls in styles and attributes', function() {
var el = document.createElement('p-r');
const testStylesAndAttributes = (elementName, folder) => () => {
var el = document.createElement(elementName);
document.body.appendChild(el);
var resolvedUrl = /sub\/foo\.z/;
var resolvedUrl = new RegExp(`${folder}/foo\\.z`);
var styleHashUrl = /url\('#bar'\)/;
var styleAbsUrl = /url\('\/zot'\)/;
var style = el.shadowRoot.querySelector('style') || document.querySelector('style[scope=p-r]');
var style = el.shadowRoot.querySelector('style') || document.querySelector(`style[scope=${elementName}]`);
assert.match(style.textContent, resolvedUrl, 'url not relative to main document');
assert.match(style.textContent, styleHashUrl, 'hash url incorrectly resolved');
assert.match(style.textContent, styleAbsUrl, 'absolute url incorrectly resolved');
Expand All @@ -78,7 +78,11 @@
assert.equal(el.$.absolute.getAttribute('href'), '/foo.z', 'absolute urls should not be resolved');
assert.equal(el.$.protocol.getAttribute('href'), 'data:foo.z', 'urls with other protocols should not be resolved');
document.body.removeChild(el);
});
};

test('Urls in styles and attributes', testStylesAndAttributes('p-r', 'sub'));

test('Urls in styles and attributes (importMeta)', testStylesAndAttributes('p-r-im', 'http://foo.com/mymodule'));

test('url changes via setting importPath/rootPath on element instance', function() {
var el = document.createElement('p-r');
Expand Down
9 changes: 9 additions & 0 deletions test/unit/sub/resolveurl-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@
static get is() { return 'p-r'; }
}
customElements.define(PR.is, PR);

class PRImportMeta extends PR {
static get importMeta() {
// Idiomatically, this would be `return import.meta`, but for purposes
// of stubbing the test without actual modules, it's shimmed
return { url: 'http://foo.com/mymodule/index.js' }
}
}
customElements.define('p-r-im', PRImportMeta);
</script>

<dom-module id="p-r-ap" assetpath="../../assets/"></dom-module>
Expand Down

0 comments on commit 689ff72

Please sign in to comment.