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 #120 from arv/event-path-again
Browse files Browse the repository at this point in the history
Fix issue with event parents
  • Loading branch information
Steve Orvell committed Apr 25, 2013
2 parents 4e6eb2e + 1f581af commit 0ea69ae
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 20 deletions.
26 changes: 14 additions & 12 deletions src/ShadowRenderer.js
Expand Up @@ -104,26 +104,28 @@
}

var distributedChildNodesTable = new SideTable();
var eventParentTable = new SideTable();
var eventParentsTable = new SideTable();
var insertionParentTable = new SideTable();
var nextOlderShadowTreeTable = new SideTable();
var rendererForHostTable = new SideTable();
var shadowDOMRendererTable = new SideTable();

var reprCounter = 0;

function repr(node) {
if (!node.displayName)
node.displayName = node.nodeName + '-' + ++reprCounter;
return node.displayName;
}

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

// If we have "a -> content1" and we now get (a, content2) the
// event parent chaing needs to be "a -> content1 -> content2".
var eventParent = child;
var tmp;
while (tmp = eventParentTable.get(eventParent)) {
eventParent = tmp;
}

eventParentTable.set(eventParent, insertionPoint);
eventParentTable.set(insertionPoint, undefined);
var eventParents = eventParentsTable.get(child);
if (!eventParents)
eventParentsTable.set(child, eventParents = []);
eventParents.push(insertionPoint);
}

function resetDistributedChildNodes(insertionPoint) {
Expand Down Expand Up @@ -536,7 +538,7 @@
}
});

scope.eventParentTable = eventParentTable;
scope.eventParentsTable = eventParentsTable;
scope.getRendererForHost = getRendererForHost;
scope.getShadowTrees = getShadowTrees;
scope.nextOlderShadowTreeTable = nextOlderShadowTreeTable;
Expand Down
25 changes: 18 additions & 7 deletions src/wrappers/EventTarget.js
Expand Up @@ -41,15 +41,23 @@
}

// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-parent
function calculateParent(node, context) {
function calculateParents(node, context, ancestors) {
if (ancestors.length)
return ancestors.shift();

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

// 2.
var distributedEventParent = scope.eventParentTable.get(node);
if (distributedEventParent)
return distributedEventParent;
var eventParents = scope.eventParentsTable.get(node);
if (eventParents) {
// Copy over the remaining event parents for next iteration.
for (var i = 1; i < eventParents.length; i++) {
ancestors[i - 1] = eventParents[i];
}
return eventParents[0];
}

// 3.
if (context && isInsertionPoint(node)) {
Expand All @@ -72,6 +80,7 @@
var stack = []; // 1.
var ancestor = node; // 2.
var targets = [];
var ancestors = [];
while (ancestor) { // 3.
var context = null; // 3.2.
// TODO(arv): Change order of these. If the stack is empty we always end
Expand All @@ -87,7 +96,8 @@
targets.push({target: target, currentTarget: ancestor}); // 3.5.
if (isShadowRoot(ancestor)) // 3.6.
stack.pop(); // 3.6.1.
ancestor = calculateParent(ancestor, context); // 3.7.

ancestor = calculateParents(ancestor, context, ancestors); // 3.7.
}
return targets;
}
Expand All @@ -102,6 +112,7 @@

// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-adjusted-related-target
function adjustRelatedTarget(target, related) {
var ancestors = [];
while (target) { // 3.
var stack = []; // 3.1.
var ancestor = related; // 3.2.
Expand Down Expand Up @@ -129,7 +140,7 @@
stack.pop();

last = ancestor; // 3.4.6.
ancestor = calculateParent(ancestor, context); // 3.4.7.
ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7.
}
if (isShadowRoot(target)) // 3.5.
target = scope.getHostForShadowRoot(target);
Expand Down
125 changes: 125 additions & 0 deletions test/events.js
Expand Up @@ -1030,4 +1030,129 @@ test('retarget order (multiple shadow roots)', function() {
assertArrayEqual(expected, log);
});

test('event path with multiple content select', function() {
var div = document.createElement('div');
div.innerHTML = '<a><one></one><two></two></a>';
var a = div.firstChild;
var one = a.firstChild;
var two = a.lastChild;

var aRoot = a.createShadowRoot();
aRoot.innerHTML = '<b><content></content></b>';
var b = aRoot.firstChild;
var contentOfA = b.firstChild;

var bRoot = b.createShadowRoot();
bRoot.innerHTML = '<content select="one"></content>' +
'<content select="two"></content>';
var contentSelectOne = bRoot.firstChild;
var contentSelectTwo = bRoot.lastChild;

var tree = {
a: a,
one: one,
two: two,
aRoot: aRoot,
b: b,
contentOfA: contentOfA,
bRoot: bRoot,
contentSelectOne: contentSelectOne,
contentSelectTwo: contentSelectTwo,
};

var log = [];
addListeners(tree, 'x', log);

div.offsetWidth;

one.dispatchEvent(new Event('x', {bubbles: true}));
var expected = [
'a, one, undefined, CAPTURING_PHASE',
'aRoot, one, undefined, CAPTURING_PHASE',
'b, one, undefined, CAPTURING_PHASE',
'bRoot, one, undefined, CAPTURING_PHASE',
'contentSelectOne, one, undefined, CAPTURING_PHASE',
'contentOfA, one, undefined, CAPTURING_PHASE',
'one, one, undefined, AT_TARGET',
'one, one, undefined, AT_TARGET',
'contentOfA, one, undefined, BUBBLING_PHASE',
'contentSelectOne, one, undefined, BUBBLING_PHASE',
'bRoot, one, undefined, BUBBLING_PHASE',
'b, one, undefined, BUBBLING_PHASE',
'aRoot, one, undefined, BUBBLING_PHASE',
'a, one, undefined, BUBBLING_PHASE',
];
assertArrayEqual(expected, log);

var log = [];
addListeners(tree, 'x', log);
two.dispatchEvent(new Event('x', {bubbles: true}));
var expected = [
'a, two, undefined, CAPTURING_PHASE',
'aRoot, two, undefined, CAPTURING_PHASE',
'b, two, undefined, CAPTURING_PHASE',
'bRoot, two, undefined, CAPTURING_PHASE',
'contentSelectTwo, two, undefined, CAPTURING_PHASE',
'contentOfA, two, undefined, CAPTURING_PHASE',
'two, two, undefined, AT_TARGET',
'two, two, undefined, AT_TARGET',
'contentOfA, two, undefined, BUBBLING_PHASE',
'contentSelectTwo, two, undefined, BUBBLING_PHASE',
'bRoot, two, undefined, BUBBLING_PHASE',
'b, two, undefined, BUBBLING_PHASE',
'aRoot, two, undefined, BUBBLING_PHASE',
'a, two, undefined, BUBBLING_PHASE',
];
assertArrayEqual(expected, log);

var log = [];
addListeners(tree, 'x', log);
contentOfA.dispatchEvent(new Event('x', {bubbles: true}));
var expected = [
'aRoot, contentOfA, undefined, CAPTURING_PHASE',
'b, contentOfA, undefined, CAPTURING_PHASE',
'contentOfA, contentOfA, undefined, AT_TARGET',
'contentOfA, contentOfA, undefined, AT_TARGET',
'b, contentOfA, undefined, BUBBLING_PHASE',
'aRoot, contentOfA, undefined, BUBBLING_PHASE',
'a, a, undefined, AT_TARGET',
'a, a, undefined, AT_TARGET',
];
assertArrayEqual(expected, log);

var log = [];
addListeners(tree, 'x', log);
contentSelectOne.dispatchEvent(new Event('x', {bubbles: true}));
var expected = [
'aRoot, b, undefined, CAPTURING_PHASE',
'bRoot, contentSelectOne, undefined, CAPTURING_PHASE',
'contentSelectOne, contentSelectOne, undefined, AT_TARGET',
'contentSelectOne, contentSelectOne, undefined, AT_TARGET',
'bRoot, contentSelectOne, undefined, BUBBLING_PHASE',
'b, b, undefined, AT_TARGET',
'b, b, undefined, AT_TARGET',
'aRoot, b, undefined, BUBBLING_PHASE',
'a, a, undefined, AT_TARGET',
'a, a, undefined, AT_TARGET',
];
assertArrayEqual(expected, log);

var log = [];
addListeners(tree, 'x', log);
contentSelectTwo.dispatchEvent(new Event('x', {bubbles: true}));
var expected = [
'aRoot, b, undefined, CAPTURING_PHASE',
'bRoot, contentSelectTwo, undefined, CAPTURING_PHASE',
'contentSelectTwo, contentSelectTwo, undefined, AT_TARGET',
'contentSelectTwo, contentSelectTwo, undefined, AT_TARGET',
'bRoot, contentSelectTwo, undefined, BUBBLING_PHASE',
'b, b, undefined, AT_TARGET',
'b, b, undefined, AT_TARGET',
'aRoot, b, undefined, BUBBLING_PHASE',
'a, a, undefined, AT_TARGET',
'a, a, undefined, AT_TARGET',
];
assertArrayEqual(expected, log);
});

});
2 changes: 1 addition & 1 deletion test/test.main.js
Expand Up @@ -38,10 +38,10 @@ function unwrapAndExpectStructure(node, nonNullFields) {
}

function assertArrayEqual(a, b, msg) {
assert.equal(a.length, b.length, msg);
for (var i = 0; i < a.length; i++) {
assert.equal(a[i], b[i], msg);
}
assert.equal(a.length, b.length, msg);
}

// TODO(arv): Use htmlTest when it has settled down.
Expand Down

0 comments on commit 0ea69ae

Please sign in to comment.