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

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

Issue 24324005: Updating Shadow DOM and including some fixes to enable it to work with CustomElements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 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/polymer/test/event_path_test.html ('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 !HTMLElement.prototype.webkitCreateShadowRoot) || 2 || window.__forceShadowDomPolyfill) {
3 window.__forceShadowDomPolyfill) {
4 3
5 /* 4 /*
6 * Copyright 2013 The Polymer Authors. All rights reserved. 5 * Copyright 2013 The Polymer Authors. All rights reserved.
7 * Use of this source code is governed by a BSD-style 6 * Use of this source code is governed by a BSD-style
8 * license that can be found in the LICENSE file. 7 * license that can be found in the LICENSE file.
9 */ 8 */
10 (function() { 9 (function() {
11 // TODO(jmesserly): fix dart:html to use unprefixed name 10 // TODO(jmesserly): fix dart:html to use unprefixed name
12 if (Element.prototype.webkitCreateShadowRoot) { 11 if (Element.prototype.webkitCreateShadowRoot) {
13 Element.prototype.webkitCreateShadowRoot = function() { 12 Element.prototype.webkitCreateShadowRoot = function() {
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 this.path.setValueFrom(this.object, newValue); 717 this.path.setValueFrom(this.object, newValue);
719 } 718 }
720 }); 719 });
721 720
722 function CompoundPathObserver(callback, target, token, valueFn) { 721 function CompoundPathObserver(callback, target, token, valueFn) {
723 Observer.call(this, undefined, callback, target, token); 722 Observer.call(this, undefined, callback, target, token);
724 this.valueFn = valueFn; 723 this.valueFn = valueFn;
725 724
726 this.observed = []; 725 this.observed = [];
727 this.values = []; 726 this.values = [];
727 this.value = undefined;
728 this.oldValue = undefined;
729 this.oldValues = undefined;
730 this.changeFlags = undefined;
728 this.started = false; 731 this.started = false;
729 } 732 }
730 733
731 CompoundPathObserver.prototype = createObject({ 734 CompoundPathObserver.prototype = createObject({
732 __proto__: PathObserver.prototype, 735 __proto__: PathObserver.prototype,
733 736
734 addPath: function(object, path) { 737 addPath: function(object, path) {
735 if (this.started) 738 if (this.started)
736 throw Error('Cannot add more paths once started.'); 739 throw Error('Cannot add more paths once started.');
737 740
(...skipping 15 matching lines...) Expand all
753 756
754 var anyChanged = false; 757 var anyChanged = false;
755 for (var i = 0; i < this.observed.length; i = i+2) { 758 for (var i = 0; i < this.observed.length; i = i+2) {
756 var path = this.observed[i+1]; 759 var path = this.observed[i+1];
757 if (!path) 760 if (!path)
758 continue; 761 continue;
759 var object = this.observed[i]; 762 var object = this.observed[i];
760 var value = path.getValueFrom(object, this.observedSet); 763 var value = path.getValueFrom(object, this.observedSet);
761 var oldValue = this.values[i/2]; 764 var oldValue = this.values[i/2];
762 if (!areSameValue(value, oldValue)) { 765 if (!areSameValue(value, oldValue)) {
766 if (!anyChanged && !this.valueFn) {
767 this.oldValues = this.oldValues || [];
768 this.changeFlags = this.changeFlags || [];
769 for (var j = 0; j < this.values.length; j++) {
770 this.oldValues[j] = this.values[j];
771 this.changeFlags[j] = false;
772 }
773 }
774
775 if (!this.valueFn)
776 this.changeFlags[i/2] = true;
777
763 this.values[i/2] = value; 778 this.values[i/2] = value;
764 anyChanged = true; 779 anyChanged = true;
765 } 780 }
766 } 781 }
767 782
768 if (this.observedSet) 783 if (this.observedSet)
769 this.observedSet.cleanup(); 784 this.observedSet.cleanup();
770 785
771 return anyChanged; 786 return anyChanged;
772 }, 787 },
773 788
774 check: function() { 789 check: function() {
775 if (!this.getValues()) 790 if (!this.getValues())
776 return; 791 return;
777 792
778 this.value = this.valueFn(this.values); 793 if (this.valueFn) {
794 this.value = this.valueFn(this.values);
779 795
780 if (areSameValue(this.value, this.oldValue)) 796 if (areSameValue(this.value, this.oldValue))
781 return false; 797 return false;
782 798
783 this.reportArgs = [this.value, this.oldValue]; 799 this.reportArgs = [this.value, this.oldValue];
800 } else {
801 this.reportArgs = [this.values, this.oldValues, this.changeFlags];
802 }
803
784 return true; 804 return true;
785 }, 805 },
786 806
787 sync: function(hard) { 807 sync: function(hard) {
788 if (hard) { 808 if (hard) {
789 this.getValues(); 809 this.getValues();
790 this.value = this.valueFn(this.values); 810 if (this.valueFn)
811 this.value = this.valueFn(this.values);
791 } 812 }
792 813
793 this.oldValue = this.value; 814 if (this.valueFn)
815 this.oldValue = this.value;
794 }, 816 },
795 817
796 close: function() { 818 close: function() {
797 if (this.observed) { 819 if (this.observed) {
798 for (var i = 0; i < this.observed.length; i = i + 2) { 820 for (var i = 0; i < this.observed.length; i = i + 2) {
799 var object = this.observed[i]; 821 var object = this.observed[i];
800 if (object && typeof object.close === 'function') 822 if (object && typeof object.close === 'function')
801 object.close(); 823 object.close();
802 } 824 }
803 this.observed = undefined; 825 this.observed = undefined;
(...skipping 2083 matching lines...) Expand 10 before | Expand all | Expand 10 after
2887 nodesWereAdded(nodes); 2909 nodesWereAdded(nodes);
2888 2910
2889 return oldChildWrapper; 2911 return oldChildWrapper;
2890 }, 2912 },
2891 2913
2892 /** 2914 /**
2893 * Called after a node was added. Subclasses override this to invalidate 2915 * Called after a node was added. Subclasses override this to invalidate
2894 * the renderer as needed. 2916 * the renderer as needed.
2895 * @private 2917 * @private
2896 */ 2918 */
2897 nodeWasAdded_: function() {}, 2919 nodeWasAdded_: function() {
2920 for (var child = this.firstChild; child; child = child.nextSibling) {
2921 child.nodeWasAdded_();
2922 }
2923 },
2898 2924
2899 hasChildNodes: function() { 2925 hasChildNodes: function() {
2900 return this.firstChild === null; 2926 return this.firstChild === null;
2901 }, 2927 },
2902 2928
2903 /** @type {Node} */ 2929 /** @type {Node} */
2904 get parentNode() { 2930 get parentNode() {
2905 // If the parentNode has not been overridden, use the original parentNode. 2931 // If the parentNode has not been overridden, use the original parentNode.
2906 return this.parentNode_ !== undefined ? 2932 return this.parentNode_ !== undefined ?
2907 this.parentNode_ : wrap(this.impl.parentNode); 2933 this.parentNode_ : wrap(this.impl.parentNode);
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
3210 var GetElementsByInterface = scope.GetElementsByInterface; 3236 var GetElementsByInterface = scope.GetElementsByInterface;
3211 var Node = scope.wrappers.Node; 3237 var Node = scope.wrappers.Node;
3212 var ParentNodeInterface = scope.ParentNodeInterface; 3238 var ParentNodeInterface = scope.ParentNodeInterface;
3213 var SelectorsInterface = scope.SelectorsInterface; 3239 var SelectorsInterface = scope.SelectorsInterface;
3214 var addWrapNodeListMethod = scope.addWrapNodeListMethod; 3240 var addWrapNodeListMethod = scope.addWrapNodeListMethod;
3215 var mixin = scope.mixin; 3241 var mixin = scope.mixin;
3216 var oneOf = scope.oneOf; 3242 var oneOf = scope.oneOf;
3217 var registerWrapper = scope.registerWrapper; 3243 var registerWrapper = scope.registerWrapper;
3218 var wrappers = scope.wrappers; 3244 var wrappers = scope.wrappers;
3219 3245
3220 var shadowRootTable = new WeakMap();
3221 var OriginalElement = window.Element; 3246 var OriginalElement = window.Element;
3222 3247
3223
3224 var matchesName = oneOf(OriginalElement.prototype, [ 3248 var matchesName = oneOf(OriginalElement.prototype, [
3225 'matches', 3249 'matches',
3226 'mozMatchesSelector', 3250 'mozMatchesSelector',
3227 'msMatchesSelector', 3251 'msMatchesSelector',
3228 'webkitMatchesSelector', 3252 'webkitMatchesSelector',
3229 ]); 3253 ]);
3230 3254
3231 var originalMatches = OriginalElement.prototype[matchesName]; 3255 var originalMatches = OriginalElement.prototype[matchesName];
3232 3256
3233 function invalidateRendererBasedOnAttribute(element, name) { 3257 function invalidateRendererBasedOnAttribute(element, name) {
3234 // Only invalidate if parent node is a shadow host. 3258 // Only invalidate if parent node is a shadow host.
3235 var p = element.parentNode; 3259 var p = element.parentNode;
3236 if (!p || !p.shadowRoot) 3260 if (!p || !p.shadowRoot)
3237 return; 3261 return;
3238 3262
3239 var renderer = scope.getRendererForHost(p); 3263 var renderer = scope.getRendererForHost(p);
3240 if (renderer.dependsOnAttribute(name)) 3264 if (renderer.dependsOnAttribute(name))
3241 renderer.invalidate(); 3265 renderer.invalidate();
3242 } 3266 }
3243 3267
3244 function Element(node) { 3268 function Element(node) {
3245 Node.call(this, node); 3269 Node.call(this, node);
3246 } 3270 }
3247 Element.prototype = Object.create(Node.prototype); 3271 Element.prototype = Object.create(Node.prototype);
3248 mixin(Element.prototype, { 3272 mixin(Element.prototype, {
3249 createShadowRoot: function() { 3273 createShadowRoot: function() {
3250 var newShadowRoot = new wrappers.ShadowRoot(this); 3274 var newShadowRoot = new wrappers.ShadowRoot(this);
3251 shadowRootTable.set(this, newShadowRoot); 3275 this.impl.polymerShadowRoot_ = newShadowRoot;
3252 3276
3253 var renderer = scope.getRendererForHost(this); 3277 var renderer = scope.getRendererForHost(this);
3254 renderer.invalidate(); 3278 renderer.invalidate();
3255 3279
3256 return newShadowRoot; 3280 return newShadowRoot;
3257 }, 3281 },
3258 3282
3259 get shadowRoot() { 3283 get shadowRoot() {
3260 return shadowRootTable.get(this) || null; 3284 return this.impl.polymerShadowRoot_ || null;
3261 }, 3285 },
3262 3286
3263 setAttribute: function(name, value) { 3287 setAttribute: function(name, value) {
3264 this.impl.setAttribute(name, value); 3288 this.impl.setAttribute(name, value);
3265 invalidateRendererBasedOnAttribute(this, name); 3289 invalidateRendererBasedOnAttribute(this, name);
3266 }, 3290 },
3267 3291
3268 removeAttribute: function(name) { 3292 removeAttribute: function(name) {
3269 this.impl.removeAttribute(name); 3293 this.impl.removeAttribute(name);
3270 invalidateRendererBasedOnAttribute(this, name); 3294 invalidateRendererBasedOnAttribute(this, name);
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
3865 if (parentNodeWrapper.firstChild === nodeWrapper) 3889 if (parentNodeWrapper.firstChild === nodeWrapper)
3866 parentNodeWrapper.firstChild_ = nodeWrapper; 3890 parentNodeWrapper.firstChild_ = nodeWrapper;
3867 3891
3868 parentNode.removeChild(node); 3892 parentNode.removeChild(node);
3869 } 3893 }
3870 3894
3871 var distributedChildNodesTable = new WeakMap(); 3895 var distributedChildNodesTable = new WeakMap();
3872 var eventParentsTable = new WeakMap(); 3896 var eventParentsTable = new WeakMap();
3873 var insertionParentTable = new WeakMap(); 3897 var insertionParentTable = new WeakMap();
3874 var rendererForHostTable = new WeakMap(); 3898 var rendererForHostTable = new WeakMap();
3875 var shadowDOMRendererTable = new WeakMap();
3876 3899
3877 function distributeChildToInsertionPoint(child, insertionPoint) { 3900 function distributeChildToInsertionPoint(child, insertionPoint) {
3878 getDistributedChildNodes(insertionPoint).push(child); 3901 getDistributedChildNodes(insertionPoint).push(child);
3879 assignToInsertionPoint(child, insertionPoint); 3902 assignToInsertionPoint(child, insertionPoint);
3880 3903
3881 var eventParents = eventParentsTable.get(child); 3904 var eventParents = eventParentsTable.get(child);
3882 if (!eventParents) 3905 if (!eventParents)
3883 eventParentsTable.set(child, eventParents = []); 3906 eventParentsTable.set(child, eventParents = []);
3884 eventParents.push(insertionPoint); 3907 eventParents.push(insertionPoint);
3885 } 3908 }
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
4318 assignToInsertionPoint(tree, point); // 4.3.2.2. 4341 assignToInsertionPoint(tree, point); // 4.3.2.2.
4319 continue; // 4.3.2.3. 4342 continue; // 4.3.2.3.
4320 } 4343 }
4321 } else { 4344 } else {
4322 break; // 4.4. 4345 break; // 4.4.
4323 } 4346 }
4324 } 4347 }
4325 }, 4348 },
4326 4349
4327 associateNode: function(node) { 4350 associateNode: function(node) {
4328 shadowDOMRendererTable.set(node, this); 4351 node.impl.polymerShadowRenderer_ = this;
4329 } 4352 }
4330 }; 4353 };
4331 4354
4332 function isInsertionPoint(node) { 4355 function isInsertionPoint(node) {
4333 // Should this include <shadow>? 4356 // Should this include <shadow>?
4334 return node instanceof HTMLContentElement; 4357 return node instanceof HTMLContentElement;
4335 } 4358 }
4336 4359
4337 function isActiveInsertionPoint(node) { 4360 function isActiveInsertionPoint(node) {
4338 // <content> inside another <content> or <shadow> is considered inactive. 4361 // <content> inside another <content> or <shadow> is considered inactive.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4377 // - a new shadow root is created 4400 // - a new shadow root is created
4378 // - a direct child to a content/shadow element is added or removed 4401 // - a direct child to a content/shadow element is added or removed
4379 // - a sibling to a content/shadow element is added or removed 4402 // - a sibling to a content/shadow element is added or removed
4380 // - content[select] is changed 4403 // - content[select] is changed
4381 // - an attribute in a direct child to a host is modified 4404 // - an attribute in a direct child to a host is modified
4382 4405
4383 /** 4406 /**
4384 * This gets called when a node was added or removed to it. 4407 * This gets called when a node was added or removed to it.
4385 */ 4408 */
4386 Node.prototype.invalidateShadowRenderer = function(force) { 4409 Node.prototype.invalidateShadowRenderer = function(force) {
4387 var renderer = shadowDOMRendererTable.get(this); 4410 var renderer = this.impl.polymerShadowRenderer_;
4388 if (renderer) { 4411 if (renderer) {
4389 renderer.invalidate(); 4412 renderer.invalidate();
4390 return true; 4413 return true;
4391 } 4414 }
4392 4415
4393 return false; 4416 return false;
4394 }; 4417 };
4395 4418
4396 HTMLContentElement.prototype.getDistributedNodes = function() { 4419 HTMLContentElement.prototype.getDistributedNodes = function() {
4397 var renderer = shadowDOMRendererTable.get(this); 4420 // TODO(arv): We should only rerender the dirty ancestor renderers (from
4398 if (renderer) 4421 // the root and down).
4399 renderer.render(); 4422 renderAllPending();
4400 return getDistributedChildNodes(this); 4423 return getDistributedChildNodes(this);
4401 }; 4424 };
4402 4425
4403 HTMLShadowElement.prototype.nodeWasAdded_ = 4426 HTMLShadowElement.prototype.nodeWasAdded_ =
4404 HTMLContentElement.prototype.nodeWasAdded_ = function() { 4427 HTMLContentElement.prototype.nodeWasAdded_ = function() {
4405 // Invalidate old renderer if any. 4428 // Invalidate old renderer if any.
4406 this.invalidateShadowRenderer(); 4429 this.invalidateShadowRenderer();
4407 4430
4408 var shadowRoot = getShadowRootAncestor(this); 4431 var shadowRoot = getShadowRootAncestor(this);
4409 var renderer; 4432 var renderer;
4410 if (shadowRoot) 4433 if (shadowRoot)
4411 renderer = getRendererForShadowRoot(shadowRoot); 4434 renderer = getRendererForShadowRoot(shadowRoot);
4412 shadowDOMRendererTable.set(this, renderer); 4435 this.impl.polymerShadowRenderer_ = renderer;
4413 if (renderer) 4436 if (renderer)
4414 renderer.invalidate(); 4437 renderer.invalidate();
4415 }; 4438 };
4416 4439
4417 scope.eventParentsTable = eventParentsTable; 4440 scope.eventParentsTable = eventParentsTable;
4418 scope.getRendererForHost = getRendererForHost; 4441 scope.getRendererForHost = getRendererForHost;
4419 scope.getShadowTrees = getShadowTrees; 4442 scope.getShadowTrees = getShadowTrees;
4420 scope.insertionParentTable = insertionParentTable; 4443 scope.insertionParentTable = insertionParentTable;
4421 scope.renderAllPending = renderAllPending; 4444 scope.renderAllPending = renderAllPending;
4422 4445
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
5128 5151
5129 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?) 5152 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?)
5130 window.dartExperimentalFixupGetTag = function(originalGetTag) { 5153 window.dartExperimentalFixupGetTag = function(originalGetTag) {
5131 var NodeList = ShadowDOMPolyfill.wrappers.NodeList; 5154 var NodeList = ShadowDOMPolyfill.wrappers.NodeList;
5132 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot; 5155 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot;
5133 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded; 5156 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded;
5134 function getTag(obj) { 5157 function getTag(obj) {
5135 // TODO(jmesserly): do we still need these? 5158 // TODO(jmesserly): do we still need these?
5136 if (obj instanceof NodeList) return 'NodeList'; 5159 if (obj instanceof NodeList) return 'NodeList';
5137 if (obj instanceof ShadowRoot) return 'ShadowRoot'; 5160 if (obj instanceof ShadowRoot) return 'ShadowRoot';
5138 if (obj instanceof MutationRecord) return 'MutationRecord'; 5161 if (window.MutationRecord && (obj instanceof MutationRecord))
5139 if (obj instanceof MutationObserver) return 'MutationObserver'; 5162 return 'MutationRecord';
5163 if (window.MutationObserver && (obj instanceof MutationObserver))
5164 return 'MutationObserver';
5140 5165
5141 var unwrapped = unwrapIfNeeded(obj); 5166 var unwrapped = unwrapIfNeeded(obj);
5142 if (obj !== unwrapped) { 5167 if (obj !== unwrapped) {
5143 // Fix up class names for Firefox. 5168 // Fix up class names for Firefox.
5144 // For some of them (like HTMLFormElement and HTMLInputElement), 5169 // For some of them (like HTMLFormElement and HTMLInputElement),
5145 // the "constructor" property of the unwrapped nodes points at the 5170 // the "constructor" property of the unwrapped nodes points at the
5146 // same constructor as the wrapper. 5171 // same constructor as the wrapper.
5147 var ctor = obj.constructor 5172 var ctor = obj.constructor
5148 if (ctor === unwrapped.constructor) { 5173 if (ctor === unwrapped.constructor) {
5149 var name = ctor._ShadowDOMPolyfill$cacheTag_; 5174 var name = ctor._ShadowDOMPolyfill$cacheTag_;
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
5682 css.push(cssRules[i].cssText); 5707 css.push(cssRules[i].cssText);
5683 } 5708 }
5684 return css.join('\n\n'); 5709 return css.join('\n\n');
5685 } 5710 }
5686 5711
5687 // exports 5712 // exports
5688 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2; 5713 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2;
5689 })(window.Platform); 5714 })(window.Platform);
5690 5715
5691 } 5716 }
OLDNEW
« no previous file with comments | « pkg/polymer/test/event_path_test.html ('k') | pkg/shadow_dom/lib/shadow_dom.min.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698