Merge branch 'master' into shady-linked

This commit is contained in:
Steven Orvell 2015-12-07 14:00:48 -08:00
commit 34031414e5
28 changed files with 793 additions and 467 deletions

View File

@ -11,11 +11,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/*
Extremely simple css parser. Intended to be not more than what we need
and definitely not necessarly correct =).
and definitely not necessarily correct =).
*/
Polymer.CssParse = (function() {
var api = {
return {
// given a string of css, return a simple rule tree
parse: function(text) {
text = this._clean(text);
@ -31,7 +31,7 @@ Polymer.CssParse = (function() {
_lex: function(text) {
var root = {start: 0, end: text.length};
var n = root;
for (var i=0, s=0, l=text.length; i < l; i++) {
for (var i=0, l=text.length; i < l; i++) {
switch (text[i]) {
case this.OPEN_BRACE:
//console.group(i);
@ -123,7 +123,7 @@ Polymer.CssParse = (function() {
}
}
}
// emit rule iff there is cssText
// emit rule if there is cssText
if (cssText) {
if (node.selector) {
text += node.selector + ' ' + this.OPEN_BRACE + '\n';
@ -185,10 +185,6 @@ Polymer.CssParse = (function() {
};
// exports
return api;
})();
</script>

View File

@ -1,200 +1,200 @@
<!--
@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
-->
<link rel="import" href="style-util.html">
<link rel="import" href="style-transformer.html">
<link rel="import" href="style-defaults.html">
<!--
The `custom-style` extension of the native `<style>` element allows defining styles
in the main document that can take advantage of several special features of
Polymer's styling system:
* Document styles defined in a `custom-style` will be shimmed to ensure they do
not leak into local DOM when running on browsers without non-native Shadow DOM.
* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on
browsers without non-native Shadow DOM.
* Custom properties used by Polymer's shim for cross-scope styling
may be defined in an `custom-style`.
* An `include` attribute may be specified to pull in style data from a
`dom-module` matching the include attribute. By using `include`, style data
can be shared between multiple `custom-style` elements.
Example:
```html
<!doctype html>
<html>
<head>
<script src="components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="components/polymer/polymer.html">
<style is="custom-style">
/* Will be prevented from affecting local DOM of Polymer elements */
* {
box-sizing: border-box;
}
/* Can use /deep/ and ::shadow combinators */
body /deep/ .my-special-view::shadow #thing-inside {
background: yellow;
}
/* Custom properties that inherit down the document tree may be defined */
body {
--my-toolbar-title-color: green;
}
</style>
</head>
<body>
...
</body>
</html>
```
Note, all features of `custom-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `custom-style` extension should only be used for defining document styles, outside of a custom element's local DOM.
-->
<script>
(function() {
var nativeShadow = Polymer.Settings.useNativeShadow;
var propertyUtils = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil;
var cssParse = Polymer.CssParse;
var styleDefaults = Polymer.StyleDefaults;
var styleTransformer = Polymer.StyleTransformer;
Polymer({
is: 'custom-style',
extends: 'style',
_template: null,
properties: {
// include is a property so that it deserializes
/**
* Specify `include` to identify a `dom-module` containing style data which
* should be used within the `custom-style`. By using `include` style data
* may be shared between multiple different `custom-style` elements.
*/
include: String
},
ready: function() {
// NOTE: we cannot just check attached because custom elements in
// HTMLImports do not get attached.
this._tryApply();
},
attached: function() {
this._tryApply();
},
_tryApply: function() {
if (!this._appliesToDocument) {
// only apply variables iff this style is not inside a dom-module
if (this.parentNode &&
(this.parentNode.localName !== 'dom-module')) {
this._appliesToDocument = true;
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
styleDefaults.addStyle(e);
// we may not have any textContent yet due to parser yielding
// if so, wait until we do...
if (e.textContent || this.include) {
this._apply(true);
} else {
var self = this;
var observer = new MutationObserver(function() {
observer.disconnect();
self._apply(true);
});
observer.observe(e, {childList: true});
}
}
}
},
// polyfill this style with root scoping and
// apply custom properties!
_apply: function(deferProperties) {
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
if (this.include) {
e.textContent = styleUtil.cssFromModules(this.include, true) +
e.textContent;
}
if (e.textContent) {
styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function(rule) {
styleTransformer.documentRule(rule);
});
// Allow all custom-styles defined in this turn to register
// before applying any properties. This helps ensure that all properties
// are defined before any are consumed.
// Premature application of properties can occur in 2 cases:
// (1) A property `--foo` is consumed in a custom-style
// before another custom-style produces `--foo`.
// In general, we require custom properties to be defined before being
// used in elements so supporting this for custom-style
// is dubious but is slightly more like native properties where this
// is supported.
// (2) A set of in order styles (A, B) are re-ordered due to a parser
// yield that makes A wait for textContent. This reorders its
// `_apply` after B.
// This case should only occur with native webcomponents.
var self = this;
function fn() {
self._applyCustomProperties(e);
}
if (this._pendingApplyProperties) {
cancelAnimationFrame(this._pendingApplyProperties);
this._pendingApplyProperties = null;
}
if (deferProperties) {
this._pendingApplyProperties = requestAnimationFrame(fn);
} else {
fn();
}
}
},
_applyCustomProperties: function(element) {
this._computeStyleProperties();
var props = this._styleProperties;
var rules = styleUtil.rulesForStyle(element);
element.textContent = styleUtil.toCssText(rules, function(rule) {
var css = rule.cssText = rule.parsedCssText;
if (rule.propertyInfo && rule.propertyInfo.cssText) {
// remove property assignments
// so next function isn't confused
// NOTE: we have 3 categories of css:
// (1) normal properties,
// (2) custom property assignments (--foo: red;),
// (3) custom property usage: border: var(--foo); @apply(--foo);
// In elements, 1 and 3 are separated for efficiency; here they
// are not and this makes this case unique.
css = cssParse.removeCustomPropAssignment(css);
// replace with reified properties, scenario is same as mixin
rule.cssText = propertyUtils.valueForProperties(css, props);
}
});
}
});
})();
</script>
<!--
@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
-->
<link rel="import" href="style-util.html">
<link rel="import" href="style-transformer.html">
<link rel="import" href="style-defaults.html">
<!--
The `custom-style` extension of the native `<style>` element allows defining styles
in the main document that can take advantage of several special features of
Polymer's styling system:
* Document styles defined in a `custom-style` will be shimmed to ensure they do
not leak into local DOM when running on browsers without non-native Shadow DOM.
* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on
browsers without non-native Shadow DOM.
* Custom properties used by Polymer's shim for cross-scope styling
may be defined in an `custom-style`.
* An `include` attribute may be specified to pull in style data from a
`dom-module` matching the include attribute. By using `include`, style data
can be shared between multiple `custom-style` elements.
Example:
```html
<!doctype html>
<html>
<head>
<script src="components/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="components/polymer/polymer.html">
<style is="custom-style">
/* Will be prevented from affecting local DOM of Polymer elements */
* {
box-sizing: border-box;
}
/* Can use /deep/ and ::shadow combinators */
body /deep/ .my-special-view::shadow #thing-inside {
background: yellow;
}
/* Custom properties that inherit down the document tree may be defined */
body {
--my-toolbar-title-color: green;
}
</style>
</head>
<body>
...
</body>
</html>
```
Note, all features of `custom-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `custom-style` extension should only be used for defining document styles, outside of a custom element's local DOM.
-->
<script>
(function() {
var nativeShadow = Polymer.Settings.useNativeShadow;
var propertyUtils = Polymer.StyleProperties;
var styleUtil = Polymer.StyleUtil;
var cssParse = Polymer.CssParse;
var styleDefaults = Polymer.StyleDefaults;
var styleTransformer = Polymer.StyleTransformer;
Polymer({
is: 'custom-style',
extends: 'style',
_template: null,
properties: {
// include is a property so that it deserializes
/**
* Specify `include` to identify a `dom-module` containing style data which
* should be used within the `custom-style`. By using `include` style data
* may be shared between multiple different `custom-style` elements.
*/
include: String
},
ready: function() {
// NOTE: we cannot just check attached because custom elements in
// HTMLImports do not get attached.
this._tryApply();
},
attached: function() {
this._tryApply();
},
_tryApply: function() {
if (!this._appliesToDocument) {
// only apply variables iff this style is not inside a dom-module
if (this.parentNode &&
(this.parentNode.localName !== 'dom-module')) {
this._appliesToDocument = true;
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
styleDefaults.addStyle(e);
// we may not have any textContent yet due to parser yielding
// if so, wait until we do...
if (e.textContent || this.include) {
this._apply(true);
} else {
var self = this;
var observer = new MutationObserver(function() {
observer.disconnect();
self._apply(true);
});
observer.observe(e, {childList: true});
}
}
}
},
// polyfill this style with root scoping and
// apply custom properties!
_apply: function(deferProperties) {
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
if (this.include) {
e.textContent = styleUtil.cssFromModules(this.include, true) +
e.textContent;
}
if (e.textContent) {
styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function(rule) {
styleTransformer.documentRule(rule);
});
// Allow all custom-styles defined in this turn to register
// before applying any properties. This helps ensure that all properties
// are defined before any are consumed.
// Premature application of properties can occur in 2 cases:
// (1) A property `--foo` is consumed in a custom-style
// before another custom-style produces `--foo`.
// In general, we require custom properties to be defined before being
// used in elements so supporting this for custom-style
// is dubious but is slightly more like native properties where this
// is supported.
// (2) A set of in order styles (A, B) are re-ordered due to a parser
// yield that makes A wait for textContent. This reorders its
// `_apply` after B.
// This case should only occur with native webcomponents.
var self = this;
var fn = function fn() {
self._applyCustomProperties(e);
}
if (this._pendingApplyProperties) {
cancelAnimationFrame(this._pendingApplyProperties);
this._pendingApplyProperties = null;
}
if (deferProperties) {
this._pendingApplyProperties = requestAnimationFrame(fn);
} else {
fn();
}
}
},
_applyCustomProperties: function(element) {
this._computeStyleProperties();
var props = this._styleProperties;
var rules = styleUtil.rulesForStyle(element);
element.textContent = styleUtil.toCssText(rules, function(rule) {
var css = rule.cssText = rule.parsedCssText;
if (rule.propertyInfo && rule.propertyInfo.cssText) {
// remove property assignments
// so next function isn't confused
// NOTE: we have 3 categories of css:
// (1) normal properties,
// (2) custom property assignments (--foo: red;),
// (3) custom property usage: border: var(--foo); @apply(--foo);
// In elements, 1 and 3 are separated for efficiency; here they
// are not and this makes this case unique.
css = cssParse.removeCustomPropAssignment(css);
// replace with reified properties, scenario is same as mixin
rule.cssText = propertyUtils.valueForProperties(css, props);
}
});
}
});
})();
</script>

View File

@ -87,9 +87,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var parts = cssText.split(';');
for (var i=0, p; i<parts.length; i++) {
p = parts[i];
if (p.match(this.rx.MIXIN_MATCH) || p.match(this.rx.VAR_MATCH)) {
customCssText += p + ';\n';
}
customCssText += p + ';\n';
}
return customCssText;
},
@ -166,7 +164,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
p || '';
}
}
return parts.filter(function(v) {return v;}).join(';');
return parts.join(';');
},
applyProperties: function(rule, props) {
@ -181,7 +179,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
rule.cssText = output;
},
// Test if the rules in these styles matche the given `element` and if so,
// Test if the rules in these styles matches the given `element` and if so,
// collect any custom properties into `props`.
propertyDataFromStyles: function(styles, element) {
var props = {}, self = this;
@ -208,7 +206,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return {properties: props, key: o};
},
// Test if a rule matches scope crteria (* or :root) and if so,
// Test if a rule matches scope criteria (* or :root) and if so,
// collect any custom properties into `props`.
scopePropertiesFromStyles: function(styles) {
if (!styles._scopeStyleProperties) {
@ -218,7 +216,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return styles._scopeStyleProperties;
},
// Test if a rule matches host crteria (:host) and if so,
// Test if a rule matches host criteria (:host) and if so,
// collect any custom properties into `props`.
//
// TODO(sorvell): this should change to collecting properties from any
@ -319,7 +317,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// otherwise, if we have css to apply, do so
} else if (cssText) {
// apply css after the scope style of the element to help with
// style predence rules.
// style precedence rules.
style = styleUtil.applyCss(cssText, selector,
nativeShadow ? element.root : null, element._scopeStyle);
}
@ -356,7 +354,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// var(--a)
// var(--a, --b)
// var(--a, fallback-literal)
// var(--a, fallback-literal(with-one-nested-parens))
// var(--a, fallback-literal(with-one-nested-parentheses))
VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi,
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
IS_VAR: /^--/,

View File

@ -34,7 +34,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
cannot otherwise be scoped:
e.g. :host ::content > .bar -> x-foo > .bar
* ::shadow, /deep/: processed simimlar to ::content
* ::shadow, /deep/: processed similar to ::content
* :host-context(...): scopeName..., ... scopeName
@ -97,7 +97,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
elementStyles: function(element, callback) {
var styles = element._styles;
var cssText = '';
for (var i=0, l=styles.length, s, text; (i<l) && (s=styles[i]); i++) {
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
var rules = styleUtil.rulesForStyle(s);
cssText += nativeShadow ?
styleUtil.toCssText(rules, callback) :
@ -152,7 +152,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
p$[i] = transformer.call(this, p, scope, hostScope);
}
// NOTE: save transformedSelector for subsequent matching of elements
// agsinst selectors (e.g. when calculating style properties)
// against selectors (e.g. when calculating style properties)
rule.selector = rule.transformedSelector =
p$.join(COMPLEX_SELECTOR_SEP);
},
@ -258,9 +258,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// parsing which seems like overkill
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var HOST_CONTEXT = ':host-context';
var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var CONTENT = '::content';
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//;
var SCOPE_JUMP = /::content|::shadow|\/deep\//;
var CSS_CLASS_PREFIX = '.';
var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
var CSS_ATTR_SUFFIX = ']';

View File

@ -44,15 +44,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return style.__cssRules;
},
clearStyleRules: function(style) {
style.__cssRules = null;
},
forEachStyleRule: function(node, callback) {
if (!node) {
return;
}
var s = node.parsedSelector;
var skipRules = false;
if (node.type === this.ruleTypes.STYLE_RULE) {
callback(node);

View File

@ -73,13 +73,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
detached: function() {
// TODO(kschaaf): add logic to re-stamp in attached?
this._teardownInstance();
if (!this.parentNode) {
this._teardownInstance();
}
},
attached: function() {
if (this.if && this.ctor) {
// TODO(sorvell): should not be async, but node can be attached
// NOTE: ideally should not be async, but node can be attached
// when shady dom is in the act of distributing/composing so push it out
this.async(this._ensureInstance);
}
@ -116,16 +117,25 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_ensureInstance: function() {
if (!this._instance) {
var parentNode = Polymer.dom(this).parentNode;
// Guard against element being detached while render was queued
if (parentNode) {
var parent = Polymer.dom(parentNode);
// TODO(sorvell): pickup stamping logic from x-repeat
var parentNode = Polymer.dom(this).parentNode;
// Guard against element being detached while render was queued
if (parentNode) {
var parent = Polymer.dom(parentNode);
if (!this._instance) {
this._instance = this.stamp();
var root = this._instance.root;
// TODO(sorvell): this incantation needs to be simpler.
parent.insertBefore(root, this);
} else {
var c$ = this._instance._children;
if (c$ && c$.length) {
// Detect case where dom-if was re-attached in new position
var lastChild = Polymer.dom(this).previousSibling;
if (lastChild !== c$[c$.length-1]) {
for (var i=0, n; (i<c$.length) && (n=c$[i]); i++) {
parent.insertBefore(n, this);
}
}
}
}
}
},
@ -133,7 +143,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_teardownInstance: function() {
if (this._instance) {
var c$ = this._instance._children;
if (c$) {
if (c$ && c$.length) {
// use first child parent, for case when dom-if may have been detached
var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode);
for (var i=0, n; (i<c$.length) && (n=c$[i]); i++) {

View File

@ -124,6 +124,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
archetype._scopeElementClass = this._scopeElementClassImpl;
archetype.listen = this._listenImpl;
archetype._showHideChildren = this._showHideChildrenImpl;
archetype.__setPropertyOrig = this.__setProperty;
archetype.__setProperty = this.__setPropertyImpl;
// boilerplate code
var _constructor = this._constructorImpl;
var ctor = function TemplateInstance(model, host) {
@ -168,6 +170,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
},
__setPropertyImpl: function(property, value, fromAbove, node) {
if (node && node.__hideTemplateChildren__ && property == 'textContent') {
property = '__polymerTextContent__';
}
this.__setPropertyOrig(property, value, fromAbove, node);
},
_debounceTemplate: function(fn) {
Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn));
},
@ -242,7 +251,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, {
kind: 'notify',
fn: Polymer.Bind._notifyEffect,
effect: {event:
effect: {event:
Polymer.CaseMap.camelToDashCase(parentProp) + '-changed'}
}];
Polymer.Bind._createAccessors(proto, parentProp, effects);
@ -259,7 +268,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
this._extendTemplate(template, proto);
template._pathEffector = function(path, value, fromAbove) {
return self._pathEffectorImpl(path, value, fromAbove);
return self._pathEffectorImpl(path, value, fromAbove);
}
}
},

View File

@ -130,8 +130,8 @@ TODO(sjmiles): this module should produce either syntactic metadata
this._notes = this._template._content._notes;
} else {
this._notes = Polymer.Annotations.parseAnnotations(this._template);
this._processAnnotations(this._notes);
}
this._processAnnotations(this._notes);
Polymer.Annotations.prepElement = null;
}
},
@ -188,10 +188,15 @@ TODO(sjmiles): this module should produce either syntactic metadata
if (p.signature) {
var args = p.signature.args;
for (var kk=0; kk<args.length; kk++) {
pp[args[kk].model] = true;
var model = args[kk].model;
if (model) {
pp[model] = true;
}
}
} else {
pp[p.model] = true;
if (p.model) {
pp[p.model] = true;
}
}
}
}

View File

@ -185,7 +185,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// method expressions are of the form: `name([arg1, arg2, .... argn])`
_parseMethod: function(expression) {
// tries to match valid javascript property names
var m = expression.match(/([^\s]+)\((.*)\)/);
var m = expression.match(/([^\s]+?)\((.*)\)/);
if (m) {
var sig = { method: m[1], static: true };
if (m[2].trim()) {
@ -222,8 +222,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
;
// basic argument descriptor
var a = {
name: arg,
model: this._modelForPath(arg)
name: arg
};
// detect literal value (must be String or Number)
var fc = arg[0];
@ -246,6 +245,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
// if not literal, look for structured path
if (!a.literal) {
a.model = this._modelForPath(arg);
// detect structured path (has dots)
a.structured = arg.indexOf('.') > 0;
if (a.structured) {

View File

@ -79,6 +79,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
style.textContent = cssText;
// extends!!
if (styleExtends.hasExtends(style.textContent)) {
// TODO(sorvell): variable is not used, should it update `style.textContent`?
cssText = styleExtends.transform(style);
}
styles.push(style);
@ -109,7 +110,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* Apply style scoping to the specified `container` and all its
* descendants. If `shoudlObserve` is true, changes to the container are
* descendants. If `shouldObserve` is true, changes to the container are
* monitored via mutation observer and scoping is applied.
*
* This method is useful for ensuring proper local DOM CSS scoping

View File

@ -139,7 +139,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
behaviors: [
Polymer.BehaviorA,
null,
Polymer.BehaviorB
],
@ -260,4 +259,4 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
</script>
</script>

View File

@ -127,6 +127,27 @@ suite('multi-behaviors element', function() {
assert.equal(el.attributes.user.value, 'user', 'Behavior hostAttribute overrode user attribute');
});
test('behaviour is null generates warning', function() {
var warned = false, oldWarn = Polymer.Base._warn;
Polymer.Base._warn = function (message) {
assert.match(message, /behavior is null/);
warned = true;
};
Polymer({
behaviors: [
null
],
is: 'behavior-null'
});
assert.equal(warned, true, 'Null behaviour should generate warning');
Polymer.Base._warn = oldWarn;
});
});

View File

@ -43,6 +43,7 @@
<span id="boundText">{{text}}</span>
<span idtest id="{{boundId}}"></span>
<s id="computedContent">{{computeFromTrickyLiterals(3, 'tricky\,\'zot\'')}}</s>
<s id="computedContent2">{{computeFromTrickyLiterals("(",3)}}</s>
<input id="boundInput" value="{{text::input}}">
<div id="compound1">{{cpnd1}}{{cpnd2}}{{cpnd3.prop}}{{computeCompound(cpnd4, cpnd5, 'literal')}}</div>
<div id="compound2">

View File

@ -174,6 +174,7 @@ suite('single-element binding effects', function() {
assert.equal(el.$.boundChild.computedFromTrickyLiterals, '3tricky,\'zot\'', 'Wrong result from tricky literal arg computation');
assert.equal(el.$.boundChild.computedFromTrickyLiterals2, '3tricky,\'zot\'', 'Wrong result from tricky literal arg computation');
assert.equal(el.$.computedContent.textContent, '3tricky,\'zot\'', 'Wrong textContent from tricky literal arg computation');
assert.equal(el.$.computedContent2.textContent, '(3', 'Wrong textContent from tricky literal arg computation');
});
test('computed annotation with no args', function() {
@ -675,7 +676,6 @@ suite('warnings', function() {
var warned = false;
el._warn = function() {
warned = true;
warn.apply(el, arguments);
};
el.noObserver = 42;
assert.equal(warned, true, 'no warning for undefined observer');
@ -685,7 +685,6 @@ suite('warnings', function() {
var warned = false;
el._warn = function() {
warned = true;
warn.apply(el, arguments);
};
el.noComplexObserver = {};
assert.equal(warned, true, 'no warning for undefined complex observer');
@ -695,7 +694,6 @@ suite('warnings', function() {
var warned = false;
el._warn = function() {
warned = true;
warn.apply(el, arguments);
};
el.noComputed = 99;
assert.equal(warned, true, 'no warning for undefined computed function');
@ -705,7 +703,6 @@ suite('warnings', function() {
var warned = false;
el._warn = function() {
warned = true;
warn.apply(el, arguments);
};
el.noInlineComputed = 99;
assert.equal(warned, true, 'no warning for undefined computed function');

View File

@ -116,7 +116,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
assert.equal(tree.rules.length, 4, 'unexpected number of rules');
assert.equal(tree.rules[2].rules.length, 8, 'unexpected number of rules in keyframes');
assert.equal(tree.rules[3].rules.length, 1, 'unexpected number of rules in @media');
console.log('test');
});
test('rule selectors parse', function() {
@ -166,7 +165,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
assert.equal(t.rules[3].selector, '.\\0c3333d-model');
assert.equal(t.rules[4].selector, '.\\d33333d-model');
assert.equal(t.rules[5].selector, '.\\e33333d-model');
});
});
test('multiple consequent spaces in CSS selector', function() {
var s4 = document.querySelector('#multiple-spaces');
var t = css.parse(s4.textContent);

View File

@ -1,5 +1,4 @@
<script>
console.log('x-needs-repeat loaded')
Polymer({
is: 'x-needs-host',
ready: function() {
@ -9,4 +8,4 @@ console.log('x-needs-repeat loaded')
this.config = this.dataHost.getAttribute('config');
}
});
</script>
</script>

View File

@ -226,6 +226,5 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</script>
<link rel="import" href="dom-bind-elements2.html">
<link rel="import" href="should-404.html">
</body>
</html>

View File

@ -165,13 +165,42 @@
<div>1</div>
<div>2</div>
<div>3</div>
Stuff
{{text}}
<div>4</div>
</template>
</template>
<script>
Polymer({
is: 'x-textcontent'
is: 'x-textcontent',
properties: {
text: {
value: 'Stuff'
}
}
});
</script>
</dom-module>
<dom-module id="x-host">
<template>
<template id="domif" is="dom-if" if>
<x-client></x-client>
<x-client></x-client>
<x-client></x-client>
</template>
</template>
<script>
Polymer({
is: 'x-host'
});
Polymer({
is: 'x-client',
statics: {
uid: 0
},
ready: function() {
this.uid = this.statics.uid++;
}
});
</script>
</dom-module>

View File

@ -56,9 +56,16 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
</div>
<template is="dom-if" id="simple">
<div></div>
</template>
<div id="outerContainer">
<template is="dom-if" id="simple">
<x-client></x-client>
<x-client></x-client>
<x-client></x-client>
</template>
<div id="innerContainer">
</div>
</div>
<script>
@ -495,21 +502,155 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
document.body.removeChild(x);
});
test('binding to text nodes changed while if=false', function() {
var x = document.createElement('x-textcontent');
document.body.appendChild(x);
x.$.domIf.render();
var stamped = Polymer.dom(x.root).childNodes;
assert.equal(stamped.length, 12);
assert.equal(stamped[7].textContent.trim(), 'Stuff');
x.$.domIf.if = false;
x.$.domIf.render();
x.text = 'Hollaaaaa!';
stamped = Polymer.dom(x.root).childNodes;
assert.equal(stamped.length, 12);
assert.equal(stamped[7].textContent.trim(), '');
x.$.domIf.if = true;
x.$.domIf.render();
stamped = Polymer.dom(x.root).childNodes;
assert.equal(stamped.length, 12);
assert.equal(stamped[7].textContent.trim(), 'Hollaaaaa!');
document.body.removeChild(x);
});
});
suite('queueing race conditions', function() {
suite('attach/detach tests', function() {
test('domif=true, attach, detach', function(done) {
test('remove, append domif', function(done) {
var domif = document.querySelector('#simple');
domif.if = true;
document.body.appendChild(domif);
document.body.removeChild(domif);
outerContainer.removeChild(domif);
setTimeout(function() {
document.body.appendChild(domif);
var clients = outerContainer.querySelectorAll('x-client');
assert.equal(clients.length, 0);
outerContainer.appendChild(domif);
setTimeout(function() {
var clients = outerContainer.querySelectorAll('x-client');
assert.equal(clients[0].uid, 0);
assert.equal(clients[1].uid, 1);
assert.equal(clients[2].uid, 2);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(domif.previousElementSibling, clients[2]);
done();
});
});
});
test('move domif (clients persist)', function(done) {
var domif = document.querySelector('#simple');
domif.if = true;
Polymer.dom(innerContainer).appendChild(domif);
setTimeout(function() {
var clients = innerContainer.querySelectorAll('x-client');
// Same clients as before since move happened in one turn
assert.equal(clients[0].uid, 0);
assert.equal(clients[1].uid, 1);
assert.equal(clients[2].uid, 2);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(domif.previousElementSibling, clients[2]);
done();
});
});
test('remove, wait, append domif (clients recreated)', function(done) {
var domif = document.querySelector('#simple');
domif.if = true;
Polymer.dom(innerContainer).removeChild(domif);
setTimeout(function() {
var clients = innerContainer.querySelectorAll('x-client');
assert.equal(clients.length, 0);
Polymer.dom(innerContainer).appendChild(domif);
setTimeout(function() {
var clients = outerContainer.querySelectorAll('x-client');
// New clients since removed for a turn
assert.equal(clients[0].uid, 3);
assert.equal(clients[1].uid, 4);
assert.equal(clients[2].uid, 5);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(domif.previousElementSibling, clients[2]);
done();
});
});
});
test('move host with domif (clients persist)', function(done) {
var host = document.createElement('x-host');
Polymer.dom(outerContainer).appendChild(host);
setTimeout(function() {
var clients = Polymer.dom(host.root).querySelectorAll('x-client');
// New clients created in host instance
assert.equal(clients[0].uid, 6);
assert.equal(clients[1].uid, 7);
assert.equal(clients[2].uid, 8);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(host.$.domif.previousElementSibling, clients[2]);
Polymer.dom(innerContainer).appendChild(host);
setTimeout(function() {
var clients = Polymer.dom(host.root).querySelectorAll('x-client');
// Clients in removed host persist
assert.equal(clients[0].uid, 6);
assert.equal(clients[1].uid, 7);
assert.equal(clients[2].uid, 8);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(host.$.domif.previousElementSibling, clients[2]);
done();
});
});
});
test('remove, wait, append host with domif (clients persist)', function(done) {
var host = document.createElement('x-host');
Polymer.dom(outerContainer).appendChild(host);
setTimeout(function() {
var clients = Polymer.dom(host.root).querySelectorAll('x-client');
// New clients created in host instance
assert.equal(clients[0].uid, 9);
assert.equal(clients[1].uid, 10);
assert.equal(clients[2].uid, 11);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(host.$.domif.previousElementSibling, clients[2]);
Polymer.dom(outerContainer).removeChild(host);
setTimeout(function() {
// Clients in removed host persist
assert.equal(clients[0].uid, 9);
assert.equal(clients[1].uid, 10);
assert.equal(clients[2].uid, 11);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(host.$.domif.previousElementSibling, clients[2]);
Polymer.dom(innerContainer).appendChild(host);
setTimeout(function() {
// Clients in removed host persist
var clients = Polymer.dom(host.root).querySelectorAll('x-client');
assert.equal(clients[0].uid, 9);
assert.equal(clients[1].uid, 10);
assert.equal(clients[2].uid, 11);
assert.equal(clients[1].previousElementSibling, clients[0]);
assert.equal(clients[2].previousElementSibling, clients[1]);
assert.equal(host.$.domif.previousElementSibling, clients[2]);
done();
});
});
});
});
});

View File

@ -103,9 +103,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
suite('errors', function() {
test('items must be array', function() {
assert.throws(function() {
inDocumentRepeater.items = {};
}, /expected array/, 'should warn when items is not array');
var warned = false;
inDocumentRepeater._error = function(message) {
assert.match(message, /expected array/)
warned = true;
}
inDocumentRepeater.items = {};
assert.equal(warned, true, 'should warn when items is not array');
});
});
@ -3646,207 +3650,204 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
suite('chunked rendering', function() {
// TODO(kschaaf): This test suite has proven to be flaky only on IE, only
// on CI (Sauce) presumably because of rAF handling in the CI environment
// disabling for IE for now to avoid Polymer tests being flaky
if (!/Trident/.test(navigator.userAgent)) {
// Patch requestAnimationFrame to setTimeout to reduce IE test flakiness on CI
var rAF;
suiteSetup(function() {
rAF = window.requestAnimationFrame;
window.requestAnimationFrame = setTimeout;
});
suiteTeardown(function() {
window.requestAnimationFrame = rAF;
});
suite('chunked rendering', function() {
test('basic chunked rendering', function(done) {
test('basic chunked rendering', function(done) {
var checkItemOrder = function(stamped) {
for (var i=0; i<stamped.length; i++) {
assert.equal(stamped[i].textContent, i);
}
};
var lastLength = 0;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
assert.isTrue(stamped.length > lastLength);
}
if (stamped.length < 100) {
lastLength = stamped.length;
checkUntilComplete();
} else {
// Final rendering at exact item count
assert.equal(stamped.length, 100);
done();
}
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
}
};
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
});
test('mutations during chunked rendering', function(done) {
var checkItemOrder = function(stamped) {
var last = -1;
for (var i=0; i<stamped.length; i++) {
var curr = parseFloat(stamped[i].textContent);
assert.isTrue(curr > last);
last = curr;
}
};
var mutateArray = function(repeater, renderedCount) {
// The goal here is to remove & add some, and do it over
// the threshold of where we have currently rendered items, and
// ensure that the prop values of the newly inserted items are in
// ascending order so we can do a simple check in checkItemOrder
var overlap = 2;
var remove = 4;
var add = 6;
var start = renderedCount.length - overlap;
if (start + add < repeater.items.length) {
var end = start + remove;
var args = ['items', start, remove];
var startVal = repeater.items[start].prop;
var endVal = repeater.items[end].prop;
var delta = (endVal - startVal) / add;
for (var i=0; i<add; i++) {
args.push({prop: startVal + i*delta});
var checkItemOrder = function(stamped) {
for (var i=0; i<stamped.length; i++) {
assert.equal(stamped[i].textContent, i);
}
repeater.splice.apply(repeater, args);
}
};
};
var lastLength = 0;
var mutateCount = 5;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
assert.isTrue(stamped.length > lastLength);
}
if (stamped.length < chunked.items.length) {
if (mutateCount-- > 0) {
mutateArray(chunked, stamped);
}
lastLength = stamped.length;
checkUntilComplete();
} else {
// Final rendering at exact item count
assert.equal(stamped.length, chunked.items.length);
done();
}
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
}
};
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
});
test('mutations during chunked rendering, sort & filtered', function(done) {
var checkItemOrder = function(stamped) {
var last = Infinity;
for (var i=0; i<stamped.length; i++) {
var curr = parseFloat(stamped[i].textContent);
assert.isTrue(curr <= last);
assert.strictEqual(curr % 2, 0);
last = curr;
}
};
var mutateArray = function(repeater, stamped) {
var start = parseInt(stamped[0].textContent);
var end = parseInt(stamped[stamped.length-1].textContent);
var mid = (end-start)/2;
for (var i=0; i<5; i++) {
chunked.push('items', {prop: mid + 1});
}
chunked.splice('items', Math.round(stamped.length/2), 3);
};
var lastLength = 0;
var mutateCount = 5;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
var filteredLength = chunked.items.filter(chunked.$.repeater.filter).length;
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
if (stamped.length < filteredLength) {
var lastLength = 0;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
assert.isTrue(stamped.length > lastLength);
}
}
if (stamped.length < filteredLength) {
if (mutateCount-- > 0) {
mutateArray(chunked, stamped);
if (stamped.length < 100) {
lastLength = stamped.length;
checkUntilComplete();
} else {
// Final rendering at exact item count
assert.equal(stamped.length, 100);
done();
}
lastLength = stamped.length;
checkUntilComplete();
} else {
assert.equal(stamped.length, filteredLength);
done();
}
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
}
};
}
};
chunked.$.repeater.sort = function(a, b) {
return b.prop - a.prop;
};
chunked.$.repeater.filter = function(a) {
return (a.prop % 2) === 0;
};
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
});
test('mutations during chunked rendering', function(done) {
var checkItemOrder = function(stamped) {
var last = -1;
for (var i=0; i<stamped.length; i++) {
var curr = parseFloat(stamped[i].textContent);
assert.isTrue(curr > last);
last = curr;
}
};
var mutateArray = function(repeater, renderedCount) {
// The goal here is to remove & add some, and do it over
// the threshold of where we have currently rendered items, and
// ensure that the prop values of the newly inserted items are in
// ascending order so we can do a simple check in checkItemOrder
var overlap = 2;
var remove = 4;
var add = 6;
var start = renderedCount.length - overlap;
if (start + add < repeater.items.length) {
var end = start + remove;
var args = ['items', start, remove];
var startVal = repeater.items[start].prop;
var endVal = repeater.items[end].prop;
var delta = (endVal - startVal) / add;
for (var i=0; i<add; i++) {
args.push({prop: startVal + i*delta});
}
repeater.splice.apply(repeater, args);
}
};
var lastLength = 0;
var mutateCount = 5;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
assert.isTrue(stamped.length > lastLength);
}
if (stamped.length < chunked.items.length) {
if (mutateCount-- > 0) {
mutateArray(chunked, stamped);
}
lastLength = stamped.length;
checkUntilComplete();
} else {
// Final rendering at exact item count
assert.equal(stamped.length, chunked.items.length);
done();
}
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
}
};
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
});
test('mutations during chunked rendering, sort & filtered', function(done) {
var checkItemOrder = function(stamped) {
var last = Infinity;
for (var i=0; i<stamped.length; i++) {
var curr = parseFloat(stamped[i].textContent);
assert.isTrue(curr <= last);
assert.strictEqual(curr % 2, 0);
last = curr;
}
};
var mutateArray = function(repeater, stamped) {
var start = parseInt(stamped[0].textContent);
var end = parseInt(stamped[stamped.length-1].textContent);
var mid = (end-start)/2;
for (var i=0; i<5; i++) {
chunked.push('items', {prop: mid + 1});
}
chunked.splice('items', Math.round(stamped.length/2), 3);
};
var lastLength = 0;
var mutateCount = 5;
var checkCount = function() {
var stamped = Polymer.dom(chunked.root).querySelectorAll('*:not(template)');
checkItemOrder(stamped);
var filteredLength = chunked.items.filter(chunked.$.repeater.filter).length;
if (stamped.length && lastLength === 0) {
// Initial rendering of initial count
assert.equal(stamped.length, 10);
} else {
// Remaining rendering incremenets
if (stamped.length < filteredLength) {
assert.isTrue(stamped.length > lastLength);
}
}
if (stamped.length < filteredLength) {
if (mutateCount-- > 0) {
mutateArray(chunked, stamped);
}
lastLength = stamped.length;
checkUntilComplete();
} else {
assert.equal(stamped.length, filteredLength);
done();
}
};
var checkUntilComplete = function() {
// On polyfilled MO, need to wait one setTimeout before rAF
if (MutationObserver._isPolyfilled) {
setTimeout(function() {
requestAnimationFrame(checkCount);
});
} else {
requestAnimationFrame(checkCount);
}
};
chunked.$.repeater.sort = function(a, b) {
return b.prop - a.prop;
};
chunked.$.repeater.filter = function(a) {
return (a.prop % 2) === 0;
};
chunked.items = chunked.preppedItems.slice();
checkUntilComplete();
});
});
});
}
</script>

View File

@ -57,7 +57,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
test(':host, :host(...)', function() {
assertComputed(styled, '1px');
assertComputed(styledWide, '2px');
});
test('scoped selectors, simple and complex', function() {
@ -209,7 +209,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
});
}
});
</script>

View File

@ -286,7 +286,6 @@
})();
</script>
<template id="dynamic-style-template">
<style>
:host {
@ -346,3 +345,100 @@
})();
</script>
</dom-module>
<dom-module id="x-specificity">
<template>
<style>
:host {
border-top: 1px solid red;
}
:host(.bar) {
border-top: 2px solid red;
}
</style>
<content></content>
</template>
<script>
Polymer({is: 'x-specificity'});
</script>
</dom-module>
<style is="custom-style">
:root {
--x-specificity-parent : {
border: 10px solid blue;
};
--x-specificity-nested : {
border: 3px solid red;
};
}
</style>
<dom-module id="x-specificity-parent">
<template>
<style>
/* TODO remove `:host` when https://github.com/Polymer/polymer/pull/2419 merged */
:host ::content > :not(template) {
@apply(--x-specificity-parent);
}
</style>
<content></content>
</template>
<script>
Polymer({is: 'x-specificity-parent', extends: 'div'});
</script>
</dom-module>
<dom-module id="x-specificity-nested">
<template>
<style>
:host {
@apply(--x-specificity-nested);
}
</style>
</template>
<script>
Polymer({is: 'x-specificity-nested', extends: 'div'});
</script>
</dom-module>
<style is="custom-style">
:root {
--x-overriding : {
border-top: 1px solid red;
}
}
</style>
<dom-module id="x-overriding">
<template>
<style>
.red {
@apply(--x-overriding);
}
.green {
@apply(--x-overriding);
border-top: 2px solid green;
}
.red-2 {
border-top: 2px solid green;
@apply(--x-overriding);
}
.blue {
@apply(--x-overriding);
border-top: 3px solid blue;
}
</style>
<div class="red">red</div>
<div class="green">green</div>
<div class="red-2">green-2</div>
<div class="blue">blue</div>
</template>
</dom-module>
<script>
Polymer({
is: 'x-overriding'
});
</script>

View File

@ -44,6 +44,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
<x-dynamic-svg></x-dynamic-svg>
<x-specificity></x-specificity>
<x-specificity class="bar"></x-specificity>
<div is="x-specificity-parent">
<div is="x-specificity-nested"></div>
</div>
<x-overriding></x-overriding>
<script>
suite('scoped-styling', function() {
@ -212,9 +218,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
test('styles shimmed in registration order', function() {
var s$ = document.head.querySelectorAll('style[scope]');
var expected = ['x-gchild', 'x-child2', 'x-styled', 'x-button',
'x-mixed-case', 'x-mixed-case-button', 'x-dynamic-scope',
'x-dynamic-template', 'x-dynamic-svg'];
var expected = ['x-gchild', 'x-child2', 'x-styled', 'x-button', 'x-mixed-case',
'x-mixed-case-button', 'x-dynamic-scope', 'x-dynamic-template',
'x-dynamic-svg', 'x-specificity', 'x-overriding',
'x-overriding-0', 'x-specificity-parent-0', 'x-specificity-nested-0'];
var actual = [];
for (var i=0; i<s$.length; i++) {
actual.push(s$[i].getAttribute('scope'));
@ -255,7 +262,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
x = document.createElement('button', 'x-mixed-case-button');
document.body.appendChild(x);
assertComputed(x, '14px');
});
test('specificity of :host selector with class', function() {
assertComputed(document.querySelector('x-specificity'), '1px');
assertComputed(document.querySelector('x-specificity.bar'), '2px');
});
test('specificity of ::content > :not(template) selector', function() {
assertComputed(document.querySelector('[is=x-specificity-nested]'), '10px');
});
test('overwriting mixin properties', function() {
var root = document.querySelector('x-overriding');
assertComputed(root.querySelector('.red'), '1px');
assertComputed(root.querySelector('.green'), '2px');
assertComputed(root.querySelector('.red-2'), '1px');
assertComputed(root.querySelector('.blue'), '3px');
});
});
@ -269,7 +292,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
computed = getComputedStyle(circle);
assert.equal(computed['fill-opacity'], '0.5');
});
});
</script>

0
test/unit/sub/foo.png Normal file
View File

0
test/unit/sub/foo.z Normal file
View File

0
test/unit/sub/google.png Normal file
View File

View File

@ -11,6 +11,7 @@
obj="{{obj}}"
obj-prop="{{obj.prop}}"
conflict="{{outerInnerConflict.prop}}"
computed-from-literal="{{computeFromLiteral(33, prop)}}"
></x-child>
</template>
</x-templatizer>
@ -238,7 +239,8 @@
],
outerObjChanged: function() {},
objAChanged: function() {},
objBChanged: function() {}
objBChanged: function() {},
computeFromLiteral: function() {}
});
</script>

View File

@ -250,6 +250,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
assert.equal(childA.conflict, 'bar');
});
test('ensure literals are not forwarded to templates', function() {
assert.notOk(host._propertyEffects[33]);
assert.notOk(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(host), 33));
});
});
</script>