Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Merge pull request #171 from Polymer/master
Browse files Browse the repository at this point in the history
6/17 master -> stable
  • Loading branch information
dfreedm committed Jun 17, 2013
2 parents 84f8977 + 7a50b20 commit af08901
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 83 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "buildbot"]
path = buildbot
url = https://github.com/Polymer/buildbot.git
[submodule "tools"]
path = tools
url = https://github.com/Polymer/tools.git
1 change: 0 additions & 1 deletion buildbot
Submodule buildbot deleted from 3a4761
16 changes: 5 additions & 11 deletions src/ShadowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@

function distributeChildToInsertionPoint(child, insertionPoint) {
getDistributedChildNodes(insertionPoint).push(child);
insertionParentTable.set(child, insertionPoint);
assignToInsertionPoint(child, insertionPoint);

var eventParents = eventParentsTable.get(child);
if (!eventParents)
Expand Down Expand Up @@ -372,8 +372,7 @@
renderShadowInsertionPoint: function(visualParent, tree, shadowInsertionPoint) {
var nextOlderTree = getNextOlderTree(tree);
if (nextOlderTree) {
// This makes ShadowRoot have its insertionParent be the <shadow>.
insertionParentTable.set(nextOlderTree, shadowInsertionPoint);
assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);
shadowInsertionPoint.olderShadowRoot_ = nextOlderTree;
this.remove(shadowInsertionPoint);
var shadowDOMChildNodes = getChildNodesSnapshot(nextOlderTree);
Expand Down Expand Up @@ -427,7 +426,7 @@
break; // 4.3.1.1.
} else {
tree = nextOlderTree; // 4.3.2.2.
assignShadowTreeToShadowInsertionPoint(tree, point); // 4.3.2.2.
assignToInsertionPoint(tree, point); // 4.3.2.2.
continue; // 4.3.2.3.
}
} else {
Expand Down Expand Up @@ -499,7 +498,7 @@
return trees;
}

function assignShadowTreeToShadowInsertionPoint(tree, point) {
function assignToInsertionPoint(tree, point) {
insertionParentTable.set(tree, point);
}

Expand Down Expand Up @@ -533,17 +532,12 @@
return getDistributedChildNodes(this);
};

mixin(Node.prototype, {
get insertionParent() {
return insertionParentTable.get(this) || null;
}
});

scope.eventParentsTable = eventParentsTable;
scope.getRendererForHost = getRendererForHost;
scope.getShadowTrees = getShadowTrees;
scope.nextOlderShadowTreeTable = nextOlderShadowTreeTable;
scope.renderAllPending = renderAllPending;
scope.insertionParentTable = insertionParentTable;

// Exposed for testing
scope.visual = {
Expand Down
29 changes: 21 additions & 8 deletions src/wrappers.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ var ShadowDOMPolyfill = {};
enumerable: true
};

function isEventHandlerName(name) {
return /^on[a-z]+$/.test(name);
}

function installProperty(source, target, allowMethod) {
Object.getOwnPropertyNames(source).forEach(function(name) {
if (name in target)
Expand All @@ -92,8 +96,8 @@ var ShadowDOMPolyfill = {};
try {
descriptor = Object.getOwnPropertyDescriptor(source, name);
} catch (ex) {
// JSC and V8 both use data properties instead accessors which can cause
// getting the property desciptor throw an exception.
// JSC and V8 both use data properties instead of accessors which can
// cause getting the property desciptor to throw an exception.
// https://bugs.webkit.org/show_bug.cgi?id=49739
descriptor = dummyDescriptor;
}
Expand All @@ -105,14 +109,23 @@ var ShadowDOMPolyfill = {};
return;
}

getter = function() {
return this.impl[name];
};
var isEvent = isEventHandlerName(name);
if (isEvent) {
getter = scope.getEventHandlerGetter(name);
} else {
getter = function() {
return this.impl[name];
};
}

if (descriptor.writable || descriptor.set) {
setter = function(value) {
this.impl[name] = value;
};
if (isEvent) {
setter = scope.getEventHandlerSetter(name);
} else {
setter = function(value) {
this.impl[name] = value;
};
}
}

Object.defineProperty(target, name, {
Expand Down
20 changes: 20 additions & 0 deletions src/wrappers/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
var Node = scope.wrappers.Node;
var ParentNodeInterface = scope.ParentNodeInterface;
var SelectorsInterface = scope.SelectorsInterface;
var ShadowRoot = scope.wrappers.ShadowRoot;
var defineWrapGetter = scope.defineWrapGetter;
var elementFromPoint = scope.elementFromPoint;
var forwardMethodsToWrapper = scope.forwardMethodsToWrapper;
Expand Down Expand Up @@ -56,9 +57,28 @@
var originalAdoptNode = document.adoptNode;
var originalWrite = document.write;

function adoptSubtree(node, doc) {
if (node.shadowRoot)
doc.adoptNode(node.shadowRoot);
if (node instanceof ShadowRoot)
adoptOlderShadowRoots(node, doc);
for (var child = node.firstChild; child; child = child.nextSibling) {
adoptSubtree(child, doc);
}
}

function adoptOlderShadowRoots(shadowRoot, doc) {
var oldShadowRoot = scope.nextOlderShadowTreeTable.get(shadowRoot);
if (oldShadowRoot)
doc.adoptNode(oldShadowRoot);
}

mixin(Document.prototype, {
adoptNode: function(node) {
if (node.parentNode)
node.parentNode.removeChild(node);
originalAdoptNode.call(this.impl, unwrap(node));
adoptSubtree(node, this);
return node;
},
elementFromPoint: function(x, y) {
Expand Down
5 changes: 5 additions & 0 deletions src/wrappers/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
}
});

if (OriginalElement.prototype.webkitCreateShadowRoot) {
Element.prototype.webkitCreateShadowRoot =
Element.prototype.createShadowRoot;
}

mixin(Element.prototype, ChildNodeInterface);
mixin(Element.prototype, GetElementsByInterface);
mixin(Element.prototype, ParentNodeInterface);
Expand Down
19 changes: 9 additions & 10 deletions src/wrappers/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@
return nodes;
}

function unwrapNodesForInsertion(nodes) {
if (nodes.length === 1)
function unwrapNodesForInsertion(owner, nodes) {
var length = nodes.length;

if (length === 1)
return unwrap(nodes[0]);

var df = unwrap(document.createDocumentFragment());
for (var i = 0; i < nodes.length; i++) {
var df = unwrap(owner.ownerDocument.createDocumentFragment());
for (var i = 0; i < length; i++) {
df.appendChild(unwrap(nodes[i]));
}
return df;
Expand Down Expand Up @@ -160,7 +162,7 @@
// A better aproach might be to make sure we only get here for nodes that
// are related to a shadow host and then invalidate that and re-render
// the host (on reflow?).
originalAppendChild.call(this.impl, unwrapNodesForInsertion(nodes));
originalAppendChild.call(this.impl, unwrapNodesForInsertion(this, nodes));

return childWrapper;
},
Expand All @@ -181,7 +183,6 @@
var nodes = collectNodes(childWrapper, this,
previousNode, nextNode);


if (this.firstChild === refWrapper)
this.firstChild_ = nodes[0];

Expand All @@ -191,7 +192,7 @@
if (parentNode) {
originalInsertBefore.call(
parentNode,
unwrapNodesForInsertion(nodes),
unwrapNodesForInsertion(this, nodes),
refNode);
}

Expand Down Expand Up @@ -266,7 +267,7 @@
if (oldChildNode.parentNode) {
originalReplaceChild.call(
oldChildNode.parentNode,
unwrapNodesForInsertion(nodes),
unwrapNodesForInsertion(this, nodes),
oldChildNode);
}

Expand Down Expand Up @@ -358,8 +359,6 @@
return clone;
},

// insertionParent is added in ShadowRender.js

contains: function(child) {
if (!child)
return false;
Expand Down
91 changes: 87 additions & 4 deletions src/wrappers/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
var eventPhaseTable = new SideTable();
var stopPropagationTable = new SideTable();
var stopImmediatePropagationTable = new SideTable();
var eventHandlersTable = new SideTable();
var eventPathTable = new SideTable();

function isShadowRoot(node) {
return node instanceof wrappers.ShadowRoot;
Expand All @@ -47,7 +49,7 @@

// 1.
if (isShadowRoot(node))
return node.insertionParent || scope.getHostForShadowRoot(node);
return getInsertionParent(node) || scope.getHostForShadowRoot(node);

// 2.
var eventParents = scope.eventParentsTable.get(node);
Expand All @@ -64,7 +66,7 @@
var parentNode = node.parentNode;
if (parentNode && isShadowHost(parentNode)) {
var trees = scope.getShadowTrees(parentNode);
var p = context.insertionParent;
var p = getInsertionParent(context);
for (var i = 0; i < trees.length; i++) {
if (trees[i].contains(p))
return p;
Expand Down Expand Up @@ -149,8 +151,12 @@
}
}

function getInsertionParent(node) {
return scope.insertionParentTable.get(node);
}

function isDistributed(node) {
return node.insertionParent;
return getInsertionParent(node);
}

function rootOfNode(node) {
Expand Down Expand Up @@ -206,13 +212,15 @@
//
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end
//
// TODO(arv): Find a loess hacky way to do this.
// TODO(arv): Find a less hacky way to do this.
if (event.type === 'load' &&
eventPath.length === 2 &&
eventPath[0].target instanceof wrappers.Document) {
eventPath.shift();
}

eventPathTable.set(event, eventPath);

if (dispatchCapturing(event, eventPath)) {
if (dispatchAtTarget(event, eventPath)) {
dispatchBubbling(event, eventPath);
Expand Down Expand Up @@ -376,6 +384,28 @@
get eventPhase() {
return eventPhaseTable.get(this);
},
get path() {
var nodeList = new wrappers.NodeList();
var eventPath = eventPathTable.get(this);
if (eventPath) {
var index = 0;
var found = false;
var currentTarget = currentTargetTable.get(this);
var lastIndex = eventPath.length - 1;
for (var i = 0; i <= lastIndex; i++) {
if (!found)
found = eventPath[i].currentTarget === currentTarget;
if (found) {
var node = eventPath[i].currentTarget;
// Do not include the top Window.
if (i !== lastIndex || node instanceof wrappers.Node)
nodeList[index++] = node;
}
}
nodeList.length = index;
}
return nodeList;
},
stopPropagation: function() {
stopPropagationTable.set(this, true);
},
Expand Down Expand Up @@ -624,8 +654,61 @@
return null;
}

/**
* Returns a function that is to be used as a getter for `onfoo` properties.
* @param {string} name
* @return {Function}
*/
function getEventHandlerGetter(name) {
return function() {
var inlineEventHandlers = eventHandlersTable.get(this);
return inlineEventHandlers && inlineEventHandlers[name] &&
inlineEventHandlers[name].value || null;
};
}

/**
* Returns a function that is to be used as a setter for `onfoo` properties.
* @param {string} name
* @return {Function}
*/
function getEventHandlerSetter(name) {
var eventType = name.slice(2);
return function(value) {
var inlineEventHandlers = eventHandlersTable.get(this);
if (!inlineEventHandlers) {
inlineEventHandlers = Object.create(null);
eventHandlersTable.set(this, inlineEventHandlers);
}

var old = inlineEventHandlers[name];
if (old)
this.removeEventListener(eventType, old.wrapped, false);

if (typeof value === 'function') {
var wrapped = function(e) {
var rv = value.call(this, e);
if (rv === false)
e.preventDefault();
else if (name === 'onbeforeunload' && typeof rv === 'string')
e.returnValue = rv;
// mouseover uses true for preventDefault but preventDefault for
// mouseover is ignored by browsers these day.
};

this.addEventListener(eventType, wrapped, false);
inlineEventHandlers[name] = {
value: value,
wrapped: wrapped
};
}
};
}

scope.adjustRelatedTarget = adjustRelatedTarget;
scope.elementFromPoint = elementFromPoint;
scope.getEventHandlerGetter = getEventHandlerGetter;
scope.getEventHandlerSetter = getEventHandlerSetter;
scope.wrapEventTargetMethods = wrapEventTargetMethods;
scope.wrappers.CustomEvent = CustomEvent;
scope.wrappers.Event = Event;
Expand Down
Loading

0 comments on commit af08901

Please sign in to comment.