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

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

Issue 105783003: restore 30868 and 30873 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/custom_element/lib/custom-elements.min.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/custom_element/lib/custom-elements.debug.js
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
index 11ae6246b304eb3c1c91e4e7acb890099ebaa041..7ff04c01d1a5b749354041f53a8fe9795e13e14d 100644
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -25,23 +25,16 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-window.CustomElements = {flags:{}};
-// SideTable is a weak map where possible. If WeakMap is not available the
-// association is stored as an expando property.
-var SideTable;
-// TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox
-if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') < 0) {
- SideTable = WeakMap;
-} else {
+if (typeof WeakMap === 'undefined') {
(function() {
var defineProperty = Object.defineProperty;
var counter = Date.now() % 1e9;
- SideTable = function() {
+ var WeakMap = function() {
this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
};
- SideTable.prototype = {
+ WeakMap.prototype = {
set: function(key, value) {
var entry = key[this.name];
if (entry && entry[0] === key)
@@ -57,13 +50,15 @@ if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
delete: function(key) {
this.set(key, undefined);
}
- }
+ };
+
+ window.WeakMap = WeakMap;
})();
}
(function(global) {
- var registrationsTable = new SideTable();
+ var registrationsTable = new WeakMap();
// We use setImmediate or postMessage for our future callback.
var setImmediate = window.msSetImmediate;
@@ -596,344 +591,333 @@ if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
global.JsMutationObserver = JsMutationObserver;
-})(this);
-
-if (!window.MutationObserver) {
- window.MutationObserver =
- window.WebKitMutationObserver ||
- window.JsMutationObserver;
- if (!MutationObserver) {
- throw new Error("no mutation observer support");
- }
-}
-
-(function(scope){
-
-var logFlags = window.logFlags || {};
-
-// walk the subtree rooted at node, applying 'find(element, data)' function
-// to each element
-// if 'find' returns true for 'element', do not search element's subtree
-function findAll(node, find, data) {
- var e = node.firstElementChild;
- if (!e) {
- e = node.firstChild;
- while (e && e.nodeType !== Node.ELEMENT_NODE) {
- e = e.nextSibling;
- }
- }
- while (e) {
- if (find(e, data) !== true) {
- findAll(e, find, data);
- }
- e = e.nextElementSibling;
- }
- return null;
-}
-
-// walk all shadowRoots on a given node.
-function forRoots(node, cb) {
- var root = node.shadowRoot;
- while(root) {
- forSubtree(root, cb);
- root = root.olderShadowRoot;
- }
-}
-
-// walk the subtree rooted at node, including descent into shadow-roots,
-// applying 'cb' to each element
-function forSubtree(node, cb) {
- //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);
- findAll(node, function(e) {
- if (cb(e)) {
- return true;
- }
- forRoots(e, cb);
- });
- forRoots(node, cb);
- //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();
-}
-
-// manage lifecycle on added node
-function added(node) {
- if (upgrade(node)) {
- insertedNode(node);
- return true;
- }
- inserted(node);
-}
-
-// manage lifecycle on added node's subtree only
-function addedSubtree(node) {
- forSubtree(node, function(e) {
- if (added(e)) {
- return true;
- }
- });
-}
-
-// manage lifecycle on added node and it's subtree
-function addedNode(node) {
- return added(node) || addedSubtree(node);
-}
-
-// upgrade custom elements at node, if applicable
-function upgrade(node) {
- if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
- var type = node.getAttribute('is') || node.localName;
- var definition = scope.registry[type];
- if (definition) {
- logFlags.dom && console.group('upgrade:', node.localName);
- scope.upgrade(node);
- logFlags.dom && console.groupEnd();
- return true;
- }
- }
-}
+ // Provide unprefixed MutationObserver with native or JS implementation
+ if (!global.MutationObserver && global.WebKitMutationObserver)
+ global.MutationObserver = global.WebKitMutationObserver;
-function insertedNode(node) {
- inserted(node);
- if (inDocument(node)) {
- forSubtree(node, function(e) {
- inserted(e);
- });
- }
-}
+ if (!global.MutationObserver)
+ global.MutationObserver = JsMutationObserver;
-// TODO(sorvell): on platforms without MutationObserver, mutations may not be
-// reliable and therefore entered/leftView are not reliable.
-// To make these callbacks less likely to fail, we defer all inserts and removes
-// to give a chance for elements to be inserted into dom.
-// This ensures enteredViewCallback fires for elements that are created and
-// immediately added to dom.
-var hasPolyfillMutations = (!window.MutationObserver ||
- (window.MutationObserver === window.JsMutationObserver));
-scope.hasPolyfillMutations = hasPolyfillMutations;
-
-var isPendingMutations = false;
-var pendingMutations = [];
-function deferMutation(fn) {
- pendingMutations.push(fn);
- if (!isPendingMutations) {
- isPendingMutations = true;
- var async = (window.Platform && window.Platform.endOfMicrotask) ||
- setTimeout;
- async(takeMutations);
- }
-}
-
-function takeMutations() {
- isPendingMutations = false;
- var $p = pendingMutations;
- for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {
- p();
- }
- pendingMutations = [];
-}
-
-function inserted(element) {
- if (hasPolyfillMutations) {
- deferMutation(function() {
- _inserted(element);
- });
- } else {
- _inserted(element);
- }
-}
-
-// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this
-function _inserted(element) {
- // TODO(sjmiles): it's possible we were inserted and removed in the space
- // of one microtask, in which case we won't be 'inDocument' here
- // But there are other cases where we are testing for inserted without
- // specific knowledge of mutations, and must test 'inDocument' to determine
- // whether to call inserted
- // If we can factor these cases into separate code paths we can have
- // better diagnostics.
- // TODO(sjmiles): when logging, do work on all custom elements so we can
- // track behavior even when callbacks not defined
- //console.log('inserted: ', element.localName);
- if (element.enteredViewCallback || (element.__upgraded__ && logFlags.dom)) {
- logFlags.dom && console.group('inserted:', element.localName);
- if (inDocument(element)) {
- element.__inserted = (element.__inserted || 0) + 1;
- // if we are in a 'removed' state, bluntly adjust to an 'inserted' state
- if (element.__inserted < 1) {
- element.__inserted = 1;
- }
- // if we are 'over inserted', squelch the callback
- if (element.__inserted > 1) {
- logFlags.dom && console.warn('inserted:', element.localName,
- 'insert/remove count:', element.__inserted)
- } else if (element.enteredViewCallback) {
- logFlags.dom && console.log('inserted:', element.localName);
- element.enteredViewCallback();
- }
- }
- logFlags.dom && console.groupEnd();
- }
-}
-
-function removedNode(node) {
- removed(node);
- forSubtree(node, function(e) {
- removed(e);
- });
-}
-
-
-function removed(element) {
- if (hasPolyfillMutations) {
- deferMutation(function() {
- _removed(element);
- });
- } else {
- _removed(element);
- }
-}
-
-function removed(element) {
- // TODO(sjmiles): temporary: do work on all custom elements so we can track
- // behavior even when callbacks not defined
- if (element.leftViewCallback || (element.__upgraded__ && logFlags.dom)) {
- logFlags.dom && console.log('removed:', element.localName);
- if (!inDocument(element)) {
- element.__inserted = (element.__inserted || 0) - 1;
- // if we are in a 'inserted' state, bluntly adjust to an 'removed' state
- if (element.__inserted > 0) {
- element.__inserted = 0;
- }
- // if we are 'over removed', squelch the callback
- if (element.__inserted < 0) {
- logFlags.dom && console.warn('removed:', element.localName,
- 'insert/remove count:', element.__inserted)
- } else if (element.leftViewCallback) {
- element.leftViewCallback();
- }
- }
- }
-}
-
-function inDocument(element) {
- var p = element;
- var doc = window.ShadowDOMPolyfill &&
- window.ShadowDOMPolyfill.wrapIfNeeded(document) || document;
- while (p) {
- if (p == doc) {
- return true;
- }
- p = p.parentNode || p.host;
- }
-}
-
-function watchShadow(node) {
- if (node.shadowRoot && !node.shadowRoot.__watched) {
- logFlags.dom && console.log('watching shadow-root for: ', node.localName);
- // watch all unwatched roots...
- var root = node.shadowRoot;
- while (root) {
- watchRoot(root);
- root = root.olderShadowRoot;
- }
- }
-}
-
-function watchRoot(root) {
- if (!root.__watched) {
- observe(root);
- root.__watched = true;
- }
-}
-
-function filter(inNode) {
- switch (inNode.localName) {
- case 'style':
- case 'script':
- case 'template':
- case undefined:
- return true;
- }
-}
-
-function handler(mutations) {
- //
- if (logFlags.dom) {
- var mx = mutations[0];
- if (mx && mx.type === 'childList' && mx.addedNodes) {
- if (mx.addedNodes) {
- var d = mx.addedNodes[0];
- while (d && d !== document && !d.host) {
- d = d.parentNode;
- }
- var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';
- u = u.split('/?').shift().split('/').pop();
- }
- }
- console.group('mutations (%d) [%s]', mutations.length, u || '');
- }
- //
- mutations.forEach(function(mx) {
- //logFlags.dom && console.group('mutation');
- if (mx.type === 'childList') {
- forEach(mx.addedNodes, function(n) {
- //logFlags.dom && console.log(n.localName);
- if (filter(n)) {
- return;
- }
- // nodes added may need lifecycle management
- addedNode(n);
- });
- // removed nodes may need lifecycle management
- forEach(mx.removedNodes, function(n) {
- //logFlags.dom && console.log(n.localName);
- if (filter(n)) {
- return;
- }
- removedNode(n);
- });
- }
- //logFlags.dom && console.groupEnd();
- });
- logFlags.dom && console.groupEnd();
-};
-
-var observer = new MutationObserver(handler);
-
-function takeRecords() {
- // TODO(sjmiles): ask Raf why we have to call handler ourselves
- handler(observer.takeRecords());
- takeMutations();
-}
-
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
-
-function observe(inRoot) {
- observer.observe(inRoot, {childList: true, subtree: true});
-}
-
-function observeDocument(document) {
- observe(document);
-}
-
-function upgradeDocument(document) {
- logFlags.dom && console.group('upgradeDocument: ', (document.URL || document._URL || '').split('/').pop());
- addedNode(document);
- logFlags.dom && console.groupEnd();
-}
-
-// exports
-
-scope.watchShadow = watchShadow;
-scope.upgradeAll = addedNode;
-scope.upgradeSubtree = addedSubtree;
-
-scope.observeDocument = observeDocument;
-scope.upgradeDocument = upgradeDocument;
-
-scope.takeRecords = takeRecords;
+})(this);
-})(window.CustomElements);
+window.CustomElements = window.CustomElements || {flags:{}};
+(function(scope){
+
+var logFlags = window.logFlags || {};
+
+// walk the subtree rooted at node, applying 'find(element, data)' function
+// to each element
+// if 'find' returns true for 'element', do not search element's subtree
+function findAll(node, find, data) {
+ var e = node.firstElementChild;
+ if (!e) {
+ e = node.firstChild;
+ while (e && e.nodeType !== Node.ELEMENT_NODE) {
+ e = e.nextSibling;
+ }
+ }
+ while (e) {
+ if (find(e, data) !== true) {
+ findAll(e, find, data);
+ }
+ e = e.nextElementSibling;
+ }
+ return null;
+}
+
+// walk all shadowRoots on a given node.
+function forRoots(node, cb) {
+ var root = node.shadowRoot;
+ while(root) {
+ forSubtree(root, cb);
+ root = root.olderShadowRoot;
+ }
+}
+
+// walk the subtree rooted at node, including descent into shadow-roots,
+// applying 'cb' to each element
+function forSubtree(node, cb) {
+ //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node);
+ findAll(node, function(e) {
+ if (cb(e)) {
+ return true;
+ }
+ forRoots(e, cb);
+ });
+ forRoots(node, cb);
+ //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd();
+}
+
+// manage lifecycle on added node
+function added(node) {
+ if (upgrade(node)) {
+ insertedNode(node);
+ return true;
+ }
+ inserted(node);
+}
+
+// manage lifecycle on added node's subtree only
+function addedSubtree(node) {
+ forSubtree(node, function(e) {
+ if (added(e)) {
+ return true;
+ }
+ });
+}
+
+// manage lifecycle on added node and it's subtree
+function addedNode(node) {
+ return added(node) || addedSubtree(node);
+}
+
+// upgrade custom elements at node, if applicable
+function upgrade(node) {
+ if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) {
+ var type = node.getAttribute('is') || node.localName;
+ var definition = scope.registry[type];
+ if (definition) {
+ logFlags.dom && console.group('upgrade:', node.localName);
+ scope.upgrade(node);
+ logFlags.dom && console.groupEnd();
+ return true;
+ }
+ }
+}
+
+function insertedNode(node) {
+ inserted(node);
+ if (inDocument(node)) {
+ forSubtree(node, function(e) {
+ inserted(e);
+ });
+ }
+}
+
+
+// TODO(sorvell): on platforms without MutationObserver, mutations may not be
+// reliable and therefore entered/leftView are not reliable.
+// To make these callbacks less likely to fail, we defer all inserts and removes
+// to give a chance for elements to be inserted into dom.
+// This ensures enteredViewCallback fires for elements that are created and
+// immediately added to dom.
+var hasPolyfillMutations = (!window.MutationObserver ||
+ (window.MutationObserver === window.JsMutationObserver));
+scope.hasPolyfillMutations = hasPolyfillMutations;
+
+var isPendingMutations = false;
+var pendingMutations = [];
+function deferMutation(fn) {
+ pendingMutations.push(fn);
+ if (!isPendingMutations) {
+ isPendingMutations = true;
+ var async = (window.Platform && window.Platform.endOfMicrotask) ||
+ setTimeout;
+ async(takeMutations);
+ }
+}
+
+function takeMutations() {
+ isPendingMutations = false;
+ var $p = pendingMutations;
+ for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) {
+ p();
+ }
+ pendingMutations = [];
+}
+
+function inserted(element) {
+ if (hasPolyfillMutations) {
+ deferMutation(function() {
+ _inserted(element);
+ });
+ } else {
+ _inserted(element);
+ }
+}
+
+// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this
+function _inserted(element) {
+ // TODO(sjmiles): it's possible we were inserted and removed in the space
+ // of one microtask, in which case we won't be 'inDocument' here
+ // But there are other cases where we are testing for inserted without
+ // specific knowledge of mutations, and must test 'inDocument' to determine
+ // whether to call inserted
+ // If we can factor these cases into separate code paths we can have
+ // better diagnostics.
+ // TODO(sjmiles): when logging, do work on all custom elements so we can
+ // track behavior even when callbacks not defined
+ //console.log('inserted: ', element.localName);
+ if (element.enteredViewCallback || (element.__upgraded__ && logFlags.dom)) {
+ logFlags.dom && console.group('inserted:', element.localName);
+ if (inDocument(element)) {
+ element.__inserted = (element.__inserted || 0) + 1;
+ // if we are in a 'removed' state, bluntly adjust to an 'inserted' state
+ if (element.__inserted < 1) {
+ element.__inserted = 1;
+ }
+ // if we are 'over inserted', squelch the callback
+ if (element.__inserted > 1) {
+ logFlags.dom && console.warn('inserted:', element.localName,
+ 'insert/remove count:', element.__inserted)
+ } else if (element.enteredViewCallback) {
+ logFlags.dom && console.log('inserted:', element.localName);
+ element.enteredViewCallback();
+ }
+ }
+ logFlags.dom && console.groupEnd();
+ }
+}
+
+function removedNode(node) {
+ removed(node);
+ forSubtree(node, function(e) {
+ removed(e);
+ });
+}
+
+function removed(element) {
+ if (hasPolyfillMutations) {
+ deferMutation(function() {
+ _removed(element);
+ });
+ } else {
+ _removed(element);
+ }
+}
+
+function _removed(element) {
+ // TODO(sjmiles): temporary: do work on all custom elements so we can track
+ // behavior even when callbacks not defined
+ if (element.leftViewCallback || (element.__upgraded__ && logFlags.dom)) {
+ logFlags.dom && console.log('removed:', element.localName);
+ if (!inDocument(element)) {
+ element.__inserted = (element.__inserted || 0) - 1;
+ // if we are in a 'inserted' state, bluntly adjust to an 'removed' state
+ if (element.__inserted > 0) {
+ element.__inserted = 0;
+ }
+ // if we are 'over removed', squelch the callback
+ if (element.__inserted < 0) {
+ logFlags.dom && console.warn('removed:', element.localName,
+ 'insert/remove count:', element.__inserted)
+ } else if (element.leftViewCallback) {
+ element.leftViewCallback();
+ }
+ }
+ }
+}
+
+function inDocument(element) {
+ var p = element;
+ var doc = window.ShadowDOMPolyfill &&
+ window.ShadowDOMPolyfill.wrapIfNeeded(document) || document;
+ while (p) {
+ if (p == doc) {
+ return true;
+ }
+ p = p.parentNode || p.host;
+ }
+}
+
+function watchShadow(node) {
+ if (node.shadowRoot && !node.shadowRoot.__watched) {
+ logFlags.dom && console.log('watching shadow-root for: ', node.localName);
+ // watch all unwatched roots...
+ var root = node.shadowRoot;
+ while (root) {
+ watchRoot(root);
+ root = root.olderShadowRoot;
+ }
+ }
+}
+
+function watchRoot(root) {
+ if (!root.__watched) {
+ observe(root);
+ root.__watched = true;
+ }
+}
+
+function handler(mutations) {
+ //
+ if (logFlags.dom) {
+ var mx = mutations[0];
+ if (mx && mx.type === 'childList' && mx.addedNodes) {
+ if (mx.addedNodes) {
+ var d = mx.addedNodes[0];
+ while (d && d !== document && !d.host) {
+ d = d.parentNode;
+ }
+ var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || '';
+ u = u.split('/?').shift().split('/').pop();
+ }
+ }
+ console.group('mutations (%d) [%s]', mutations.length, u || '');
+ }
+ //
+ mutations.forEach(function(mx) {
+ //logFlags.dom && console.group('mutation');
+ if (mx.type === 'childList') {
+ forEach(mx.addedNodes, function(n) {
+ //logFlags.dom && console.log(n.localName);
+ if (!n.localName) {
+ return;
+ }
+ // nodes added may need lifecycle management
+ addedNode(n);
+ });
+ // removed nodes may need lifecycle management
+ forEach(mx.removedNodes, function(n) {
+ //logFlags.dom && console.log(n.localName);
+ if (!n.localName) {
+ return;
+ }
+ removedNode(n);
+ });
+ }
+ //logFlags.dom && console.groupEnd();
+ });
+ logFlags.dom && console.groupEnd();
+};
+
+var observer = new MutationObserver(handler);
+
+function takeRecords() {
+ // TODO(sjmiles): ask Raf why we have to call handler ourselves
+ handler(observer.takeRecords());
+ takeMutations();
+}
+
+var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
+
+function observe(inRoot) {
+ observer.observe(inRoot, {childList: true, subtree: true});
+}
+
+function observeDocument(document) {
+ observe(document);
+}
+
+function upgradeDocument(document) {
+ logFlags.dom && console.group('upgradeDocument: ', (document.URL || document._URL || '').split('/').pop());
+ addedNode(document);
+ logFlags.dom && console.groupEnd();
+}
+
+// exports
+
+scope.watchShadow = watchShadow;
+scope.upgradeAll = addedNode;
+scope.upgradeSubtree = addedSubtree;
+
+scope.observeDocument = observeDocument;
+scope.upgradeDocument = upgradeDocument;
+
+scope.takeRecords = takeRecords;
+
+})(window.CustomElements);
/**
* Implements `document.register`
@@ -1031,8 +1015,10 @@ if (useNative) {
// offer guidance)
throw new Error('document.register: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.');
}
- // record name
- definition.name = name;
+ // elements may only be registered once
+ if (getRegisteredDefinition(name)) {
+ throw new Error('DuplicateDefinitionError: a type with name \'' + String(name) + '\' is already registered');
+ }
// must have a prototype, default to an extension of HTMLElement
// TODO(sjmiles): probably should throw if no prototype, check spec
if (!definition.prototype) {
@@ -1040,6 +1026,8 @@ if (useNative) {
// offer guidance)
throw new Error('Options missing required prototype property');
}
+ // record name
+ definition.name = name.toLowerCase();
// ensure a lifecycle object so we don't have to null test it
definition.lifecycle = definition.lifecycle || {};
// build a list of ancestral custom elements (for native base detection)
@@ -1055,7 +1043,7 @@ if (useNative) {
// overrides to implement attributeChanged callback
overrideAttributeApi(definition.prototype);
// 7.1.5: Register the DEFINITION with DOCUMENT
- registerDefinition(name, definition);
+ registerDefinition(definition.name, definition);
// 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
// 7.1.8. Return the output of the previous step.
definition.ctor = generateConstructor(definition);
@@ -1071,7 +1059,7 @@ if (useNative) {
}
function ancestry(extnds) {
- var extendee = registry[extnds];
+ var extendee = getRegisteredDefinition(extnds);
if (extendee) {
return ancestry(extendee.extends).concat([extendee]);
}
@@ -1139,6 +1127,8 @@ if (useNative) {
if (definition.is) {
element.setAttribute('is', definition.is);
}
+ // remove 'unresolved' attr, which is a standin for :unresolved.
+ element.removeAttribute('unresolved');
// make 'element' implement definition.prototype
implement(element, definition);
// flag as upgraded
@@ -1176,7 +1166,7 @@ if (useNative) {
// HTMLElement.prototype, so we add a test
// the idea is to avoid mixing in native prototypes, so adding
// the second test is WLOG
- while (p && p !== inNative && p !== HTMLUnknownElement.prototype) {
+ while (p !== inNative && p !== HTMLUnknownElement.prototype) {
var keys = Object.getOwnPropertyNames(p);
for (var i=0, k; k=keys[i]; i++) {
if (!used[k]) {
@@ -1202,6 +1192,9 @@ if (useNative) {
// overrides to implement callbacks
// TODO(sjmiles): should support access via .attributes NamedNodeMap
// TODO(sjmiles): preserves user defined overrides, if any
+ if (prototype.setAttribute._polyfilled) {
+ return;
+ }
var setAttribute = prototype.setAttribute;
prototype.setAttribute = function(name, value) {
changeAttribute.call(this, name, value, setAttribute);
@@ -1210,14 +1203,18 @@ if (useNative) {
prototype.removeAttribute = function(name) {
changeAttribute.call(this, name, null, removeAttribute);
}
+ prototype.setAttribute._polyfilled = true;
}
+ // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/
+ // index.html#dfn-attribute-changed-callback
function changeAttribute(name, value, operation) {
var oldValue = this.getAttribute(name);
operation.apply(this, arguments);
+ var newValue = this.getAttribute(name);
if (this.attributeChangedCallback
- && (this.getAttribute(name) !== oldValue)) {
- this.attributeChangedCallback(name, oldValue, value);
+ && (newValue !== oldValue)) {
+ this.attributeChangedCallback(name, oldValue, newValue);
}
}
@@ -1225,9 +1222,15 @@ if (useNative) {
var registry = {};
+ function getRegisteredDefinition(name) {
+ if (name) {
+ return registry[name.toLowerCase()];
+ }
+ }
+
function registerDefinition(name, definition) {
if (registry[name]) {
- throw new Error('Cannot register a tag more than once');
+ throw new Error('a type with that name is already registered.');
}
registry[name] = definition;
}
@@ -1239,7 +1242,9 @@ if (useNative) {
}
function createElement(tag, typeExtension) {
- var definition = registry[typeExtension || tag];
+ // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
+ // error check it, or perhaps there should only ever be one argument
+ var definition = getRegisteredDefinition(typeExtension || tag);
if (definition) {
if (tag == definition.tag && typeExtension == definition.is) {
return new definition.ctor();
@@ -1377,7 +1382,7 @@ var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
CustomElements.parser = parser;
})();
-(function(){
+(function(scope){
// bootstrap parsing
function bootstrap() {
@@ -1409,21 +1414,31 @@ function bootstrap() {
// CustomEvent shim for IE
if (typeof window.CustomEvent !== 'function') {
window.CustomEvent = function(inType) {
- var e = document.createEvent('HTMLEvents');
- e.initEvent(inType, true, true);
- return e;
+ var e = document.createEvent('HTMLEvents');
+ e.initEvent(inType, true, true);
+ return e;
};
}
-if (document.readyState === 'complete') {
+// When loading at readyState complete time (or via flag), boot custom elements
+// immediately.
+// If relevant, HTMLImports must already be loaded.
+if (document.readyState === 'complete' || scope.flags.eager) {
bootstrap();
+// When loading at readyState interactive time, bootstrap only if HTMLImports
+// are not pending. Also avoid IE as the semantics of this state are unreliable.
+} else if (document.readyState === 'interactive' && !window.attachEvent &&
+ (!window.HTMLImports || window.HTMLImports.ready)) {
+ bootstrap();
+// When loading at other readyStates, wait for the appropriate DOM event to
+// bootstrap.
} else {
var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' :
document.readyState == 'loading' ? 'DOMContentLoaded' : 'load';
window.addEventListener(loadEvent, bootstrap);
}
-})();
+})(window.CustomElements);
(function() {
// Patch to allow custom element and shadow dom to work together, from:
@@ -1440,13 +1455,8 @@ if (HTMLElement.prototype.createShadowRoot) {
// Patch to allow custom elements and shadow dom to work together, from:
-// https://github.com/Polymer/platform/blob/master/src/patches-custom-elements.js
+// https://github.com/Polymer/platform-dev/blob/2bb9c56d90f9ac19c2e65cdad368668aff514f14/src/patches-custom-elements.js
if (window.ShadowDOMPolyfill) {
- function nop() {};
-
- // disable shadow dom watching
- CustomElements.watchShadow = nop;
- CustomElements.watchAllShadows = nop;
// ensure wrapped inputs for these functions
var fns = ['upgradeAll', 'upgradeSubtree', 'observeDocument',
@@ -1461,9 +1471,21 @@ if (window.ShadowDOMPolyfill) {
// override
fns.forEach(function(fn) {
CustomElements[fn] = function(inNode) {
- return original[fn](ShadowDOMPolyfill.wrapIfNeeded(inNode));
+ return original[fn](window.ShadowDOMPolyfill.wrapIfNeeded(inNode));
};
});
+
+}
+
+// Patch to make importNode work.
+// https://github.com/Polymer/platform-dev/blob/64a92f273462f04a84abbe2f054294f2b62dbcd6/src/patches-mdv.js
+if (window.CustomElements && !CustomElements.useNative) {
+ var originalImportNode = Document.prototype.importNode;
+ Document.prototype.importNode = function(node, deep) {
+ var imported = originalImportNode.call(this, node, deep);
+ CustomElements.upgradeAll(imported);
+ return imported;
+ }
}
})();
« 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