Skip to content

Commit

Permalink
Merge pull request #7 from PolymerLabs/shady
Browse files Browse the repository at this point in the history
Shady
  • Loading branch information
kevinpschaaf authored Jul 13, 2016
2 parents 3ba174c + a72b846 commit 9d622ae
Show file tree
Hide file tree
Showing 31 changed files with 9,585 additions and 8 deletions.
4 changes: 3 additions & 1 deletion src/compat/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
__isPolymerInstance__: true,

createdCallback: function() {
var proto = this.constructor.prototype;
// note: `this.constructor.prototype` is wrong in Safari so make sure to
// use `__proto__`
var proto = this.__proto__;
if (!proto.hasOwnProperty('__hasRegisterFinished')) {
proto.__hasRegisterFinished = true;
var meta = behaviors.register(proto);
Expand Down
2 changes: 1 addition & 1 deletion src/compat/polymer-fn.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}
// support mixin for properties on ES6 classes...
if (mixin) {
Polymer.Base.mixin(prototype, mixin);
Polymer.Utils.extend(prototype, mixin);
}

// desugar the prototype and return a factory object
Expand Down
5 changes: 4 additions & 1 deletion src/properties/batched-effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@
inst.__pendingClients = null;
}

set(inst, path, value) {
__set(inst, path, value) {
path = Array.isArray(path) ? path.join('.') : path;
this._propertySetter(inst, path, value);
}
Expand Down Expand Up @@ -328,6 +328,9 @@

}

// NOTE: Safari can't deal with an ES6 style function named `set`
BatchedEffects.prototype.set = BatchedEffects.prototype.__set;

// export
Polymer.BatchedEffects = BatchedEffects;

Expand Down
120 changes: 120 additions & 0 deletions src/shady/distributor-v0.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<!--
@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="../utils/boot.html">
<link rel="import" href="distributor-v1.html">
<script>

(function() {

var Tree = Polymer.ShadyDom.Tree;

class DistributorV0 extends Polymer.ShadyDom.DistributorV1 {

constructor(root) {
super(root)
this.insertionPointTag = 'content';
}

resetChild(child) {
if (child._destinationInsertionPoints) {
child._destinationInsertionPoints = undefined;
}
if (this.isInsertionPoint(child)) {
this.clearDistributedDestinationInsertionPoints(child);
}
}

resetInsertionPoint(insertionPoint) {
insertionPoint._distributedNodes = [];
}

clearDistributedDestinationInsertionPoints(content) {
var e$ = content._distributedNodes;
if (e$) {
for (var i=0; i < e$.length; i++) {
var d = e$[i]._destinationInsertionPoints;
if (d) {
// this is +1 because these insertion points are *not* in this scope
d.splice(d.indexOf(content)+1, d.length);
}
}
}
}

// Gather the pool of nodes that should be distributed. We will combine
// these with the "content root" to arrive at the composed tree.
collectPool() {
var pool = [];
var children = Tree.Logical.getChildNodes(this.root.host);
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (this.isInsertionPoint(child)) {
pool.push.apply(pool, child._distributedNodes);
} else {
pool.push(child);
}
}
return pool;
}

distributeNodeInto(child, insertionPoint) {
insertionPoint._distributedNodes.push(child);
var points = child._destinationInsertionPoints;
if (!points) {
child._destinationInsertionPoints = [insertionPoint];
} else {
points.push(insertionPoint);
}
}

setDistributedNodesOnInsertionPoint(insertionPoint) {}

matchesInsertionPoint(node, insertionPoint) {
var select = insertionPoint.getAttribute('select');
// no selector matches all nodes (including text)
if (!select) {
return true;
}
select = select.trim();
// same thing if it had only whitespace
if (!select) {
return true;
}
// selectors can only match Elements
if (!(node instanceof Element)) {
return false;
}
// only valid selectors can match:
// TypeSelector
// *
// ClassSelector
// IDSelector
// AttributeSelector
// negation
var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
if (!validSelectors.test(select)) {
return false;
}
return Polymer.ShadyDom.matchesSelector(node, select);
}

// TODO(sorvell): util?
isFinalDestination(insertionPoint, node) {
var points = node._destinationInsertionPoints;
return points && points[points.length - 1] === insertionPoint;
}

}

Polymer.ShadyDom.DistributorV0 = DistributorV0;

})();

</script>
177 changes: 177 additions & 0 deletions src/shady/distributor-v1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<!--
@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="../utils/boot.html">
<script>

(function() {

var Tree = Polymer.ShadyDom.Tree;

class DistributorV1 {

constructor(root) {
this.root = root;
this.insertionPointTag = 'slot';
}

getInsertionPoints() {
return this.root.querySelectorAll(this.insertionPointTag);
}

hasInsertionPoint() {
return Boolean(this.root._insertionPoints &&
this.root._insertionPoints.length);
}

isInsertionPoint(node) {
return node.localName && node.localName == this.insertionPointTag;
}

reset() {
// light children
var children = Tree.Logical.getChildNodes(this.root.host);
for (var i = 0; i < children.length; i++) {
this.resetChild(children[i]);
}
// insertion points
var p$ = this.root._insertionPoints;
for (var j = 0; j < p$.length; j++) {
this.resetInsertionPoint(p$[j]);
}
}

resetChild(child) {
child._assignedSlot = undefined;
}

resetInsertionPoint(insertionPoint) {
insertionPoint._distributedNodes = [];
insertionPoint._assignedNodes = [];
}

distribute() {
if (this.hasInsertionPoint()) {
this.reset();
return this.distributePool(this.root, this.collectPool());
}
return [];
}

// Gather the pool of nodes that should be distributed. We will combine
// these with the "content root" to arrive at the composed tree.
collectPool() {
return Tree.arrayCopy(
Tree.Logical.getChildNodes(this.root.host));
}

// perform "logical" distribution; note, no actual dom is moved here,
// instead elements are distributed into a `content._distributedNodes`
// array where applicable.
distributePool(node, pool) {
var dirtyRoots = [];
var p$ = this.root._insertionPoints;
for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) {
this.distributeInsertionPoint(p, pool);
// provoke redistribution on insertion point parents
// must do this on all candidate hosts since distribution in this
// scope invalidates their distribution.
// only get logical parent.
var parent = Tree.Logical.getParentNode(p);
// TODO(sorvell): why is the clean check needed?
if (parent && parent.shadyRoot &&
this.hasInsertionPoint(parent.shadyRoot) /*&&
parent.shadyRoot._clean*/) {
dirtyRoots.push(parent.shadyRoot);
}
}
return dirtyRoots;
}

distributeInsertionPoint(insertionPoint, pool) {
// distribute nodes from the pool that this selector matches
var anyDistributed = false;
for (var i=0, l=pool.length, node; i < l; i++) {
node=pool[i];
// skip nodes that were already used
if (!node) {
continue;
}
// distribute this node if it matches
if (this.matchesInsertionPoint(node, insertionPoint)) {
this.distributeNodeInto(node, insertionPoint);
// remove this node from the pool
pool[i] = undefined;
// since at least one node matched, we won't need fallback content
anyDistributed = true;
}
}
// Fallback content if nothing was distributed here
if (!anyDistributed) {
var children = Tree.Logical.getChildNodes(insertionPoint);
for (var j = 0; j < children.length; j++) {
this.distributeNodeInto(children[j], insertionPoint);
}
}
this.setDistributedNodesOnInsertionPoint(insertionPoint);
}

matchesInsertionPoint(node, insertionPoint) {
var slotName = insertionPoint.getAttribute('name');
// no selector matches all nodes (including text)
if (!slotName) {
return true;
}
slotName = slotName.trim();
// same thing if it had only whitespace
if (!slotName) {
return true;
}
// only elements can have attributes
if (!(node instanceof Element)) {
return false;
}
var slot = node.getAttribute('slot');
return (slot && (slot.trim() == slotName));
}

distributeNodeInto(child, insertionPoint) {
insertionPoint._assignedNodes.push(child);
child._assignedSlot = insertionPoint;
}

// TODO(sorvell): this currently needs to be no-op'd for v0, which is odd.
setDistributedNodesOnInsertionPoint(insertionPoint) {
var n$ = insertionPoint._assignedNodes;
insertionPoint._distributedNodes = [];
for (var i=0, n; (i<n$.length) && (n=n$[i]) ; i++) {
if (this.isInsertionPoint(n)) {
var d$ = n._distributedNodes;
if (d$) {
for (var j=0; j < d$.length; j++) {
insertionPoint._distributedNodes.push(d$[j]);
}
}
} else {
insertionPoint._distributedNodes.push(n$[i]);
}
}
}

isFinalDestination(insertionPoint, node) {
return !Boolean(insertionPoint._assignedSlot);
}

}

Polymer.ShadyDom.DistributorV1 = DistributorV1;

})();

</script>
Loading

0 comments on commit 9d622ae

Please sign in to comment.