Skip to content

Commit

Permalink
Merge branch 'master' into 5422-ldm-templatizer-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinpschaaf committed Nov 20, 2018
2 parents 2c560bc + a7c861b commit c23ff5e
Show file tree
Hide file tree
Showing 16 changed files with 2,605 additions and 973 deletions.
316 changes: 236 additions & 80 deletions lib/legacy/class.js

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions lib/legacy/legacy-element-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ export const LegacyElementMixin = dedupingMixin((base) => {
this.__boundListeners;
/** @type {Object<string, Function>} */
this._debouncers;
// Ensure listeners are applied immediately so that they are
// added before declarative event listeners. This allows an element to
// decorate itself via an event prior to any declarative listeners
// seeing the event. Note, this ensures compatibility with 1.x ordering.
this._applyListeners();
}

/**
Expand Down Expand Up @@ -180,12 +175,18 @@ export const LegacyElementMixin = dedupingMixin((base) => {
_initializeProperties() {
let proto = Object.getPrototypeOf(this);
if (!proto.hasOwnProperty('__hasRegisterFinished')) {
proto.__hasRegisterFinished = true;
this._registered();
// backstop in case the `_registered` implementation does not set this
proto.__hasRegisterFinished = true;
}
super._initializeProperties();
this.root = /** @type {HTMLElement} */(this);
this.created();
// Ensure listeners are applied immediately so that they are
// added before declarative event listeners. This allows an element to
// decorate itself via an event prior to any declarative listeners
// seeing the event. Note, this ensures compatibility with 1.x ordering.
this._applyListeners();
}

/**
Expand Down
22 changes: 14 additions & 8 deletions lib/mixins/dir-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const HOST_DIR_REPLACMENT = ':host([dir="$1"])';
const EL_DIR = /([\s\w-#\.\[\]\*]*):dir\((ltr|rtl)\)/g;
const EL_DIR_REPLACMENT = ':host([dir="$2"]) $1';

const DIR_CHECK = /:dir\((?:ltr|rtl)\)/;

const SHIM_SHADOW = Boolean(window['ShadyDOM'] && window['ShadyDOM']['inUse']);

/**
* @type {!Array<!Polymer_DirMixin>}
*/
Expand Down Expand Up @@ -80,10 +84,12 @@ function takeRecords() {
*/
export const DirMixin = dedupingMixin((base) => {

if (!observer) {
getRTL();
observer = new MutationObserver(updateDirection);
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['dir']});
if (!SHIM_SHADOW) {
if (!observer) {
getRTL();
observer = new MutationObserver(updateDirection);
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['dir']});
}
}

/**
Expand All @@ -107,7 +113,10 @@ export const DirMixin = dedupingMixin((base) => {
*/
static _processStyleText(cssText, baseURI) {
cssText = super._processStyleText(cssText, baseURI);
cssText = this._replaceDirInCssText(cssText);
if (!SHIM_SHADOW && DIR_CHECK.test(cssText)) {
cssText = this._replaceDirInCssText(cssText);
this.__activateDir = true;
}
return cssText;
}

Expand All @@ -121,9 +130,6 @@ export const DirMixin = dedupingMixin((base) => {
let replacedText = text;
replacedText = replacedText.replace(HOST_DIR, HOST_DIR_REPLACMENT);
replacedText = replacedText.replace(EL_DIR, EL_DIR_REPLACMENT);
if (text !== replacedText) {
this.__activateDir = true;
}
return replacedText;
}

Expand Down
105 changes: 34 additions & 71 deletions lib/mixins/element-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/
import '../utils/boot.js';

import { rootPath, strictTemplatePolicy, allowTemplateFromDomModule } from '../utils/settings.js';
import { rootPath, strictTemplatePolicy, allowTemplateFromDomModule, legacyOptimizations } from '../utils/settings.js';
import { dedupingMixin } from '../utils/mixin.js';
import { stylesFromTemplate, stylesFromModuleImports } from '../utils/style-gather.js';
import { pathFromUrl, resolveCss, resolveUrl } from '../utils/resolve-url.js';
Expand All @@ -23,6 +23,8 @@ import { PropertiesMixin } from './properties-mixin.js';
*/
export const version = '3.0.5';

const builtCSS = window.ShadyCSS && window.ShadyCSS['cssBuild'];

/**
* Element class mixin that provides the core API for Polymer's meta-programming
* features including template stamping, data-binding, attribute deserialization,
Expand Down Expand Up @@ -245,31 +247,33 @@ export const ElementMixin = dedupingMixin(base => {
* @private
*/
function processElementStyles(klass, template, is, baseURI) {
const templateStyles = template.content.querySelectorAll('style');
const stylesWithImports = stylesFromTemplate(template);
// insert styles from <link rel="import" type="css"> at the top of the template
const linkedStyles = stylesFromModuleImports(is);
const firstTemplateChild = template.content.firstElementChild;
for (let idx = 0; idx < linkedStyles.length; idx++) {
let s = linkedStyles[idx];
s.textContent = klass._processStyleText(s.textContent, baseURI);
template.content.insertBefore(s, firstTemplateChild);
}
// keep track of the last "concrete" style in the template we have encountered
let templateStyleIndex = 0;
// ensure all gathered styles are actually in this template.
for (let i = 0; i < stylesWithImports.length; i++) {
let s = stylesWithImports[i];
let templateStyle = templateStyles[templateStyleIndex];
// if the style is not in this template, it's been "included" and
// we put a clone of it in the template before the style that included it
if (templateStyle !== s) {
s = s.cloneNode(true);
templateStyle.parentNode.insertBefore(s, templateStyle);
} else {
templateStyleIndex++;
if (!builtCSS) {
const templateStyles = template.content.querySelectorAll('style');
const stylesWithImports = stylesFromTemplate(template);
// insert styles from <link rel="import" type="css"> at the top of the template
const linkedStyles = stylesFromModuleImports(is);
const firstTemplateChild = template.content.firstElementChild;
for (let idx = 0; idx < linkedStyles.length; idx++) {
let s = linkedStyles[idx];
s.textContent = klass._processStyleText(s.textContent, baseURI);
template.content.insertBefore(s, firstTemplateChild);
}
// keep track of the last "concrete" style in the template we have encountered
let templateStyleIndex = 0;
// ensure all gathered styles are actually in this template.
for (let i = 0; i < stylesWithImports.length; i++) {
let s = stylesWithImports[i];
let templateStyle = templateStyles[templateStyleIndex];
// if the style is not in this template, it's been "included" and
// we put a clone of it in the template before the style that included it
if (templateStyle !== s) {
s = s.cloneNode(true);
templateStyle.parentNode.insertBefore(s, templateStyle);
} else {
templateStyleIndex++;
}
s.textContent = klass._processStyleText(s.textContent, baseURI);
}
s.textContent = klass._processStyleText(s.textContent, baseURI);
}
if (window.ShadyCSS) {
window.ShadyCSS.prepareTemplate(template, is);
Expand Down Expand Up @@ -325,21 +329,21 @@ export const ElementMixin = dedupingMixin(base => {
*/
static _finalizeClass() {
super._finalizeClass();
if (this.hasOwnProperty(
JSCompiler_renameProperty('is', this)) && this.is) {
register(this.prototype);
}
const observers = ownObservers(this);
if (observers) {
this.createObservers(observers, this._properties);
}
this._prepareTemplate();
}

static _prepareTemplate() {
// note: create "working" template that is finalized at instance time
let template = /** @type {PolymerElementConstructor} */ (this).template;
if (template) {
if (typeof template === 'string') {
console.error('template getter must return HTMLTemplateElement');
template = null;
} else {
} else if (!legacyOptimizations) {
template = template.cloneNode(true);
}
}
Expand Down Expand Up @@ -514,7 +518,6 @@ export const ElementMixin = dedupingMixin(base => {
* @suppress {invalidCasts}
*/
_initializeProperties() {
instanceCount++;
this.constructor.finalize();
// note: finalize template when we have access to `localName` to
// avoid dependence on `is` for polyfilling styling.
Expand Down Expand Up @@ -733,46 +736,6 @@ export const ElementMixin = dedupingMixin(base => {
return PolymerElement;
});

/**
* Total number of Polymer element instances created.
* @type {number}
*/
export let instanceCount = 0;

/**
* Array of Polymer element classes that have been finalized.
* @type {Array<PolymerElement>}
*/
export const registrations = [];

/**
* @param {!PolymerElementConstructor} prototype Element prototype to log
* @this {this}
* @private
*/
function _regLog(prototype) {
console.log('[' + prototype.is + ']: registered');
}

/**
* Registers a class prototype for telemetry purposes.
* @param {HTMLElement} prototype Element prototype to register
* @this {this}
* @protected
*/
export function register(prototype) {
registrations.push(prototype);
}

/**
* Logs all elements registered with an `is` to the console.
* @public
* @this {this}
*/
export function dumpRegistrations() {
registrations.forEach(_regLog);
}

/**
* When using the ShadyCSS scoping and custom property shim, causes all
* shimmed `styles` (via `custom-style`) in the document (and its subtree)
Expand Down
10 changes: 8 additions & 2 deletions lib/mixins/properties-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
import '../utils/boot.js';

import { dedupingMixin } from '../utils/mixin.js';
import { register, incrementInstanceCount } from '../utils/telemetry.js';
import { PropertiesChanged } from './properties-changed.js';

/**
Expand Down Expand Up @@ -114,8 +115,12 @@ export const PropertiesMixin = dedupingMixin(superClass => {
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
*/
static get observedAttributes() {
const props = this._properties;
return props ? Object.keys(props).map(p => this.attributeNameForProperty(p)) : [];
if (!this.hasOwnProperty('__observedAttributes')) {
register(this.prototype);
const props = this._properties;
this.__observedAttributes = props ? Object.keys(props).map(p => this.attributeNameForProperty(p)) : [];
}
return this.__observedAttributes;
}

/**
Expand Down Expand Up @@ -189,6 +194,7 @@ export const PropertiesMixin = dedupingMixin(superClass => {
* @return {void}
*/
_initializeProperties() {
incrementInstanceCount();
this.constructor.finalize();
super._initializeProperties();
}
Expand Down
5 changes: 5 additions & 0 deletions lib/mixins/property-effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,11 @@ export const PropertyEffects = dedupingMixin(superClass => {
// Initialize attribute bindings with any literal parts
let literal = literalFromParts(parts);
if (literal && kind == 'attribute') {
// Ensure a ShadyCSS template scoped style is not removed
// when a class$ binding's initial literal value is set.
if (name == 'class' && node.hasAttribute('class')) {
literal += ' ' + node.getAttribute(name);
}
node.setAttribute(name, literal);
}
// Clear attribute before removing, since IE won't allow removing
Expand Down
23 changes: 16 additions & 7 deletions lib/mixins/template-stamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
import '../utils/boot.js';

import { dedupingMixin } from '../utils/mixin.js';
import { legacyOptimizations } from '../utils/settings.js';

const walker = document.createTreeWalker(document, NodeFilter.SHOW_ALL,
null, false);

// 1.x backwards-compatible auto-wrapper for template type extensions
// This is a clear layering violation and gives favored-nation status to
Expand Down Expand Up @@ -45,7 +49,8 @@ function findTemplateNode(root, nodeInfo) {
if (parent) {
// note: marginally faster than indexing via childNodes
// (http://jsperf.com/childnodes-lookup)
for (let n=parent.firstChild, i=0; n; n=n.nextSibling) {
walker.currentNode = parent;
for (let n=walker.firstChild(), i=0; n; n=walker.nextSibling()) {
if (nodeInfo.parentIndex === i++) {
return n;
}
Expand Down Expand Up @@ -200,7 +205,7 @@ export const TemplateStamp = dedupingMixin(
if (!template._templateInfo) {
let templateInfo = template._templateInfo = {};
templateInfo.nodeInfoList = [];
templateInfo.stripWhiteSpace =
templateInfo.stripWhiteSpace = legacyOptimizations ||
(outerTemplateInfo && outerTemplateInfo.stripWhiteSpace) ||
template.hasAttribute('strip-whitespace');
this._parseTemplateContent(template, templateInfo, {parent: null});
Expand Down Expand Up @@ -234,7 +239,8 @@ export const TemplateStamp = dedupingMixin(
// For ShadyDom optimization, indicating there is an insertion point
templateInfo.hasInsertionPoint = true;
}
if (element.firstChild) {
walker.currentNode = element;
if (walker.firstChild()) {
noted = this._parseTemplateChildNodes(element, templateInfo, nodeInfo) || noted;
}
if (element.hasAttributes && element.hasAttributes()) {
Expand All @@ -260,7 +266,8 @@ export const TemplateStamp = dedupingMixin(
if (root.localName === 'script' || root.localName === 'style') {
return;
}
for (let node=root.firstChild, parentIndex=0, next; node; node=next) {
walker.currentNode = root;
for (let node=walker.firstChild(), parentIndex=0, next; node; node=next) {
// Wrap templates
if (node.localName == 'template') {
node = wrapTemplateExtension(node);
Expand All @@ -269,12 +276,13 @@ export const TemplateStamp = dedupingMixin(
// text nodes to be inexplicably split =(
// note that root.normalize() should work but does not so we do this
// manually.
next = node.nextSibling;
walker.currentNode = node;
next = walker.nextSibling();
if (node.nodeType === Node.TEXT_NODE) {
let /** Node */ n = next;
while (n && (n.nodeType === Node.TEXT_NODE)) {
node.textContent += n.textContent;
next = n.nextSibling;
next = walker.nextSibling();
root.removeChild(n);
n = next;
}
Expand All @@ -289,7 +297,8 @@ export const TemplateStamp = dedupingMixin(
childInfo.infoIndex = templateInfo.nodeInfoList.push(/** @type {!NodeInfo} */(childInfo)) - 1;
}
// Increment if not removed
if (node.parentNode) {
walker.currentNode = node;
if (walker.parentNode()) {
parentIndex++;
}
}
Expand Down
23 changes: 22 additions & 1 deletion lib/utils/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,31 @@ export let allowTemplateFromDomModule = false;
/**
* Sets `lookupTemplateFromDomModule` globally for all elements
*
* @param {boolean} allowDomModule enable or disable template lookup
* @param {boolean} allowDomModule enable or disable template lookup
* globally
* @return {void}
*/
export const setAllowTemplateFromDomModule = function(allowDomModule) {
allowTemplateFromDomModule = allowDomModule;
};

/**
* Setting to skip processing style includes and re-writing urls in css styles.
* Normally "included" styles are pulled into the element and all urls in styles
* are re-written to be relative to the containing script url.
* If no includes or relative urls are used in styles, these steps can be
* skipped as an optimization.
*/
export let legacyOptimizations = false;

/**
* Sets `legacyOptimizations` globally for all elements to enable optimizations
* when only legacy based elements are used.
*
* @param {boolean} useLegacyOptimizations enable or disable legacy optimizations
* includes and url rewriting
* @return {void}
*/
export const setLegacyOptimizations = function(useLegacyOptimizations) {
legacyOptimizations = useLegacyOptimizations;
};
Loading

0 comments on commit c23ff5e

Please sign in to comment.