| Index: pkg/shadow_dom/lib/shadow_dom.debug.js
|
| diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
|
| index 447f29c3a9926d8f8527e63278ded6ed60aa7876..4e84b7e70823a98b65ab07f7f4a10b6b3ce0e890 100644
|
| --- a/pkg/shadow_dom/lib/shadow_dom.debug.js
|
| +++ b/pkg/shadow_dom/lib/shadow_dom.debug.js
|
| @@ -592,6 +592,8 @@ if (!HTMLElement.prototype.createShadowRoot
|
| this.isObserved = true;
|
| }
|
|
|
| + // TODO(rafaelw): Consider surfacing a way to avoid observing prototype
|
| + // ancestors which are expected not to change (e.g. Element, Node...).
|
| var objProto = Object.getPrototypeOf({});
|
| var arrayProto = Object.getPrototypeOf([]);
|
| ObservedSet.prototype = {
|
| @@ -734,6 +736,8 @@ if (!HTMLElement.prototype.createShadowRoot
|
| CompoundPathObserver.prototype = createObject({
|
| __proto__: PathObserver.prototype,
|
|
|
| + // TODO(rafaelw): Consider special-casing when |object| is a PathObserver
|
| + // and path 'value' to avoid explicit observation.
|
| addPath: function(object, path) {
|
| if (this.started)
|
| throw Error('Cannot add more paths once started.');
|
| @@ -798,7 +802,8 @@ if (!HTMLElement.prototype.createShadowRoot
|
|
|
| this.reportArgs = [this.value, this.oldValue];
|
| } else {
|
| - this.reportArgs = [this.values, this.oldValues, this.changeFlags];
|
| + this.reportArgs = [this.values, this.oldValues, this.changeFlags,
|
| + this.observed];
|
| }
|
|
|
| return true;
|
| @@ -1947,22 +1952,18 @@ var ShadowDOMPolyfill = {};
|
| return false;
|
| }
|
|
|
| - function isMutationEvent(type) {
|
| - switch (type) {
|
| - case 'DOMAttrModified':
|
| - case 'DOMAttributeNameChanged':
|
| - case 'DOMCharacterDataModified':
|
| - case 'DOMElementNameChanged':
|
| - case 'DOMNodeInserted':
|
| - case 'DOMNodeInsertedIntoDocument':
|
| - case 'DOMNodeRemoved':
|
| - case 'DOMNodeRemovedFromDocument':
|
| - case 'DOMSubtreeModified':
|
| - return true;
|
| - }
|
| - return false;
|
| + var mutationEventsAreSilenced = 0;
|
| +
|
| + function muteMutationEvents() {
|
| + mutationEventsAreSilenced++;
|
| + }
|
| +
|
| + function unmuteMutationEvents() {
|
| + mutationEventsAreSilenced--;
|
| }
|
|
|
| + var OriginalMutationEvent = window.MutationEvent;
|
| +
|
| function dispatchOriginalEvent(originalEvent) {
|
| // Make sure this event is only dispatched once.
|
| if (handledEventsTable.get(originalEvent))
|
| @@ -1972,8 +1973,12 @@ var ShadowDOMPolyfill = {};
|
| // Don't do rendering if this is a mutation event since rendering might
|
| // mutate the DOM which would fire more events and we would most likely
|
| // just iloop.
|
| - if (!isMutationEvent(originalEvent.type))
|
| + if (originalEvent instanceof OriginalMutationEvent) {
|
| + if (mutationEventsAreSilenced)
|
| + return;
|
| + } else {
|
| scope.renderAllPending();
|
| + }
|
|
|
| var target = wrap(originalEvent.target);
|
| var event = wrap(originalEvent);
|
| @@ -2102,7 +2107,7 @@ var ShadowDOMPolyfill = {};
|
| if (window.onerror)
|
| window.onerror(ex.message);
|
| else
|
| - console.error(ex);
|
| + console.error(ex, ex.stack);
|
| }
|
| }
|
|
|
| @@ -2491,6 +2496,8 @@ var ShadowDOMPolyfill = {};
|
| scope.elementFromPoint = elementFromPoint;
|
| scope.getEventHandlerGetter = getEventHandlerGetter;
|
| scope.getEventHandlerSetter = getEventHandlerSetter;
|
| + scope.muteMutationEvents = muteMutationEvents;
|
| + scope.unmuteMutationEvents = unmuteMutationEvents;
|
| scope.wrapEventTargetMethods = wrapEventTargetMethods;
|
| scope.wrappers.CustomEvent = CustomEvent;
|
| scope.wrappers.Event = Event;
|
| @@ -3602,8 +3609,10 @@ var ShadowDOMPolyfill = {};
|
| var HTMLElement = scope.wrappers.HTMLElement;
|
| var getInnerHTML = scope.getInnerHTML;
|
| var mixin = scope.mixin;
|
| + var muteMutationEvents = scope.muteMutationEvents;
|
| var registerWrapper = scope.registerWrapper;
|
| var setInnerHTML = scope.setInnerHTML;
|
| + var unmuteMutationEvents = scope.unmuteMutationEvents;
|
| var unwrap = scope.unwrap;
|
| var wrap = scope.wrap;
|
|
|
| @@ -3632,9 +3641,11 @@ var ShadowDOMPolyfill = {};
|
| var doc = getTemplateContentsOwner(templateElement.ownerDocument);
|
| var df = unwrap(doc.createDocumentFragment());
|
| var child;
|
| + muteMutationEvents();
|
| while (child = templateElement.firstChild) {
|
| df.appendChild(child);
|
| }
|
| + unmuteMutationEvents();
|
| return df;
|
| }
|
|
|
| @@ -3808,7 +3819,9 @@ var ShadowDOMPolyfill = {};
|
| var assert = scope.assert;
|
| var getHostForShadowRoot = scope.getHostForShadowRoot;
|
| var mixin = scope.mixin;
|
| + var muteMutationEvents = scope.muteMutationEvents;
|
| var oneOf = scope.oneOf;
|
| + var unmuteMutationEvents = scope.unmuteMutationEvents;
|
| var unwrap = scope.unwrap;
|
| var wrap = scope.wrap;
|
|
|
| @@ -4119,7 +4132,7 @@ var ShadowDOMPolyfill = {};
|
| }
|
|
|
| for (var i = lastIndex; i < newChildren.length; i++) {
|
| - newChildren[i++].sync(added);
|
| + newChildren[i].sync(added);
|
| }
|
| }
|
| };
|
| @@ -4152,8 +4165,11 @@ var ShadowDOMPolyfill = {};
|
| this.renderNode(shadowRoot, renderNode, node, false);
|
| }
|
|
|
| - if (topMostRenderer)
|
| + if (topMostRenderer) {
|
| + //muteMutationEvents();
|
| renderNode.sync();
|
| + //unmuteMutationEvents();
|
| + }
|
|
|
| this.dirty = false;
|
| },
|
| @@ -5163,6 +5179,13 @@ var ShadowDOMPolyfill = {};
|
| if (window.MutationObserver && (obj instanceof MutationObserver))
|
| return 'MutationObserver';
|
|
|
| + // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
|
| + // and dart:html's <template> polyfill. Essentially, ShadowDOM is
|
| + // polyfilling native template, but our Dart polyfill fails to detect this
|
| + // because the unwrapped node is an HTMLUnknownElement, leading it to
|
| + // think the node has no content.
|
| + if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';
|
| +
|
| var unwrapped = unwrapIfNeeded(obj);
|
| if (obj !== unwrapped) {
|
| // Fix up class names for Firefox.
|
|
|