Skip to content

Commit

Permalink
Merge pull request #3740 from Polymer/fix-3739
Browse files Browse the repository at this point in the history
Fixes #3739: correctly shim `:host(.element-name)` as `element-name.e…
  • Loading branch information
Steve Orvell authored Jun 28, 2016
2 parents 06bc9db + 4817d61 commit 645bcd0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 7 deletions.
30 changes: 23 additions & 7 deletions src/lib/style-transformer.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,7 @@
if (selector.indexOf(HOST_CONTEXT) >=0) {
hostContext = true;
} else if (selector.indexOf(HOST) >=0) {
// :host(...) -> scopeName...
selector = selector.replace(HOST_PAREN, function(m, host, paren) {
return (m.indexOf(hostScope) === -1 ? hostScope : '') + paren;
});
// now normal :host
selector = selector.replace(HOST, hostScope);
selector = this._transformHostSelector(selector, hostScope);
// replace other selectors with scoping class
} else if (jumpIndex !== 0) {
selector = scope ? this._transformSimpleSelector(selector, scope) :
Expand All @@ -238,6 +233,25 @@
return p$.join(PSEUDO_PREFIX);
},

// :host(...) -> scopeName...
_transformHostSelector: function(selector, hostScope) {
var m = selector.match(HOST_PAREN);
var paren = m && m[2].trim() || '';
if (paren && !paren[0].match(SIMPLE_SELECTOR_PREFIX)) {
// paren starts with a type selector
var typeSelector = paren.split(SIMPLE_SELECTOR_PREFIX)[0];
// if the type selector is our hostScope then avoid pre-pending it
if (typeSelector === hostScope) {
return paren;
// otherwise, this selector should not match in this scope so
// output a bogus selector.
} else {
return SELECTOR_NO_MATCH;
}
}
return hostScope + paren;
},

documentRule: function(rule) {
// reset selector in case this is redone.
rule.selector = rule.parsedSelector;
Expand Down Expand Up @@ -267,12 +281,13 @@
':not(.' + SCOPE_NAME + ')';
var COMPLEX_SELECTOR_SEP = ',';
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;
var SIMPLE_SELECTOR_PREFIX = /[[.:#*]/;
var HOST = ':host';
var ROOT = ':root';
// NOTE: this supports 1 nested () pair for things like
// :host(:not([selected]), more general support requires
// parsing which seems like overkill
var HOST_PAREN = /(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var HOST_PAREN = /(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;
var HOST_CONTEXT = ':host-context';
var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var CONTENT = '::content';
Expand All @@ -283,6 +298,7 @@
var PSEUDO_PREFIX = ':';
var CLASS = 'class';
var CONTENT_START = new RegExp('^(' + CONTENT + ')');
var SELECTOR_NO_MATCH = 'should_not_match';

// exports
return api;
Expand Down
4 changes: 4 additions & 0 deletions test/unit/styling-scoped-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@
display: block;
border: 4px solid orange;
}

:host(.x-shared1) {
top: 10px;
};
</style>
</template>
</dom-module>
Expand Down
19 changes: 19 additions & 0 deletions test/unit/styling-scoped.html
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,25 @@
assertComputed(s2, '4px');
});

test(':host with superset of element tag selector does not leak', function() {
var t = document.createElement('div');
t.textContent = 'host leak test';
t.classList.add('x-shared1');
document.body.appendChild(t);
assertComputed(t, 'auto', 'top');
});

test(':host(...) with non-matching type selector does not leak', function() {
var t = document.createElement('x-shared1x-shared2');
t.textContent = ':host(non-matching-type-selector)';
document.body.appendChild(t);
assertComputed(t, '0px');
t = document.createElement('x-shared2x-shared1');
t.textContent = ':host(non-matching-type-selector)';
document.body.appendChild(t);
assertComputed(t, '0px');
});

});

</script>
Expand Down

0 comments on commit 645bcd0

Please sign in to comment.