| OLD | NEW |
| 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 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 window.CustomElements = {flags:{}}; | 124 window.CustomElements = {flags:{}}; |
| 125 // SideTable is a weak map where possible. If WeakMap is not available the | 125 // SideTable is a weak map where possible. If WeakMap is not available the |
| 126 // association is stored as an expando property. | 126 // association is stored as an expando property. |
| 127 var SideTable; | 127 var SideTable; |
| 128 // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox | 128 // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox |
| 129 if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
0) { | 129 if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
0) { |
| 130 SideTable = WeakMap; | 130 SideTable = WeakMap; |
| 131 } else { | 131 } else { |
| 132 (function() { | 132 (function() { |
| 133 var defineProperty = Object.defineProperty; | 133 var defineProperty = Object.defineProperty; |
| 134 var hasOwnProperty = Object.hasOwnProperty; | 134 var counter = Date.now() % 1e9; |
| 135 var counter = new Date().getTime() % 1e9; | |
| 136 | 135 |
| 137 SideTable = function() { | 136 SideTable = function() { |
| 138 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); | 137 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); |
| 139 }; | 138 }; |
| 140 | 139 |
| 141 SideTable.prototype = { | 140 SideTable.prototype = { |
| 142 set: function(key, value) { | 141 set: function(key, value) { |
| 143 defineProperty(key, this.name, {value: value, writable: true}); | 142 var entry = key[this.name]; |
| 143 if (entry && entry[0] === key) |
| 144 entry[1] = value; |
| 145 else |
| 146 defineProperty(key, this.name, {value: [key, value], writable: true}); |
| 144 }, | 147 }, |
| 145 get: function(key) { | 148 get: function(key) { |
| 146 return hasOwnProperty.call(key, this.name) ? key[this.name] : undefined; | 149 var entry; |
| 150 return (entry = key[this.name]) && entry[0] === key ? |
| 151 entry[1] : undefined; |
| 147 }, | 152 }, |
| 148 delete: function(key) { | 153 delete: function(key) { |
| 149 this.set(key, undefined); | 154 this.set(key, undefined); |
| 150 } | 155 } |
| 151 } | 156 } |
| 152 })(); | 157 })(); |
| 153 } | 158 } |
| 154 | 159 |
| 155 (function(global) { | 160 (function(global) { |
| 156 | 161 |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 window.MutationObserver = | 698 window.MutationObserver = |
| 694 window.WebKitMutationObserver || | 699 window.WebKitMutationObserver || |
| 695 window.JsMutationObserver; | 700 window.JsMutationObserver; |
| 696 if (!MutationObserver) { | 701 if (!MutationObserver) { |
| 697 throw new Error("no mutation observer support"); | 702 throw new Error("no mutation observer support"); |
| 698 } | 703 } |
| 699 } | 704 } |
| 700 | 705 |
| 701 (function(scope){ | 706 (function(scope){ |
| 702 | 707 |
| 703 /* | 708 var logFlags = window.logFlags || {}; |
| 704 if (HTMLElement.prototype.webkitShadowRoot) { | |
| 705 Object.defineProperty(HTMLElement.prototype, 'shadowRoot', { | |
| 706 get: function() { | |
| 707 return this.webkitShadowRoot; | |
| 708 } | |
| 709 }; | |
| 710 } | |
| 711 */ | |
| 712 | 709 |
| 713 // walk the subtree rooted at node, applying 'find(element, data)' function | 710 // walk the subtree rooted at node, applying 'find(element, data)' function |
| 714 // to each element | 711 // to each element |
| 715 // if 'find' returns true for 'element', do not search element's subtree | 712 // if 'find' returns true for 'element', do not search element's subtree |
| 716 function findAll(node, find, data) { | 713 function findAll(node, find, data) { |
| 717 var e = node.firstElementChild; | 714 var e = node.firstElementChild; |
| 718 if (!e) { | 715 if (!e) { |
| 719 e = node.firstChild; | 716 e = node.firstChild; |
| 720 while (e && e.nodeType !== Node.ELEMENT_NODE) { | 717 while (e && e.nodeType !== Node.ELEMENT_NODE) { |
| 721 e = e.nextSibling; | 718 e = e.nextSibling; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 // TODO(sjmiles): it's possible we were inserted and removed in the space | 802 // TODO(sjmiles): it's possible we were inserted and removed in the space |
| 806 // of one microtask, in which case we won't be 'inDocument' here | 803 // of one microtask, in which case we won't be 'inDocument' here |
| 807 // But there are other cases where we are testing for inserted without | 804 // But there are other cases where we are testing for inserted without |
| 808 // specific knowledge of mutations, and must test 'inDocument' to determine | 805 // specific knowledge of mutations, and must test 'inDocument' to determine |
| 809 // whether to call inserted | 806 // whether to call inserted |
| 810 // If we can factor these cases into separate code paths we can have | 807 // If we can factor these cases into separate code paths we can have |
| 811 // better diagnostics. | 808 // better diagnostics. |
| 812 // TODO(sjmiles): when logging, do work on all custom elements so we can | 809 // TODO(sjmiles): when logging, do work on all custom elements so we can |
| 813 // track behavior even when callbacks not defined | 810 // track behavior even when callbacks not defined |
| 814 //console.log('inserted: ', element.localName); | 811 //console.log('inserted: ', element.localName); |
| 815 if (element.enteredDocumentCallback || (element.__upgraded__ && logFlags.dom))
{ | 812 if (element.enteredViewCallback || (element.__upgraded__ && logFlags.dom)) { |
| 816 logFlags.dom && console.group('inserted:', element.localName); | 813 logFlags.dom && console.group('inserted:', element.localName); |
| 817 if (inDocument(element)) { | 814 if (inDocument(element)) { |
| 818 element.__inserted = (element.__inserted || 0) + 1; | 815 element.__inserted = (element.__inserted || 0) + 1; |
| 819 // if we are in a 'removed' state, bluntly adjust to an 'inserted' state | 816 // if we are in a 'removed' state, bluntly adjust to an 'inserted' state |
| 820 if (element.__inserted < 1) { | 817 if (element.__inserted < 1) { |
| 821 element.__inserted = 1; | 818 element.__inserted = 1; |
| 822 } | 819 } |
| 823 // if we are 'over inserted', squelch the callback | 820 // if we are 'over inserted', squelch the callback |
| 824 if (element.__inserted > 1) { | 821 if (element.__inserted > 1) { |
| 825 logFlags.dom && console.warn('inserted:', element.localName, | 822 logFlags.dom && console.warn('inserted:', element.localName, |
| 826 'insert/remove count:', element.__inserted) | 823 'insert/remove count:', element.__inserted) |
| 827 } else if (element.enteredDocumentCallback) { | 824 } else if (element.enteredViewCallback) { |
| 828 logFlags.dom && console.log('inserted:', element.localName); | 825 logFlags.dom && console.log('inserted:', element.localName); |
| 829 element.enteredDocumentCallback(); | 826 element.enteredViewCallback(); |
| 830 } | 827 } |
| 831 } | 828 } |
| 832 logFlags.dom && console.groupEnd(); | 829 logFlags.dom && console.groupEnd(); |
| 833 } | 830 } |
| 834 } | 831 } |
| 835 | 832 |
| 836 function removedNode(node) { | 833 function removedNode(node) { |
| 837 removed(node); | 834 removed(node); |
| 838 forSubtree(node, function(e) { | 835 forSubtree(node, function(e) { |
| 839 removed(e); | 836 removed(e); |
| 840 }); | 837 }); |
| 841 } | 838 } |
| 842 | 839 |
| 843 function removed(element) { | 840 function removed(element) { |
| 844 // TODO(sjmiles): temporary: do work on all custom elements so we can track | 841 // TODO(sjmiles): temporary: do work on all custom elements so we can track |
| 845 // behavior even when callbacks not defined | 842 // behavior even when callbacks not defined |
| 846 if (element.leftDocumentCallback || (element.__upgraded__ && logFlags.dom)) { | 843 if (element.leftViewCallback || (element.__upgraded__ && logFlags.dom)) { |
| 847 logFlags.dom && console.log('removed:', element.localName); | 844 logFlags.dom && console.log('removed:', element.localName); |
| 848 if (!inDocument(element)) { | 845 if (!inDocument(element)) { |
| 849 element.__inserted = (element.__inserted || 0) - 1; | 846 element.__inserted = (element.__inserted || 0) - 1; |
| 850 // if we are in a 'inserted' state, bluntly adjust to an 'removed' state | 847 // if we are in a 'inserted' state, bluntly adjust to an 'removed' state |
| 851 if (element.__inserted > 0) { | 848 if (element.__inserted > 0) { |
| 852 element.__inserted = 0; | 849 element.__inserted = 0; |
| 853 } | 850 } |
| 854 // if we are 'over removed', squelch the callback | 851 // if we are 'over removed', squelch the callback |
| 855 if (element.__inserted < 0) { | 852 if (element.__inserted < 0) { |
| 856 logFlags.dom && console.warn('removed:', element.localName, | 853 logFlags.dom && console.warn('removed:', element.localName, |
| 857 'insert/remove count:', element.__inserted) | 854 'insert/remove count:', element.__inserted) |
| 858 } else if (element.leftDocumentCallback) { | 855 } else if (element.leftViewCallback) { |
| 859 element.leftDocumentCallback(); | 856 element.leftViewCallback(); |
| 860 } | 857 } |
| 861 } | 858 } |
| 862 } | 859 } |
| 863 } | 860 } |
| 864 | 861 |
| 865 function inDocument(element) { | 862 function inDocument(element) { |
| 866 var p = element; | 863 var p = element; |
| 864 var doc = window.ShadowDOMPolyfill && |
| 865 window.ShadowDOMPolyfill.wrapIfNeeded(document) || document; |
| 867 while (p) { | 866 while (p) { |
| 868 if (p == element.ownerDocument) { | 867 if (p == doc) { |
| 869 return true; | 868 return true; |
| 870 } | 869 } |
| 871 p = p.parentNode || p.host; | 870 p = p.parentNode || p.host; |
| 872 } | 871 } |
| 873 } | 872 } |
| 874 | 873 |
| 875 function watchShadow(node) { | 874 function watchShadow(node) { |
| 876 if (node.webkitShadowRoot && !node.webkitShadowRoot.__watched) { | 875 if (node.webkitShadowRoot && !node.webkitShadowRoot.__watched) { |
| 877 logFlags.dom && console.log('watching shadow-root for: ', node.localName); | 876 logFlags.dom && console.log('watching shadow-root for: ', node.localName); |
| 878 // watch all unwatched roots... | 877 // watch all unwatched roots... |
| 879 var root = node.webkitShadowRoot; | 878 var root = node.webkitShadowRoot; |
| 880 while (root) { | 879 while (root) { |
| 881 watchRoot(root); | 880 watchRoot(root); |
| 882 root = root.olderShadowRoot; | 881 root = root.olderShadowRoot; |
| 883 } | 882 } |
| 884 } | 883 } |
| 885 } | 884 } |
| 886 | 885 |
| 887 function watchRoot(root) { | 886 function watchRoot(root) { |
| 888 if (!root.__watched) { | 887 if (!root.__watched) { |
| 889 observe(root); | 888 observe(root); |
| 890 root.__watched = true; | 889 root.__watched = true; |
| 891 } | 890 } |
| 892 } | 891 } |
| 893 | 892 |
| 894 function watchAllShadows(node) { | |
| 895 watchShadow(node); | |
| 896 forSubtree(node, function(e) { | |
| 897 watchShadow(node); | |
| 898 }); | |
| 899 } | |
| 900 | |
| 901 function filter(inNode) { | 893 function filter(inNode) { |
| 902 switch (inNode.localName) { | 894 switch (inNode.localName) { |
| 903 case 'style': | 895 case 'style': |
| 904 case 'script': | 896 case 'script': |
| 905 case 'template': | 897 case 'template': |
| 906 case undefined: | 898 case undefined: |
| 907 return true; | 899 return true; |
| 908 } | 900 } |
| 909 } | 901 } |
| 910 | 902 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 926 } | 918 } |
| 927 // | 919 // |
| 928 mutations.forEach(function(mx) { | 920 mutations.forEach(function(mx) { |
| 929 //logFlags.dom && console.group('mutation'); | 921 //logFlags.dom && console.group('mutation'); |
| 930 if (mx.type === 'childList') { | 922 if (mx.type === 'childList') { |
| 931 forEach(mx.addedNodes, function(n) { | 923 forEach(mx.addedNodes, function(n) { |
| 932 //logFlags.dom && console.log(n.localName); | 924 //logFlags.dom && console.log(n.localName); |
| 933 if (filter(n)) { | 925 if (filter(n)) { |
| 934 return; | 926 return; |
| 935 } | 927 } |
| 936 // watch shadow-roots on nodes that have had them attached manually | |
| 937 // TODO(sjmiles): remove if createShadowRoot is overridden | |
| 938 // TODO(sjmiles): removed as an optimization, manual shadow roots | |
| 939 // must be watched explicitly | |
| 940 //watchAllShadows(n); | |
| 941 // nodes added may need lifecycle management | 928 // nodes added may need lifecycle management |
| 942 addedNode(n); | 929 addedNode(n); |
| 943 }); | 930 }); |
| 944 // removed nodes may need lifecycle management | 931 // removed nodes may need lifecycle management |
| 945 forEach(mx.removedNodes, function(n) { | 932 forEach(mx.removedNodes, function(n) { |
| 946 //logFlags.dom && console.log(n.localName); | 933 //logFlags.dom && console.log(n.localName); |
| 947 if (filter(n)) { | 934 if (filter(n)) { |
| 948 return; | 935 return; |
| 949 } | 936 } |
| 950 removedNode(n); | 937 removedNode(n); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 974 | 961 |
| 975 function upgradeDocument(document) { | 962 function upgradeDocument(document) { |
| 976 logFlags.dom && console.group('upgradeDocument: ', (document.URL || document._
URL || '').split('/').pop()); | 963 logFlags.dom && console.group('upgradeDocument: ', (document.URL || document._
URL || '').split('/').pop()); |
| 977 addedNode(document); | 964 addedNode(document); |
| 978 logFlags.dom && console.groupEnd(); | 965 logFlags.dom && console.groupEnd(); |
| 979 } | 966 } |
| 980 | 967 |
| 981 // exports | 968 // exports |
| 982 | 969 |
| 983 scope.watchShadow = watchShadow; | 970 scope.watchShadow = watchShadow; |
| 984 scope.watchAllShadows = watchAllShadows; | |
| 985 | |
| 986 scope.upgradeAll = addedNode; | 971 scope.upgradeAll = addedNode; |
| 987 scope.upgradeSubtree = addedSubtree; | 972 scope.upgradeSubtree = addedSubtree; |
| 988 | 973 |
| 989 scope.observeDocument = observeDocument; | 974 scope.observeDocument = observeDocument; |
| 990 scope.upgradeDocument = upgradeDocument; | 975 scope.upgradeDocument = upgradeDocument; |
| 991 | 976 |
| 992 scope.takeRecords = takeRecords; | 977 scope.takeRecords = takeRecords; |
| 993 | 978 |
| 994 })(window.CustomElements); | 979 })(window.CustomElements); |
| 995 | 980 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1007 | 992 |
| 1008 // imports | 993 // imports |
| 1009 | 994 |
| 1010 if (!scope) { | 995 if (!scope) { |
| 1011 scope = window.CustomElements = {flags:{}}; | 996 scope = window.CustomElements = {flags:{}}; |
| 1012 } | 997 } |
| 1013 var flags = scope.flags; | 998 var flags = scope.flags; |
| 1014 | 999 |
| 1015 // native document.register? | 1000 // native document.register? |
| 1016 | 1001 |
| 1017 var hasNative = Boolean(document.webkitRegister || document.register); | 1002 var hasNative = Boolean(document.register); |
| 1018 var useNative = !flags.register && hasNative; | 1003 var useNative = !flags.register && hasNative; |
| 1019 | 1004 |
| 1020 if (useNative) { | 1005 if (useNative) { |
| 1021 | 1006 |
| 1022 // normalize | |
| 1023 document.register = document.register || document.webkitRegister; | |
| 1024 | |
| 1025 // stub | 1007 // stub |
| 1026 var nop = function() {}; | 1008 var nop = function() {}; |
| 1027 | 1009 |
| 1028 // exports | 1010 // exports |
| 1029 scope.registry = {}; | 1011 scope.registry = {}; |
| 1030 scope.upgradeElement = nop; | 1012 scope.upgradeElement = nop; |
| 1031 | 1013 |
| 1032 scope.watchShadow = nop; | 1014 scope.watchShadow = nop; |
| 1033 scope.watchAllShadows = nop; | |
| 1034 scope.upgrade = nop; | 1015 scope.upgrade = nop; |
| 1035 scope.upgradeAll = nop; | 1016 scope.upgradeAll = nop; |
| 1036 scope.upgradeSubtree = nop; | 1017 scope.upgradeSubtree = nop; |
| 1037 scope.observeDocument = nop; | 1018 scope.observeDocument = nop; |
| 1038 scope.upgradeDocument = nop; | 1019 scope.upgradeDocument = nop; |
| 1039 scope.takeRecords = nop; | 1020 scope.takeRecords = nop; |
| 1040 | 1021 |
| 1041 } else { | 1022 } else { |
| 1042 | 1023 |
| 1043 /** | 1024 /** |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 // TODO(sjmiles): probably should clone options instead of mutating it | 1065 // TODO(sjmiles): probably should clone options instead of mutating it |
| 1085 var definition = options || {}; | 1066 var definition = options || {}; |
| 1086 if (!name) { | 1067 if (!name) { |
| 1087 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 1068 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1088 // offer guidance) | 1069 // offer guidance) |
| 1089 throw new Error('document.register: first argument `name` must not be empt
y'); | 1070 throw new Error('document.register: first argument `name` must not be empt
y'); |
| 1090 } | 1071 } |
| 1091 if (name.indexOf('-') < 0) { | 1072 if (name.indexOf('-') < 0) { |
| 1092 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 1073 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1093 // offer guidance) | 1074 // offer guidance) |
| 1094 throw new Error('document.register: first argument `name` must contain a d
ash (\'-\'). Argument was \'' + String(name) + '\'.'); | 1075 throw new Error('document.register: first argument (\'name\') must contain
a dash (\'-\'). Argument provided was \'' + String(name) + '\'.'); |
| 1095 } | 1076 } |
| 1096 // record name | 1077 // record name |
| 1097 definition.name = name; | 1078 definition.name = name; |
| 1098 // must have a prototype, default to an extension of HTMLElement | 1079 // must have a prototype, default to an extension of HTMLElement |
| 1099 // TODO(sjmiles): probably should throw if no prototype, check spec | 1080 // TODO(sjmiles): probably should throw if no prototype, check spec |
| 1100 if (!definition.prototype) { | 1081 if (!definition.prototype) { |
| 1101 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 1082 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1102 // offer guidance) | 1083 // offer guidance) |
| 1103 throw new Error('Options missing required prototype property'); | 1084 throw new Error('Options missing required prototype property'); |
| 1104 } | 1085 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 // if there is a base tag, use secondary 'is' specifier | 1136 // if there is a base tag, use secondary 'is' specifier |
| 1156 definition.is = definition.name; | 1137 definition.is = definition.name; |
| 1157 } | 1138 } |
| 1158 } | 1139 } |
| 1159 | 1140 |
| 1160 function resolvePrototypeChain(definition) { | 1141 function resolvePrototypeChain(definition) { |
| 1161 // if we don't support __proto__ we need to locate the native level | 1142 // if we don't support __proto__ we need to locate the native level |
| 1162 // prototype for precise mixing in | 1143 // prototype for precise mixing in |
| 1163 if (!Object.__proto__) { | 1144 if (!Object.__proto__) { |
| 1164 // default prototype | 1145 // default prototype |
| 1165 var native = HTMLElement.prototype; | 1146 var nativePrototype = HTMLElement.prototype; |
| 1166 // work out prototype when using type-extension | 1147 // work out prototype when using type-extension |
| 1167 if (definition.is) { | 1148 if (definition.is) { |
| 1168 var inst = document.createElement(definition.tag); | 1149 var inst = document.createElement(definition.tag); |
| 1169 native = Object.getPrototypeOf(inst); | 1150 nativePrototype = Object.getPrototypeOf(inst); |
| 1170 } | 1151 } |
| 1171 // ensure __proto__ reference is installed at each point on the prototype | 1152 // ensure __proto__ reference is installed at each point on the prototype |
| 1172 // chain. | 1153 // chain. |
| 1173 // NOTE: On platforms without __proto__, a mixin strategy is used instead | 1154 // NOTE: On platforms without __proto__, a mixin strategy is used instead |
| 1174 // of prototype swizzling. In this case, this generated __proto__ provides | 1155 // of prototype swizzling. In this case, this generated __proto__ provides |
| 1175 // limited support for prototype traversal. | 1156 // limited support for prototype traversal. |
| 1176 var proto = definition.prototype, ancestor; | 1157 var proto = definition.prototype, ancestor; |
| 1177 while (proto && (proto !== native)) { | 1158 while (proto && (proto !== nativePrototype)) { |
| 1178 var ancestor = Object.getPrototypeOf(proto); | 1159 var ancestor = Object.getPrototypeOf(proto); |
| 1179 proto.__proto__ = ancestor; | 1160 proto.__proto__ = ancestor; |
| 1180 proto = ancestor; | 1161 proto = ancestor; |
| 1181 } | 1162 } |
| 1182 } | 1163 } |
| 1183 // cache this in case of mixin | 1164 // cache this in case of mixin |
| 1184 definition.native = native; | 1165 definition.native = nativePrototype; |
| 1185 } | 1166 } |
| 1186 | 1167 |
| 1187 // SECTION 4 | 1168 // SECTION 4 |
| 1188 | 1169 |
| 1189 function instantiate(definition) { | 1170 function instantiate(definition) { |
| 1190 // 4.a.1. Create a new object that implements PROTOTYPE | 1171 // 4.a.1. Create a new object that implements PROTOTYPE |
| 1191 // 4.a.2. Let ELEMENT by this new object | 1172 // 4.a.2. Let ELEMENT by this new object |
| 1192 // | 1173 // |
| 1193 // the custom element instantiation algorithm must also ensure that the | 1174 // the custom element instantiation algorithm must also ensure that the |
| 1194 // output is a valid DOM element with the proper wrapper in place. | 1175 // output is a valid DOM element with the proper wrapper in place. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1282 this.attributeChangedCallback(name, oldValue); | 1263 this.attributeChangedCallback(name, oldValue); |
| 1283 } | 1264 } |
| 1284 } | 1265 } |
| 1285 | 1266 |
| 1286 // element registry (maps tag names to definitions) | 1267 // element registry (maps tag names to definitions) |
| 1287 | 1268 |
| 1288 var registry = {}; | 1269 var registry = {}; |
| 1289 | 1270 |
| 1290 function registerDefinition(name, definition) { | 1271 function registerDefinition(name, definition) { |
| 1291 if (registry[name]) { | 1272 if (registry[name]) { |
| 1292 throw new Error('a type with that name is already registered.'); | 1273 throw new Error('Cannot register a tag more than once'); |
| 1293 } | 1274 } |
| 1294 registry[name] = definition; | 1275 registry[name] = definition; |
| 1295 } | 1276 } |
| 1296 | 1277 |
| 1297 function generateConstructor(definition) { | 1278 function generateConstructor(definition) { |
| 1298 return function() { | 1279 return function() { |
| 1299 return instantiate(definition); | 1280 return instantiate(definition); |
| 1300 }; | 1281 }; |
| 1301 } | 1282 } |
| 1302 | 1283 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); | 1416 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
| 1436 | 1417 |
| 1437 // exports | 1418 // exports |
| 1438 | 1419 |
| 1439 CustomElements.parser = parser; | 1420 CustomElements.parser = parser; |
| 1440 | 1421 |
| 1441 })(); | 1422 })(); |
| 1442 (function(){ | 1423 (function(){ |
| 1443 | 1424 |
| 1444 // bootstrap parsing | 1425 // bootstrap parsing |
| 1445 | |
| 1446 function bootstrap() { | 1426 function bootstrap() { |
| 1447 // go async so call stack can unwind | 1427 // parse document |
| 1448 setTimeout(function() { | 1428 CustomElements.parser.parse(document); |
| 1449 // parse document | 1429 // one more pass before register is 'live' |
| 1450 CustomElements.parser.parse(document); | 1430 CustomElements.upgradeDocument(document); |
| 1451 // one more pass before register is 'live' | 1431 // choose async |
| 1452 CustomElements.upgradeDocument(document); | 1432 var async = window.Platform && Platform.endOfMicrotask ? |
| 1433 Platform.endOfMicrotask : |
| 1434 setTimeout; |
| 1435 async(function() { |
| 1453 // set internal 'ready' flag, now document.register will trigger | 1436 // set internal 'ready' flag, now document.register will trigger |
| 1454 // synchronous upgrades | 1437 // synchronous upgrades |
| 1455 CustomElements.ready = true; | 1438 CustomElements.ready = true; |
| 1456 // capture blunt profiling data | 1439 // capture blunt profiling data |
| 1457 CustomElements.readyTime = Date.now(); | 1440 CustomElements.readyTime = Date.now(); |
| 1458 if (window.HTMLImports) { | 1441 if (window.HTMLImports) { |
| 1459 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; | 1442 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; |
| 1460 } | 1443 } |
| 1461 // notify the system that we are bootstrapped | 1444 // notify the system that we are bootstrapped |
| 1462 document.body.dispatchEvent( | 1445 document.body.dispatchEvent( |
| 1463 new CustomEvent('WebComponentsReady', {bubbles: true}) | 1446 new CustomEvent('WebComponentsReady', {bubbles: true}) |
| 1464 ); | 1447 ); |
| 1465 }, 0); | 1448 }); |
| 1466 } | 1449 } |
| 1467 | 1450 |
| 1468 // CustomEvent shim for IE | 1451 // CustomEvent shim for IE |
| 1469 if (typeof window.CustomEvent !== 'function') { | 1452 if (typeof window.CustomEvent !== 'function') { |
| 1470 window.CustomEvent = function(inType) { | 1453 window.CustomEvent = function(inType) { |
| 1471 var e = document.createEvent('HTMLEvents'); | 1454 var e = document.createEvent('HTMLEvents'); |
| 1472 e.initEvent(inType, true, true); | 1455 e.initEvent(inType, true, true); |
| 1473 return e; | 1456 return e; |
| 1474 }; | 1457 }; |
| 1475 } | 1458 } |
| 1476 | 1459 |
| 1477 if (document.readyState === 'complete') { | 1460 if (document.readyState === 'complete') { |
| 1478 bootstrap(); | 1461 bootstrap(); |
| 1479 } else { | 1462 } else { |
| 1480 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 'DOMContentLoaded'; | 1463 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 'DOMContentLoaded'; |
| 1481 window.addEventListener(loadEvent, bootstrap); | 1464 window.addEventListener(loadEvent, bootstrap); |
| 1482 } | 1465 } |
| 1483 | 1466 |
| 1484 })(); | 1467 })(); |
| OLD | NEW |