Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(668)

Side by Side Diff: pkg/shadow_dom/lib/shadow_dom.debug.js

Issue 26391003: fix ShadowDOM on browsers with non-native template (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/pkg.status ('k') | pkg/shadow_dom/lib/shadow_dom.min.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 if (!HTMLElement.prototype.createShadowRoot 1 if (!HTMLElement.prototype.createShadowRoot
2 || window.__forceShadowDomPolyfill) { 2 || window.__forceShadowDomPolyfill) {
3 3
4 /* 4 /*
5 * Copyright 2013 The Polymer Authors. All rights reserved. 5 * Copyright 2013 The Polymer Authors. All rights reserved.
6 * Use of this source code is governed by a BSD-style 6 * Use of this source code is governed by a BSD-style
7 * license that can be found in the LICENSE file. 7 * license that can be found in the LICENSE file.
8 */ 8 */
9 (function() { 9 (function() {
10 // TODO(jmesserly): fix dart:html to use unprefixed name 10 // TODO(jmesserly): fix dart:html to use unprefixed name
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 Array.prototype.splice.apply(previous, spliceArgs); 585 Array.prototype.splice.apply(previous, spliceArgs);
586 }); 586 });
587 }; 587 };
588 588
589 function ObservedSet(callback) { 589 function ObservedSet(callback) {
590 this.arr = []; 590 this.arr = [];
591 this.callback = callback; 591 this.callback = callback;
592 this.isObserved = true; 592 this.isObserved = true;
593 } 593 }
594 594
595 // TODO(rafaelw): Consider surfacing a way to avoid observing prototype
596 // ancestors which are expected not to change (e.g. Element, Node...).
595 var objProto = Object.getPrototypeOf({}); 597 var objProto = Object.getPrototypeOf({});
596 var arrayProto = Object.getPrototypeOf([]); 598 var arrayProto = Object.getPrototypeOf([]);
597 ObservedSet.prototype = { 599 ObservedSet.prototype = {
598 reset: function() { 600 reset: function() {
599 this.isObserved = !this.isObserved; 601 this.isObserved = !this.isObserved;
600 }, 602 },
601 603
602 observe: function(obj) { 604 observe: function(obj) {
603 if (!isObject(obj) || obj === objProto || obj === arrayProto) 605 if (!isObject(obj) || obj === objProto || obj === arrayProto)
604 return; 606 return;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 this.value = undefined; 729 this.value = undefined;
728 this.oldValue = undefined; 730 this.oldValue = undefined;
729 this.oldValues = undefined; 731 this.oldValues = undefined;
730 this.changeFlags = undefined; 732 this.changeFlags = undefined;
731 this.started = false; 733 this.started = false;
732 } 734 }
733 735
734 CompoundPathObserver.prototype = createObject({ 736 CompoundPathObserver.prototype = createObject({
735 __proto__: PathObserver.prototype, 737 __proto__: PathObserver.prototype,
736 738
739 // TODO(rafaelw): Consider special-casing when |object| is a PathObserver
740 // and path 'value' to avoid explicit observation.
737 addPath: function(object, path) { 741 addPath: function(object, path) {
738 if (this.started) 742 if (this.started)
739 throw Error('Cannot add more paths once started.'); 743 throw Error('Cannot add more paths once started.');
740 744
741 var path = path instanceof Path ? path : getPath(path); 745 var path = path instanceof Path ? path : getPath(path);
742 var value = path ? path.getValueFrom(object) : undefined; 746 var value = path ? path.getValueFrom(object) : undefined;
743 747
744 this.observed.push(object, path); 748 this.observed.push(object, path);
745 this.values.push(value); 749 this.values.push(value);
746 }, 750 },
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 return; 795 return;
792 796
793 if (this.valueFn) { 797 if (this.valueFn) {
794 this.value = this.valueFn(this.values); 798 this.value = this.valueFn(this.values);
795 799
796 if (areSameValue(this.value, this.oldValue)) 800 if (areSameValue(this.value, this.oldValue))
797 return false; 801 return false;
798 802
799 this.reportArgs = [this.value, this.oldValue]; 803 this.reportArgs = [this.value, this.oldValue];
800 } else { 804 } else {
801 this.reportArgs = [this.values, this.oldValues, this.changeFlags]; 805 this.reportArgs = [this.values, this.oldValues, this.changeFlags,
806 this.observed];
802 } 807 }
803 808
804 return true; 809 return true;
805 }, 810 },
806 811
807 sync: function(hard) { 812 sync: function(hard) {
808 if (hard) { 813 if (hard) {
809 this.getValues(); 814 this.getValues();
810 if (this.valueFn) 815 if (this.valueFn)
811 this.value = this.valueFn(this.values); 816 this.value = this.valueFn(this.values);
(...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 function enclosedBy(a, b) { 1945 function enclosedBy(a, b) {
1941 if (a === b) 1946 if (a === b)
1942 return true; 1947 return true;
1943 if (a instanceof wrappers.ShadowRoot) { 1948 if (a instanceof wrappers.ShadowRoot) {
1944 var host = scope.getHostForShadowRoot(a); 1949 var host = scope.getHostForShadowRoot(a);
1945 return enclosedBy(rootOfNode(host), b); 1950 return enclosedBy(rootOfNode(host), b);
1946 } 1951 }
1947 return false; 1952 return false;
1948 } 1953 }
1949 1954
1950 function isMutationEvent(type) { 1955 var mutationEventsAreSilenced = 0;
1951 switch (type) { 1956
1952 case 'DOMAttrModified': 1957 function muteMutationEvents() {
1953 case 'DOMAttributeNameChanged': 1958 mutationEventsAreSilenced++;
1954 case 'DOMCharacterDataModified':
1955 case 'DOMElementNameChanged':
1956 case 'DOMNodeInserted':
1957 case 'DOMNodeInsertedIntoDocument':
1958 case 'DOMNodeRemoved':
1959 case 'DOMNodeRemovedFromDocument':
1960 case 'DOMSubtreeModified':
1961 return true;
1962 }
1963 return false;
1964 } 1959 }
1965 1960
1961 function unmuteMutationEvents() {
1962 mutationEventsAreSilenced--;
1963 }
1964
1965 var OriginalMutationEvent = window.MutationEvent;
1966
1966 function dispatchOriginalEvent(originalEvent) { 1967 function dispatchOriginalEvent(originalEvent) {
1967 // Make sure this event is only dispatched once. 1968 // Make sure this event is only dispatched once.
1968 if (handledEventsTable.get(originalEvent)) 1969 if (handledEventsTable.get(originalEvent))
1969 return; 1970 return;
1970 handledEventsTable.set(originalEvent, true); 1971 handledEventsTable.set(originalEvent, true);
1971 1972
1972 // Don't do rendering if this is a mutation event since rendering might 1973 // Don't do rendering if this is a mutation event since rendering might
1973 // mutate the DOM which would fire more events and we would most likely 1974 // mutate the DOM which would fire more events and we would most likely
1974 // just iloop. 1975 // just iloop.
1975 if (!isMutationEvent(originalEvent.type)) 1976 if (originalEvent instanceof OriginalMutationEvent) {
1977 if (mutationEventsAreSilenced)
1978 return;
1979 } else {
1976 scope.renderAllPending(); 1980 scope.renderAllPending();
1981 }
1977 1982
1978 var target = wrap(originalEvent.target); 1983 var target = wrap(originalEvent.target);
1979 var event = wrap(originalEvent); 1984 var event = wrap(originalEvent);
1980 return dispatchEvent(event, target); 1985 return dispatchEvent(event, target);
1981 } 1986 }
1982 1987
1983 function dispatchEvent(event, originalWrapperTarget) { 1988 function dispatchEvent(event, originalWrapperTarget) {
1984 var eventPath = retarget(originalWrapperTarget); 1989 var eventPath = retarget(originalWrapperTarget);
1985 1990
1986 // For window load events the load event is dispatched at the window but 1991 // For window load events the load event is dispatched at the window but
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 else 2100 else
2096 listener.handler.handleEvent(event); 2101 listener.handler.handleEvent(event);
2097 2102
2098 if (stopImmediatePropagationTable.get(event)) 2103 if (stopImmediatePropagationTable.get(event))
2099 return false; 2104 return false;
2100 2105
2101 } catch (ex) { 2106 } catch (ex) {
2102 if (window.onerror) 2107 if (window.onerror)
2103 window.onerror(ex.message); 2108 window.onerror(ex.message);
2104 else 2109 else
2105 console.error(ex); 2110 console.error(ex, ex.stack);
2106 } 2111 }
2107 } 2112 }
2108 2113
2109 if (anyRemoved) { 2114 if (anyRemoved) {
2110 var copy = listeners.slice(); 2115 var copy = listeners.slice();
2111 listeners.length = 0; 2116 listeners.length = 0;
2112 for (var i = 0; i < copy.length; i++) { 2117 for (var i = 0; i < copy.length; i++) {
2113 if (!copy[i].removed) 2118 if (!copy[i].removed)
2114 listeners.push(copy[i]); 2119 listeners.push(copy[i]);
2115 } 2120 }
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2484 wrapped: wrapped 2489 wrapped: wrapped
2485 }; 2490 };
2486 } 2491 }
2487 }; 2492 };
2488 } 2493 }
2489 2494
2490 scope.adjustRelatedTarget = adjustRelatedTarget; 2495 scope.adjustRelatedTarget = adjustRelatedTarget;
2491 scope.elementFromPoint = elementFromPoint; 2496 scope.elementFromPoint = elementFromPoint;
2492 scope.getEventHandlerGetter = getEventHandlerGetter; 2497 scope.getEventHandlerGetter = getEventHandlerGetter;
2493 scope.getEventHandlerSetter = getEventHandlerSetter; 2498 scope.getEventHandlerSetter = getEventHandlerSetter;
2499 scope.muteMutationEvents = muteMutationEvents;
2500 scope.unmuteMutationEvents = unmuteMutationEvents;
2494 scope.wrapEventTargetMethods = wrapEventTargetMethods; 2501 scope.wrapEventTargetMethods = wrapEventTargetMethods;
2495 scope.wrappers.CustomEvent = CustomEvent; 2502 scope.wrappers.CustomEvent = CustomEvent;
2496 scope.wrappers.Event = Event; 2503 scope.wrappers.Event = Event;
2497 scope.wrappers.EventTarget = EventTarget; 2504 scope.wrappers.EventTarget = EventTarget;
2498 scope.wrappers.FocusEvent = FocusEvent; 2505 scope.wrappers.FocusEvent = FocusEvent;
2499 scope.wrappers.MouseEvent = MouseEvent; 2506 scope.wrappers.MouseEvent = MouseEvent;
2500 scope.wrappers.MutationEvent = MutationEvent; 2507 scope.wrappers.MutationEvent = MutationEvent;
2501 scope.wrappers.UIEvent = UIEvent; 2508 scope.wrappers.UIEvent = UIEvent;
2502 2509
2503 })(this.ShadowDOMPolyfill); 2510 })(this.ShadowDOMPolyfill);
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after
3595 // Copyright 2013 The Polymer Authors. All rights reserved. 3602 // Copyright 2013 The Polymer Authors. All rights reserved.
3596 // Use of this source code is goverened by a BSD-style 3603 // Use of this source code is goverened by a BSD-style
3597 // license that can be found in the LICENSE file. 3604 // license that can be found in the LICENSE file.
3598 3605
3599 (function(scope) { 3606 (function(scope) {
3600 'use strict'; 3607 'use strict';
3601 3608
3602 var HTMLElement = scope.wrappers.HTMLElement; 3609 var HTMLElement = scope.wrappers.HTMLElement;
3603 var getInnerHTML = scope.getInnerHTML; 3610 var getInnerHTML = scope.getInnerHTML;
3604 var mixin = scope.mixin; 3611 var mixin = scope.mixin;
3612 var muteMutationEvents = scope.muteMutationEvents;
3605 var registerWrapper = scope.registerWrapper; 3613 var registerWrapper = scope.registerWrapper;
3606 var setInnerHTML = scope.setInnerHTML; 3614 var setInnerHTML = scope.setInnerHTML;
3615 var unmuteMutationEvents = scope.unmuteMutationEvents;
3607 var unwrap = scope.unwrap; 3616 var unwrap = scope.unwrap;
3608 var wrap = scope.wrap; 3617 var wrap = scope.wrap;
3609 3618
3610 var contentTable = new WeakMap(); 3619 var contentTable = new WeakMap();
3611 var templateContentsOwnerTable = new WeakMap(); 3620 var templateContentsOwnerTable = new WeakMap();
3612 3621
3613 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html# dfn-template-contents-owner 3622 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html# dfn-template-contents-owner
3614 function getTemplateContentsOwner(doc) { 3623 function getTemplateContentsOwner(doc) {
3615 if (!doc.defaultView) 3624 if (!doc.defaultView)
3616 return doc; 3625 return doc;
3617 var d = templateContentsOwnerTable.get(doc); 3626 var d = templateContentsOwnerTable.get(doc);
3618 if (!d) { 3627 if (!d) {
3619 // TODO(arv): This should either be a Document or HTMLDocument depending 3628 // TODO(arv): This should either be a Document or HTMLDocument depending
3620 // on doc. 3629 // on doc.
3621 d = doc.implementation.createHTMLDocument(''); 3630 d = doc.implementation.createHTMLDocument('');
3622 while (d.lastChild) { 3631 while (d.lastChild) {
3623 d.removeChild(d.lastChild); 3632 d.removeChild(d.lastChild);
3624 } 3633 }
3625 templateContentsOwnerTable.set(doc, d); 3634 templateContentsOwnerTable.set(doc, d);
3626 } 3635 }
3627 return d; 3636 return d;
3628 } 3637 }
3629 3638
3630 function extractContent(templateElement) { 3639 function extractContent(templateElement) {
3631 // templateElement is not a wrapper here. 3640 // templateElement is not a wrapper here.
3632 var doc = getTemplateContentsOwner(templateElement.ownerDocument); 3641 var doc = getTemplateContentsOwner(templateElement.ownerDocument);
3633 var df = unwrap(doc.createDocumentFragment()); 3642 var df = unwrap(doc.createDocumentFragment());
3634 var child; 3643 var child;
3644 muteMutationEvents();
3635 while (child = templateElement.firstChild) { 3645 while (child = templateElement.firstChild) {
3636 df.appendChild(child); 3646 df.appendChild(child);
3637 } 3647 }
3648 unmuteMutationEvents();
3638 return df; 3649 return df;
3639 } 3650 }
3640 3651
3641 var OriginalHTMLTemplateElement = window.HTMLTemplateElement; 3652 var OriginalHTMLTemplateElement = window.HTMLTemplateElement;
3642 3653
3643 function HTMLTemplateElement(node) { 3654 function HTMLTemplateElement(node) {
3644 HTMLElement.call(this, node); 3655 HTMLElement.call(this, node);
3645 if (!OriginalHTMLTemplateElement) { 3656 if (!OriginalHTMLTemplateElement) {
3646 var content = extractContent(node); 3657 var content = extractContent(node);
3647 contentTable.set(this, wrap(content)); 3658 contentTable.set(this, wrap(content));
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
3801 'use strict'; 3812 'use strict';
3802 3813
3803 var Element = scope.wrappers.Element; 3814 var Element = scope.wrappers.Element;
3804 var HTMLContentElement = scope.wrappers.HTMLContentElement; 3815 var HTMLContentElement = scope.wrappers.HTMLContentElement;
3805 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; 3816 var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
3806 var Node = scope.wrappers.Node; 3817 var Node = scope.wrappers.Node;
3807 var ShadowRoot = scope.wrappers.ShadowRoot; 3818 var ShadowRoot = scope.wrappers.ShadowRoot;
3808 var assert = scope.assert; 3819 var assert = scope.assert;
3809 var getHostForShadowRoot = scope.getHostForShadowRoot; 3820 var getHostForShadowRoot = scope.getHostForShadowRoot;
3810 var mixin = scope.mixin; 3821 var mixin = scope.mixin;
3822 var muteMutationEvents = scope.muteMutationEvents;
3811 var oneOf = scope.oneOf; 3823 var oneOf = scope.oneOf;
3824 var unmuteMutationEvents = scope.unmuteMutationEvents;
3812 var unwrap = scope.unwrap; 3825 var unwrap = scope.unwrap;
3813 var wrap = scope.wrap; 3826 var wrap = scope.wrap;
3814 3827
3815 /** 3828 /**
3816 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. 3829 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed.
3817 * Up means parentNode 3830 * Up means parentNode
3818 * Sideways means previous and next sibling. 3831 * Sideways means previous and next sibling.
3819 * @param {!Node} wrapper 3832 * @param {!Node} wrapper
3820 */ 3833 */
3821 function updateWrapperUpAndSideways(wrapper) { 3834 function updateWrapperUpAndSideways(wrapper) {
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
4112 // has been added. 4125 // has been added.
4113 added.set(newChildWrapper, true); 4126 added.set(newChildWrapper, true);
4114 4127
4115 newChildRenderNode.sync(added); 4128 newChildRenderNode.sync(added);
4116 } 4129 }
4117 4130
4118 lastIndex += addedCount; 4131 lastIndex += addedCount;
4119 } 4132 }
4120 4133
4121 for (var i = lastIndex; i < newChildren.length; i++) { 4134 for (var i = lastIndex; i < newChildren.length; i++) {
4122 newChildren[i++].sync(added); 4135 newChildren[i].sync(added);
4123 } 4136 }
4124 } 4137 }
4125 }; 4138 };
4126 4139
4127 function ShadowRenderer(host) { 4140 function ShadowRenderer(host) {
4128 this.host = host; 4141 this.host = host;
4129 this.dirty = false; 4142 this.dirty = false;
4130 this.invalidateAttributes(); 4143 this.invalidateAttributes();
4131 this.associateNode(host); 4144 this.associateNode(host);
4132 } 4145 }
(...skipping 12 matching lines...) Expand all
4145 var shadowRoot = host.shadowRoot; 4158 var shadowRoot = host.shadowRoot;
4146 4159
4147 this.associateNode(host); 4160 this.associateNode(host);
4148 var topMostRenderer = !renderNode; 4161 var topMostRenderer = !renderNode;
4149 var renderNode = opt_renderNode || new RenderNode(host); 4162 var renderNode = opt_renderNode || new RenderNode(host);
4150 4163
4151 for (var node = shadowRoot.firstChild; node; node = node.nextSibling) { 4164 for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {
4152 this.renderNode(shadowRoot, renderNode, node, false); 4165 this.renderNode(shadowRoot, renderNode, node, false);
4153 } 4166 }
4154 4167
4155 if (topMostRenderer) 4168 if (topMostRenderer) {
4169 //muteMutationEvents();
4156 renderNode.sync(); 4170 renderNode.sync();
4171 //unmuteMutationEvents();
4172 }
4157 4173
4158 this.dirty = false; 4174 this.dirty = false;
4159 }, 4175 },
4160 4176
4161 invalidate: function() { 4177 invalidate: function() {
4162 if (!this.dirty) { 4178 if (!this.dirty) {
4163 this.dirty = true; 4179 this.dirty = true;
4164 pendingDirtyRenderers.push(this); 4180 pendingDirtyRenderers.push(this);
4165 if (renderTimer) 4181 if (renderTimer)
4166 return; 4182 return;
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
5156 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded; 5172 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
5157 function getTag(obj) { 5173 function getTag(obj) {
5158 // TODO(jmesserly): do we still need these? 5174 // TODO(jmesserly): do we still need these?
5159 if (obj instanceof NodeList) return 'NodeList'; 5175 if (obj instanceof NodeList) return 'NodeList';
5160 if (obj instanceof ShadowRoot) return 'ShadowRoot'; 5176 if (obj instanceof ShadowRoot) return 'ShadowRoot';
5161 if (window.MutationRecord && (obj instanceof MutationRecord)) 5177 if (window.MutationRecord && (obj instanceof MutationRecord))
5162 return 'MutationRecord'; 5178 return 'MutationRecord';
5163 if (window.MutationObserver && (obj instanceof MutationObserver)) 5179 if (window.MutationObserver && (obj instanceof MutationObserver))
5164 return 'MutationObserver'; 5180 return 'MutationObserver';
5165 5181
5182 // TODO(jmesserly): this prevents incorrect interaction between ShadowDOM
5183 // and dart:html's <template> polyfill. Essentially, ShadowDOM is
5184 // polyfilling native template, but our Dart polyfill fails to detect this
5185 // because the unwrapped node is an HTMLUnknownElement, leading it to
5186 // think the node has no content.
5187 if (obj instanceof HTMLTemplateElement) return 'HTMLTemplateElement';
5188
5166 var unwrapped = unwrapIfNeeded(obj); 5189 var unwrapped = unwrapIfNeeded(obj);
5167 if (obj !== unwrapped) { 5190 if (obj !== unwrapped) {
5168 // Fix up class names for Firefox. 5191 // Fix up class names for Firefox.
5169 // For some of them (like HTMLFormElement and HTMLInputElement), 5192 // For some of them (like HTMLFormElement and HTMLInputElement),
5170 // the "constructor" property of the unwrapped nodes points at the 5193 // the "constructor" property of the unwrapped nodes points at the
5171 // same constructor as the wrapper. 5194 // same constructor as the wrapper.
5172 var ctor = obj.constructor 5195 var ctor = obj.constructor
5173 if (ctor === unwrapped.constructor) { 5196 if (ctor === unwrapped.constructor) {
5174 var name = ctor._ShadowDOMPolyfill$cacheTag_; 5197 var name = ctor._ShadowDOMPolyfill$cacheTag_;
5175 if (!name) { 5198 if (!name) {
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
5707 css.push(cssRules[i].cssText); 5730 css.push(cssRules[i].cssText);
5708 } 5731 }
5709 return css.join('\n\n'); 5732 return css.join('\n\n');
5710 } 5733 }
5711 5734
5712 // exports 5735 // exports
5713 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2; 5736 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2;
5714 })(window.Platform); 5737 })(window.Platform);
5715 5738
5716 } 5739 }
OLDNEW
« no previous file with comments | « pkg/pkg.status ('k') | pkg/shadow_dom/lib/shadow_dom.min.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698