Skip to content

Fixes #4357. #4360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 3, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/elements/dom-module.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@
// element's location; accomodate polyfilled HTMLImports
const owner = window.HTMLImports && HTMLImports.importForElement ?
HTMLImports.importForElement(this) || document : this.ownerDocument;
this.__assetpath = Polymer.ResolveUrl.resolveUrl(
const url = Polymer.ResolveUrl.resolveUrl(
this.getAttribute('assetpath') || '', owner.baseURI);
this.__assetpath = Polymer.ResolveUrl.pathFromUrl(url);
}
return this.__assetpath;
}
Expand Down
47 changes: 39 additions & 8 deletions lib/mixins/element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,16 @@
* style scoping.
* @param {HTMLElement} proto
* @param {HTMLTemplateElement} template
* @param {string} baseURI URL against which to resolve urls in
* style element cssText.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@returns {HTMLTemplateElement}

* @param {string} is
* @param {string} ext
* @private
*/
function finalizeTemplate(proto, template, is, ext) {
function finalizeTemplate(proto, template, baseURI, is, ext) {
// support `include="module-name"`
let cssText = Polymer.StyleGather.cssFromTemplate(template) +
let cssText =
Polymer.StyleGather.cssFromTemplate(template, baseURI) +
Polymer.StyleGather.cssFromModuleImports(is);
if (cssText) {
let style = document.createElement('style');
Expand Down Expand Up @@ -489,6 +492,8 @@
* return memoizedTemplate;
* }
* }
*
* @returns {HTMLTemplateElement|string}
*/
static get template() {
if (!this.hasOwnProperty(goog.reflect.objectProperty('_template', this))) {
Expand All @@ -501,6 +506,26 @@
return this._template;
}

/**
* 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.
* Note, this path should contain a trailing `/`.
*
* @returns {string}
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@returns {string}

static get importPath() {
if (!this.hasOwnProperty(goog.reflect.objectProperty('_importPath', this))) {
const module = Polymer.DomModule.import(this.is);
this._importPath = module ? module.assetpath : '' ||
Object.getPrototypeOf(this.prototype).constructor.importPath;
}
return this._importPath;
}

constructor() {
super();
Polymer.telemetry.instanceCount++;
Expand All @@ -524,13 +549,20 @@
*/
_initializeProperties() {
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.
if (this._template && !this._template.__polymerFinalized) {
this._template.__polymerFinalized = true;
finalizeTemplate(this.__proto__, this._template, this.localName);
const baseURI =
importPath ? Polymer.ResolveUrl.resolveUrl(importPath) : '';
finalizeTemplate(this.__proto__, this._template, baseURI,
this.localName);
}
super._initializeProperties();
// set path defaults
this.rootPath = Polymer.rootPath;
this.importPath = importPath;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to discuss why it was bad if these went before initializeProperties

// apply property defaults...
let p$ = propertyDefaultsForClass(this.constructor);
if (!p$) {
Expand Down Expand Up @@ -673,13 +705,12 @@
*
* @param {string} url URL to resolve.
* @param {string=} base Optional base URL to resolve against, defaults
* to the element template's ownerDocument baseURI.
* @return {string} Rewritten URL relative to the import
* to the element's `importPath`
* @return {string} Rewritten URL relative to base
*/
resolveUrl(url, base) {
if (!base) {
const module = Polymer.DomModule.import(this.constructor.is);
base = module ? module.assetpath : document.baseURI;
if (!base && this.importPath) {
base = Polymer.ResolveUrl.resolveUrl(this.importPath);
}
return Polymer.ResolveUrl.resolveUrl(url, base);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/mixins/property-effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,8 @@
* @param {Function} effectFn Function to run when arguments change
* @param {*=} methodInfo
* @param {Object=} dynamicFns Map indicating whether method names should
* be included as a dependency to the effect.
* be included as a dependency to the effect. Note, defaults to true
* if the signature is statci (sig.static is true).
* @private
*/
function createMethodEffect(model, sig, type, effectFn, methodInfo, dynamicFns) {
Expand Down
1 change: 0 additions & 1 deletion lib/mixins/template-stamp.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@
parseChildNodesAnnotations(element, note, list, stripWhiteSpace, ownerDocument);
if (element.attributes) {
parseNodeAttributeAnnotations(element, note);
Polymer.ResolveUrl.resolveAttrs(element, ownerDocument);
}
if (note.bindings.length || note.events.length || note.id) {
list.push(note);
Expand Down
13 changes: 12 additions & 1 deletion lib/utils/boot.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>
(function() {

const userPolymer = window.Polymer;

/**
* @namespace Polymer
Expand All @@ -18,6 +21,12 @@
window.Polymer = function(info) {
return window.Polymer._polymerFn(info);
}

// support user settings on the Polymer object
if (userPolymer) {
Object.assign(Polymer, userPolymer);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting, this fixes the ability to set Polymer.sanitizeDOMValue before loading polymer, closing a loophole where it's conceivable that main-document e.g. dom-repeat's could upgrade before the sanitization hook is installed. 👍


// To be plugged by legacy implementation if loaded
window.Polymer._polymerFn = function() {
throw new Error('Load polymer.html to use the Polymer() function.');
Expand All @@ -29,12 +38,14 @@
When using Closure Compiler, goog.reflect.objectProperty(property, object) is replaced by the munged name for object[property]
We cannot alias this function, so we have to use a small shim that has the same behavior when not compiling.
*/
var goog = {
window.goog = {
reflect: {
objectProperty(s, o) {
return s;
}
}
}
/* eslint-enable */

})();
</script>
137 changes: 61 additions & 76 deletions lib/utils/resolve-url.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,99 +13,82 @@

(function() {

let CSS_URL_RX = /(url\()([^)]*)(\))/g;
let ABS_URL = /(^\/)|(^#)|(^[\w-\d]*:)/;
let workingURL;
let resolveDoc;
/**
* Resolves the given URL against the provided `baseUri'.
*
* @memberof Polymer.ResolveUrl
* @param {string} url Input URL to resolve
* @param {string} baseURI Base URI to resolve the URL against
* @return {string} resolved URL
*/
function resolveUrl(url, baseURI) {
if (url && ABS_URL.test(url)) {
return url;
}
// Lazy feature detection.
if (workingURL === undefined) {
workingURL = false;
try {
const u = new URL('b', 'http://a');
u.pathname = 'c%20d';
workingURL = (u.href === 'http://a/c%20d');
} catch (e) {
// silently fail
}
}
if (!baseURI) {
baseURI = document.baseURI || window.location.href;
}
if (workingURL) {
return (new URL(url, baseURI)).href;
}
// Fallback to creating an anchor into a disconnected document.
if (!resolveDoc) {
resolveDoc = document.implementation.createHTMLDocument('temp');
resolveDoc.base = resolveDoc.createElement('base');
resolveDoc.head.appendChild(resolveDoc.base);
resolveDoc.anchor = resolveDoc.createElement('a');
resolveDoc.body.appendChild(resolveDoc.anchor);
}
resolveDoc.base.href = baseURI;
resolveDoc.anchor.href = url;
return resolveDoc.anchor.href || url;

}

/**
* Resolves any relative URL's in the given CSS text against the provided
* `ownerDocument`'s `baseURI`.
*
* @memberof Polymer.ResolveUrl
* @param {string} cssText CSS text to process
* @param {Document} ownerDocument Owner document to base URL's on
* @param {string} baseURI Base URI to resolve the URL against
* @return {string} Processed CSS text with resolved URL's
*/
function resolveCss(cssText, ownerDocument) {
function resolveCss(cssText, baseURI) {
return cssText.replace(CSS_URL_RX, function(m, pre, url, post) {
return pre + '\'' +
resolve(url.replace(/["']/g, ''), ownerDocument) +
resolveUrl(url.replace(/["']/g, ''), baseURI) +
'\'' + post;
});
}

/**
* Resolves any relative URL's in `src` or `style` attributes of the given
* `element` against the provided `ownerDocument`'s `baseURI`.
* Returns a path from a given `url`. The path includes the trailing
* `/` from the url.
*
* @memberof Polymer.ResolveUrl
* @param {HTMLElement} element Element whose attributes will be processed
* @param {Document} ownerDocument Owner document to base URL's on
* @param {string} url Input URL to transform
* @return {string} resolved path
*/
function resolveAttrs(element, ownerDocument) {
for (var name in URL_ATTRS) {
var a$ = URL_ATTRS[name];
for (var i=0, l=a$.length, a, at, v; (i<l) && (a=a$[i]); i++) {
if (name === '*' || element.localName === name) {
at = element.attributes[a];
v = at && at.value;
if (v && (v.search(BINDING_RX) < 0)) {
at.value = (a === 'style') ?
resolveCss(v, ownerDocument) :
resolve(v, ownerDocument);
}
}
}
}
function pathFromUrl(url) {
return url.substring(0, url.lastIndexOf('/') + 1);
}

/**
* Resolves the given URL against the provided `ownerDocument`'s `baseURI'.
*
* Does not modify `#` links or absolute URL's.
*
* @private
*/
function resolve(url, ownerDocument) {
// do not resolve '#' links, they are used for routing
if (url && ABS_URL.test(url)) {
return url;
}
var resolver = getUrlResolver(ownerDocument);
resolver.href = url;
return resolver.href || url;
}

var tempDoc;
var tempDocBase;

/**
* Resolves the given URL against the provided `baseUri'.
*
* @memberof Polymer.ResolveUrl
* @param {string} url Input URL to resolve
* @param {string} baseUri Base URI to resolve the URL against
* @param {type} name Description
*/
function resolveUrl(url, baseUri) {
if (!tempDoc) {
tempDoc = document.implementation.createHTMLDocument('temp');
tempDocBase = tempDoc.createElement('base');
tempDoc.head.appendChild(tempDocBase);
}
tempDocBase.href = baseUri;
return resolve(url, tempDoc);
}

function getUrlResolver(ownerDocument) {
return ownerDocument.__urlResolver ||
(ownerDocument.__urlResolver = ownerDocument.createElement('a'));
}

var CSS_URL_RX = /(url\()([^)]*)(\))/g;
var URL_ATTRS = {
'*': ['href', 'src', 'style', 'url'],
form: ['action']
};
var ABS_URL = /(^\/)|(^#)|(^[\w-\d]*:)/;
var BINDING_RX = /\{\{|\[\[/;

/**
* Module with utilities for resolving relative URL's.
*
Expand All @@ -114,12 +97,14 @@
* @summary Module with utilities for resolving relative URL's.
*/
Polymer.ResolveUrl = {
// exports
resolveCss: resolveCss,
resolveAttrs: resolveAttrs,
resolveUrl: resolveUrl
resolveUrl: resolveUrl,
pathFromUrl: pathFromUrl
};

// NOTE: baseURI is not supported on IE?
Polymer.rootPath = pathFromUrl(document.baseURI || window.location.href);

})();

</script>
12 changes: 7 additions & 5 deletions lib/utils/style-gather.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
// include css from the first template in the module
let t = m.querySelector('template');
if (t) {
cssText += this.cssFromTemplate(t);
cssText += this.cssFromTemplate(t, m.assetpath);
}
// module imports: <link rel="import" type="css">
cssText += this.cssFromModuleImports(moduleId);
Expand All @@ -86,9 +86,10 @@
*
* @memberof Polymer.StyleGather
* @param {HTMLTemplateElement} template Template to gather styles from
* @param {string} baseURI Base URI to resolve the URL against
* @return {string} Concatenated CSS content from specified template
*/
cssFromTemplate(template) {
cssFromTemplate(template, baseURI) {
let cssText = '';
// if element is a template, get content from its .content
let e$ = template.content.querySelectorAll('style');
Expand All @@ -101,8 +102,8 @@
cssText += this.cssFromModules(include);
}
e.parentNode.removeChild(e);
cssText +=
Polymer.ResolveUrl.resolveCss(e.textContent, template.ownerDocument);
cssText += baseURI ?
Polymer.ResolveUrl.resolveCss(e.textContent, baseURI) : e.textContent;
}
return cssText;
},
Expand Down Expand Up @@ -131,7 +132,8 @@
// but the import pseudo-doc can be used directly.
let container = importDoc.body ? importDoc.body : importDoc;
cssText +=
Polymer.ResolveUrl.resolveCss(container.textContent, importDoc);
Polymer.ResolveUrl.resolveCss(container.textContent,
importDoc.baseURI);
}
}
return cssText;
Expand Down
Loading