| 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 }, | 49 }, |
| 50 delete: function(key) { | 50 delete: function(key) { |
| 51 this.set(key, undefined); | 51 this.set(key, undefined); |
| 52 } | 52 } |
| 53 }; | 53 }; |
| 54 | 54 |
| 55 window.WeakMap = WeakMap; | 55 window.WeakMap = WeakMap; |
| 56 })(); | 56 })(); |
| 57 } | 57 } |
| 58 | 58 |
| 59 (function(global) { |
| 60 |
| 61 var registrationsTable = new WeakMap(); |
| 62 |
| 63 // We use setImmediate or postMessage for our future callback. |
| 64 var setImmediate = window.msSetImmediate; |
| 65 |
| 66 // Use post message to emulate setImmediate. |
| 67 if (!setImmediate) { |
| 68 var setImmediateQueue = []; |
| 69 var sentinel = String(Math.random()); |
| 70 window.addEventListener('message', function(e) { |
| 71 if (e.data === sentinel) { |
| 72 var queue = setImmediateQueue; |
| 73 setImmediateQueue = []; |
| 74 queue.forEach(function(func) { |
| 75 func(); |
| 76 }); |
| 77 } |
| 78 }); |
| 79 setImmediate = function(func) { |
| 80 setImmediateQueue.push(func); |
| 81 window.postMessage(sentinel, '*'); |
| 82 }; |
| 83 } |
| 84 |
| 85 // This is used to ensure that we never schedule 2 callas to setImmediate |
| 86 var isScheduled = false; |
| 87 |
| 88 // Keep track of observers that needs to be notified next time. |
| 89 var scheduledObservers = []; |
| 90 |
| 91 /** |
| 92 * Schedules |dispatchCallback| to be called in the future. |
| 93 * @param {MutationObserver} observer |
| 94 */ |
| 95 function scheduleCallback(observer) { |
| 96 scheduledObservers.push(observer); |
| 97 if (!isScheduled) { |
| 98 isScheduled = true; |
| 99 setImmediate(dispatchCallbacks); |
| 100 } |
| 101 } |
| 102 |
| 103 function wrapIfNeeded(node) { |
| 104 return window.ShadowDOMPolyfill && |
| 105 window.ShadowDOMPolyfill.wrapIfNeeded(node) || |
| 106 node; |
| 107 } |
| 108 |
| 109 function dispatchCallbacks() { |
| 110 // http://dom.spec.whatwg.org/#mutation-observers |
| 111 |
| 112 isScheduled = false; // Used to allow a new setImmediate call above. |
| 113 |
| 114 var observers = scheduledObservers; |
| 115 scheduledObservers = []; |
| 116 // Sort observers based on their creation UID (incremental). |
| 117 observers.sort(function(o1, o2) { |
| 118 return o1.uid_ - o2.uid_; |
| 119 }); |
| 120 |
| 121 var anyNonEmpty = false; |
| 122 observers.forEach(function(observer) { |
| 123 |
| 124 // 2.1, 2.2 |
| 125 var queue = observer.takeRecords(); |
| 126 // 2.3. Remove all transient registered observers whose observer is mo. |
| 127 removeTransientObserversFor(observer); |
| 128 |
| 129 // 2.4 |
| 130 if (queue.length) { |
| 131 observer.callback_(queue, observer); |
| 132 anyNonEmpty = true; |
| 133 } |
| 134 }); |
| 135 |
| 136 // 3. |
| 137 if (anyNonEmpty) |
| 138 dispatchCallbacks(); |
| 139 } |
| 140 |
| 141 function removeTransientObserversFor(observer) { |
| 142 observer.nodes_.forEach(function(node) { |
| 143 var registrations = registrationsTable.get(node); |
| 144 if (!registrations) |
| 145 return; |
| 146 registrations.forEach(function(registration) { |
| 147 if (registration.observer === observer) |
| 148 registration.removeTransientObservers(); |
| 149 }); |
| 150 }); |
| 151 } |
| 152 |
| 153 /** |
| 154 * This function is used for the "For each registered observer observer (with |
| 155 * observer's options as options) in target's list of registered observers, |
| 156 * run these substeps:" and the "For each ancestor ancestor of target, and for |
| 157 * each registered observer observer (with options options) in ancestor's list |
| 158 * of registered observers, run these substeps:" part of the algorithms. The |
| 159 * |options.subtree| is checked to ensure that the callback is called |
| 160 * correctly. |
| 161 * |
| 162 * @param {Node} target |
| 163 * @param {function(MutationObserverInit):MutationRecord} callback |
| 164 */ |
| 165 function forEachAncestorAndObserverEnqueueRecord(target, callback) { |
| 166 for (var node = target; node; node = node.parentNode) { |
| 167 var registrations = registrationsTable.get(node); |
| 168 |
| 169 if (registrations) { |
| 170 for (var j = 0; j < registrations.length; j++) { |
| 171 var registration = registrations[j]; |
| 172 var options = registration.options; |
| 173 |
| 174 // Only target ignores subtree. |
| 175 if (node !== target && !options.subtree) |
| 176 continue; |
| 177 |
| 178 var record = callback(options); |
| 179 if (record) |
| 180 registration.enqueue(record); |
| 181 } |
| 182 } |
| 183 } |
| 184 } |
| 185 |
| 186 var uidCounter = 0; |
| 187 |
| 188 /** |
| 189 * The class that maps to the DOM MutationObserver interface. |
| 190 * @param {Function} callback. |
| 191 * @constructor |
| 192 */ |
| 193 function JsMutationObserver(callback) { |
| 194 this.callback_ = callback; |
| 195 this.nodes_ = []; |
| 196 this.records_ = []; |
| 197 this.uid_ = ++uidCounter; |
| 198 } |
| 199 |
| 200 JsMutationObserver.prototype = { |
| 201 observe: function(target, options) { |
| 202 target = wrapIfNeeded(target); |
| 203 |
| 204 // 1.1 |
| 205 if (!options.childList && !options.attributes && !options.characterData || |
| 206 |
| 207 // 1.2 |
| 208 options.attributeOldValue && !options.attributes || |
| 209 |
| 210 // 1.3 |
| 211 options.attributeFilter && options.attributeFilter.length && |
| 212 !options.attributes || |
| 213 |
| 214 // 1.4 |
| 215 options.characterDataOldValue && !options.characterData) { |
| 216 |
| 217 throw new SyntaxError(); |
| 218 } |
| 219 |
| 220 var registrations = registrationsTable.get(target); |
| 221 if (!registrations) |
| 222 registrationsTable.set(target, registrations = []); |
| 223 |
| 224 // 2 |
| 225 // If target's list of registered observers already includes a registered |
| 226 // observer associated with the context object, replace that registered |
| 227 // observer's options with options. |
| 228 var registration; |
| 229 for (var i = 0; i < registrations.length; i++) { |
| 230 if (registrations[i].observer === this) { |
| 231 registration = registrations[i]; |
| 232 registration.removeListeners(); |
| 233 registration.options = options; |
| 234 break; |
| 235 } |
| 236 } |
| 237 |
| 238 // 3. |
| 239 // Otherwise, add a new registered observer to target's list of registered |
| 240 // observers with the context object as the observer and options as the |
| 241 // options, and add target to context object's list of nodes on which it |
| 242 // is registered. |
| 243 if (!registration) { |
| 244 registration = new Registration(this, target, options); |
| 245 registrations.push(registration); |
| 246 this.nodes_.push(target); |
| 247 } |
| 248 |
| 249 registration.addListeners(); |
| 250 }, |
| 251 |
| 252 disconnect: function() { |
| 253 this.nodes_.forEach(function(node) { |
| 254 var registrations = registrationsTable.get(node); |
| 255 for (var i = 0; i < registrations.length; i++) { |
| 256 var registration = registrations[i]; |
| 257 if (registration.observer === this) { |
| 258 registration.removeListeners(); |
| 259 registrations.splice(i, 1); |
| 260 // Each node can only have one registered observer associated with |
| 261 // this observer. |
| 262 break; |
| 263 } |
| 264 } |
| 265 }, this); |
| 266 this.records_ = []; |
| 267 }, |
| 268 |
| 269 takeRecords: function() { |
| 270 var copyOfRecords = this.records_; |
| 271 this.records_ = []; |
| 272 return copyOfRecords; |
| 273 } |
| 274 }; |
| 275 |
| 276 /** |
| 277 * @param {string} type |
| 278 * @param {Node} target |
| 279 * @constructor |
| 280 */ |
| 281 function MutationRecord(type, target) { |
| 282 this.type = type; |
| 283 this.target = target; |
| 284 this.addedNodes = []; |
| 285 this.removedNodes = []; |
| 286 this.previousSibling = null; |
| 287 this.nextSibling = null; |
| 288 this.attributeName = null; |
| 289 this.attributeNamespace = null; |
| 290 this.oldValue = null; |
| 291 } |
| 292 |
| 293 function copyMutationRecord(original) { |
| 294 var record = new MutationRecord(original.type, original.target); |
| 295 record.addedNodes = original.addedNodes.slice(); |
| 296 record.removedNodes = original.removedNodes.slice(); |
| 297 record.previousSibling = original.previousSibling; |
| 298 record.nextSibling = original.nextSibling; |
| 299 record.attributeName = original.attributeName; |
| 300 record.attributeNamespace = original.attributeNamespace; |
| 301 record.oldValue = original.oldValue; |
| 302 return record; |
| 303 }; |
| 304 |
| 305 // We keep track of the two (possibly one) records used in a single mutation. |
| 306 var currentRecord, recordWithOldValue; |
| 307 |
| 308 /** |
| 309 * Creates a record without |oldValue| and caches it as |currentRecord| for |
| 310 * later use. |
| 311 * @param {string} oldValue |
| 312 * @return {MutationRecord} |
| 313 */ |
| 314 function getRecord(type, target) { |
| 315 return currentRecord = new MutationRecord(type, target); |
| 316 } |
| 317 |
| 318 /** |
| 319 * Gets or creates a record with |oldValue| based in the |currentRecord| |
| 320 * @param {string} oldValue |
| 321 * @return {MutationRecord} |
| 322 */ |
| 323 function getRecordWithOldValue(oldValue) { |
| 324 if (recordWithOldValue) |
| 325 return recordWithOldValue; |
| 326 recordWithOldValue = copyMutationRecord(currentRecord); |
| 327 recordWithOldValue.oldValue = oldValue; |
| 328 return recordWithOldValue; |
| 329 } |
| 330 |
| 331 function clearRecords() { |
| 332 currentRecord = recordWithOldValue = undefined; |
| 333 } |
| 334 |
| 335 /** |
| 336 * @param {MutationRecord} record |
| 337 * @return {boolean} Whether the record represents a record from the current |
| 338 * mutation event. |
| 339 */ |
| 340 function recordRepresentsCurrentMutation(record) { |
| 341 return record === recordWithOldValue || record === currentRecord; |
| 342 } |
| 343 |
| 344 /** |
| 345 * Selects which record, if any, to replace the last record in the queue. |
| 346 * This returns |null| if no record should be replaced. |
| 347 * |
| 348 * @param {MutationRecord} lastRecord |
| 349 * @param {MutationRecord} newRecord |
| 350 * @param {MutationRecord} |
| 351 */ |
| 352 function selectRecord(lastRecord, newRecord) { |
| 353 if (lastRecord === newRecord) |
| 354 return lastRecord; |
| 355 |
| 356 // Check if the the record we are adding represents the same record. If |
| 357 // so, we keep the one with the oldValue in it. |
| 358 if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) |
| 359 return recordWithOldValue; |
| 360 |
| 361 return null; |
| 362 } |
| 363 |
| 364 /** |
| 365 * Class used to represent a registered observer. |
| 366 * @param {MutationObserver} observer |
| 367 * @param {Node} target |
| 368 * @param {MutationObserverInit} options |
| 369 * @constructor |
| 370 */ |
| 371 function Registration(observer, target, options) { |
| 372 this.observer = observer; |
| 373 this.target = target; |
| 374 this.options = options; |
| 375 this.transientObservedNodes = []; |
| 376 } |
| 377 |
| 378 Registration.prototype = { |
| 379 enqueue: function(record) { |
| 380 var records = this.observer.records_; |
| 381 var length = records.length; |
| 382 |
| 383 // There are cases where we replace the last record with the new record. |
| 384 // For example if the record represents the same mutation we need to use |
| 385 // the one with the oldValue. If we get same record (this can happen as we |
| 386 // walk up the tree) we ignore the new record. |
| 387 if (records.length > 0) { |
| 388 var lastRecord = records[length - 1]; |
| 389 var recordToReplaceLast = selectRecord(lastRecord, record); |
| 390 if (recordToReplaceLast) { |
| 391 records[length - 1] = recordToReplaceLast; |
| 392 return; |
| 393 } |
| 394 } else { |
| 395 scheduleCallback(this.observer); |
| 396 } |
| 397 |
| 398 records[length] = record; |
| 399 }, |
| 400 |
| 401 addListeners: function() { |
| 402 this.addListeners_(this.target); |
| 403 }, |
| 404 |
| 405 addListeners_: function(node) { |
| 406 var options = this.options; |
| 407 if (options.attributes) |
| 408 node.addEventListener('DOMAttrModified', this, true); |
| 409 |
| 410 if (options.characterData) |
| 411 node.addEventListener('DOMCharacterDataModified', this, true); |
| 412 |
| 413 if (options.childList) |
| 414 node.addEventListener('DOMNodeInserted', this, true); |
| 415 |
| 416 if (options.childList || options.subtree) |
| 417 node.addEventListener('DOMNodeRemoved', this, true); |
| 418 }, |
| 419 |
| 420 removeListeners: function() { |
| 421 this.removeListeners_(this.target); |
| 422 }, |
| 423 |
| 424 removeListeners_: function(node) { |
| 425 var options = this.options; |
| 426 if (options.attributes) |
| 427 node.removeEventListener('DOMAttrModified', this, true); |
| 428 |
| 429 if (options.characterData) |
| 430 node.removeEventListener('DOMCharacterDataModified', this, true); |
| 431 |
| 432 if (options.childList) |
| 433 node.removeEventListener('DOMNodeInserted', this, true); |
| 434 |
| 435 if (options.childList || options.subtree) |
| 436 node.removeEventListener('DOMNodeRemoved', this, true); |
| 437 }, |
| 438 |
| 439 /** |
| 440 * Adds a transient observer on node. The transient observer gets removed |
| 441 * next time we deliver the change records. |
| 442 * @param {Node} node |
| 443 */ |
| 444 addTransientObserver: function(node) { |
| 445 // Don't add transient observers on the target itself. We already have all |
| 446 // the required listeners set up on the target. |
| 447 if (node === this.target) |
| 448 return; |
| 449 |
| 450 this.addListeners_(node); |
| 451 this.transientObservedNodes.push(node); |
| 452 var registrations = registrationsTable.get(node); |
| 453 if (!registrations) |
| 454 registrationsTable.set(node, registrations = []); |
| 455 |
| 456 // We know that registrations does not contain this because we already |
| 457 // checked if node === this.target. |
| 458 registrations.push(this); |
| 459 }, |
| 460 |
| 461 removeTransientObservers: function() { |
| 462 var transientObservedNodes = this.transientObservedNodes; |
| 463 this.transientObservedNodes = []; |
| 464 |
| 465 transientObservedNodes.forEach(function(node) { |
| 466 // Transient observers are never added to the target. |
| 467 this.removeListeners_(node); |
| 468 |
| 469 var registrations = registrationsTable.get(node); |
| 470 for (var i = 0; i < registrations.length; i++) { |
| 471 if (registrations[i] === this) { |
| 472 registrations.splice(i, 1); |
| 473 // Each node can only have one registered observer associated with |
| 474 // this observer. |
| 475 break; |
| 476 } |
| 477 } |
| 478 }, this); |
| 479 }, |
| 480 |
| 481 handleEvent: function(e) { |
| 482 // Stop propagation since we are managing the propagation manually. |
| 483 // This means that other mutation events on the page will not work |
| 484 // correctly but that is by design. |
| 485 e.stopImmediatePropagation(); |
| 486 |
| 487 switch (e.type) { |
| 488 case 'DOMAttrModified': |
| 489 // http://dom.spec.whatwg.org/#concept-mo-queue-attributes |
| 490 |
| 491 var name = e.attrName; |
| 492 var namespace = e.relatedNode.namespaceURI; |
| 493 var target = e.target; |
| 494 |
| 495 // 1. |
| 496 var record = new getRecord('attributes', target); |
| 497 record.attributeName = name; |
| 498 record.attributeNamespace = namespace; |
| 499 |
| 500 // 2. |
| 501 var oldValue = |
| 502 e.attrChange === MutationEvent.ADDITION ? null : e.prevValue; |
| 503 |
| 504 forEachAncestorAndObserverEnqueueRecord(target, function(options) { |
| 505 // 3.1, 4.2 |
| 506 if (!options.attributes) |
| 507 return; |
| 508 |
| 509 // 3.2, 4.3 |
| 510 if (options.attributeFilter && options.attributeFilter.length && |
| 511 options.attributeFilter.indexOf(name) === -1 && |
| 512 options.attributeFilter.indexOf(namespace) === -1) { |
| 513 return; |
| 514 } |
| 515 // 3.3, 4.4 |
| 516 if (options.attributeOldValue) |
| 517 return getRecordWithOldValue(oldValue); |
| 518 |
| 519 // 3.4, 4.5 |
| 520 return record; |
| 521 }); |
| 522 |
| 523 break; |
| 524 |
| 525 case 'DOMCharacterDataModified': |
| 526 // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata |
| 527 var target = e.target; |
| 528 |
| 529 // 1. |
| 530 var record = getRecord('characterData', target); |
| 531 |
| 532 // 2. |
| 533 var oldValue = e.prevValue; |
| 534 |
| 535 |
| 536 forEachAncestorAndObserverEnqueueRecord(target, function(options) { |
| 537 // 3.1, 4.2 |
| 538 if (!options.characterData) |
| 539 return; |
| 540 |
| 541 // 3.2, 4.3 |
| 542 if (options.characterDataOldValue) |
| 543 return getRecordWithOldValue(oldValue); |
| 544 |
| 545 // 3.3, 4.4 |
| 546 return record; |
| 547 }); |
| 548 |
| 549 break; |
| 550 |
| 551 case 'DOMNodeRemoved': |
| 552 this.addTransientObserver(e.target); |
| 553 // Fall through. |
| 554 case 'DOMNodeInserted': |
| 555 // http://dom.spec.whatwg.org/#concept-mo-queue-childlist |
| 556 var target = e.relatedNode; |
| 557 var changedNode = e.target; |
| 558 var addedNodes, removedNodes; |
| 559 if (e.type === 'DOMNodeInserted') { |
| 560 addedNodes = [changedNode]; |
| 561 removedNodes = []; |
| 562 } else { |
| 563 |
| 564 addedNodes = []; |
| 565 removedNodes = [changedNode]; |
| 566 } |
| 567 var previousSibling = changedNode.previousSibling; |
| 568 var nextSibling = changedNode.nextSibling; |
| 569 |
| 570 // 1. |
| 571 var record = getRecord('childList', target); |
| 572 record.addedNodes = addedNodes; |
| 573 record.removedNodes = removedNodes; |
| 574 record.previousSibling = previousSibling; |
| 575 record.nextSibling = nextSibling; |
| 576 |
| 577 forEachAncestorAndObserverEnqueueRecord(target, function(options) { |
| 578 // 2.1, 3.2 |
| 579 if (!options.childList) |
| 580 return; |
| 581 |
| 582 // 2.2, 3.3 |
| 583 return record; |
| 584 }); |
| 585 |
| 586 } |
| 587 |
| 588 clearRecords(); |
| 589 } |
| 590 }; |
| 591 |
| 592 global.JsMutationObserver = JsMutationObserver; |
| 593 |
| 594 if (!global.MutationObserver) |
| 595 global.MutationObserver = JsMutationObserver; |
| 596 |
| 597 |
| 598 })(this); |
| 599 |
| 59 window.CustomElements = window.CustomElements || {flags:{}}; | 600 window.CustomElements = window.CustomElements || {flags:{}}; |
| 60 (function(scope){ | 601 (function(scope){ |
| 61 | 602 |
| 62 var logFlags = window.logFlags || {}; | 603 var logFlags = window.logFlags || {}; |
| 63 var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none
'; | 604 var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none
'; |
| 64 | 605 |
| 65 // walk the subtree rooted at node, applying 'find(element, data)' function | 606 // walk the subtree rooted at node, applying 'find(element, data)' function |
| 66 // to each element | 607 // to each element |
| 67 // if 'find' returns true for 'element', do not search element's subtree | 608 // if 'find' returns true for 'element', do not search element's subtree |
| 68 function findAll(node, find, data) { | 609 function findAll(node, find, data) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 function insertedNode(node) { | 686 function insertedNode(node) { |
| 146 inserted(node); | 687 inserted(node); |
| 147 if (inDocument(node)) { | 688 if (inDocument(node)) { |
| 148 forSubtree(node, function(e) { | 689 forSubtree(node, function(e) { |
| 149 inserted(e); | 690 inserted(e); |
| 150 }); | 691 }); |
| 151 } | 692 } |
| 152 } | 693 } |
| 153 | 694 |
| 154 | 695 |
| 155 // TODO(sorvell): on platforms without MutationObserver, mutations may not be | 696 // TODO(sorvell): on platforms without MutationObserver, mutations may not be |
| 156 // reliable and therefore attached/detached are not reliable. | 697 // reliable and therefore attached/detached are not reliable. |
| 157 // To make these callbacks less likely to fail, we defer all inserts and removes | 698 // To make these callbacks less likely to fail, we defer all inserts and removes |
| 158 // to give a chance for elements to be inserted into dom. | 699 // to give a chance for elements to be inserted into dom. |
| 159 // This ensures attachedCallback fires for elements that are created and | 700 // This ensures attachedCallback fires for elements that are created and |
| 160 // immediately added to dom. | 701 // immediately added to dom. |
| 161 var hasPolyfillMutations = (!window.MutationObserver || | 702 var hasPolyfillMutations = (!window.MutationObserver || |
| 162 (window.MutationObserver === window.JsMutationObserver)); | 703 (window.MutationObserver === window.JsMutationObserver)); |
| 163 scope.hasPolyfillMutations = hasPolyfillMutations; | 704 scope.hasPolyfillMutations = hasPolyfillMutations; |
| 164 | 705 |
| 165 var isPendingMutations = false; | 706 var isPendingMutations = false; |
| 166 var pendingMutations = []; | 707 var pendingMutations = []; |
| 167 function deferMutation(fn) { | 708 function deferMutation(fn) { |
| 168 pendingMutations.push(fn); | 709 pendingMutations.push(fn); |
| 169 if (!isPendingMutations) { | 710 if (!isPendingMutations) { |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 // exports | 974 // exports |
| 434 scope.registry = {}; | 975 scope.registry = {}; |
| 435 scope.upgradeElement = nop; | 976 scope.upgradeElement = nop; |
| 436 | 977 |
| 437 scope.watchShadow = nop; | 978 scope.watchShadow = nop; |
| 438 scope.upgrade = nop; | 979 scope.upgrade = nop; |
| 439 scope.upgradeAll = nop; | 980 scope.upgradeAll = nop; |
| 440 scope.upgradeSubtree = nop; | 981 scope.upgradeSubtree = nop; |
| 441 scope.observeDocument = nop; | 982 scope.observeDocument = nop; |
| 442 scope.upgradeDocument = nop; | 983 scope.upgradeDocument = nop; |
| 984 scope.upgradeDocumentTree = nop; |
| 443 scope.takeRecords = nop; | 985 scope.takeRecords = nop; |
| 444 | 986 |
| 445 } else { | 987 } else { |
| 446 | 988 |
| 447 /** | 989 /** |
| 448 * Registers a custom tag name with the document. | 990 * Registers a custom tag name with the document. |
| 449 * | 991 * |
| 450 * When a registered element is created, a `readyCallback` method is called | 992 * When a registered element is created, a `readyCallback` method is called |
| 451 * in the scope of the element. The `readyCallback` method can be specified on | 993 * in the scope of the element. The `readyCallback` method can be specified on |
| 452 * either `options.prototype` or `options.lifecycle` with the latter taking | 994 * either `options.prototype` or `options.lifecycle` with the latter taking |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 // some definitions specify an 'is' attribute | 1150 // some definitions specify an 'is' attribute |
| 609 if (definition.is) { | 1151 if (definition.is) { |
| 610 element.setAttribute('is', definition.is); | 1152 element.setAttribute('is', definition.is); |
| 611 } | 1153 } |
| 612 // remove 'unresolved' attr, which is a standin for :unresolved. | 1154 // remove 'unresolved' attr, which is a standin for :unresolved. |
| 613 element.removeAttribute('unresolved'); | 1155 element.removeAttribute('unresolved'); |
| 614 // make 'element' implement definition.prototype | 1156 // make 'element' implement definition.prototype |
| 615 implement(element, definition); | 1157 implement(element, definition); |
| 616 // flag as upgraded | 1158 // flag as upgraded |
| 617 element.__upgraded__ = true; | 1159 element.__upgraded__ = true; |
| 1160 // lifecycle management |
| 1161 created(element); |
| 618 // there should never be a shadow root on element at this point | 1162 // there should never be a shadow root on element at this point |
| 619 // we require child nodes be upgraded before `created` | 1163 // we require child nodes be upgraded before `created` |
| 620 scope.upgradeSubtree(element); | 1164 scope.upgradeSubtree(element); |
| 621 // lifecycle management | |
| 622 created(element); | |
| 623 // OUTPUT | 1165 // OUTPUT |
| 624 return element; | 1166 return element; |
| 625 } | 1167 } |
| 626 | 1168 |
| 627 function implement(element, definition) { | 1169 function implement(element, definition) { |
| 628 // prototype swizzling is best | 1170 // prototype swizzling is best |
| 629 if (Object.__proto__) { | 1171 if (Object.__proto__) { |
| 630 element.__proto__ = definition.prototype; | 1172 element.__proto__ = definition.prototype; |
| 631 } else { | 1173 } else { |
| 632 // where above we can re-acquire inPrototype via | 1174 // where above we can re-acquire inPrototype via |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 // parse document | 1422 // parse document |
| 881 CustomElements.parser.parse(document); | 1423 CustomElements.parser.parse(document); |
| 882 // one more pass before register is 'live' | 1424 // one more pass before register is 'live' |
| 883 CustomElements.upgradeDocument(document); | 1425 CustomElements.upgradeDocument(document); |
| 884 CustomElements.performedInitialDocumentUpgrade = true; | 1426 CustomElements.performedInitialDocumentUpgrade = true; |
| 885 // choose async | 1427 // choose async |
| 886 var async = window.Platform && Platform.endOfMicrotask ? | 1428 var async = window.Platform && Platform.endOfMicrotask ? |
| 887 Platform.endOfMicrotask : | 1429 Platform.endOfMicrotask : |
| 888 setTimeout; | 1430 setTimeout; |
| 889 async(function() { | 1431 async(function() { |
| 890 // set internal 'ready' flag, now document.registerElement will trigger | 1432 // set internal 'ready' flag, now document.registerElement will trigger |
| 891 // synchronous upgrades | 1433 // synchronous upgrades |
| 892 CustomElements.ready = true; | 1434 CustomElements.ready = true; |
| 893 // capture blunt profiling data | 1435 // capture blunt profiling data |
| 894 CustomElements.readyTime = Date.now(); | 1436 CustomElements.readyTime = Date.now(); |
| 895 if (window.HTMLImports) { | 1437 if (window.HTMLImports) { |
| 896 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; | 1438 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; |
| 897 } | 1439 } |
| 898 // notify the system that we are bootstrapped | 1440 // notify the system that we are bootstrapped |
| 899 document.dispatchEvent( | 1441 document.dispatchEvent( |
| 900 new CustomEvent('WebComponentsReady', {bubbles: true}) | 1442 new CustomEvent('WebComponentsReady', {bubbles: true}) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 917 if (document.readyState === 'complete' || scope.flags.eager) { | 1459 if (document.readyState === 'complete' || scope.flags.eager) { |
| 918 bootstrap(); | 1460 bootstrap(); |
| 919 // When loading at readyState interactive time, bootstrap only if HTMLImports | 1461 // When loading at readyState interactive time, bootstrap only if HTMLImports |
| 920 // are not pending. Also avoid IE as the semantics of this state are unreliable. | 1462 // are not pending. Also avoid IE as the semantics of this state are unreliable. |
| 921 } else if (document.readyState === 'interactive' && !window.attachEvent && | 1463 } else if (document.readyState === 'interactive' && !window.attachEvent && |
| 922 (!window.HTMLImports || window.HTMLImports.ready)) { | 1464 (!window.HTMLImports || window.HTMLImports.ready)) { |
| 923 bootstrap(); | 1465 bootstrap(); |
| 924 // When loading at other readyStates, wait for the appropriate DOM event to | 1466 // When loading at other readyStates, wait for the appropriate DOM event to |
| 925 // bootstrap. | 1467 // bootstrap. |
| 926 } else { | 1468 } else { |
| 927 var loadEvent = window.HTMLImports && !HTMLImports.ready | 1469 var loadEvent = window.HTMLImports && !HTMLImports.ready ? |
| 928 ? 'HTMLImportsLoaded' | 1470 'HTMLImportsLoaded' : document.readyState == 'loading' ? |
| 929 : document.readyState == 'loading' ? 'DOMContentLoaded' : 'load'; | 1471 'DOMContentLoaded' : 'load'; |
| 930 window.addEventListener(loadEvent, bootstrap); | 1472 window.addEventListener(loadEvent, bootstrap); |
| 931 } | 1473 } |
| 932 | 1474 |
| 933 })(window.CustomElements); | 1475 })(window.CustomElements); |
| 934 | 1476 |
| 935 (function() { | 1477 (function() { |
| 936 // Patch to allow custom element and shadow dom to work together, from: | 1478 // Patch to allow custom element and shadow dom to work together, from: |
| 937 // https://github.com/Polymer/platform-dev/blob/60ece8c323c5d9325cbfdfd6e8cd180d
4f38a3bc/src/patches-shadowdom-polyfill.js | 1479 // https://github.com/Polymer/platform-dev/blob/60ece8c323c5d9325cbfdfd6e8cd180d
4f38a3bc/src/patches-shadowdom-polyfill.js |
| 938 // include .host reference | 1480 // include .host reference |
| 939 if (HTMLElement.prototype.createShadowRoot) { | 1481 if (HTMLElement.prototype.createShadowRoot) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 if (window.CustomElements && !CustomElements.useNative) { | 1517 if (window.CustomElements && !CustomElements.useNative) { |
| 976 var originalImportNode = Document.prototype.importNode; | 1518 var originalImportNode = Document.prototype.importNode; |
| 977 Document.prototype.importNode = function(node, deep) { | 1519 Document.prototype.importNode = function(node, deep) { |
| 978 var imported = originalImportNode.call(this, node, deep); | 1520 var imported = originalImportNode.call(this, node, deep); |
| 979 CustomElements.upgradeAll(imported); | 1521 CustomElements.upgradeAll(imported); |
| 980 return imported; | 1522 return imported; |
| 981 } | 1523 } |
| 982 } | 1524 } |
| 983 | 1525 |
| 984 })(); | 1526 })(); |
| OLD | NEW |