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

Side by Side Diff: pkg/custom_element/lib/custom-elements.debug.js

Issue 98533004: update TemplateBinding and Custom Elements polyfills (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: update pubspecs Created 7 years 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 | « no previous file | pkg/custom_element/lib/custom-elements.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 // Copyright (c) 2012 The Polymer Authors. All rights reserved. 1 // Copyright (c) 2012 The Polymer Authors. All rights reserved.
2 // 2 //
3 // Redistribution and use in source and binary forms, with or without 3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are 4 // modification, are permitted provided that the following conditions are
5 // met: 5 // met:
6 // 6 //
7 // * Redistributions of source code must retain the above copyright 7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer. 8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above 9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer 10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the 11 // in the documentation and/or other materials provided with the
12 // distribution. 12 // distribution.
13 // * Neither the name of Google Inc. nor the names of its 13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from 14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission. 15 // this software without specific prior written permission.
16 // 16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 window.CustomElements = {flags:{}}; 28 if (typeof WeakMap === 'undefined') {
29 // SideTable is a weak map where possible. If WeakMap is not available the
30 // association is stored as an expando property.
31 var SideTable;
32 // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox
33 if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') < 0) {
34 SideTable = WeakMap;
35 } else {
36 (function() { 29 (function() {
37 var defineProperty = Object.defineProperty; 30 var defineProperty = Object.defineProperty;
38 var counter = Date.now() % 1e9; 31 var counter = Date.now() % 1e9;
39 32
40 SideTable = function() { 33 var WeakMap = function() {
41 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); 34 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
42 }; 35 };
43 36
44 SideTable.prototype = { 37 WeakMap.prototype = {
45 set: function(key, value) { 38 set: function(key, value) {
46 var entry = key[this.name]; 39 var entry = key[this.name];
47 if (entry && entry[0] === key) 40 if (entry && entry[0] === key)
48 entry[1] = value; 41 entry[1] = value;
49 else 42 else
50 defineProperty(key, this.name, {value: [key, value], writable: true}); 43 defineProperty(key, this.name, {value: [key, value], writable: true});
51 }, 44 },
52 get: function(key) { 45 get: function(key) {
53 var entry; 46 var entry;
54 return (entry = key[this.name]) && entry[0] === key ? 47 return (entry = key[this.name]) && entry[0] === key ?
55 entry[1] : undefined; 48 entry[1] : undefined;
56 }, 49 },
57 delete: function(key) { 50 delete: function(key) {
58 this.set(key, undefined); 51 this.set(key, undefined);
59 } 52 }
60 } 53 };
54
55 window.WeakMap = WeakMap;
61 })(); 56 })();
62 } 57 }
63 58
64 (function(global) { 59 (function(global) {
65 60
66 var registrationsTable = new SideTable(); 61 var registrationsTable = new WeakMap();
67 62
68 // We use setImmediate or postMessage for our future callback. 63 // We use setImmediate or postMessage for our future callback.
69 var setImmediate = window.msSetImmediate; 64 var setImmediate = window.msSetImmediate;
70 65
71 // Use post message to emulate setImmediate. 66 // Use post message to emulate setImmediate.
72 if (!setImmediate) { 67 if (!setImmediate) {
73 var setImmediateQueue = []; 68 var setImmediateQueue = [];
74 var sentinel = String(Math.random()); 69 var sentinel = String(Math.random());
75 window.addEventListener('message', function(e) { 70 window.addEventListener('message', function(e) {
76 if (e.data === sentinel) { 71 if (e.data === sentinel) {
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 }); 584 });
590 585
591 } 586 }
592 587
593 clearRecords(); 588 clearRecords();
594 } 589 }
595 }; 590 };
596 591
597 global.JsMutationObserver = JsMutationObserver; 592 global.JsMutationObserver = JsMutationObserver;
598 593
594 // Provide unprefixed MutationObserver with native or JS implementation
595 if (!global.MutationObserver && global.WebKitMutationObserver)
596 global.MutationObserver = global.WebKitMutationObserver;
597
598 if (!global.MutationObserver)
599 global.MutationObserver = JsMutationObserver;
600
601
599 })(this); 602 })(this);
600 603
601 if (!window.MutationObserver) { 604 window.CustomElements = window.CustomElements || {flags:{}};
602 window.MutationObserver =
603 window.WebKitMutationObserver ||
604 window.JsMutationObserver;
605 if (!MutationObserver) {
606 throw new Error("no mutation observer support");
607 }
608 }
609
610 (function(scope){ 605 (function(scope){
611 606
612 var logFlags = window.logFlags || {}; 607 var logFlags = window.logFlags || {};
613 608
614 // walk the subtree rooted at node, applying 'find(element, data)' function 609 // walk the subtree rooted at node, applying 'find(element, data)' function
615 // to each element 610 // to each element
616 // if 'find' returns true for 'element', do not search element's subtree 611 // if 'find' returns true for 'element', do not search element's subtree
617 function findAll(node, find, data) { 612 function findAll(node, find, data) {
618 var e = node.firstElementChild; 613 var e = node.firstElementChild;
619 if (!e) { 614 if (!e) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 } 770 }
776 } 771 }
777 772
778 function removedNode(node) { 773 function removedNode(node) {
779 removed(node); 774 removed(node);
780 forSubtree(node, function(e) { 775 forSubtree(node, function(e) {
781 removed(e); 776 removed(e);
782 }); 777 });
783 } 778 }
784 779
785
786 function removed(element) { 780 function removed(element) {
787 if (hasPolyfillMutations) { 781 if (hasPolyfillMutations) {
788 deferMutation(function() { 782 deferMutation(function() {
789 _removed(element); 783 _removed(element);
790 }); 784 });
791 } else { 785 } else {
792 _removed(element); 786 _removed(element);
793 } 787 }
794 } 788 }
795 789
796 function removed(element) { 790 function _removed(element) {
797 // TODO(sjmiles): temporary: do work on all custom elements so we can track 791 // TODO(sjmiles): temporary: do work on all custom elements so we can track
798 // behavior even when callbacks not defined 792 // behavior even when callbacks not defined
799 if (element.leftViewCallback || (element.__upgraded__ && logFlags.dom)) { 793 if (element.leftViewCallback || (element.__upgraded__ && logFlags.dom)) {
800 logFlags.dom && console.log('removed:', element.localName); 794 logFlags.dom && console.log('removed:', element.localName);
801 if (!inDocument(element)) { 795 if (!inDocument(element)) {
802 element.__inserted = (element.__inserted || 0) - 1; 796 element.__inserted = (element.__inserted || 0) - 1;
803 // if we are in a 'inserted' state, bluntly adjust to an 'removed' state 797 // if we are in a 'inserted' state, bluntly adjust to an 'removed' state
804 if (element.__inserted > 0) { 798 if (element.__inserted > 0) {
805 element.__inserted = 0; 799 element.__inserted = 0;
806 } 800 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 } 833 }
840 } 834 }
841 835
842 function watchRoot(root) { 836 function watchRoot(root) {
843 if (!root.__watched) { 837 if (!root.__watched) {
844 observe(root); 838 observe(root);
845 root.__watched = true; 839 root.__watched = true;
846 } 840 }
847 } 841 }
848 842
849 function filter(inNode) {
850 switch (inNode.localName) {
851 case 'style':
852 case 'script':
853 case 'template':
854 case undefined:
855 return true;
856 }
857 }
858
859 function handler(mutations) { 843 function handler(mutations) {
860 // 844 //
861 if (logFlags.dom) { 845 if (logFlags.dom) {
862 var mx = mutations[0]; 846 var mx = mutations[0];
863 if (mx && mx.type === 'childList' && mx.addedNodes) { 847 if (mx && mx.type === 'childList' && mx.addedNodes) {
864 if (mx.addedNodes) { 848 if (mx.addedNodes) {
865 var d = mx.addedNodes[0]; 849 var d = mx.addedNodes[0];
866 while (d && d !== document && !d.host) { 850 while (d && d !== document && !d.host) {
867 d = d.parentNode; 851 d = d.parentNode;
868 } 852 }
869 var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || ''; 853 var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';
870 u = u.split('/?').shift().split('/').pop(); 854 u = u.split('/?').shift().split('/').pop();
871 } 855 }
872 } 856 }
873 console.group('mutations (%d) [%s]', mutations.length, u || ''); 857 console.group('mutations (%d) [%s]', mutations.length, u || '');
874 } 858 }
875 // 859 //
876 mutations.forEach(function(mx) { 860 mutations.forEach(function(mx) {
877 //logFlags.dom && console.group('mutation'); 861 //logFlags.dom && console.group('mutation');
878 if (mx.type === 'childList') { 862 if (mx.type === 'childList') {
879 forEach(mx.addedNodes, function(n) { 863 forEach(mx.addedNodes, function(n) {
880 //logFlags.dom && console.log(n.localName); 864 //logFlags.dom && console.log(n.localName);
881 if (filter(n)) { 865 if (!n.localName) {
882 return; 866 return;
883 } 867 }
884 // nodes added may need lifecycle management 868 // nodes added may need lifecycle management
885 addedNode(n); 869 addedNode(n);
886 }); 870 });
887 // removed nodes may need lifecycle management 871 // removed nodes may need lifecycle management
888 forEach(mx.removedNodes, function(n) { 872 forEach(mx.removedNodes, function(n) {
889 //logFlags.dom && console.log(n.localName); 873 //logFlags.dom && console.log(n.localName);
890 if (filter(n)) { 874 if (!n.localName) {
891 return; 875 return;
892 } 876 }
893 removedNode(n); 877 removedNode(n);
894 }); 878 });
895 } 879 }
896 //logFlags.dom && console.groupEnd(); 880 //logFlags.dom && console.groupEnd();
897 }); 881 });
898 logFlags.dom && console.groupEnd(); 882 logFlags.dom && console.groupEnd();
899 }; 883 };
900 884
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 if (!name) { 1008 if (!name) {
1025 // TODO(sjmiles): replace with more appropriate error (EricB can probably 1009 // TODO(sjmiles): replace with more appropriate error (EricB can probably
1026 // offer guidance) 1010 // offer guidance)
1027 throw new Error('document.register: first argument `name` must not be empt y'); 1011 throw new Error('document.register: first argument `name` must not be empt y');
1028 } 1012 }
1029 if (name.indexOf('-') < 0) { 1013 if (name.indexOf('-') < 0) {
1030 // TODO(sjmiles): replace with more appropriate error (EricB can probably 1014 // TODO(sjmiles): replace with more appropriate error (EricB can probably
1031 // offer guidance) 1015 // offer guidance)
1032 throw new Error('document.register: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.'); 1016 throw new Error('document.register: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.');
1033 } 1017 }
1034 // record name 1018 // elements may only be registered once
1035 definition.name = name; 1019 if (getRegisteredDefinition(name)) {
1020 throw new Error('DuplicateDefinitionError: a type with name \'' + String(n ame) + '\' is already registered');
1021 }
1036 // must have a prototype, default to an extension of HTMLElement 1022 // must have a prototype, default to an extension of HTMLElement
1037 // TODO(sjmiles): probably should throw if no prototype, check spec 1023 // TODO(sjmiles): probably should throw if no prototype, check spec
1038 if (!definition.prototype) { 1024 if (!definition.prototype) {
1039 // TODO(sjmiles): replace with more appropriate error (EricB can probably 1025 // TODO(sjmiles): replace with more appropriate error (EricB can probably
1040 // offer guidance) 1026 // offer guidance)
1041 throw new Error('Options missing required prototype property'); 1027 throw new Error('Options missing required prototype property');
1042 } 1028 }
1029 // record name
1030 definition.name = name.toLowerCase();
1043 // ensure a lifecycle object so we don't have to null test it 1031 // ensure a lifecycle object so we don't have to null test it
1044 definition.lifecycle = definition.lifecycle || {}; 1032 definition.lifecycle = definition.lifecycle || {};
1045 // build a list of ancestral custom elements (for native base detection) 1033 // build a list of ancestral custom elements (for native base detection)
1046 // TODO(sjmiles): we used to need to store this, but current code only 1034 // TODO(sjmiles): we used to need to store this, but current code only
1047 // uses it in 'resolveTagName': it should probably be inlined 1035 // uses it in 'resolveTagName': it should probably be inlined
1048 definition.ancestry = ancestry(definition.extends); 1036 definition.ancestry = ancestry(definition.extends);
1049 // extensions of native specializations of HTMLElement require localName 1037 // extensions of native specializations of HTMLElement require localName
1050 // to remain native, and use secondary 'is' specifier for extension type 1038 // to remain native, and use secondary 'is' specifier for extension type
1051 resolveTagName(definition); 1039 resolveTagName(definition);
1052 // some platforms require modifications to the user-supplied prototype 1040 // some platforms require modifications to the user-supplied prototype
1053 // chain 1041 // chain
1054 resolvePrototypeChain(definition); 1042 resolvePrototypeChain(definition);
1055 // overrides to implement attributeChanged callback 1043 // overrides to implement attributeChanged callback
1056 overrideAttributeApi(definition.prototype); 1044 overrideAttributeApi(definition.prototype);
1057 // 7.1.5: Register the DEFINITION with DOCUMENT 1045 // 7.1.5: Register the DEFINITION with DOCUMENT
1058 registerDefinition(name, definition); 1046 registerDefinition(definition.name, definition);
1059 // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE 1047 // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
1060 // 7.1.8. Return the output of the previous step. 1048 // 7.1.8. Return the output of the previous step.
1061 definition.ctor = generateConstructor(definition); 1049 definition.ctor = generateConstructor(definition);
1062 definition.ctor.prototype = definition.prototype; 1050 definition.ctor.prototype = definition.prototype;
1063 // force our .constructor to be our actual constructor 1051 // force our .constructor to be our actual constructor
1064 definition.prototype.constructor = definition.ctor; 1052 definition.prototype.constructor = definition.ctor;
1065 // if initial parsing is complete 1053 // if initial parsing is complete
1066 if (scope.ready || scope.performedInitialDocumentUpgrade) { 1054 if (scope.ready || scope.performedInitialDocumentUpgrade) {
1067 // upgrade any pre-existing nodes of this type 1055 // upgrade any pre-existing nodes of this type
1068 scope.upgradeAll(document); 1056 scope.upgradeAll(document);
1069 } 1057 }
1070 return definition.ctor; 1058 return definition.ctor;
1071 } 1059 }
1072 1060
1073 function ancestry(extnds) { 1061 function ancestry(extnds) {
1074 var extendee = registry[extnds]; 1062 var extendee = getRegisteredDefinition(extnds);
1075 if (extendee) { 1063 if (extendee) {
1076 return ancestry(extendee.extends).concat([extendee]); 1064 return ancestry(extendee.extends).concat([extendee]);
1077 } 1065 }
1078 return []; 1066 return [];
1079 } 1067 }
1080 1068
1081 function resolveTagName(definition) { 1069 function resolveTagName(definition) {
1082 // if we are explicitly extending something, that thing is our 1070 // if we are explicitly extending something, that thing is our
1083 // baseTag, unless it represents a custom component 1071 // baseTag, unless it represents a custom component
1084 var baseTag = definition.extends; 1072 var baseTag = definition.extends;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 // output is a valid DOM element with the proper wrapper in place. 1120 // output is a valid DOM element with the proper wrapper in place.
1133 // 1121 //
1134 return upgrade(domCreateElement(definition.tag), definition); 1122 return upgrade(domCreateElement(definition.tag), definition);
1135 } 1123 }
1136 1124
1137 function upgrade(element, definition) { 1125 function upgrade(element, definition) {
1138 // some definitions specify an 'is' attribute 1126 // some definitions specify an 'is' attribute
1139 if (definition.is) { 1127 if (definition.is) {
1140 element.setAttribute('is', definition.is); 1128 element.setAttribute('is', definition.is);
1141 } 1129 }
1130 // remove 'unresolved' attr, which is a standin for :unresolved.
1131 element.removeAttribute('unresolved');
1142 // make 'element' implement definition.prototype 1132 // make 'element' implement definition.prototype
1143 implement(element, definition); 1133 implement(element, definition);
1144 // flag as upgraded 1134 // flag as upgraded
1145 element.__upgraded__ = true; 1135 element.__upgraded__ = true;
1146 // there should never be a shadow root on element at this point 1136 // there should never be a shadow root on element at this point
1147 // we require child nodes be upgraded before `created` 1137 // we require child nodes be upgraded before `created`
1148 scope.upgradeSubtree(element); 1138 scope.upgradeSubtree(element);
1149 // lifecycle management 1139 // lifecycle management
1150 created(element); 1140 created(element);
1151 // OUTPUT 1141 // OUTPUT
(...skipping 17 matching lines...) Expand all
1169 // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of 1159 // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of
1170 // any property. This set should be precalculated. We also need to 1160 // any property. This set should be precalculated. We also need to
1171 // consider this for supporting 'super'. 1161 // consider this for supporting 'super'.
1172 var used = {}; 1162 var used = {};
1173 // start with inSrc 1163 // start with inSrc
1174 var p = inSrc; 1164 var p = inSrc;
1175 // sometimes the default is HTMLUnknownElement.prototype instead of 1165 // sometimes the default is HTMLUnknownElement.prototype instead of
1176 // HTMLElement.prototype, so we add a test 1166 // HTMLElement.prototype, so we add a test
1177 // the idea is to avoid mixing in native prototypes, so adding 1167 // the idea is to avoid mixing in native prototypes, so adding
1178 // the second test is WLOG 1168 // the second test is WLOG
1179 while (p && p !== inNative && p !== HTMLUnknownElement.prototype) { 1169 while (p !== inNative && p !== HTMLUnknownElement.prototype) {
1180 var keys = Object.getOwnPropertyNames(p); 1170 var keys = Object.getOwnPropertyNames(p);
1181 for (var i=0, k; k=keys[i]; i++) { 1171 for (var i=0, k; k=keys[i]; i++) {
1182 if (!used[k]) { 1172 if (!used[k]) {
1183 Object.defineProperty(inTarget, k, 1173 Object.defineProperty(inTarget, k,
1184 Object.getOwnPropertyDescriptor(p, k)); 1174 Object.getOwnPropertyDescriptor(p, k));
1185 used[k] = 1; 1175 used[k] = 1;
1186 } 1176 }
1187 } 1177 }
1188 p = Object.getPrototypeOf(p); 1178 p = Object.getPrototypeOf(p);
1189 } 1179 }
1190 } 1180 }
1191 1181
1192 function created(element) { 1182 function created(element) {
1193 // invoke createdCallback 1183 // invoke createdCallback
1194 if (element.createdCallback) { 1184 if (element.createdCallback) {
1195 element.createdCallback(); 1185 element.createdCallback();
1196 } 1186 }
1197 } 1187 }
1198 1188
1199 // attribute watching 1189 // attribute watching
1200 1190
1201 function overrideAttributeApi(prototype) { 1191 function overrideAttributeApi(prototype) {
1202 // overrides to implement callbacks 1192 // overrides to implement callbacks
1203 // TODO(sjmiles): should support access via .attributes NamedNodeMap 1193 // TODO(sjmiles): should support access via .attributes NamedNodeMap
1204 // TODO(sjmiles): preserves user defined overrides, if any 1194 // TODO(sjmiles): preserves user defined overrides, if any
1195 if (prototype.setAttribute._polyfilled) {
1196 return;
1197 }
1205 var setAttribute = prototype.setAttribute; 1198 var setAttribute = prototype.setAttribute;
1206 prototype.setAttribute = function(name, value) { 1199 prototype.setAttribute = function(name, value) {
1207 changeAttribute.call(this, name, value, setAttribute); 1200 changeAttribute.call(this, name, value, setAttribute);
1208 } 1201 }
1209 var removeAttribute = prototype.removeAttribute; 1202 var removeAttribute = prototype.removeAttribute;
1210 prototype.removeAttribute = function(name) { 1203 prototype.removeAttribute = function(name) {
1211 changeAttribute.call(this, name, null, removeAttribute); 1204 changeAttribute.call(this, name, null, removeAttribute);
1212 } 1205 }
1206 prototype.setAttribute._polyfilled = true;
1213 } 1207 }
1214 1208
1209 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/
1210 // index.html#dfn-attribute-changed-callback
1215 function changeAttribute(name, value, operation) { 1211 function changeAttribute(name, value, operation) {
1216 var oldValue = this.getAttribute(name); 1212 var oldValue = this.getAttribute(name);
1217 operation.apply(this, arguments); 1213 operation.apply(this, arguments);
1214 var newValue = this.getAttribute(name);
1218 if (this.attributeChangedCallback 1215 if (this.attributeChangedCallback
1219 && (this.getAttribute(name) !== oldValue)) { 1216 && (newValue !== oldValue)) {
1220 this.attributeChangedCallback(name, oldValue, value); 1217 this.attributeChangedCallback(name, oldValue, newValue);
1221 } 1218 }
1222 } 1219 }
1223 1220
1224 // element registry (maps tag names to definitions) 1221 // element registry (maps tag names to definitions)
1225 1222
1226 var registry = {}; 1223 var registry = {};
1227 1224
1225 function getRegisteredDefinition(name) {
1226 if (name) {
1227 return registry[name.toLowerCase()];
1228 }
1229 }
1230
1228 function registerDefinition(name, definition) { 1231 function registerDefinition(name, definition) {
1229 if (registry[name]) {
1230 throw new Error('Cannot register a tag more than once');
1231 }
1232 registry[name] = definition; 1232 registry[name] = definition;
1233 } 1233 }
1234 1234
1235 function generateConstructor(definition) { 1235 function generateConstructor(definition) {
1236 return function() { 1236 return function() {
1237 return instantiate(definition); 1237 return instantiate(definition);
1238 }; 1238 };
1239 } 1239 }
1240 1240
1241 function createElement(tag, typeExtension) { 1241 function createElement(tag, typeExtension) {
1242 var definition = registry[typeExtension || tag]; 1242 // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
1243 // error check it, or perhaps there should only ever be one argument
1244 var definition = getRegisteredDefinition(typeExtension || tag);
1243 if (definition) { 1245 if (definition) {
1244 if (tag == definition.tag && typeExtension == definition.is) { 1246 if (tag == definition.tag && typeExtension == definition.is) {
1245 return new definition.ctor(); 1247 return new definition.ctor();
1246 } 1248 }
1247 // Handle empty string for type extension. 1249 // Handle empty string for type extension.
1248 if (!typeExtension && !definition.is) { 1250 if (!typeExtension && !definition.is) {
1249 return new definition.ctor(); 1251 return new definition.ctor();
1250 } 1252 }
1251 } 1253 }
1252 1254
1253 if (typeExtension) { 1255 if (typeExtension) {
1254 var element = createElement(tag); 1256 var element = createElement(tag);
1255 element.setAttribute('is', typeExtension); 1257 element.setAttribute('is', typeExtension);
1256 return element; 1258 return element;
1257 } 1259 }
1258 var element = domCreateElement(tag); 1260 var element = domCreateElement(tag);
1259 // Custom tags should be HTMLElements even if not upgraded. 1261 // Custom tags should be HTMLElements even if not upgraded.
1260 if (tag.indexOf('-') >= 0) { 1262 if (tag.indexOf('-') >= 0) {
1261 implement(element, HTMLElement); 1263 implement(element, HTMLElement);
1262 } 1264 }
1263 return element; 1265 return element;
1264 } 1266 }
1265 1267
1266 function upgradeElement(element) { 1268 function upgradeElement(element) {
1267 if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) { 1269 if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {
1268 var is = element.getAttribute('is'); 1270 var type = element.getAttribute('is') || element.localName;
1269 var definition = registry[is || element.localName]; 1271 var definition = getRegisteredDefinition(type);
1270 if (definition) { 1272 return definition && upgrade(element, definition);
1271 if (is && definition.tag == element.localName) {
1272 return upgrade(element, definition);
1273 } else if (!is && !definition.extends) {
1274 return upgrade(element, definition);
1275 }
1276 }
1277 } 1273 }
1278 } 1274 }
1279 1275
1280 function cloneNode(deep) { 1276 function cloneNode(deep) {
1281 // call original clone 1277 // call original clone
1282 var n = domCloneNode.call(this, deep); 1278 var n = domCloneNode.call(this, deep);
1283 // upgrade the element and subtree 1279 // upgrade the element and subtree
1284 scope.upgradeAll(n); 1280 scope.upgradeAll(n);
1285 // return the clone 1281 // return the clone
1286 return n; 1282 return n;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 && inElt.getAttribute('rel') === IMPORT_LINK_TYPE); 1366 && inElt.getAttribute('rel') === IMPORT_LINK_TYPE);
1371 } 1367 }
1372 1368
1373 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); 1369 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
1374 1370
1375 // exports 1371 // exports
1376 1372
1377 CustomElements.parser = parser; 1373 CustomElements.parser = parser;
1378 1374
1379 })(); 1375 })();
1380 (function(){ 1376 (function(scope){
1381 1377
1382 // bootstrap parsing 1378 // bootstrap parsing
1383 function bootstrap() { 1379 function bootstrap() {
1384 // parse document 1380 // parse document
1385 CustomElements.parser.parse(document); 1381 CustomElements.parser.parse(document);
1386 // one more pass before register is 'live' 1382 // one more pass before register is 'live'
1387 CustomElements.upgradeDocument(document); 1383 CustomElements.upgradeDocument(document);
1388 CustomElements.performedInitialDocumentUpgrade = true; 1384 CustomElements.performedInitialDocumentUpgrade = true;
1389 // choose async 1385 // choose async
1390 var async = window.Platform && Platform.endOfMicrotask ? 1386 var async = window.Platform && Platform.endOfMicrotask ?
(...skipping 11 matching lines...) Expand all
1402 // notify the system that we are bootstrapped 1398 // notify the system that we are bootstrapped
1403 document.body.dispatchEvent( 1399 document.body.dispatchEvent(
1404 new CustomEvent('WebComponentsReady', {bubbles: true}) 1400 new CustomEvent('WebComponentsReady', {bubbles: true})
1405 ); 1401 );
1406 }); 1402 });
1407 } 1403 }
1408 1404
1409 // CustomEvent shim for IE 1405 // CustomEvent shim for IE
1410 if (typeof window.CustomEvent !== 'function') { 1406 if (typeof window.CustomEvent !== 'function') {
1411 window.CustomEvent = function(inType) { 1407 window.CustomEvent = function(inType) {
1412 var e = document.createEvent('HTMLEvents'); 1408 var e = document.createEvent('HTMLEvents');
1413 e.initEvent(inType, true, true); 1409 e.initEvent(inType, true, true);
1414 return e; 1410 return e;
1415 }; 1411 };
1416 } 1412 }
1417 1413
1418 if (document.readyState === 'complete') { 1414 // When loading at readyState complete time (or via flag), boot custom elements
1415 // immediately.
1416 // If relevant, HTMLImports must already be loaded.
1417 if (document.readyState === 'complete' || scope.flags.eager) {
1419 bootstrap(); 1418 bootstrap();
1419 // When loading at readyState interactive time, bootstrap only if HTMLImports
1420 // are not pending. Also avoid IE as the semantics of this state are unreliable.
1421 } else if (document.readyState === 'interactive' && !window.attachEvent &&
1422 (!window.HTMLImports || window.HTMLImports.ready)) {
1423 bootstrap();
1424 // When loading at other readyStates, wait for the appropriate DOM event to
1425 // bootstrap.
1420 } else { 1426 } else {
1421 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 1427 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' :
1422 document.readyState == 'loading' ? 'DOMContentLoaded' : 'load'; 1428 document.readyState == 'loading' ? 'DOMContentLoaded' : 'load';
1423 window.addEventListener(loadEvent, bootstrap); 1429 window.addEventListener(loadEvent, bootstrap);
1424 } 1430 }
1425 1431
1426 })(); 1432 })(window.CustomElements);
1427 1433
1428 (function() { 1434 (function() {
1429 // Patch to allow custom element and shadow dom to work together, from: 1435 // Patch to allow custom element and shadow dom to work together, from:
1430 // https://github.com/Polymer/platform/blob/master/src/patches-shadowdom-polyfil l.js 1436 // https://github.com/Polymer/platform/blob/master/src/patches-shadowdom-polyfil l.js
1431 // include .host reference 1437 // include .host reference
1432 if (HTMLElement.prototype.createShadowRoot) { 1438 if (HTMLElement.prototype.createShadowRoot) {
1433 var originalCreateShadowRoot = HTMLElement.prototype.createShadowRoot; 1439 var originalCreateShadowRoot = HTMLElement.prototype.createShadowRoot;
1434 HTMLElement.prototype.createShadowRoot = function() { 1440 HTMLElement.prototype.createShadowRoot = function() {
1435 var root = originalCreateShadowRoot.call(this); 1441 var root = originalCreateShadowRoot.call(this);
1436 root.host = this; 1442 root.host = this;
1437 return root; 1443 return root;
1438 } 1444 }
1439 } 1445 }
1440 1446
1441 1447
1442 // Patch to allow custom elements and shadow dom to work together, from: 1448 // Patch to allow custom elements and shadow dom to work together, from:
1443 // https://github.com/Polymer/platform/blob/master/src/patches-custom-elements.j s 1449 // https://github.com/Polymer/platform-dev/blob/2bb9c56d90f9ac19c2e65cdad368668a ff514f14/src/patches-custom-elements.js
1444 if (window.ShadowDOMPolyfill) { 1450 if (window.ShadowDOMPolyfill) {
1445 function nop() {};
1446
1447 // disable shadow dom watching
1448 CustomElements.watchShadow = nop;
1449 CustomElements.watchAllShadows = nop;
1450 1451
1451 // ensure wrapped inputs for these functions 1452 // ensure wrapped inputs for these functions
1452 var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument', 1453 var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',
1453 'upgradeDocument']; 1454 'upgradeDocument'];
1454 1455
1455 // cache originals 1456 // cache originals
1456 var original = {}; 1457 var original = {};
1457 fns.forEach(function(fn) { 1458 fns.forEach(function(fn) {
1458 original[fn] = CustomElements[fn]; 1459 original[fn] = CustomElements[fn];
1459 }); 1460 });
1460 1461
1461 // override 1462 // override
1462 fns.forEach(function(fn) { 1463 fns.forEach(function(fn) {
1463 CustomElements[fn] = function(inNode) { 1464 CustomElements[fn] = function(inNode) {
1464 return original[fn](ShadowDOMPolyfill.wrapIfNeeded(inNode)); 1465 return original[fn](window.ShadowDOMPolyfill.wrapIfNeeded(inNode));
1465 }; 1466 };
1466 }); 1467 });
1468
1469 }
1470
1471 // Patch to make importNode work.
1472 // https://github.com/Polymer/platform-dev/blob/64a92f273462f04a84abbe2f054294f2 b62dbcd6/src/patches-mdv.js
1473 if (window.CustomElements && !CustomElements.useNative) {
1474 var originalImportNode = Document.prototype.importNode;
1475 Document.prototype.importNode = function(node, deep) {
1476 var imported = originalImportNode.call(this, node, deep);
1477 CustomElements.upgradeAll(imported);
1478 return imported;
1479 }
1467 } 1480 }
1468 1481
1469 })(); 1482 })();
OLDNEW
« no previous file with comments | « no previous file | pkg/custom_element/lib/custom-elements.min.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698