| OLD | NEW |
| 1 if (!HTMLElement.prototype.createShadowRoot | 1 if (!HTMLElement.prototype.createShadowRoot |
| 2 || window.__forceShadowDomPolyfill) { | 2 || window.__forceShadowDomPolyfill) { |
| 3 | 3 |
| 4 /* | 4 /* |
| 5 * Copyright 2013 The Polymer Authors. All rights reserved. | 5 * Copyright 2013 The Polymer Authors. All rights reserved. |
| 6 * Use of this source code is governed by a BSD-style | 6 * Use of this source code is governed by a BSD-style |
| 7 * license that can be found in the LICENSE file. | 7 * license that can be found in the LICENSE file. |
| 8 */ | 8 */ |
| 9 (function() { | 9 (function() { |
| 10 // TODO(jmesserly): fix dart:html to use unprefixed name | 10 // TODO(jmesserly): fix dart:html to use unprefixed name |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 this.push(s); | 190 this.push(s); |
| 191 return this; | 191 return this; |
| 192 } | 192 } |
| 193 | 193 |
| 194 s.split(/\s*\.\s*/).filter(function(part) { | 194 s.split(/\s*\.\s*/).filter(function(part) { |
| 195 return part; | 195 return part; |
| 196 }).forEach(function(part) { | 196 }).forEach(function(part) { |
| 197 this.push(part); | 197 this.push(part); |
| 198 }, this); | 198 }, this); |
| 199 | 199 |
| 200 if (hasEval && !hasObserve && this.length) { | 200 if (hasEval && this.length) { |
| 201 this.getValueFrom = this.compiledGetValueFromFn(); | 201 this.getValueFrom = this.compiledGetValueFromFn(); |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 | 204 |
| 205 // TODO(rafaelw): Make simple LRU cache | 205 // TODO(rafaelw): Make simple LRU cache |
| 206 var pathCache = {}; | 206 var pathCache = {}; |
| 207 | 207 |
| 208 function getPath(pathString) { | 208 function getPath(pathString) { |
| 209 if (pathString instanceof Path) | 209 if (pathString instanceof Path) |
| 210 return pathString; | 210 return pathString; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 228 Path.get = getPath; | 228 Path.get = getPath; |
| 229 | 229 |
| 230 Path.prototype = createObject({ | 230 Path.prototype = createObject({ |
| 231 __proto__: [], | 231 __proto__: [], |
| 232 valid: true, | 232 valid: true, |
| 233 | 233 |
| 234 toString: function() { | 234 toString: function() { |
| 235 return this.join('.'); | 235 return this.join('.'); |
| 236 }, | 236 }, |
| 237 | 237 |
| 238 getValueFrom: function(obj, observedSet) { | 238 getValueFrom: function(obj, directObserver) { |
| 239 for (var i = 0; i < this.length; i++) { | 239 for (var i = 0; i < this.length; i++) { |
| 240 if (obj == null) | 240 if (obj == null) |
| 241 return; | 241 return; |
| 242 if (observedSet) | |
| 243 observedSet.observe(obj); | |
| 244 obj = obj[this[i]]; | 242 obj = obj[this[i]]; |
| 245 } | 243 } |
| 246 return obj; | 244 return obj; |
| 247 }, | 245 }, |
| 248 | 246 |
| 247 iterateObjects: function(obj, observe) { |
| 248 for (var i = 0; i < this.length; i++) { |
| 249 if (i) |
| 250 obj = obj[this[i - 1]]; |
| 251 if (!obj) |
| 252 return; |
| 253 observe(obj); |
| 254 } |
| 255 }, |
| 256 |
| 249 compiledGetValueFromFn: function() { | 257 compiledGetValueFromFn: function() { |
| 250 var accessors = this.map(function(ident) { | 258 var accessors = this.map(function(ident) { |
| 251 return isIndex(ident) ? '["' + ident + '"]' : '.' + ident; | 259 return isIndex(ident) ? '["' + ident + '"]' : '.' + ident; |
| 252 }); | 260 }); |
| 253 | 261 |
| 254 var str = ''; | 262 var str = ''; |
| 255 var pathString = 'obj'; | 263 var pathString = 'obj'; |
| 256 str += 'if (obj != null'; | 264 str += 'if (obj != null'; |
| 257 var i = 0; | 265 var i = 0; |
| 258 for (; i < (this.length - 1); i++) { | 266 for (; i < (this.length - 1); i++) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 287 }); | 295 }); |
| 288 | 296 |
| 289 var invalidPath = new Path('', constructorIsPrivate); | 297 var invalidPath = new Path('', constructorIsPrivate); |
| 290 invalidPath.valid = false; | 298 invalidPath.valid = false; |
| 291 invalidPath.getValueFrom = invalidPath.setValueFrom = function() {}; | 299 invalidPath.getValueFrom = invalidPath.setValueFrom = function() {}; |
| 292 | 300 |
| 293 var MAX_DIRTY_CHECK_CYCLES = 1000; | 301 var MAX_DIRTY_CHECK_CYCLES = 1000; |
| 294 | 302 |
| 295 function dirtyCheck(observer) { | 303 function dirtyCheck(observer) { |
| 296 var cycles = 0; | 304 var cycles = 0; |
| 297 while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check()) { | 305 while (cycles < MAX_DIRTY_CHECK_CYCLES && observer.check_()) { |
| 298 observer.report(); | |
| 299 cycles++; | 306 cycles++; |
| 300 } | 307 } |
| 301 if (global.testingExposeCycleCount) | 308 if (global.testingExposeCycleCount) |
| 302 global.dirtyCheckCycleCount = cycles; | 309 global.dirtyCheckCycleCount = cycles; |
| 310 |
| 311 return cycles > 0; |
| 303 } | 312 } |
| 304 | 313 |
| 305 function objectIsEmpty(object) { | 314 function objectIsEmpty(object) { |
| 306 for (var prop in object) | 315 for (var prop in object) |
| 307 return false; | 316 return false; |
| 308 return true; | 317 return true; |
| 309 } | 318 } |
| 310 | 319 |
| 311 function diffIsEmpty(diff) { | 320 function diffIsEmpty(diff) { |
| 312 return objectIsEmpty(diff.added) && | 321 return objectIsEmpty(diff.added) && |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 if (Array.isArray(object) && object.length !== oldObject.length) | 354 if (Array.isArray(object) && object.length !== oldObject.length) |
| 346 changed.length = object.length; | 355 changed.length = object.length; |
| 347 | 356 |
| 348 return { | 357 return { |
| 349 added: added, | 358 added: added, |
| 350 removed: removed, | 359 removed: removed, |
| 351 changed: changed | 360 changed: changed |
| 352 }; | 361 }; |
| 353 } | 362 } |
| 354 | 363 |
| 355 function copyObject(object, opt_copy) { | 364 var eomTasks = []; |
| 356 var copy = opt_copy || (Array.isArray(object) ? [] : {}); | 365 function runEOMTasks() { |
| 357 for (var prop in object) { | 366 if (!eomTasks.length) |
| 358 copy[prop] = object[prop]; | 367 return false; |
| 359 }; | 368 |
| 360 if (Array.isArray(object)) | 369 for (var i = 0; i < eomTasks.length; i++) { |
| 361 copy.length = object.length; | 370 eomTasks[i](); |
| 362 return copy; | 371 } |
| 363 } | 372 eomTasks.length = 0; |
| 364 | 373 return true; |
| 365 function Observer(object, callback, target, token) { | 374 } |
| 366 this.closed = false; | 375 |
| 367 this.object = object; | 376 var runEOM = hasObserve ? (function(){ |
| 368 this.callback = callback; | 377 var eomObj = { pingPong: true }; |
| 369 // TODO(rafaelw): Hold this.target weakly when WeakRef is available. | 378 var eomRunScheduled = false; |
| 370 this.target = target; | 379 |
| 371 this.token = token; | 380 Object.observe(eomObj, function() { |
| 372 this.reporting = true; | 381 runEOMTasks(); |
| 373 if (hasObserve) { | 382 eomRunScheduled = false; |
| 374 var self = this; | 383 }); |
| 375 this.boundInternalCallback = function(records) { | 384 |
| 376 self.internalCallback(records); | 385 return function(fn) { |
| 377 }; | 386 eomTasks.push(fn); |
| 378 } | 387 if (!eomRunScheduled) { |
| 379 | 388 eomRunScheduled = true; |
| 380 addToAll(this); | 389 eomObj.pingPong = !eomObj.pingPong; |
| 390 } |
| 391 }; |
| 392 })() : |
| 393 (function() { |
| 394 return function(fn) { |
| 395 eomTasks.push(fn); |
| 396 }; |
| 397 })(); |
| 398 |
| 399 var observedObjectCache = []; |
| 400 |
| 401 function newObservedObject() { |
| 402 var observer; |
| 403 var object; |
| 404 var discardRecords = false; |
| 405 var first = true; |
| 406 |
| 407 function callback(records) { |
| 408 if (observer && observer.state_ === OPENED && !discardRecords) |
| 409 observer.check_(records); |
| 410 } |
| 411 |
| 412 return { |
| 413 open: function(obs) { |
| 414 if (observer) |
| 415 throw Error('ObservedObject in use'); |
| 416 |
| 417 if (!first) |
| 418 Object.deliverChangeRecords(callback); |
| 419 |
| 420 observer = obs; |
| 421 first = false; |
| 422 }, |
| 423 observe: function(obj, arrayObserve) { |
| 424 object = obj; |
| 425 if (arrayObserve) |
| 426 Array.observe(object, callback); |
| 427 else |
| 428 Object.observe(object, callback); |
| 429 }, |
| 430 deliver: function(discard) { |
| 431 discardRecords = discard; |
| 432 Object.deliverChangeRecords(callback); |
| 433 discardRecords = false; |
| 434 }, |
| 435 close: function() { |
| 436 observer = undefined; |
| 437 Object.unobserve(object, callback); |
| 438 observedObjectCache.push(this); |
| 439 } |
| 440 }; |
| 441 } |
| 442 |
| 443 function getObservedObject(observer, object, arrayObserve) { |
| 444 var dir = observedObjectCache.pop() || newObservedObject(); |
| 445 dir.open(observer); |
| 446 dir.observe(object, arrayObserve); |
| 447 return dir; |
| 448 } |
| 449 |
| 450 var emptyArray = []; |
| 451 var observedSetCache = []; |
| 452 |
| 453 function newObservedSet() { |
| 454 var observers = []; |
| 455 var observerCount = 0; |
| 456 var objects = []; |
| 457 var toRemove = emptyArray; |
| 458 var resetNeeded = false; |
| 459 var resetScheduled = false; |
| 460 |
| 461 function observe(obj) { |
| 462 if (!isObject(obj)) |
| 463 return; |
| 464 |
| 465 var index = toRemove.indexOf(obj); |
| 466 if (index >= 0) { |
| 467 toRemove[index] = undefined; |
| 468 objects.push(obj); |
| 469 } else if (objects.indexOf(obj) < 0) { |
| 470 objects.push(obj); |
| 471 Object.observe(obj, callback); |
| 472 } |
| 473 |
| 474 observe(Object.getPrototypeOf(obj)); |
| 475 } |
| 476 |
| 477 function reset() { |
| 478 resetScheduled = false; |
| 479 if (!resetNeeded) |
| 480 return; |
| 481 |
| 482 var objs = toRemove === emptyArray ? [] : toRemove; |
| 483 toRemove = objects; |
| 484 objects = objs; |
| 485 |
| 486 var observer; |
| 487 for (var id in observers) { |
| 488 observer = observers[id]; |
| 489 if (!observer || observer.state_ != OPENED) |
| 490 continue; |
| 491 |
| 492 observer.iterateObjects_(observe); |
| 493 } |
| 494 |
| 495 for (var i = 0; i < toRemove.length; i++) { |
| 496 var obj = toRemove[i]; |
| 497 if (obj) |
| 498 Object.unobserve(obj, callback); |
| 499 } |
| 500 |
| 501 toRemove.length = 0; |
| 502 } |
| 503 |
| 504 function scheduleReset() { |
| 505 if (resetScheduled) |
| 506 return; |
| 507 |
| 508 resetNeeded = true; |
| 509 resetScheduled = true; |
| 510 runEOM(reset); |
| 511 } |
| 512 |
| 513 function callback() { |
| 514 var observer; |
| 515 |
| 516 for (var id in observers) { |
| 517 observer = observers[id]; |
| 518 if (!observer || observer.state_ != OPENED) |
| 519 continue; |
| 520 |
| 521 observer.check_(); |
| 522 } |
| 523 |
| 524 scheduleReset(); |
| 525 } |
| 526 |
| 527 var record = { |
| 528 object: undefined, |
| 529 objects: objects, |
| 530 open: function(obs) { |
| 531 observers[obs.id_] = obs; |
| 532 observerCount++; |
| 533 obs.iterateObjects_(observe); |
| 534 }, |
| 535 close: function(obs) { |
| 536 var anyLeft = false; |
| 537 |
| 538 observers[obs.id_] = undefined; |
| 539 observerCount--; |
| 540 |
| 541 if (observerCount) { |
| 542 scheduleReset(); |
| 543 return; |
| 544 } |
| 545 resetNeeded = false; |
| 546 |
| 547 for (var i = 0; i < objects.length; i++) { |
| 548 Object.unobserve(objects[i], callback); |
| 549 Observer.unobservedCount++; |
| 550 } |
| 551 |
| 552 observers.length = 0; |
| 553 objects.length = 0; |
| 554 observedSetCache.push(this); |
| 555 }, |
| 556 reset: scheduleReset |
| 557 }; |
| 558 |
| 559 return record; |
| 560 } |
| 561 |
| 562 var lastObservedSet; |
| 563 |
| 564 function getObservedSet(observer, obj) { |
| 565 if (!lastObservedSet || lastObservedSet.object !== obj) { |
| 566 lastObservedSet = observedSetCache.pop() || newObservedSet(); |
| 567 lastObservedSet.object = obj; |
| 568 } |
| 569 lastObservedSet.open(observer); |
| 570 return lastObservedSet; |
| 571 } |
| 572 |
| 573 var UNOPENED = 0; |
| 574 var OPENED = 1; |
| 575 var CLOSED = 2; |
| 576 var RESETTING = 3; |
| 577 |
| 578 var nextObserverId = 1; |
| 579 |
| 580 function Observer() { |
| 581 this.state_ = UNOPENED; |
| 582 this.callback_ = undefined; |
| 583 this.target_ = undefined; // TODO(rafaelw): Should be WeakRef |
| 584 this.directObserver_ = undefined; |
| 585 this.value_ = undefined; |
| 586 this.id_ = nextObserverId++; |
| 381 } | 587 } |
| 382 | 588 |
| 383 Observer.prototype = { | 589 Observer.prototype = { |
| 384 internalCallback: function(records) { | 590 open: function(callback, target) { |
| 385 if (this.closed) | 591 if (this.state_ != UNOPENED) |
| 386 return; | 592 throw Error('Observer has already been opened.'); |
| 387 if (this.reporting && this.check(records)) { | 593 |
| 388 this.report(); | 594 addToAll(this); |
| 389 if (this.testingResults) | 595 this.callback_ = callback; |
| 390 this.testingResults.anyChanged = true; | 596 this.target_ = target; |
| 391 } | 597 this.state_ = OPENED; |
| 598 this.connect_(); |
| 599 return this.value_; |
| 392 }, | 600 }, |
| 393 | 601 |
| 394 close: function() { | 602 close: function() { |
| 395 if (this.closed) | 603 if (this.state_ != OPENED) |
| 396 return; | 604 return; |
| 397 if (this.object && typeof this.object.close === 'function') | 605 |
| 398 this.object.close(); | 606 removeFromAll(this); |
| 399 | 607 this.state_ = CLOSED; |
| 400 this.disconnect(); | 608 this.disconnect_(); |
| 401 this.object = undefined; | 609 this.value_ = undefined; |
| 402 this.closed = true; | 610 this.callback_ = undefined; |
| 403 }, | 611 this.target_ = undefined; |
| 404 | 612 }, |
| 405 deliver: function(testingResults) { | 613 |
| 406 if (this.closed) | 614 deliver: function() { |
| 407 return; | 615 if (this.state_ != OPENED) |
| 408 if (hasObserve) { | 616 return; |
| 409 this.testingResults = testingResults; | 617 |
| 410 Object.deliverChangeRecords(this.boundInternalCallback); | 618 dirtyCheck(this); |
| 411 this.testingResults = undefined; | 619 }, |
| 412 } else { | 620 |
| 413 dirtyCheck(this); | 621 report_: function(changes) { |
| 414 } | |
| 415 }, | |
| 416 | |
| 417 report: function() { | |
| 418 if (!this.reporting) | |
| 419 return; | |
| 420 | |
| 421 this.sync(false); | |
| 422 if (this.callback) { | |
| 423 this.reportArgs.push(this.token); | |
| 424 this.invokeCallback(this.reportArgs); | |
| 425 } | |
| 426 this.reportArgs = undefined; | |
| 427 }, | |
| 428 | |
| 429 invokeCallback: function(args) { | |
| 430 try { | 622 try { |
| 431 this.callback.apply(this.target, args); | 623 this.callback_.apply(this.target_, changes); |
| 432 } catch (ex) { | 624 } catch (ex) { |
| 433 Observer._errorThrownDuringCallback = true; | 625 Observer._errorThrownDuringCallback = true; |
| 434 console.error('Exception caught during observer callback: ' + (ex.stack
|| ex)); | 626 console.error('Exception caught during observer callback: ' + |
| 435 } | 627 (ex.stack || ex)); |
| 436 }, | 628 } |
| 437 | 629 }, |
| 438 reset: function() { | 630 |
| 439 if (this.closed) | 631 discardChanges: function() { |
| 440 return; | 632 this.check_(undefined, true); |
| 441 | 633 return this.value_; |
| 442 if (hasObserve) { | 634 } |
| 443 this.reporting = false; | 635 } |
| 444 Object.deliverChangeRecords(this.boundInternalCallback); | 636 |
| 445 this.reporting = true; | 637 var collectObservers = !hasObserve; |
| 446 } | |
| 447 | |
| 448 this.sync(true); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 var collectObservers = !hasObserve || global.forceCollectObservers; | |
| 453 var allObservers; | 638 var allObservers; |
| 454 Observer._allObserversCount = 0; | 639 Observer._allObserversCount = 0; |
| 455 | 640 |
| 456 if (collectObservers) { | 641 if (collectObservers) { |
| 457 allObservers = []; | 642 allObservers = []; |
| 458 } | 643 } |
| 459 | 644 |
| 460 function addToAll(observer) { | 645 function addToAll(observer) { |
| 646 Observer._allObserversCount++; |
| 461 if (!collectObservers) | 647 if (!collectObservers) |
| 462 return; | 648 return; |
| 463 | 649 |
| 464 allObservers.push(observer); | 650 allObservers.push(observer); |
| 465 Observer._allObserversCount++; | 651 } |
| 652 |
| 653 function removeFromAll(observer) { |
| 654 Observer._allObserversCount--; |
| 466 } | 655 } |
| 467 | 656 |
| 468 var runningMicrotaskCheckpoint = false; | 657 var runningMicrotaskCheckpoint = false; |
| 469 | 658 |
| 470 var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'func
tion'; | 659 var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'func
tion'; |
| 471 | 660 |
| 472 global.Platform = global.Platform || {}; | 661 global.Platform = global.Platform || {}; |
| 473 | 662 |
| 474 global.Platform.performMicrotaskCheckpoint = function() { | 663 global.Platform.performMicrotaskCheckpoint = function() { |
| 475 if (runningMicrotaskCheckpoint) | 664 if (runningMicrotaskCheckpoint) |
| 476 return; | 665 return; |
| 477 | 666 |
| 478 if (hasDebugForceFullDelivery) { | 667 if (hasDebugForceFullDelivery) { |
| 479 Object.deliverAllChangeRecords(); | 668 Object.deliverAllChangeRecords(); |
| 480 return; | 669 return; |
| 481 } | 670 } |
| 482 | 671 |
| 483 if (!collectObservers) | 672 if (!collectObservers) |
| 484 return; | 673 return; |
| 485 | 674 |
| 486 runningMicrotaskCheckpoint = true; | 675 runningMicrotaskCheckpoint = true; |
| 487 | 676 |
| 488 var cycles = 0; | 677 var cycles = 0; |
| 489 var results = {}; | 678 var anyChanged, toCheck; |
| 490 | 679 |
| 491 do { | 680 do { |
| 492 cycles++; | 681 cycles++; |
| 493 var toCheck = allObservers; | 682 toCheck = allObservers; |
| 494 allObservers = []; | 683 allObservers = []; |
| 495 results.anyChanged = false; | 684 anyChanged = false; |
| 496 | 685 |
| 497 for (var i = 0; i < toCheck.length; i++) { | 686 for (var i = 0; i < toCheck.length; i++) { |
| 498 var observer = toCheck[i]; | 687 var observer = toCheck[i]; |
| 499 if (observer.closed) | 688 if (observer.state_ != OPENED) |
| 500 continue; | 689 continue; |
| 501 | 690 |
| 502 if (hasObserve) { | 691 if (observer.check_()) |
| 503 observer.deliver(results); | 692 anyChanged = true; |
| 504 } else if (observer.check()) { | |
| 505 results.anyChanged = true; | |
| 506 observer.report(); | |
| 507 } | |
| 508 | 693 |
| 509 allObservers.push(observer); | 694 allObservers.push(observer); |
| 510 } | 695 } |
| 511 } while (cycles < MAX_DIRTY_CHECK_CYCLES && results.anyChanged); | 696 if (runEOMTasks()) |
| 697 anyChanged = true; |
| 698 } while (cycles < MAX_DIRTY_CHECK_CYCLES && anyChanged); |
| 512 | 699 |
| 513 if (global.testingExposeCycleCount) | 700 if (global.testingExposeCycleCount) |
| 514 global.dirtyCheckCycleCount = cycles; | 701 global.dirtyCheckCycleCount = cycles; |
| 515 | 702 |
| 516 Observer._allObserversCount = allObservers.length; | |
| 517 runningMicrotaskCheckpoint = false; | 703 runningMicrotaskCheckpoint = false; |
| 518 }; | 704 }; |
| 519 | 705 |
| 520 if (collectObservers) { | 706 if (collectObservers) { |
| 521 global.Platform.clearObservers = function() { | 707 global.Platform.clearObservers = function() { |
| 522 allObservers = []; | 708 allObservers = []; |
| 523 }; | 709 }; |
| 524 } | 710 } |
| 525 | 711 |
| 526 function ObjectObserver(object, callback, target, token) { | 712 function ObjectObserver(object) { |
| 527 Observer.call(this, object, callback, target, token); | 713 Observer.call(this); |
| 528 this.connect(); | 714 this.value_ = object; |
| 529 this.sync(true); | 715 this.oldObject_ = undefined; |
| 530 } | 716 } |
| 531 | 717 |
| 532 ObjectObserver.prototype = createObject({ | 718 ObjectObserver.prototype = createObject({ |
| 533 __proto__: Observer.prototype, | 719 __proto__: Observer.prototype, |
| 534 | 720 |
| 535 connect: function() { | 721 arrayObserve: false, |
| 536 if (hasObserve) | 722 |
| 537 Object.observe(this.object, this.boundInternalCallback); | 723 connect_: function(callback, target) { |
| 724 if (hasObserve) { |
| 725 this.directObserver_ = getObservedObject(this, this.value_, |
| 726 this.arrayObserve); |
| 727 } else { |
| 728 this.oldObject_ = this.copyObject(this.value_); |
| 729 } |
| 730 |
| 538 }, | 731 }, |
| 539 | 732 |
| 540 sync: function(hard) { | 733 copyObject: function(object) { |
| 541 if (!hasObserve) | 734 var copy = Array.isArray(object) ? [] : {}; |
| 542 this.oldObject = copyObject(this.object); | 735 for (var prop in object) { |
| 736 copy[prop] = object[prop]; |
| 737 }; |
| 738 if (Array.isArray(object)) |
| 739 copy.length = object.length; |
| 740 return copy; |
| 543 }, | 741 }, |
| 544 | 742 |
| 545 check: function(changeRecords) { | 743 check_: function(changeRecords, skipChanges) { |
| 546 var diff; | 744 var diff; |
| 547 var oldValues; | 745 var oldValues; |
| 548 if (hasObserve) { | 746 if (hasObserve) { |
| 549 if (!changeRecords) | 747 if (!changeRecords) |
| 550 return false; | 748 return false; |
| 551 | 749 |
| 552 oldValues = {}; | 750 oldValues = {}; |
| 553 diff = diffObjectFromChangeRecords(this.object, changeRecords, | 751 diff = diffObjectFromChangeRecords(this.value_, changeRecords, |
| 554 oldValues); | 752 oldValues); |
| 555 } else { | 753 } else { |
| 556 oldValues = this.oldObject; | 754 oldValues = this.oldObject_; |
| 557 diff = diffObjectFromOldObject(this.object, this.oldObject); | 755 diff = diffObjectFromOldObject(this.value_, this.oldObject_); |
| 558 } | 756 } |
| 559 | 757 |
| 560 if (diffIsEmpty(diff)) | 758 if (diffIsEmpty(diff)) |
| 561 return false; | 759 return false; |
| 562 | 760 |
| 563 this.reportArgs = | 761 if (!hasObserve) |
| 564 [diff.added || {}, diff.removed || {}, diff.changed || {}]; | 762 this.oldObject_ = this.copyObject(this.value_); |
| 565 this.reportArgs.push(function(property) { | 763 |
| 566 return oldValues[property]; | 764 this.report_([ |
| 567 }); | 765 diff.added || {}, |
| 766 diff.removed || {}, |
| 767 diff.changed || {}, |
| 768 function(property) { |
| 769 return oldValues[property]; |
| 770 } |
| 771 ]); |
| 568 | 772 |
| 569 return true; | 773 return true; |
| 570 }, | 774 }, |
| 571 | 775 |
| 572 disconnect: function() { | 776 disconnect_: function() { |
| 573 if (!hasObserve) | 777 if (hasObserve) { |
| 574 this.oldObject = undefined; | 778 this.directObserver_.close(); |
| 575 else if (this.object) | 779 this.directObserver_ = undefined; |
| 576 Object.unobserve(this.object, this.boundInternalCallback); | 780 } else { |
| 781 this.oldObject_ = undefined; |
| 782 } |
| 783 }, |
| 784 |
| 785 deliver: function() { |
| 786 if (this.state_ != OPENED) |
| 787 return; |
| 788 |
| 789 if (hasObserve) |
| 790 this.directObserver_.deliver(false); |
| 791 else |
| 792 dirtyCheck(this); |
| 793 }, |
| 794 |
| 795 discardChanges: function() { |
| 796 if (this.directObserver_) |
| 797 this.directObserver_.deliver(true); |
| 798 else |
| 799 this.oldObject_ = this.copyObject(this.value_); |
| 800 |
| 801 return this.value_; |
| 577 } | 802 } |
| 578 }); | 803 }); |
| 579 | 804 |
| 580 function ArrayObserver(array, callback, target, token) { | 805 function ArrayObserver(array) { |
| 581 if (!Array.isArray(array)) | 806 if (!Array.isArray(array)) |
| 582 throw Error('Provided object is not an Array'); | 807 throw Error('Provided object is not an Array'); |
| 583 ObjectObserver.call(this, array, callback, target, token); | 808 ObjectObserver.call(this, array); |
| 584 } | 809 } |
| 585 | 810 |
| 586 ArrayObserver.prototype = createObject({ | 811 ArrayObserver.prototype = createObject({ |
| 812 |
| 587 __proto__: ObjectObserver.prototype, | 813 __proto__: ObjectObserver.prototype, |
| 588 | 814 |
| 589 connect: function() { | 815 arrayObserve: true, |
| 590 if (hasObserve) | 816 |
| 591 Array.observe(this.object, this.boundInternalCallback); | 817 copyObject: function(arr) { |
| 818 return arr.slice(); |
| 592 }, | 819 }, |
| 593 | 820 |
| 594 sync: function() { | 821 check_: function(changeRecords) { |
| 595 if (!hasObserve) | |
| 596 this.oldObject = this.object.slice(); | |
| 597 }, | |
| 598 | |
| 599 check: function(changeRecords) { | |
| 600 var splices; | 822 var splices; |
| 601 if (hasObserve) { | 823 if (hasObserve) { |
| 602 if (!changeRecords) | 824 if (!changeRecords) |
| 603 return false; | 825 return false; |
| 604 splices = projectArraySplices(this.object, changeRecords); | 826 splices = projectArraySplices(this.value_, changeRecords); |
| 605 } else { | 827 } else { |
| 606 splices = calcSplices(this.object, 0, this.object.length, | 828 splices = calcSplices(this.value_, 0, this.value_.length, |
| 607 this.oldObject, 0, this.oldObject.length); | 829 this.oldObject_, 0, this.oldObject_.length); |
| 608 } | 830 } |
| 609 | 831 |
| 610 if (!splices || !splices.length) | 832 if (!splices || !splices.length) |
| 611 return false; | 833 return false; |
| 612 | 834 |
| 613 this.reportArgs = [splices]; | 835 if (!hasObserve) |
| 836 this.oldObject_ = this.copyObject(this.value_); |
| 837 |
| 838 this.report_([splices]); |
| 614 return true; | 839 return true; |
| 615 } | 840 } |
| 616 }); | 841 }); |
| 617 | 842 |
| 618 ArrayObserver.applySplices = function(previous, current, splices) { | 843 ArrayObserver.applySplices = function(previous, current, splices) { |
| 619 splices.forEach(function(splice) { | 844 splices.forEach(function(splice) { |
| 620 var spliceArgs = [splice.index, splice.removed.length]; | 845 var spliceArgs = [splice.index, splice.removed.length]; |
| 621 var addIndex = splice.index; | 846 var addIndex = splice.index; |
| 622 while (addIndex < splice.index + splice.addedCount) { | 847 while (addIndex < splice.index + splice.addedCount) { |
| 623 spliceArgs.push(current[addIndex]); | 848 spliceArgs.push(current[addIndex]); |
| 624 addIndex++; | 849 addIndex++; |
| 625 } | 850 } |
| 626 | 851 |
| 627 Array.prototype.splice.apply(previous, spliceArgs); | 852 Array.prototype.splice.apply(previous, spliceArgs); |
| 628 }); | 853 }); |
| 629 }; | 854 }; |
| 630 | 855 |
| 631 function ObservedSet(callback) { | 856 function PathObserver(object, path) { |
| 632 this.arr = []; | 857 Observer.call(this); |
| 633 this.callback = callback; | 858 |
| 634 this.isObserved = true; | 859 this.object_ = object; |
| 635 } | 860 this.path_ = path instanceof Path ? path : getPath(path); |
| 636 | 861 this.directObserver_ = undefined; |
| 637 // TODO(rafaelw): Consider surfacing a way to avoid observing prototype | |
| 638 // ancestors which are expected not to change (e.g. Element, Node...). | |
| 639 var objProto = Object.getPrototypeOf({}); | |
| 640 var arrayProto = Object.getPrototypeOf([]); | |
| 641 ObservedSet.prototype = { | |
| 642 reset: function() { | |
| 643 this.isObserved = !this.isObserved; | |
| 644 }, | |
| 645 | |
| 646 observe: function(obj) { | |
| 647 if (!isObject(obj) || obj === objProto || obj === arrayProto) | |
| 648 return; | |
| 649 var i = this.arr.indexOf(obj); | |
| 650 if (i >= 0 && this.arr[i+1] === this.isObserved) | |
| 651 return; | |
| 652 | |
| 653 if (i < 0) { | |
| 654 i = this.arr.length; | |
| 655 this.arr[i] = obj; | |
| 656 Object.observe(obj, this.callback); | |
| 657 } | |
| 658 | |
| 659 this.arr[i+1] = this.isObserved; | |
| 660 this.observe(Object.getPrototypeOf(obj)); | |
| 661 }, | |
| 662 | |
| 663 cleanup: function() { | |
| 664 var i = 0, j = 0; | |
| 665 var isObserved = this.isObserved; | |
| 666 while(j < this.arr.length) { | |
| 667 var obj = this.arr[j]; | |
| 668 if (this.arr[j + 1] == isObserved) { | |
| 669 if (i < j) { | |
| 670 this.arr[i] = obj; | |
| 671 this.arr[i + 1] = isObserved; | |
| 672 } | |
| 673 i += 2; | |
| 674 } else { | |
| 675 Object.unobserve(obj, this.callback); | |
| 676 } | |
| 677 j += 2; | |
| 678 } | |
| 679 | |
| 680 this.arr.length = i; | |
| 681 } | |
| 682 }; | |
| 683 | |
| 684 function PathObserver(object, path, callback, target, token, valueFn, | |
| 685 setValueFn) { | |
| 686 var path = path instanceof Path ? path : getPath(path); | |
| 687 if (!path || !path.length || !isObject(object)) { | |
| 688 this.value_ = path ? path.getValueFrom(object) : undefined; | |
| 689 this.value = valueFn ? valueFn(this.value_) : this.value_; | |
| 690 this.closed = true; | |
| 691 return; | |
| 692 } | |
| 693 | |
| 694 Observer.call(this, object, callback, target, token); | |
| 695 this.valueFn = valueFn; | |
| 696 this.setValueFn = setValueFn; | |
| 697 this.path = path; | |
| 698 | |
| 699 this.connect(); | |
| 700 this.sync(true); | |
| 701 } | 862 } |
| 702 | 863 |
| 703 PathObserver.prototype = createObject({ | 864 PathObserver.prototype = createObject({ |
| 704 __proto__: Observer.prototype, | 865 __proto__: Observer.prototype, |
| 705 | 866 |
| 706 connect: function() { | 867 connect_: function() { |
| 707 if (hasObserve) | 868 if (hasObserve) |
| 708 this.observedSet = new ObservedSet(this.boundInternalCallback); | 869 this.directObserver_ = getObservedSet(this, this.object_); |
| 709 }, | 870 |
| 710 | 871 this.check_(undefined, true); |
| 711 disconnect: function() { | 872 }, |
| 712 this.value = undefined; | 873 |
| 874 disconnect_: function() { |
| 713 this.value_ = undefined; | 875 this.value_ = undefined; |
| 714 if (this.observedSet) { | 876 |
| 715 this.observedSet.reset(); | 877 if (this.directObserver_) { |
| 716 this.observedSet.cleanup(); | 878 this.directObserver_.close(this); |
| 717 this.observedSet = undefined; | 879 this.directObserver_ = undefined; |
| 718 } | 880 } |
| 719 }, | 881 }, |
| 720 | 882 |
| 721 check: function() { | 883 iterateObjects_: function(observe) { |
| 722 // Note: Extracting this to a member function for use here and below | 884 this.path_.iterateObjects(this.object_, observe); |
| 723 // regresses dirty-checking path perf by about 25% =-(. | 885 }, |
| 724 if (this.observedSet) | 886 |
| 725 this.observedSet.reset(); | 887 check_: function(changeRecords, skipChanges) { |
| 726 | 888 var oldValue = this.value_; |
| 727 this.value_ = this.path.getValueFrom(this.object, this.observedSet); | 889 this.value_ = this.path_.getValueFrom(this.object_); |
| 728 | 890 if (skipChanges || areSameValue(this.value_, oldValue)) |
| 729 if (this.observedSet) | |
| 730 this.observedSet.cleanup(); | |
| 731 | |
| 732 if (areSameValue(this.value_, this.oldValue_)) | |
| 733 return false; | 891 return false; |
| 734 | 892 |
| 735 this.value = this.valueFn ? this.valueFn(this.value_) : this.value_; | 893 this.report_([this.value_, oldValue]); |
| 736 this.reportArgs = [this.value, this.oldValue]; | |
| 737 return true; | 894 return true; |
| 738 }, | 895 }, |
| 739 | 896 |
| 740 sync: function(hard) { | |
| 741 if (hard) { | |
| 742 if (this.observedSet) | |
| 743 this.observedSet.reset(); | |
| 744 | |
| 745 this.value_ = this.path.getValueFrom(this.object, this.observedSet); | |
| 746 this.value = this.valueFn ? this.valueFn(this.value_) : this.value_; | |
| 747 | |
| 748 if (this.observedSet) | |
| 749 this.observedSet.cleanup(); | |
| 750 } | |
| 751 | |
| 752 this.oldValue_ = this.value_; | |
| 753 this.oldValue = this.value; | |
| 754 }, | |
| 755 | |
| 756 setValue: function(newValue) { | 897 setValue: function(newValue) { |
| 757 if (!this.path) | 898 if (this.path_) |
| 758 return; | 899 this.path_.setValueFrom(this.object_, newValue); |
| 759 if (typeof this.setValueFn === 'function') | |
| 760 newValue = this.setValueFn(newValue); | |
| 761 this.path.setValueFrom(this.object, newValue); | |
| 762 } | 900 } |
| 763 }); | 901 }); |
| 764 | 902 |
| 765 function CompoundPathObserver(callback, target, token, valueFn) { | 903 function CompoundObserver() { |
| 766 Observer.call(this, undefined, callback, target, token); | 904 Observer.call(this); |
| 767 this.valueFn = valueFn; | 905 |
| 768 | 906 this.value_ = []; |
| 769 this.observed = []; | 907 this.directObserver_ = undefined; |
| 770 this.values = []; | 908 this.observed_ = []; |
| 771 this.value = undefined; | 909 } |
| 772 this.oldValue = undefined; | 910 |
| 773 this.oldValues = undefined; | 911 var observerSentinel = {}; |
| 774 this.changeFlags = undefined; | 912 |
| 775 this.started = false; | 913 CompoundObserver.prototype = createObject({ |
| 776 } | 914 __proto__: Observer.prototype, |
| 777 | 915 |
| 778 CompoundPathObserver.prototype = createObject({ | 916 connect_: function() { |
| 779 __proto__: PathObserver.prototype, | 917 this.check_(undefined, true); |
| 780 | 918 |
| 781 // TODO(rafaelw): Consider special-casing when |object| is a PathObserver | 919 if (!hasObserve) |
| 782 // and path 'value' to avoid explicit observation. | 920 return; |
| 921 |
| 922 var object; |
| 923 var needsDirectObserver = false; |
| 924 for (var i = 0; i < this.observed_.length; i += 2) { |
| 925 object = this.observed_[i] |
| 926 if (object !== observerSentinel) { |
| 927 needsDirectObserver = true; |
| 928 break; |
| 929 } |
| 930 } |
| 931 |
| 932 if (this.directObserver_) { |
| 933 if (needsDirectObserver) { |
| 934 this.directObserver_.reset(); |
| 935 return; |
| 936 } |
| 937 this.directObserver_.close(); |
| 938 this.directObserver_ = undefined; |
| 939 return; |
| 940 } |
| 941 |
| 942 if (needsDirectObserver) |
| 943 this.directObserver_ = getObservedSet(this, object); |
| 944 }, |
| 945 |
| 946 closeObservers_: function() { |
| 947 for (var i = 0; i < this.observed_.length; i += 2) { |
| 948 if (this.observed_[i] === observerSentinel) |
| 949 this.observed_[i + 1].close(); |
| 950 } |
| 951 this.observed_.length = 0; |
| 952 }, |
| 953 |
| 954 disconnect_: function() { |
| 955 this.value_ = undefined; |
| 956 |
| 957 if (this.directObserver_) { |
| 958 this.directObserver_.close(this); |
| 959 this.directObserver_ = undefined; |
| 960 } |
| 961 |
| 962 this.closeObservers_(); |
| 963 }, |
| 964 |
| 783 addPath: function(object, path) { | 965 addPath: function(object, path) { |
| 784 if (this.started) | 966 if (this.state_ != UNOPENED && this.state_ != RESETTING) |
| 785 throw Error('Cannot add more paths once started.'); | 967 throw Error('Cannot add paths once started.'); |
| 786 | 968 |
| 787 var path = path instanceof Path ? path : getPath(path); | 969 this.observed_.push(object, path instanceof Path ? path : getPath(path)); |
| 788 var value = path ? path.getValueFrom(object) : undefined; | 970 }, |
| 789 | 971 |
| 790 this.observed.push(object, path); | 972 addObserver: function(observer) { |
| 791 this.values.push(value); | 973 if (this.state_ != UNOPENED && this.state_ != RESETTING) |
| 792 }, | 974 throw Error('Cannot add observers once started.'); |
| 793 | 975 |
| 794 start: function() { | 976 observer.open(this.deliver, this); |
| 795 this.started = true; | 977 this.observed_.push(observerSentinel, observer); |
| 796 this.connect(); | 978 }, |
| 797 this.sync(true); | 979 |
| 798 }, | 980 startReset: function() { |
| 799 | 981 if (this.state_ != OPENED) |
| 800 getValues: function() { | 982 throw Error('Can only reset while open'); |
| 801 if (this.observedSet) | 983 |
| 802 this.observedSet.reset(); | 984 this.state_ = RESETTING; |
| 803 | 985 this.closeObservers_(); |
| 804 var anyChanged = false; | 986 }, |
| 805 for (var i = 0; i < this.observed.length; i = i+2) { | 987 |
| 806 var path = this.observed[i+1]; | 988 finishReset: function() { |
| 807 if (!path) | 989 if (this.state_ != RESETTING) |
| 990 throw Error('Can only finishReset after startReset'); |
| 991 this.state_ = OPENED; |
| 992 this.connect_(); |
| 993 |
| 994 return this.value_; |
| 995 }, |
| 996 |
| 997 iterateObjects_: function(observe) { |
| 998 var object; |
| 999 for (var i = 0; i < this.observed_.length; i += 2) { |
| 1000 object = this.observed_[i] |
| 1001 if (object !== observerSentinel) |
| 1002 this.observed_[i + 1].iterateObjects(object, observe) |
| 1003 } |
| 1004 }, |
| 1005 |
| 1006 check_: function(changeRecords, skipChanges) { |
| 1007 var oldValues; |
| 1008 for (var i = 0; i < this.observed_.length; i += 2) { |
| 1009 var pathOrObserver = this.observed_[i+1]; |
| 1010 var object = this.observed_[i]; |
| 1011 var value = object === observerSentinel ? |
| 1012 pathOrObserver.discardChanges() : |
| 1013 pathOrObserver.getValueFrom(object) |
| 1014 |
| 1015 if (skipChanges) { |
| 1016 this.value_[i / 2] = value; |
| 808 continue; | 1017 continue; |
| 809 var object = this.observed[i]; | |
| 810 var value = path.getValueFrom(object, this.observedSet); | |
| 811 var oldValue = this.values[i/2]; | |
| 812 if (!areSameValue(value, oldValue)) { | |
| 813 if (!anyChanged && !this.valueFn) { | |
| 814 this.oldValues = this.oldValues || []; | |
| 815 this.changeFlags = this.changeFlags || []; | |
| 816 for (var j = 0; j < this.values.length; j++) { | |
| 817 this.oldValues[j] = this.values[j]; | |
| 818 this.changeFlags[j] = false; | |
| 819 } | |
| 820 } | |
| 821 | |
| 822 if (!this.valueFn) | |
| 823 this.changeFlags[i/2] = true; | |
| 824 | |
| 825 this.values[i/2] = value; | |
| 826 anyChanged = true; | |
| 827 } | 1018 } |
| 828 } | 1019 |
| 829 | 1020 if (areSameValue(value, this.value_[i / 2])) |
| 830 if (this.observedSet) | 1021 continue; |
| 831 this.observedSet.cleanup(); | 1022 |
| 832 | 1023 oldValues = oldValues || []; |
| 833 return anyChanged; | 1024 oldValues[i / 2] = this.value_[i / 2]; |
| 834 }, | 1025 this.value_[i / 2] = value; |
| 835 | 1026 } |
| 836 check: function() { | 1027 |
| 837 if (!this.getValues()) | 1028 if (!oldValues) |
| 838 return; | 1029 return false; |
| 839 | 1030 |
| 840 if (this.valueFn) { | 1031 // TODO(rafaelw): Having observed_ as the third callback arg here is |
| 841 this.value = this.valueFn(this.values); | 1032 // pretty lame API. Fix. |
| 842 | 1033 this.report_([this.value_, oldValues, this.observed_]); |
| 843 if (areSameValue(this.value, this.oldValue)) | |
| 844 return false; | |
| 845 | |
| 846 this.reportArgs = [this.value, this.oldValue]; | |
| 847 } else { | |
| 848 this.reportArgs = [this.values, this.oldValues, this.changeFlags, | |
| 849 this.observed]; | |
| 850 } | |
| 851 | |
| 852 return true; | 1034 return true; |
| 853 }, | |
| 854 | |
| 855 sync: function(hard) { | |
| 856 if (hard) { | |
| 857 this.getValues(); | |
| 858 if (this.valueFn) | |
| 859 this.value = this.valueFn(this.values); | |
| 860 } | |
| 861 | |
| 862 if (this.valueFn) | |
| 863 this.oldValue = this.value; | |
| 864 }, | |
| 865 | |
| 866 close: function() { | |
| 867 if (this.observed) { | |
| 868 for (var i = 0; i < this.observed.length; i = i + 2) { | |
| 869 var object = this.observed[i]; | |
| 870 if (object && typeof object.close === 'function') | |
| 871 object.close(); | |
| 872 } | |
| 873 this.observed = undefined; | |
| 874 this.values = undefined; | |
| 875 } | |
| 876 | |
| 877 Observer.prototype.close.call(this); | |
| 878 } | 1035 } |
| 879 }); | 1036 }); |
| 880 | 1037 |
| 1038 function identFn(value) { return value; } |
| 1039 |
| 1040 function ObserverTransform(observable, getValueFn, setValueFn, |
| 1041 dontPassThroughSet) { |
| 1042 this.callback_ = undefined; |
| 1043 this.target_ = undefined; |
| 1044 this.value_ = undefined; |
| 1045 this.observable_ = observable; |
| 1046 this.getValueFn_ = getValueFn || identFn; |
| 1047 this.setValueFn_ = setValueFn || identFn; |
| 1048 // TODO(rafaelw): This is a temporary hack. PolymerExpressions needs this |
| 1049 // at the moment because of a bug in it's dependency tracking. |
| 1050 this.dontPassThroughSet_ = dontPassThroughSet; |
| 1051 } |
| 1052 |
| 1053 ObserverTransform.prototype = { |
| 1054 open: function(callback, target) { |
| 1055 this.callback_ = callback; |
| 1056 this.target_ = target; |
| 1057 this.value_ = |
| 1058 this.getValueFn_(this.observable_.open(this.observedCallback_, this)); |
| 1059 return this.value_; |
| 1060 }, |
| 1061 |
| 1062 observedCallback_: function(value) { |
| 1063 value = this.getValueFn_(value); |
| 1064 if (areSameValue(value, this.value_)) |
| 1065 return; |
| 1066 var oldValue = this.value_; |
| 1067 this.value_ = value; |
| 1068 this.callback_.call(this.target_, this.value_, oldValue); |
| 1069 }, |
| 1070 |
| 1071 discardChanges: function() { |
| 1072 this.value_ = this.getValueFn_(this.observable_.discardChanges()); |
| 1073 return this.value_; |
| 1074 }, |
| 1075 |
| 1076 deliver: function() { |
| 1077 return this.observable_.deliver(); |
| 1078 }, |
| 1079 |
| 1080 setValue: function(value) { |
| 1081 value = this.setValueFn_(value); |
| 1082 if (!this.dontPassThroughSet_ && this.observable_.setValue) |
| 1083 return this.observable_.setValue(value); |
| 1084 }, |
| 1085 |
| 1086 close: function() { |
| 1087 if (this.observable_) |
| 1088 this.observable_.close(); |
| 1089 this.callback_ = undefined; |
| 1090 this.target_ = undefined; |
| 1091 this.observable_ = undefined; |
| 1092 this.value_ = undefined; |
| 1093 this.getValueFn_ = undefined; |
| 1094 this.setValueFn_ = undefined; |
| 1095 } |
| 1096 } |
| 1097 |
| 881 var expectedRecordTypes = {}; | 1098 var expectedRecordTypes = {}; |
| 882 expectedRecordTypes[PROP_ADD_TYPE] = true; | 1099 expectedRecordTypes[PROP_ADD_TYPE] = true; |
| 883 expectedRecordTypes[PROP_UPDATE_TYPE] = true; | 1100 expectedRecordTypes[PROP_UPDATE_TYPE] = true; |
| 884 expectedRecordTypes[PROP_DELETE_TYPE] = true; | 1101 expectedRecordTypes[PROP_DELETE_TYPE] = true; |
| 885 | 1102 |
| 886 function notifyFunction(object, name) { | 1103 function notifyFunction(object, name) { |
| 887 if (typeof Object.observe !== 'function') | 1104 if (typeof Object.observe !== 'function') |
| 888 return; | 1105 return; |
| 889 | 1106 |
| 890 var notifier = Object.getNotifier(object); | 1107 var notifier = Object.getNotifier(object); |
| 891 return function(type, oldValue) { | 1108 return function(type, oldValue) { |
| 892 var changeRecord = { | 1109 var changeRecord = { |
| 893 object: object, | 1110 object: object, |
| 894 type: type, | 1111 type: type, |
| 895 name: name | 1112 name: name |
| 896 }; | 1113 }; |
| 897 if (arguments.length === 2) | 1114 if (arguments.length === 2) |
| 898 changeRecord.oldValue = oldValue; | 1115 changeRecord.oldValue = oldValue; |
| 899 notifier.notify(changeRecord); | 1116 notifier.notify(changeRecord); |
| 900 } | 1117 } |
| 901 } | 1118 } |
| 902 | 1119 |
| 903 // TODO(rafaelw): It should be possible for the Object.observe case to have | 1120 Observer.defineComputedProperty = function(target, name, observable) { |
| 904 // every PathObserver used by defineProperty share a single Object.observe | |
| 905 // callback, and thus get() can simply call observer.deliver() and any changes | |
| 906 // to any dependent value will be observed. | |
| 907 PathObserver.defineProperty = function(target, name, object, path) { | |
| 908 // TODO(rafaelw): Validate errors | |
| 909 path = getPath(path); | |
| 910 var notify = notifyFunction(target, name); | 1121 var notify = notifyFunction(target, name); |
| 911 | 1122 var value = observable.open(function(newValue, oldValue) { |
| 912 var observer = new PathObserver(object, path, | 1123 value = newValue; |
| 913 function(newValue, oldValue) { | 1124 if (notify) |
| 914 if (notify) | 1125 notify(PROP_UPDATE_TYPE, oldValue); |
| 915 notify(PROP_UPDATE_TYPE, oldValue); | 1126 }); |
| 916 } | |
| 917 ); | |
| 918 | 1127 |
| 919 Object.defineProperty(target, name, { | 1128 Object.defineProperty(target, name, { |
| 920 get: function() { | 1129 get: function() { |
| 921 return path.getValueFrom(object); | 1130 observable.deliver(); |
| 1131 return value; |
| 922 }, | 1132 }, |
| 923 set: function(newValue) { | 1133 set: function(newValue) { |
| 924 path.setValueFrom(object, newValue); | 1134 observable.setValue(newValue); |
| 1135 return newValue; |
| 925 }, | 1136 }, |
| 926 configurable: true | 1137 configurable: true |
| 927 }); | 1138 }); |
| 928 | 1139 |
| 929 return { | 1140 return { |
| 930 close: function() { | 1141 close: function() { |
| 931 var oldValue = path.getValueFrom(object); | 1142 observable.close(); |
| 932 if (notify) | |
| 933 observer.deliver(); | |
| 934 observer.close(); | |
| 935 Object.defineProperty(target, name, { | 1143 Object.defineProperty(target, name, { |
| 936 value: oldValue, | 1144 value: value, |
| 937 writable: true, | 1145 writable: true, |
| 938 configurable: true | 1146 configurable: true |
| 939 }); | 1147 }); |
| 940 } | 1148 } |
| 941 }; | 1149 }; |
| 942 } | 1150 } |
| 943 | 1151 |
| 944 function diffObjectFromChangeRecords(object, changeRecords, oldValues) { | 1152 function diffObjectFromChangeRecords(object, changeRecords, oldValues) { |
| 945 var added = {}; | 1153 var added = {}; |
| 946 var removed = {}; | 1154 var removed = {}; |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 }; | 1598 }; |
| 1391 | 1599 |
| 1392 splices = splices.concat(calcSplices(array, splice.index, splice.index + s
plice.addedCount, | 1600 splices = splices.concat(calcSplices(array, splice.index, splice.index + s
plice.addedCount, |
| 1393 splice.removed, 0, splice.removed.len
gth)); | 1601 splice.removed, 0, splice.removed.len
gth)); |
| 1394 }); | 1602 }); |
| 1395 | 1603 |
| 1396 return splices; | 1604 return splices; |
| 1397 } | 1605 } |
| 1398 | 1606 |
| 1399 global.Observer = Observer; | 1607 global.Observer = Observer; |
| 1608 global.Observer.runEOM_ = runEOM; |
| 1400 global.Observer.hasObjectObserve = hasObserve; | 1609 global.Observer.hasObjectObserve = hasObserve; |
| 1401 global.ArrayObserver = ArrayObserver; | 1610 global.ArrayObserver = ArrayObserver; |
| 1402 global.ArrayObserver.calculateSplices = function(current, previous) { | 1611 global.ArrayObserver.calculateSplices = function(current, previous) { |
| 1403 return arraySplice.calculateSplices(current, previous); | 1612 return arraySplice.calculateSplices(current, previous); |
| 1404 }; | 1613 }; |
| 1405 | 1614 |
| 1406 global.ArraySplice = ArraySplice; | 1615 global.ArraySplice = ArraySplice; |
| 1407 global.ObjectObserver = ObjectObserver; | 1616 global.ObjectObserver = ObjectObserver; |
| 1408 global.PathObserver = PathObserver; | 1617 global.PathObserver = PathObserver; |
| 1409 global.CompoundPathObserver = CompoundPathObserver; | 1618 global.CompoundObserver = CompoundObserver; |
| 1410 global.Path = Path; | 1619 global.Path = Path; |
| 1620 global.ObserverTransform = ObserverTransform; |
| 1411 | 1621 |
| 1412 // TODO(rafaelw): Only needed for testing until new change record names | 1622 // TODO(rafaelw): Only needed for testing until new change record names |
| 1413 // make it to release. | 1623 // make it to release. |
| 1414 global.Observer.changeRecordTypes = { | 1624 global.Observer.changeRecordTypes = { |
| 1415 add: PROP_ADD_TYPE, | 1625 add: PROP_ADD_TYPE, |
| 1416 update: PROP_UPDATE_TYPE, | 1626 update: PROP_UPDATE_TYPE, |
| 1417 reconfigure: PROP_RECONFIGURE_TYPE, | 1627 reconfigure: PROP_RECONFIGURE_TYPE, |
| 1418 'delete': PROP_DELETE_TYPE, | 1628 'delete': PROP_DELETE_TYPE, |
| 1419 splice: ARRAY_SPLICE_TYPE | 1629 splice: ARRAY_SPLICE_TYPE |
| 1420 }; | 1630 }; |
| 1421 })(typeof global !== 'undefined' && global ? global : this || window); | 1631 })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && m
odule ? global : this || window); |
| 1422 | 1632 |
| 1423 /* | 1633 /* |
| 1424 * Copyright 2012 The Polymer Authors. All rights reserved. | 1634 * Copyright 2012 The Polymer Authors. All rights reserved. |
| 1425 * Use of this source code is governed by a BSD-style | 1635 * Use of this source code is governed by a BSD-style |
| 1426 * license that can be found in the LICENSE file. | 1636 * license that can be found in the LICENSE file. |
| 1427 */ | 1637 */ |
| 1428 | 1638 |
| 1429 if (typeof WeakMap === 'undefined') { | 1639 if (typeof WeakMap === 'undefined') { |
| 1430 (function() { | 1640 (function() { |
| 1431 var defineProperty = Object.defineProperty; | 1641 var defineProperty = Object.defineProperty; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1701 superWrapperConstructor.call(this, node); | 1911 superWrapperConstructor.call(this, node); |
| 1702 } | 1912 } |
| 1703 GeneratedWrapper.prototype = | 1913 GeneratedWrapper.prototype = |
| 1704 Object.create(superWrapperConstructor.prototype); | 1914 Object.create(superWrapperConstructor.prototype); |
| 1705 GeneratedWrapper.prototype.constructor = GeneratedWrapper; | 1915 GeneratedWrapper.prototype.constructor = GeneratedWrapper; |
| 1706 | 1916 |
| 1707 return GeneratedWrapper; | 1917 return GeneratedWrapper; |
| 1708 } | 1918 } |
| 1709 | 1919 |
| 1710 var OriginalDOMImplementation = window.DOMImplementation; | 1920 var OriginalDOMImplementation = window.DOMImplementation; |
| 1921 var OriginalEventTarget = window.EventTarget; |
| 1711 var OriginalEvent = window.Event; | 1922 var OriginalEvent = window.Event; |
| 1712 var OriginalNode = window.Node; | 1923 var OriginalNode = window.Node; |
| 1713 var OriginalWindow = window.Window; | 1924 var OriginalWindow = window.Window; |
| 1714 var OriginalRange = window.Range; | 1925 var OriginalRange = window.Range; |
| 1715 var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D; | 1926 var OriginalCanvasRenderingContext2D = window.CanvasRenderingContext2D; |
| 1716 var OriginalWebGLRenderingContext = window.WebGLRenderingContext; | 1927 var OriginalWebGLRenderingContext = window.WebGLRenderingContext; |
| 1928 var OriginalSVGElementInstance = window.SVGElementInstance; |
| 1717 | 1929 |
| 1718 function isWrapper(object) { | 1930 function isWrapper(object) { |
| 1719 return object instanceof wrappers.EventTarget || | 1931 return object instanceof wrappers.EventTarget || |
| 1720 object instanceof wrappers.Event || | 1932 object instanceof wrappers.Event || |
| 1721 object instanceof wrappers.Range || | 1933 object instanceof wrappers.Range || |
| 1722 object instanceof wrappers.DOMImplementation || | 1934 object instanceof wrappers.DOMImplementation || |
| 1723 object instanceof wrappers.CanvasRenderingContext2D || | 1935 object instanceof wrappers.CanvasRenderingContext2D || |
| 1724 wrappers.WebGLRenderingContext && | 1936 wrappers.WebGLRenderingContext && |
| 1725 object instanceof wrappers.WebGLRenderingContext; | 1937 object instanceof wrappers.WebGLRenderingContext; |
| 1726 } | 1938 } |
| 1727 | 1939 |
| 1728 function isNative(object) { | 1940 function isNative(object) { |
| 1729 return object instanceof OriginalNode || | 1941 return OriginalEventTarget && object instanceof OriginalEventTarget || |
| 1942 object instanceof OriginalNode || |
| 1730 object instanceof OriginalEvent || | 1943 object instanceof OriginalEvent || |
| 1731 object instanceof OriginalWindow || | 1944 object instanceof OriginalWindow || |
| 1732 object instanceof OriginalRange || | 1945 object instanceof OriginalRange || |
| 1733 object instanceof OriginalDOMImplementation || | 1946 object instanceof OriginalDOMImplementation || |
| 1734 object instanceof OriginalCanvasRenderingContext2D || | 1947 object instanceof OriginalCanvasRenderingContext2D || |
| 1735 OriginalWebGLRenderingContext && | 1948 OriginalWebGLRenderingContext && |
| 1736 object instanceof OriginalWebGLRenderingContext; | 1949 object instanceof OriginalWebGLRenderingContext || |
| 1950 OriginalSVGElementInstance && |
| 1951 object instanceof OriginalSVGElementInstance; |
| 1737 } | 1952 } |
| 1738 | 1953 |
| 1739 /** | 1954 /** |
| 1740 * Wraps a node in a WrapperNode. If there already exists a wrapper for the | 1955 * Wraps a node in a WrapperNode. If there already exists a wrapper for the |
| 1741 * |node| that wrapper is returned instead. | 1956 * |node| that wrapper is returned instead. |
| 1742 * @param {Node} node | 1957 * @param {Node} node |
| 1743 * @return {WrapperNode} | 1958 * @return {WrapperNode} |
| 1744 */ | 1959 */ |
| 1745 function wrap(impl) { | 1960 function wrap(impl) { |
| 1746 if (impl === null) | 1961 if (impl === null) |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1825 }; | 2040 }; |
| 1826 }); | 2041 }); |
| 1827 }); | 2042 }); |
| 1828 } | 2043 } |
| 1829 | 2044 |
| 1830 scope.assert = assert; | 2045 scope.assert = assert; |
| 1831 scope.constructorTable = constructorTable; | 2046 scope.constructorTable = constructorTable; |
| 1832 scope.defineGetter = defineGetter; | 2047 scope.defineGetter = defineGetter; |
| 1833 scope.defineWrapGetter = defineWrapGetter; | 2048 scope.defineWrapGetter = defineWrapGetter; |
| 1834 scope.forwardMethodsToWrapper = forwardMethodsToWrapper; | 2049 scope.forwardMethodsToWrapper = forwardMethodsToWrapper; |
| 2050 scope.isWrapper = isWrapper; |
| 1835 scope.isWrapperFor = isWrapperFor; | 2051 scope.isWrapperFor = isWrapperFor; |
| 1836 scope.mixin = mixin; | 2052 scope.mixin = mixin; |
| 1837 scope.nativePrototypeTable = nativePrototypeTable; | 2053 scope.nativePrototypeTable = nativePrototypeTable; |
| 1838 scope.oneOf = oneOf; | 2054 scope.oneOf = oneOf; |
| 1839 scope.registerObject = registerObject; | 2055 scope.registerObject = registerObject; |
| 1840 scope.registerWrapper = register; | 2056 scope.registerWrapper = register; |
| 1841 scope.rewrap = rewrap; | 2057 scope.rewrap = rewrap; |
| 1842 scope.unwrap = unwrap; | 2058 scope.unwrap = unwrap; |
| 1843 scope.unwrapIfNeeded = unwrapIfNeeded; | 2059 scope.unwrapIfNeeded = unwrapIfNeeded; |
| 1844 scope.wrap = wrap; | 2060 scope.wrap = wrap; |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2280 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 2496 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
| 2281 var mixin = scope.mixin; | 2497 var mixin = scope.mixin; |
| 2282 var registerWrapper = scope.registerWrapper; | 2498 var registerWrapper = scope.registerWrapper; |
| 2283 var unwrap = scope.unwrap; | 2499 var unwrap = scope.unwrap; |
| 2284 var wrap = scope.wrap; | 2500 var wrap = scope.wrap; |
| 2285 var wrappers = scope.wrappers; | 2501 var wrappers = scope.wrappers; |
| 2286 | 2502 |
| 2287 var wrappedFuns = new WeakMap(); | 2503 var wrappedFuns = new WeakMap(); |
| 2288 var listenersTable = new WeakMap(); | 2504 var listenersTable = new WeakMap(); |
| 2289 var handledEventsTable = new WeakMap(); | 2505 var handledEventsTable = new WeakMap(); |
| 2506 var currentlyDispatchingEvents = new WeakMap(); |
| 2290 var targetTable = new WeakMap(); | 2507 var targetTable = new WeakMap(); |
| 2291 var currentTargetTable = new WeakMap(); | 2508 var currentTargetTable = new WeakMap(); |
| 2292 var relatedTargetTable = new WeakMap(); | 2509 var relatedTargetTable = new WeakMap(); |
| 2293 var eventPhaseTable = new WeakMap(); | 2510 var eventPhaseTable = new WeakMap(); |
| 2294 var stopPropagationTable = new WeakMap(); | 2511 var stopPropagationTable = new WeakMap(); |
| 2295 var stopImmediatePropagationTable = new WeakMap(); | 2512 var stopImmediatePropagationTable = new WeakMap(); |
| 2296 var eventHandlersTable = new WeakMap(); | 2513 var eventHandlersTable = new WeakMap(); |
| 2297 var eventPathTable = new WeakMap(); | 2514 var eventPathTable = new WeakMap(); |
| 2298 | 2515 |
| 2299 function isShadowRoot(node) { | 2516 function isShadowRoot(node) { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2451 return false; | 2668 return false; |
| 2452 } | 2669 } |
| 2453 | 2670 |
| 2454 | 2671 |
| 2455 function dispatchOriginalEvent(originalEvent) { | 2672 function dispatchOriginalEvent(originalEvent) { |
| 2456 // Make sure this event is only dispatched once. | 2673 // Make sure this event is only dispatched once. |
| 2457 if (handledEventsTable.get(originalEvent)) | 2674 if (handledEventsTable.get(originalEvent)) |
| 2458 return; | 2675 return; |
| 2459 handledEventsTable.set(originalEvent, true); | 2676 handledEventsTable.set(originalEvent, true); |
| 2460 | 2677 |
| 2461 // Render before dispatching the event to ensure that the event path is | 2678 return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); |
| 2462 // correct. | |
| 2463 scope.renderAllPending(); | |
| 2464 | |
| 2465 var target = wrap(originalEvent.target); | |
| 2466 var event = wrap(originalEvent); | |
| 2467 return dispatchEvent(event, target); | |
| 2468 } | 2679 } |
| 2469 | 2680 |
| 2470 function dispatchEvent(event, originalWrapperTarget) { | 2681 function dispatchEvent(event, originalWrapperTarget) { |
| 2682 if (currentlyDispatchingEvents.get(event)) |
| 2683 throw new Error('InvalidStateError') |
| 2684 currentlyDispatchingEvents.set(event, true); |
| 2685 |
| 2686 // Render to ensure that the event path is correct. |
| 2687 scope.renderAllPending(); |
| 2471 var eventPath = retarget(originalWrapperTarget); | 2688 var eventPath = retarget(originalWrapperTarget); |
| 2472 | 2689 |
| 2473 // For window load events the load event is dispatched at the window but | 2690 // For window load events the load event is dispatched at the window but |
| 2474 // the target is set to the document. | 2691 // the target is set to the document. |
| 2475 // | 2692 // |
| 2476 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end | 2693 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end |
| 2477 // | 2694 // |
| 2478 // TODO(arv): Find a less hacky way to do this. | 2695 // TODO(arv): Find a less hacky way to do this. |
| 2479 if (event.type === 'load' && | 2696 if (event.type === 'load' && |
| 2480 eventPath.length === 2 && | 2697 eventPath.length === 2 && |
| 2481 eventPath[0].target instanceof wrappers.Document) { | 2698 eventPath[0].target instanceof wrappers.Document) { |
| 2482 eventPath.shift(); | 2699 eventPath.shift(); |
| 2483 } | 2700 } |
| 2484 | 2701 |
| 2485 eventPathTable.set(event, eventPath); | 2702 eventPathTable.set(event, eventPath); |
| 2486 | 2703 |
| 2487 if (dispatchCapturing(event, eventPath)) { | 2704 if (dispatchCapturing(event, eventPath)) { |
| 2488 if (dispatchAtTarget(event, eventPath)) { | 2705 if (dispatchAtTarget(event, eventPath)) { |
| 2489 dispatchBubbling(event, eventPath); | 2706 dispatchBubbling(event, eventPath); |
| 2490 } | 2707 } |
| 2491 } | 2708 } |
| 2492 | 2709 |
| 2493 eventPhaseTable.set(event, Event.NONE); | 2710 eventPhaseTable.set(event, Event.NONE); |
| 2494 currentTargetTable.set(event, null); | 2711 currentTargetTable.delete(event, null); |
| 2712 currentlyDispatchingEvents.delete(event); |
| 2495 | 2713 |
| 2496 return event.defaultPrevented; | 2714 return event.defaultPrevented; |
| 2497 } | 2715 } |
| 2498 | 2716 |
| 2499 function dispatchCapturing(event, eventPath) { | 2717 function dispatchCapturing(event, eventPath) { |
| 2500 var phase; | 2718 var phase; |
| 2501 | 2719 |
| 2502 for (var i = eventPath.length - 1; i > 0; i--) { | 2720 for (var i = eventPath.length - 1; i > 0; i--) { |
| 2503 var target = eventPath[i].target; | 2721 var target = eventPath[i].target; |
| 2504 var currentTarget = eventPath[i].currentTarget; | 2722 var currentTarget = eventPath[i].currentTarget; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2623 }, | 2841 }, |
| 2624 get removed() { | 2842 get removed() { |
| 2625 return this.handler === null; | 2843 return this.handler === null; |
| 2626 }, | 2844 }, |
| 2627 remove: function() { | 2845 remove: function() { |
| 2628 this.handler = null; | 2846 this.handler = null; |
| 2629 } | 2847 } |
| 2630 }; | 2848 }; |
| 2631 | 2849 |
| 2632 var OriginalEvent = window.Event; | 2850 var OriginalEvent = window.Event; |
| 2633 OriginalEvent.prototype.polymerBlackList_ = {returnValue: true}; | 2851 OriginalEvent.prototype.polymerBlackList_ = { |
| 2852 returnValue: true, |
| 2853 // TODO(arv): keyLocation is part of KeyboardEvent but Firefox does not |
| 2854 // support constructable KeyboardEvent so we keep it here for now. |
| 2855 keyLocation: true |
| 2856 }; |
| 2634 | 2857 |
| 2635 /** | 2858 /** |
| 2636 * Creates a new Event wrapper or wraps an existin native Event object. | 2859 * Creates a new Event wrapper or wraps an existin native Event object. |
| 2637 * @param {string|Event} type | 2860 * @param {string|Event} type |
| 2638 * @param {Object=} options | 2861 * @param {Object=} options |
| 2639 * @constructor | 2862 * @constructor |
| 2640 */ | 2863 */ |
| 2641 function Event(type, options) { | 2864 function Event(type, options) { |
| 2642 if (type instanceof OriginalEvent) | 2865 if (type instanceof OriginalEvent) |
| 2643 this.impl = type; | 2866 this.impl = type; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2698 var GenericEvent = function(type, options) { | 2921 var GenericEvent = function(type, options) { |
| 2699 if (type instanceof OriginalEvent) | 2922 if (type instanceof OriginalEvent) |
| 2700 this.impl = type; | 2923 this.impl = type; |
| 2701 else | 2924 else |
| 2702 return wrap(constructEvent(OriginalEvent, name, type, options)); | 2925 return wrap(constructEvent(OriginalEvent, name, type, options)); |
| 2703 }; | 2926 }; |
| 2704 GenericEvent.prototype = Object.create(SuperEvent.prototype); | 2927 GenericEvent.prototype = Object.create(SuperEvent.prototype); |
| 2705 if (prototype) | 2928 if (prototype) |
| 2706 mixin(GenericEvent.prototype, prototype); | 2929 mixin(GenericEvent.prototype, prototype); |
| 2707 if (OriginalEvent) { | 2930 if (OriginalEvent) { |
| 2708 // IE does not support event constructors but FocusEvent can only be | 2931 // - Old versions of Safari fails on new FocusEvent (and others?). |
| 2709 // created using new FocusEvent in Firefox. | 2932 // - IE does not support event constructors. |
| 2710 // https://bugzilla.mozilla.org/show_bug.cgi?id=882165 | 2933 // - createEvent('FocusEvent') throws in Firefox. |
| 2711 if (OriginalEvent.prototype['init' + name]) { | 2934 // => Try the best practice solution first and fallback to the old way |
| 2935 // if needed. |
| 2936 try { |
| 2937 registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp')); |
| 2938 } catch (ex) { |
| 2712 registerWrapper(OriginalEvent, GenericEvent, | 2939 registerWrapper(OriginalEvent, GenericEvent, |
| 2713 document.createEvent(name)); | 2940 document.createEvent(name)); |
| 2714 } else { | |
| 2715 registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp')); | |
| 2716 } | 2941 } |
| 2717 } | 2942 } |
| 2718 return GenericEvent; | 2943 return GenericEvent; |
| 2719 } | 2944 } |
| 2720 | 2945 |
| 2721 var UIEvent = registerGenericEvent('UIEvent', Event); | 2946 var UIEvent = registerGenericEvent('UIEvent', Event); |
| 2722 var CustomEvent = registerGenericEvent('CustomEvent', Event); | 2947 var CustomEvent = registerGenericEvent('CustomEvent', Event); |
| 2723 | 2948 |
| 2724 var relatedTargetProto = { | 2949 var relatedTargetProto = { |
| 2725 get relatedTarget() { | 2950 get relatedTarget() { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2746 var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto); | 2971 var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto); |
| 2747 var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto); | 2972 var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto); |
| 2748 | 2973 |
| 2749 // In case the browser does not support event constructors we polyfill that | 2974 // In case the browser does not support event constructors we polyfill that |
| 2750 // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to | 2975 // by calling `createEvent('Foo')` and `initFooEvent` where the arguments to |
| 2751 // `initFooEvent` are derived from the registered default event init dict. | 2976 // `initFooEvent` are derived from the registered default event init dict. |
| 2752 var defaultInitDicts = Object.create(null); | 2977 var defaultInitDicts = Object.create(null); |
| 2753 | 2978 |
| 2754 var supportsEventConstructors = (function() { | 2979 var supportsEventConstructors = (function() { |
| 2755 try { | 2980 try { |
| 2756 new window.MouseEvent('click'); | 2981 new window.FocusEvent('focus'); |
| 2757 } catch (ex) { | 2982 } catch (ex) { |
| 2758 return false; | 2983 return false; |
| 2759 } | 2984 } |
| 2760 return true; | 2985 return true; |
| 2761 })(); | 2986 })(); |
| 2762 | 2987 |
| 2763 /** | 2988 /** |
| 2764 * Constructs a new native event. | 2989 * Constructs a new native event. |
| 2765 */ | 2990 */ |
| 2766 function constructEvent(OriginalEvent, name, type, options) { | 2991 function constructEvent(OriginalEvent, name, type, options) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 } | 3142 } |
| 2918 } | 3143 } |
| 2919 } | 3144 } |
| 2920 | 3145 |
| 2921 if (found && count === 1) { | 3146 if (found && count === 1) { |
| 2922 var target = getTargetToListenAt(this); | 3147 var target = getTargetToListenAt(this); |
| 2923 target.removeEventListener_(type, dispatchOriginalEvent, true); | 3148 target.removeEventListener_(type, dispatchOriginalEvent, true); |
| 2924 } | 3149 } |
| 2925 }, | 3150 }, |
| 2926 dispatchEvent: function(event) { | 3151 dispatchEvent: function(event) { |
| 2927 var target = getTargetToListenAt(this); | 3152 // We want to use the native dispatchEvent because it triggers the default |
| 3153 // actions (like checking a checkbox). However, if there are no listeners |
| 3154 // in the composed tree then there are no events that will trigger and |
| 3155 // listeners in the non composed tree that are part of the event path are |
| 3156 // not notified. |
| 3157 // |
| 3158 // If we find out that there are no listeners in the composed tree we add |
| 3159 // a temporary listener to the target which makes us get called back even |
| 3160 // in that case. |
| 3161 |
| 2928 var nativeEvent = unwrap(event); | 3162 var nativeEvent = unwrap(event); |
| 3163 var eventType = nativeEvent.type; |
| 3164 |
| 2929 // Allow dispatching the same event again. This is safe because if user | 3165 // Allow dispatching the same event again. This is safe because if user |
| 2930 // code calls this during an existing dispatch of the same event the | 3166 // code calls this during an existing dispatch of the same event the |
| 2931 // native dispatchEvent throws (that is required by the spec). | 3167 // native dispatchEvent throws (that is required by the spec). |
| 2932 handledEventsTable.set(nativeEvent, false); | 3168 handledEventsTable.set(nativeEvent, false); |
| 2933 return target.dispatchEvent_(nativeEvent); | 3169 |
| 3170 // Force rendering since we prefer native dispatch and that works on the |
| 3171 // composed tree. |
| 3172 scope.renderAllPending(); |
| 3173 |
| 3174 var tempListener; |
| 3175 if (!hasListenerInAncestors(this, eventType)) { |
| 3176 tempListener = function() {}; |
| 3177 this.addEventListener(eventType, tempListener, true); |
| 3178 } |
| 3179 |
| 3180 try { |
| 3181 return unwrap(this).dispatchEvent_(nativeEvent); |
| 3182 } finally { |
| 3183 if (tempListener) |
| 3184 this.removeEventListener(eventType, tempListener, true); |
| 3185 } |
| 2934 } | 3186 } |
| 2935 }; | 3187 }; |
| 2936 | 3188 |
| 3189 function hasListener(node, type) { |
| 3190 var listeners = listenersTable.get(node); |
| 3191 if (listeners) { |
| 3192 for (var i = 0; i < listeners.length; i++) { |
| 3193 if (!listeners[i].removed && listeners[i].type === type) |
| 3194 return true; |
| 3195 } |
| 3196 } |
| 3197 return false; |
| 3198 } |
| 3199 |
| 3200 function hasListenerInAncestors(target, type) { |
| 3201 for (var node = unwrap(target); node; node = node.parentNode) { |
| 3202 if (hasListener(wrap(node), type)) |
| 3203 return true; |
| 3204 } |
| 3205 return false; |
| 3206 } |
| 3207 |
| 2937 if (OriginalEventTarget) | 3208 if (OriginalEventTarget) |
| 2938 registerWrapper(OriginalEventTarget, EventTarget); | 3209 registerWrapper(OriginalEventTarget, EventTarget); |
| 2939 | 3210 |
| 2940 function wrapEventTargetMethods(constructors) { | 3211 function wrapEventTargetMethods(constructors) { |
| 2941 forwardMethodsToWrapper(constructors, methodNames); | 3212 forwardMethodsToWrapper(constructors, methodNames); |
| 2942 } | 3213 } |
| 2943 | 3214 |
| 2944 var originalElementFromPoint = document.elementFromPoint; | 3215 var originalElementFromPoint = document.elementFromPoint; |
| 2945 | 3216 |
| 2946 function elementFromPoint(self, document, x, y) { | 3217 function elementFromPoint(self, document, x, y) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3074 // license that can be found in the LICENSE file. | 3345 // license that can be found in the LICENSE file. |
| 3075 | 3346 |
| 3076 (function(scope) { | 3347 (function(scope) { |
| 3077 'use strict'; | 3348 'use strict'; |
| 3078 | 3349 |
| 3079 var EventTarget = scope.wrappers.EventTarget; | 3350 var EventTarget = scope.wrappers.EventTarget; |
| 3080 var NodeList = scope.wrappers.NodeList; | 3351 var NodeList = scope.wrappers.NodeList; |
| 3081 var assert = scope.assert; | 3352 var assert = scope.assert; |
| 3082 var defineWrapGetter = scope.defineWrapGetter; | 3353 var defineWrapGetter = scope.defineWrapGetter; |
| 3083 var enqueueMutation = scope.enqueueMutation; | 3354 var enqueueMutation = scope.enqueueMutation; |
| 3355 var isWrapper = scope.isWrapper; |
| 3084 var mixin = scope.mixin; | 3356 var mixin = scope.mixin; |
| 3085 var registerTransientObservers = scope.registerTransientObservers; | 3357 var registerTransientObservers = scope.registerTransientObservers; |
| 3086 var registerWrapper = scope.registerWrapper; | 3358 var registerWrapper = scope.registerWrapper; |
| 3087 var unwrap = scope.unwrap; | 3359 var unwrap = scope.unwrap; |
| 3088 var wrap = scope.wrap; | 3360 var wrap = scope.wrap; |
| 3089 var wrapIfNeeded = scope.wrapIfNeeded; | 3361 var wrapIfNeeded = scope.wrapIfNeeded; |
| 3090 | 3362 |
| 3091 function assertIsNodeWrapper(node) { | 3363 function assertIsNodeWrapper(node) { |
| 3092 assert(node instanceof Node); | 3364 assert(node instanceof Node); |
| 3093 } | 3365 } |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3247 if (length === 1) | 3519 if (length === 1) |
| 3248 return unwrap(nodes[0]); | 3520 return unwrap(nodes[0]); |
| 3249 | 3521 |
| 3250 var df = unwrap(owner.ownerDocument.createDocumentFragment()); | 3522 var df = unwrap(owner.ownerDocument.createDocumentFragment()); |
| 3251 for (var i = 0; i < length; i++) { | 3523 for (var i = 0; i < length; i++) { |
| 3252 df.appendChild(unwrap(nodes[i])); | 3524 df.appendChild(unwrap(nodes[i])); |
| 3253 } | 3525 } |
| 3254 return df; | 3526 return df; |
| 3255 } | 3527 } |
| 3256 | 3528 |
| 3529 function clearChildNodes(wrapper) { |
| 3530 if (wrapper.firstChild_ !== undefined) { |
| 3531 var child = wrapper.firstChild_; |
| 3532 while (child) { |
| 3533 var tmp = child; |
| 3534 child = child.nextSibling_; |
| 3535 tmp.parentNode_ = tmp.previousSibling_ = tmp.nextSibling_ = undefined; |
| 3536 } |
| 3537 } |
| 3538 wrapper.firstChild_ = wrapper.lastChild_ = undefined; |
| 3539 } |
| 3540 |
| 3257 function removeAllChildNodes(wrapper) { | 3541 function removeAllChildNodes(wrapper) { |
| 3258 if (wrapper.invalidateShadowRenderer()) { | 3542 if (wrapper.invalidateShadowRenderer()) { |
| 3259 var childWrapper = wrapper.firstChild; | 3543 var childWrapper = wrapper.firstChild; |
| 3260 while (childWrapper) { | 3544 while (childWrapper) { |
| 3261 assert(childWrapper.parentNode === wrapper); | 3545 assert(childWrapper.parentNode === wrapper); |
| 3262 var nextSibling = childWrapper.nextSibling; | 3546 var nextSibling = childWrapper.nextSibling; |
| 3263 var childNode = unwrap(childWrapper); | 3547 var childNode = unwrap(childWrapper); |
| 3264 var parentNode = childNode.parentNode; | 3548 var parentNode = childNode.parentNode; |
| 3265 if (parentNode) | 3549 if (parentNode) |
| 3266 originalRemoveChild.call(parentNode, childNode); | 3550 originalRemoveChild.call(parentNode, childNode); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3325 * @type {Node|undefined} | 3609 * @type {Node|undefined} |
| 3326 * @private | 3610 * @private |
| 3327 */ | 3611 */ |
| 3328 this.nextSibling_ = undefined; | 3612 this.nextSibling_ = undefined; |
| 3329 | 3613 |
| 3330 /** | 3614 /** |
| 3331 * @type {Node|undefined} | 3615 * @type {Node|undefined} |
| 3332 * @private | 3616 * @private |
| 3333 */ | 3617 */ |
| 3334 this.previousSibling_ = undefined; | 3618 this.previousSibling_ = undefined; |
| 3335 }; | 3619 } |
| 3336 | 3620 |
| 3337 var OriginalDocumentFragment = window.DocumentFragment; | 3621 var OriginalDocumentFragment = window.DocumentFragment; |
| 3338 var originalAppendChild = OriginalNode.prototype.appendChild; | 3622 var originalAppendChild = OriginalNode.prototype.appendChild; |
| 3339 var originalCompareDocumentPosition = | 3623 var originalCompareDocumentPosition = |
| 3340 OriginalNode.prototype.compareDocumentPosition; | 3624 OriginalNode.prototype.compareDocumentPosition; |
| 3341 var originalInsertBefore = OriginalNode.prototype.insertBefore; | 3625 var originalInsertBefore = OriginalNode.prototype.insertBefore; |
| 3342 var originalRemoveChild = OriginalNode.prototype.removeChild; | 3626 var originalRemoveChild = OriginalNode.prototype.removeChild; |
| 3343 var originalReplaceChild = OriginalNode.prototype.replaceChild; | 3627 var originalReplaceChild = OriginalNode.prototype.replaceChild; |
| 3344 | 3628 |
| 3345 var isIe = /Trident/.test(navigator.userAgent); | 3629 var isIe = /Trident/.test(navigator.userAgent); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3359 | 3643 |
| 3360 Node.prototype = Object.create(EventTarget.prototype); | 3644 Node.prototype = Object.create(EventTarget.prototype); |
| 3361 mixin(Node.prototype, { | 3645 mixin(Node.prototype, { |
| 3362 appendChild: function(childWrapper) { | 3646 appendChild: function(childWrapper) { |
| 3363 return this.insertBefore(childWrapper, null); | 3647 return this.insertBefore(childWrapper, null); |
| 3364 }, | 3648 }, |
| 3365 | 3649 |
| 3366 insertBefore: function(childWrapper, refWrapper) { | 3650 insertBefore: function(childWrapper, refWrapper) { |
| 3367 assertIsNodeWrapper(childWrapper); | 3651 assertIsNodeWrapper(childWrapper); |
| 3368 | 3652 |
| 3369 refWrapper = refWrapper || null; | 3653 var refNode; |
| 3370 refWrapper && assertIsNodeWrapper(refWrapper); | 3654 if (refWrapper) { |
| 3655 if (isWrapper(refWrapper)) { |
| 3656 refNode = unwrap(refWrapper); |
| 3657 } else { |
| 3658 refNode = refWrapper; |
| 3659 refWrapper = wrap(refNode); |
| 3660 } |
| 3661 } else { |
| 3662 refWrapper = null; |
| 3663 refNode = null; |
| 3664 } |
| 3665 |
| 3371 refWrapper && assert(refWrapper.parentNode === this); | 3666 refWrapper && assert(refWrapper.parentNode === this); |
| 3372 | 3667 |
| 3373 var nodes; | 3668 var nodes; |
| 3374 var previousNode = | 3669 var previousNode = |
| 3375 refWrapper ? refWrapper.previousSibling : this.lastChild; | 3670 refWrapper ? refWrapper.previousSibling : this.lastChild; |
| 3376 | 3671 |
| 3377 var useNative = !this.invalidateShadowRenderer() && | 3672 var useNative = !this.invalidateShadowRenderer() && |
| 3378 !invalidateParent(childWrapper); | 3673 !invalidateParent(childWrapper); |
| 3379 | 3674 |
| 3380 if (useNative) | 3675 if (useNative) |
| 3381 nodes = collectNodesNative(childWrapper); | 3676 nodes = collectNodesNative(childWrapper); |
| 3382 else | 3677 else |
| 3383 nodes = collectNodes(childWrapper, this, previousNode, refWrapper); | 3678 nodes = collectNodes(childWrapper, this, previousNode, refWrapper); |
| 3384 | 3679 |
| 3385 if (useNative) { | 3680 if (useNative) { |
| 3386 ensureSameOwnerDocument(this, childWrapper); | 3681 ensureSameOwnerDocument(this, childWrapper); |
| 3387 originalInsertBefore.call(this.impl, unwrap(childWrapper), | 3682 clearChildNodes(this); |
| 3388 unwrap(refWrapper)); | 3683 originalInsertBefore.call(this.impl, unwrap(childWrapper), refNode); |
| 3389 } else { | 3684 } else { |
| 3390 if (!previousNode) | 3685 if (!previousNode) |
| 3391 this.firstChild_ = nodes[0]; | 3686 this.firstChild_ = nodes[0]; |
| 3392 if (!refWrapper) | 3687 if (!refWrapper) |
| 3393 this.lastChild_ = nodes[nodes.length - 1]; | 3688 this.lastChild_ = nodes[nodes.length - 1]; |
| 3394 | 3689 |
| 3395 var refNode = unwrap(refWrapper); | |
| 3396 var parentNode = refNode ? refNode.parentNode : this.impl; | 3690 var parentNode = refNode ? refNode.parentNode : this.impl; |
| 3397 | 3691 |
| 3398 // insertBefore refWrapper no matter what the parent is? | 3692 // insertBefore refWrapper no matter what the parent is? |
| 3399 if (parentNode) { | 3693 if (parentNode) { |
| 3400 originalInsertBefore.call(parentNode, | 3694 originalInsertBefore.call(parentNode, |
| 3401 unwrapNodesForInsertion(this, nodes), refNode); | 3695 unwrapNodesForInsertion(this, nodes), refNode); |
| 3402 } else { | 3696 } else { |
| 3403 adoptNodesIfNeeded(this, nodes); | 3697 adoptNodesIfNeeded(this, nodes); |
| 3404 } | 3698 } |
| 3405 } | 3699 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3456 if (childWrapperPreviousSibling) | 3750 if (childWrapperPreviousSibling) |
| 3457 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; | 3751 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; |
| 3458 if (childWrapperNextSibling) { | 3752 if (childWrapperNextSibling) { |
| 3459 childWrapperNextSibling.previousSibling_ = | 3753 childWrapperNextSibling.previousSibling_ = |
| 3460 childWrapperPreviousSibling; | 3754 childWrapperPreviousSibling; |
| 3461 } | 3755 } |
| 3462 | 3756 |
| 3463 childWrapper.previousSibling_ = childWrapper.nextSibling_ = | 3757 childWrapper.previousSibling_ = childWrapper.nextSibling_ = |
| 3464 childWrapper.parentNode_ = undefined; | 3758 childWrapper.parentNode_ = undefined; |
| 3465 } else { | 3759 } else { |
| 3760 clearChildNodes(this); |
| 3466 removeChildOriginalHelper(this.impl, childNode); | 3761 removeChildOriginalHelper(this.impl, childNode); |
| 3467 } | 3762 } |
| 3468 | 3763 |
| 3469 if (!surpressMutations) { | 3764 if (!surpressMutations) { |
| 3470 enqueueMutation(this, 'childList', { | 3765 enqueueMutation(this, 'childList', { |
| 3471 removedNodes: createOneElementNodeList(childWrapper), | 3766 removedNodes: createOneElementNodeList(childWrapper), |
| 3472 nextSibling: childWrapperNextSibling, | 3767 nextSibling: childWrapperNextSibling, |
| 3473 previousSibling: childWrapperPreviousSibling | 3768 previousSibling: childWrapperPreviousSibling |
| 3474 }); | 3769 }); |
| 3475 } | 3770 } |
| 3476 | 3771 |
| 3477 registerTransientObservers(this, childWrapper); | 3772 registerTransientObservers(this, childWrapper); |
| 3478 | 3773 |
| 3479 return childWrapper; | 3774 return childWrapper; |
| 3480 }, | 3775 }, |
| 3481 | 3776 |
| 3482 replaceChild: function(newChildWrapper, oldChildWrapper) { | 3777 replaceChild: function(newChildWrapper, oldChildWrapper) { |
| 3483 assertIsNodeWrapper(newChildWrapper); | 3778 assertIsNodeWrapper(newChildWrapper); |
| 3484 assertIsNodeWrapper(oldChildWrapper); | 3779 |
| 3780 var oldChildNode; |
| 3781 if (isWrapper(oldChildWrapper)) { |
| 3782 oldChildNode = unwrap(oldChildWrapper); |
| 3783 } else { |
| 3784 oldChildNode = oldChildWrapper; |
| 3785 oldChildWrapper = wrap(oldChildNode); |
| 3786 } |
| 3485 | 3787 |
| 3486 if (oldChildWrapper.parentNode !== this) { | 3788 if (oldChildWrapper.parentNode !== this) { |
| 3487 // TODO(arv): DOMException | 3789 // TODO(arv): DOMException |
| 3488 throw new Error('NotFoundError'); | 3790 throw new Error('NotFoundError'); |
| 3489 } | 3791 } |
| 3490 | 3792 |
| 3491 var oldChildNode = unwrap(oldChildWrapper); | |
| 3492 var nextNode = oldChildWrapper.nextSibling; | 3793 var nextNode = oldChildWrapper.nextSibling; |
| 3493 var previousNode = oldChildWrapper.previousSibling; | 3794 var previousNode = oldChildWrapper.previousSibling; |
| 3494 var nodes; | 3795 var nodes; |
| 3495 | 3796 |
| 3496 var useNative = !this.invalidateShadowRenderer() && | 3797 var useNative = !this.invalidateShadowRenderer() && |
| 3497 !invalidateParent(newChildWrapper); | 3798 !invalidateParent(newChildWrapper); |
| 3498 | 3799 |
| 3499 if (useNative) { | 3800 if (useNative) { |
| 3500 nodes = collectNodesNative(newChildWrapper); | 3801 nodes = collectNodesNative(newChildWrapper); |
| 3501 } else { | 3802 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3515 | 3816 |
| 3516 // replaceChild no matter what the parent is? | 3817 // replaceChild no matter what the parent is? |
| 3517 if (oldChildNode.parentNode) { | 3818 if (oldChildNode.parentNode) { |
| 3518 originalReplaceChild.call( | 3819 originalReplaceChild.call( |
| 3519 oldChildNode.parentNode, | 3820 oldChildNode.parentNode, |
| 3520 unwrapNodesForInsertion(this, nodes), | 3821 unwrapNodesForInsertion(this, nodes), |
| 3521 oldChildNode); | 3822 oldChildNode); |
| 3522 } | 3823 } |
| 3523 } else { | 3824 } else { |
| 3524 ensureSameOwnerDocument(this, newChildWrapper); | 3825 ensureSameOwnerDocument(this, newChildWrapper); |
| 3826 clearChildNodes(this); |
| 3525 originalReplaceChild.call(this.impl, unwrap(newChildWrapper), | 3827 originalReplaceChild.call(this.impl, unwrap(newChildWrapper), |
| 3526 oldChildNode); | 3828 oldChildNode); |
| 3527 } | 3829 } |
| 3528 | 3830 |
| 3529 enqueueMutation(this, 'childList', { | 3831 enqueueMutation(this, 'childList', { |
| 3530 addedNodes: nodes, | 3832 addedNodes: nodes, |
| 3531 removedNodes: createOneElementNodeList(oldChildWrapper), | 3833 removedNodes: createOneElementNodeList(oldChildWrapper), |
| 3532 nextSibling: nextNode, | 3834 nextSibling: nextNode, |
| 3533 previousSibling: previousNode | 3835 previousSibling: previousNode |
| 3534 }); | 3836 }); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3591 p = p.parentNode; | 3893 p = p.parentNode; |
| 3592 } | 3894 } |
| 3593 return p; | 3895 return p; |
| 3594 }, | 3896 }, |
| 3595 | 3897 |
| 3596 get textContent() { | 3898 get textContent() { |
| 3597 // TODO(arv): This should fallback to this.impl.textContent if there | 3899 // TODO(arv): This should fallback to this.impl.textContent if there |
| 3598 // are no shadow trees below or above the context node. | 3900 // are no shadow trees below or above the context node. |
| 3599 var s = ''; | 3901 var s = ''; |
| 3600 for (var child = this.firstChild; child; child = child.nextSibling) { | 3902 for (var child = this.firstChild; child; child = child.nextSibling) { |
| 3601 s += child.textContent; | 3903 if (child.nodeType != Node.COMMENT_NODE) { |
| 3904 s += child.textContent; |
| 3905 } |
| 3602 } | 3906 } |
| 3603 return s; | 3907 return s; |
| 3604 }, | 3908 }, |
| 3605 set textContent(textContent) { | 3909 set textContent(textContent) { |
| 3606 var removedNodes = snapshotNodeList(this.childNodes); | 3910 var removedNodes = snapshotNodeList(this.childNodes); |
| 3607 | 3911 |
| 3608 if (this.invalidateShadowRenderer()) { | 3912 if (this.invalidateShadowRenderer()) { |
| 3609 removeAllChildNodes(this); | 3913 removeAllChildNodes(this); |
| 3610 if (textContent !== '') { | 3914 if (textContent !== '') { |
| 3611 var textNode = this.impl.ownerDocument.createTextNode(textContent); | 3915 var textNode = this.impl.ownerDocument.createTextNode(textContent); |
| 3612 this.appendChild(textNode); | 3916 this.appendChild(textNode); |
| 3613 } | 3917 } |
| 3614 } else { | 3918 } else { |
| 3919 clearChildNodes(this); |
| 3615 this.impl.textContent = textContent; | 3920 this.impl.textContent = textContent; |
| 3616 } | 3921 } |
| 3617 | 3922 |
| 3618 var addedNodes = snapshotNodeList(this.childNodes); | 3923 var addedNodes = snapshotNodeList(this.childNodes); |
| 3619 | 3924 |
| 3620 enqueueMutation(this, 'childList', { | 3925 enqueueMutation(this, 'childList', { |
| 3621 addedNodes: addedNodes, | 3926 addedNodes: addedNodes, |
| 3622 removedNodes: removedNodes | 3927 removedNodes: removedNodes |
| 3623 }); | 3928 }); |
| 3624 | 3929 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3871 }); | 4176 }); |
| 3872 | 4177 |
| 3873 mixin(CharacterData.prototype, ChildNodeInterface); | 4178 mixin(CharacterData.prototype, ChildNodeInterface); |
| 3874 | 4179 |
| 3875 registerWrapper(OriginalCharacterData, CharacterData, | 4180 registerWrapper(OriginalCharacterData, CharacterData, |
| 3876 document.createTextNode('')); | 4181 document.createTextNode('')); |
| 3877 | 4182 |
| 3878 scope.wrappers.CharacterData = CharacterData; | 4183 scope.wrappers.CharacterData = CharacterData; |
| 3879 })(window.ShadowDOMPolyfill); | 4184 })(window.ShadowDOMPolyfill); |
| 3880 | 4185 |
| 4186 // Copyright 2014 The Polymer Authors. All rights reserved. |
| 4187 // Use of this source code is goverened by a BSD-style |
| 4188 // license that can be found in the LICENSE file. |
| 4189 |
| 4190 (function(scope) { |
| 4191 'use strict'; |
| 4192 |
| 4193 var CharacterData = scope.wrappers.CharacterData; |
| 4194 var enqueueMutation = scope.enqueueMutation; |
| 4195 var mixin = scope.mixin; |
| 4196 var registerWrapper = scope.registerWrapper; |
| 4197 |
| 4198 function toUInt32(x) { |
| 4199 return x >>> 0; |
| 4200 } |
| 4201 |
| 4202 var OriginalText = window.Text; |
| 4203 |
| 4204 function Text(node) { |
| 4205 CharacterData.call(this, node); |
| 4206 } |
| 4207 Text.prototype = Object.create(CharacterData.prototype); |
| 4208 mixin(Text.prototype, { |
| 4209 splitText: function(offset) { |
| 4210 offset = toUInt32(offset); |
| 4211 var s = this.data; |
| 4212 if (offset > s.length) |
| 4213 throw new Error('IndexSizeError'); |
| 4214 var head = s.slice(0, offset); |
| 4215 var tail = s.slice(offset); |
| 4216 this.data = head; |
| 4217 var newTextNode = this.ownerDocument.createTextNode(tail); |
| 4218 if (this.parentNode) |
| 4219 this.parentNode.insertBefore(newTextNode, this.nextSibling); |
| 4220 return newTextNode; |
| 4221 } |
| 4222 }); |
| 4223 |
| 4224 registerWrapper(OriginalText, Text, document.createTextNode('')); |
| 4225 |
| 4226 scope.wrappers.Text = Text; |
| 4227 })(window.ShadowDOMPolyfill); |
| 4228 |
| 3881 // Copyright 2013 The Polymer Authors. All rights reserved. | 4229 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3882 // Use of this source code is goverened by a BSD-style | 4230 // Use of this source code is goverened by a BSD-style |
| 3883 // license that can be found in the LICENSE file. | 4231 // license that can be found in the LICENSE file. |
| 3884 | 4232 |
| 3885 (function(scope) { | 4233 (function(scope) { |
| 3886 'use strict'; | 4234 'use strict'; |
| 3887 | 4235 |
| 3888 var ChildNodeInterface = scope.ChildNodeInterface; | 4236 var ChildNodeInterface = scope.ChildNodeInterface; |
| 3889 var GetElementsByInterface = scope.GetElementsByInterface; | 4237 var GetElementsByInterface = scope.GetElementsByInterface; |
| 3890 var Node = scope.wrappers.Node; | 4238 var Node = scope.wrappers.Node; |
| 3891 var ParentNodeInterface = scope.ParentNodeInterface; | 4239 var ParentNodeInterface = scope.ParentNodeInterface; |
| 3892 var SelectorsInterface = scope.SelectorsInterface; | 4240 var SelectorsInterface = scope.SelectorsInterface; |
| 3893 var addWrapNodeListMethod = scope.addWrapNodeListMethod; | 4241 var addWrapNodeListMethod = scope.addWrapNodeListMethod; |
| 3894 var enqueueMutation = scope.enqueueMutation; | 4242 var enqueueMutation = scope.enqueueMutation; |
| 3895 var mixin = scope.mixin; | 4243 var mixin = scope.mixin; |
| 3896 var oneOf = scope.oneOf; | 4244 var oneOf = scope.oneOf; |
| 3897 var registerWrapper = scope.registerWrapper; | 4245 var registerWrapper = scope.registerWrapper; |
| 3898 var wrappers = scope.wrappers; | 4246 var wrappers = scope.wrappers; |
| 3899 | 4247 |
| 3900 var OriginalElement = window.Element; | 4248 var OriginalElement = window.Element; |
| 3901 | 4249 |
| 3902 var matchesName = oneOf(OriginalElement.prototype, [ | 4250 var matchesNames = [ |
| 3903 'matches', | 4251 'matches', // needs to come first. |
| 3904 'mozMatchesSelector', | 4252 'mozMatchesSelector', |
| 3905 'msMatchesSelector', | 4253 'msMatchesSelector', |
| 3906 'webkitMatchesSelector', | 4254 'webkitMatchesSelector', |
| 3907 ]); | 4255 ].filter(function(name) { |
| 4256 return OriginalElement.prototype[name]; |
| 4257 }); |
| 4258 |
| 4259 var matchesName = matchesNames[0]; |
| 3908 | 4260 |
| 3909 var originalMatches = OriginalElement.prototype[matchesName]; | 4261 var originalMatches = OriginalElement.prototype[matchesName]; |
| 3910 | 4262 |
| 3911 function invalidateRendererBasedOnAttribute(element, name) { | 4263 function invalidateRendererBasedOnAttribute(element, name) { |
| 3912 // Only invalidate if parent node is a shadow host. | 4264 // Only invalidate if parent node is a shadow host. |
| 3913 var p = element.parentNode; | 4265 var p = element.parentNode; |
| 3914 if (!p || !p.shadowRoot) | 4266 if (!p || !p.shadowRoot) |
| 3915 return; | 4267 return; |
| 3916 | 4268 |
| 3917 var renderer = scope.getRendererForHost(p); | 4269 var renderer = scope.getRendererForHost(p); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3961 this.impl.removeAttribute(name); | 4313 this.impl.removeAttribute(name); |
| 3962 enqueAttributeChange(this, name, oldValue); | 4314 enqueAttributeChange(this, name, oldValue); |
| 3963 invalidateRendererBasedOnAttribute(this, name); | 4315 invalidateRendererBasedOnAttribute(this, name); |
| 3964 }, | 4316 }, |
| 3965 | 4317 |
| 3966 matches: function(selector) { | 4318 matches: function(selector) { |
| 3967 return originalMatches.call(this.impl, selector); | 4319 return originalMatches.call(this.impl, selector); |
| 3968 } | 4320 } |
| 3969 }); | 4321 }); |
| 3970 | 4322 |
| 3971 Element.prototype[matchesName] = function(selector) { | 4323 matchesNames.forEach(function(name) { |
| 3972 return this.matches(selector); | 4324 if (name !== 'matches') { |
| 3973 }; | 4325 Element.prototype[name] = function(selector) { |
| 4326 return this.matches(selector); |
| 4327 }; |
| 4328 } |
| 4329 }); |
| 3974 | 4330 |
| 3975 if (OriginalElement.prototype.webkitCreateShadowRoot) { | 4331 if (OriginalElement.prototype.webkitCreateShadowRoot) { |
| 3976 Element.prototype.webkitCreateShadowRoot = | 4332 Element.prototype.webkitCreateShadowRoot = |
| 3977 Element.prototype.createShadowRoot; | 4333 Element.prototype.createShadowRoot; |
| 3978 } | 4334 } |
| 3979 | 4335 |
| 3980 /** | 4336 /** |
| 3981 * Useful for generating the accessor pair for a property that reflects an | 4337 * Useful for generating the accessor pair for a property that reflects an |
| 3982 * attribute. | 4338 * attribute. |
| 3983 */ | 4339 */ |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3997 } | 4353 } |
| 3998 | 4354 |
| 3999 setterDirtiesAttribute(Element.prototype, 'id'); | 4355 setterDirtiesAttribute(Element.prototype, 'id'); |
| 4000 setterDirtiesAttribute(Element.prototype, 'className', 'class'); | 4356 setterDirtiesAttribute(Element.prototype, 'className', 'class'); |
| 4001 | 4357 |
| 4002 mixin(Element.prototype, ChildNodeInterface); | 4358 mixin(Element.prototype, ChildNodeInterface); |
| 4003 mixin(Element.prototype, GetElementsByInterface); | 4359 mixin(Element.prototype, GetElementsByInterface); |
| 4004 mixin(Element.prototype, ParentNodeInterface); | 4360 mixin(Element.prototype, ParentNodeInterface); |
| 4005 mixin(Element.prototype, SelectorsInterface); | 4361 mixin(Element.prototype, SelectorsInterface); |
| 4006 | 4362 |
| 4007 registerWrapper(OriginalElement, Element); | 4363 registerWrapper(OriginalElement, Element, |
| 4364 document.createElementNS(null, 'x')); |
| 4008 | 4365 |
| 4009 // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings | 4366 // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings |
| 4010 // that reflect attributes. | 4367 // that reflect attributes. |
| 4011 scope.matchesName = matchesName; | 4368 scope.matchesNames = matchesNames; |
| 4012 scope.wrappers.Element = Element; | 4369 scope.wrappers.Element = Element; |
| 4013 })(window.ShadowDOMPolyfill); | 4370 })(window.ShadowDOMPolyfill); |
| 4014 | 4371 |
| 4015 // Copyright 2013 The Polymer Authors. All rights reserved. | 4372 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 4016 // Use of this source code is goverened by a BSD-style | 4373 // Use of this source code is goverened by a BSD-style |
| 4017 // license that can be found in the LICENSE file. | 4374 // license that can be found in the LICENSE file. |
| 4018 | 4375 |
| 4019 (function(scope) { | 4376 (function(scope) { |
| 4020 'use strict'; | 4377 'use strict'; |
| 4021 | 4378 |
| 4022 var Element = scope.wrappers.Element; | 4379 var Element = scope.wrappers.Element; |
| 4023 var defineGetter = scope.defineGetter; | 4380 var defineGetter = scope.defineGetter; |
| 4024 var enqueueMutation = scope.enqueueMutation; | 4381 var enqueueMutation = scope.enqueueMutation; |
| 4025 var mixin = scope.mixin; | 4382 var mixin = scope.mixin; |
| 4026 var nodesWereAdded = scope.nodesWereAdded; | 4383 var nodesWereAdded = scope.nodesWereAdded; |
| 4027 var nodesWereRemoved = scope.nodesWereRemoved; | 4384 var nodesWereRemoved = scope.nodesWereRemoved; |
| 4028 var registerWrapper = scope.registerWrapper; | 4385 var registerWrapper = scope.registerWrapper; |
| 4029 var snapshotNodeList = scope.snapshotNodeList; | 4386 var snapshotNodeList = scope.snapshotNodeList; |
| 4030 var unwrap = scope.unwrap; | 4387 var unwrap = scope.unwrap; |
| 4031 var wrap = scope.wrap; | 4388 var wrap = scope.wrap; |
| 4032 | 4389 |
| 4033 ///////////////////////////////////////////////////////////////////////////// | 4390 ///////////////////////////////////////////////////////////////////////////// |
| 4034 // innerHTML and outerHTML | 4391 // innerHTML and outerHTML |
| 4035 | 4392 |
| 4036 var escapeRegExp = /&|<|"/g; | 4393 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#es
capingString |
| 4394 var escapeAttrRegExp = /[&\u00A0"]/g; |
| 4395 var escapeDataRegExp = /[&\u00A0<>]/g; |
| 4037 | 4396 |
| 4038 function escapeReplace(c) { | 4397 function escapeReplace(c) { |
| 4039 switch (c) { | 4398 switch (c) { |
| 4040 case '&': | 4399 case '&': |
| 4041 return '&'; | 4400 return '&'; |
| 4042 case '<': | 4401 case '<': |
| 4043 return '<'; | 4402 return '<'; |
| 4403 case '>': |
| 4404 return '>'; |
| 4044 case '"': | 4405 case '"': |
| 4045 return '"' | 4406 return '"' |
| 4407 case '\u00A0': |
| 4408 return ' '; |
| 4046 } | 4409 } |
| 4047 } | 4410 } |
| 4048 | 4411 |
| 4049 function escape(s) { | 4412 function escapeAttr(s) { |
| 4050 return s.replace(escapeRegExp, escapeReplace); | 4413 return s.replace(escapeAttrRegExp, escapeReplace); |
| 4414 } |
| 4415 |
| 4416 function escapeData(s) { |
| 4417 return s.replace(escapeDataRegExp, escapeReplace); |
| 4418 } |
| 4419 |
| 4420 function makeSet(arr) { |
| 4421 var set = {}; |
| 4422 for (var i = 0; i < arr.length; i++) { |
| 4423 set[arr[i]] = true; |
| 4424 } |
| 4425 return set; |
| 4051 } | 4426 } |
| 4052 | 4427 |
| 4053 // http://www.whatwg.org/specs/web-apps/current-work/#void-elements | 4428 // http://www.whatwg.org/specs/web-apps/current-work/#void-elements |
| 4054 var voidElements = { | 4429 var voidElements = makeSet([ |
| 4055 'area': true, | 4430 'area', |
| 4056 'base': true, | 4431 'base', |
| 4057 'br': true, | 4432 'br', |
| 4058 'col': true, | 4433 'col', |
| 4059 'command': true, | 4434 'command', |
| 4060 'embed': true, | 4435 'embed', |
| 4061 'hr': true, | 4436 'hr', |
| 4062 'img': true, | 4437 'img', |
| 4063 'input': true, | 4438 'input', |
| 4064 'keygen': true, | 4439 'keygen', |
| 4065 'link': true, | 4440 'link', |
| 4066 'meta': true, | 4441 'meta', |
| 4067 'param': true, | 4442 'param', |
| 4068 'source': true, | 4443 'source', |
| 4069 'track': true, | 4444 'track', |
| 4070 'wbr': true | 4445 'wbr' |
| 4071 }; | 4446 ]); |
| 4072 | 4447 |
| 4073 function getOuterHTML(node) { | 4448 var plaintextParents = makeSet([ |
| 4449 'style', |
| 4450 'script', |
| 4451 'xmp', |
| 4452 'iframe', |
| 4453 'noembed', |
| 4454 'noframes', |
| 4455 'plaintext', |
| 4456 'noscript' |
| 4457 ]); |
| 4458 |
| 4459 function getOuterHTML(node, parentNode) { |
| 4074 switch (node.nodeType) { | 4460 switch (node.nodeType) { |
| 4075 case Node.ELEMENT_NODE: | 4461 case Node.ELEMENT_NODE: |
| 4076 var tagName = node.tagName.toLowerCase(); | 4462 var tagName = node.tagName.toLowerCase(); |
| 4077 var s = '<' + tagName; | 4463 var s = '<' + tagName; |
| 4078 var attrs = node.attributes; | 4464 var attrs = node.attributes; |
| 4079 for (var i = 0, attr; attr = attrs[i]; i++) { | 4465 for (var i = 0, attr; attr = attrs[i]; i++) { |
| 4080 s += ' ' + attr.name + '="' + escape(attr.value) + '"'; | 4466 s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"'; |
| 4081 } | 4467 } |
| 4082 s += '>'; | 4468 s += '>'; |
| 4083 if (voidElements[tagName]) | 4469 if (voidElements[tagName]) |
| 4084 return s; | 4470 return s; |
| 4085 | 4471 |
| 4086 return s + getInnerHTML(node) + '</' + tagName + '>'; | 4472 return s + getInnerHTML(node) + '</' + tagName + '>'; |
| 4087 | 4473 |
| 4088 case Node.TEXT_NODE: | 4474 case Node.TEXT_NODE: |
| 4089 return escape(node.nodeValue); | 4475 var data = node.data; |
| 4476 if (parentNode && plaintextParents[parentNode.localName]) |
| 4477 return data; |
| 4478 return escapeData(data); |
| 4090 | 4479 |
| 4091 case Node.COMMENT_NODE: | 4480 case Node.COMMENT_NODE: |
| 4092 return '<!--' + escape(node.nodeValue) + '-->'; | 4481 return '<!--' + node.data + '-->'; |
| 4482 |
| 4093 default: | 4483 default: |
| 4094 console.error(node); | 4484 console.error(node); |
| 4095 throw new Error('not implemented'); | 4485 throw new Error('not implemented'); |
| 4096 } | 4486 } |
| 4097 } | 4487 } |
| 4098 | 4488 |
| 4099 function getInnerHTML(node) { | 4489 function getInnerHTML(node) { |
| 4100 var s = ''; | 4490 var s = ''; |
| 4101 for (var child = node.firstChild; child; child = child.nextSibling) { | 4491 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 4102 s += getOuterHTML(child); | 4492 s += getOuterHTML(child, node); |
| 4103 } | 4493 } |
| 4104 return s; | 4494 return s; |
| 4105 } | 4495 } |
| 4106 | 4496 |
| 4107 function setInnerHTML(node, value, opt_tagName) { | 4497 function setInnerHTML(node, value, opt_tagName) { |
| 4108 var tagName = opt_tagName || 'div'; | 4498 var tagName = opt_tagName || 'div'; |
| 4109 node.textContent = ''; | 4499 node.textContent = ''; |
| 4110 var tempElement = unwrap(node.ownerDocument.createElement(tagName)); | 4500 var tempElement = unwrap(node.ownerDocument.createElement(tagName)); |
| 4111 tempElement.innerHTML = value; | 4501 tempElement.innerHTML = value; |
| 4112 var firstChild; | 4502 var firstChild; |
| 4113 while (firstChild = tempElement.firstChild) { | 4503 while (firstChild = tempElement.firstChild) { |
| 4114 node.appendChild(wrap(firstChild)); | 4504 node.appendChild(wrap(firstChild)); |
| 4115 } | 4505 } |
| 4116 } | 4506 } |
| 4117 | 4507 |
| 4508 // IE11 does not have MSIE in the user agent string. |
| 4509 var oldIe = /MSIE/.test(navigator.userAgent); |
| 4510 |
| 4118 var OriginalHTMLElement = window.HTMLElement; | 4511 var OriginalHTMLElement = window.HTMLElement; |
| 4119 | 4512 |
| 4120 function HTMLElement(node) { | 4513 function HTMLElement(node) { |
| 4121 Element.call(this, node); | 4514 Element.call(this, node); |
| 4122 } | 4515 } |
| 4123 HTMLElement.prototype = Object.create(Element.prototype); | 4516 HTMLElement.prototype = Object.create(Element.prototype); |
| 4124 mixin(HTMLElement.prototype, { | 4517 mixin(HTMLElement.prototype, { |
| 4125 get innerHTML() { | 4518 get innerHTML() { |
| 4126 // TODO(arv): This should fallback to this.impl.innerHTML if there | 4519 // TODO(arv): This should fallback to this.impl.innerHTML if there |
| 4127 // are no shadow trees below or above the context node. | 4520 // are no shadow trees below or above the context node. |
| 4128 return getInnerHTML(this); | 4521 return getInnerHTML(this); |
| 4129 }, | 4522 }, |
| 4130 set innerHTML(value) { | 4523 set innerHTML(value) { |
| 4524 // IE9 does not handle set innerHTML correctly on plaintextParents. It |
| 4525 // creates element children. For example |
| 4526 // |
| 4527 // scriptElement.innerHTML = '<a>test</a>' |
| 4528 // |
| 4529 // Creates a single HTMLAnchorElement child. |
| 4530 if (oldIe && plaintextParents[this.localName]) { |
| 4531 this.textContent = value; |
| 4532 return; |
| 4533 } |
| 4534 |
| 4131 var removedNodes = snapshotNodeList(this.childNodes); | 4535 var removedNodes = snapshotNodeList(this.childNodes); |
| 4132 | 4536 |
| 4133 if (this.invalidateShadowRenderer()) | 4537 if (this.invalidateShadowRenderer()) |
| 4134 setInnerHTML(this, value, this.tagName); | 4538 setInnerHTML(this, value, this.tagName); |
| 4135 else | 4539 else |
| 4136 this.impl.innerHTML = value; | 4540 this.impl.innerHTML = value; |
| 4137 var addedNodes = snapshotNodeList(this.childNodes); | 4541 var addedNodes = snapshotNodeList(this.childNodes); |
| 4138 | 4542 |
| 4139 enqueueMutation(this, 'childList', { | 4543 enqueueMutation(this, 'childList', { |
| 4140 addedNodes: addedNodes, | 4544 addedNodes: addedNodes, |
| 4141 removedNodes: removedNodes | 4545 removedNodes: removedNodes |
| 4142 }); | 4546 }); |
| 4143 | 4547 |
| 4144 nodesWereRemoved(removedNodes); | 4548 nodesWereRemoved(removedNodes); |
| 4145 nodesWereAdded(addedNodes); | 4549 nodesWereAdded(addedNodes); |
| 4146 }, | 4550 }, |
| 4147 | 4551 |
| 4148 get outerHTML() { | 4552 get outerHTML() { |
| 4149 // TODO(arv): This should fallback to HTMLElement_prototype.outerHTML if t
here | 4553 return getOuterHTML(this, this.parentNode); |
| 4150 // are no shadow trees below or above the context node. | |
| 4151 return getOuterHTML(this); | |
| 4152 }, | 4554 }, |
| 4153 set outerHTML(value) { | 4555 set outerHTML(value) { |
| 4154 var p = this.parentNode; | 4556 var p = this.parentNode; |
| 4155 if (p) { | 4557 if (p) { |
| 4156 p.invalidateShadowRenderer(); | 4558 p.invalidateShadowRenderer(); |
| 4157 this.impl.outerHTML = value; | 4559 var df = frag(p, value); |
| 4560 p.replaceChild(df, this); |
| 4158 } | 4561 } |
| 4562 }, |
| 4563 |
| 4564 insertAdjacentHTML: function(position, text) { |
| 4565 var contextElement, refNode; |
| 4566 switch (String(position).toLowerCase()) { |
| 4567 case 'beforebegin': |
| 4568 contextElement = this.parentNode; |
| 4569 refNode = this; |
| 4570 break; |
| 4571 case 'afterend': |
| 4572 contextElement = this.parentNode; |
| 4573 refNode = this.nextSibling; |
| 4574 break; |
| 4575 case 'afterbegin': |
| 4576 contextElement = this; |
| 4577 refNode = this.firstChild; |
| 4578 break; |
| 4579 case 'beforeend': |
| 4580 contextElement = this; |
| 4581 refNode = null; |
| 4582 break; |
| 4583 default: |
| 4584 return; |
| 4585 } |
| 4586 |
| 4587 var df = frag(contextElement, text); |
| 4588 contextElement.insertBefore(df, refNode); |
| 4159 } | 4589 } |
| 4160 }); | 4590 }); |
| 4161 | 4591 |
| 4592 function frag(contextElement, html) { |
| 4593 // TODO(arv): This does not work with SVG and other non HTML elements. |
| 4594 var p = unwrap(contextElement.cloneNode(false)); |
| 4595 p.innerHTML = html; |
| 4596 var df = unwrap(document.createDocumentFragment()); |
| 4597 var c; |
| 4598 while (c = p.firstChild) { |
| 4599 df.appendChild(c); |
| 4600 } |
| 4601 return wrap(df); |
| 4602 } |
| 4603 |
| 4162 function getter(name) { | 4604 function getter(name) { |
| 4163 return function() { | 4605 return function() { |
| 4164 scope.renderAllPending(); | 4606 scope.renderAllPending(); |
| 4165 return this.impl[name]; | 4607 return this.impl[name]; |
| 4166 }; | 4608 }; |
| 4167 } | 4609 } |
| 4168 | 4610 |
| 4169 function getterRequiresRendering(name) { | 4611 function getterRequiresRendering(name) { |
| 4170 defineGetter(HTMLElement, name, getter(name)); | 4612 defineGetter(HTMLElement, name, getter(name)); |
| 4171 } | 4613 } |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4609 case 'template': | 5051 case 'template': |
| 4610 return new HTMLTemplateElement(node); | 5052 return new HTMLTemplateElement(node); |
| 4611 } | 5053 } |
| 4612 HTMLElement.call(this, node); | 5054 HTMLElement.call(this, node); |
| 4613 } | 5055 } |
| 4614 HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype); | 5056 HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype); |
| 4615 registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement); | 5057 registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement); |
| 4616 scope.wrappers.HTMLUnknownElement = HTMLUnknownElement; | 5058 scope.wrappers.HTMLUnknownElement = HTMLUnknownElement; |
| 4617 })(window.ShadowDOMPolyfill); | 5059 })(window.ShadowDOMPolyfill); |
| 4618 | 5060 |
| 5061 // Copyright 2014 The Polymer Authors. All rights reserved. |
| 5062 // Use of this source code is goverened by a BSD-style |
| 5063 // license that can be found in the LICENSE file. |
| 5064 |
| 5065 (function(scope) { |
| 5066 'use strict'; |
| 5067 |
| 5068 var registerObject = scope.registerObject; |
| 5069 |
| 5070 var SVG_NS = 'http://www.w3.org/2000/svg'; |
| 5071 var svgTitleElement = document.createElementNS(SVG_NS, 'title'); |
| 5072 var SVGTitleElement = registerObject(svgTitleElement); |
| 5073 var SVGElement = Object.getPrototypeOf(SVGTitleElement.prototype).constructor; |
| 5074 |
| 5075 scope.wrappers.SVGElement = SVGElement; |
| 5076 })(window.ShadowDOMPolyfill); |
| 5077 |
| 5078 // Copyright 2014 The Polymer Authors. All rights reserved. |
| 5079 // Use of this source code is goverened by a BSD-style |
| 5080 // license that can be found in the LICENSE file. |
| 5081 |
| 5082 (function(scope) { |
| 5083 'use strict'; |
| 5084 |
| 5085 var mixin = scope.mixin; |
| 5086 var registerWrapper = scope.registerWrapper; |
| 5087 var unwrap = scope.unwrap; |
| 5088 var wrap = scope.wrap; |
| 5089 |
| 5090 var OriginalSVGUseElement = window.SVGUseElement; |
| 5091 |
| 5092 // IE uses SVGElement as parent interface, SVG2 (Blink & Gecko) uses |
| 5093 // SVGGraphicsElement. Use the <g> element to get the right prototype. |
| 5094 |
| 5095 var SVG_NS = 'http://www.w3.org/2000/svg'; |
| 5096 var gWrapper = wrap(document.createElementNS(SVG_NS, 'g')); |
| 5097 var useElement = document.createElementNS(SVG_NS, 'use'); |
| 5098 var SVGGElement = gWrapper.constructor; |
| 5099 var parentInterfacePrototype = Object.getPrototypeOf(SVGGElement.prototype); |
| 5100 var parentInterface = parentInterfacePrototype.constructor; |
| 5101 |
| 5102 function SVGUseElement(impl) { |
| 5103 parentInterface.call(this, impl); |
| 5104 } |
| 5105 |
| 5106 SVGUseElement.prototype = Object.create(parentInterfacePrototype); |
| 5107 |
| 5108 // Firefox does not expose instanceRoot. |
| 5109 if ('instanceRoot' in useElement) { |
| 5110 mixin(SVGUseElement.prototype, { |
| 5111 get instanceRoot() { |
| 5112 return wrap(unwrap(this).instanceRoot); |
| 5113 }, |
| 5114 get animatedInstanceRoot() { |
| 5115 return wrap(unwrap(this).animatedInstanceRoot); |
| 5116 }, |
| 5117 }); |
| 5118 } |
| 5119 |
| 5120 registerWrapper(OriginalSVGUseElement, SVGUseElement, useElement); |
| 5121 |
| 5122 scope.wrappers.SVGUseElement = SVGUseElement; |
| 5123 })(window.ShadowDOMPolyfill); |
| 5124 |
| 5125 // Copyright 2014 The Polymer Authors. All rights reserved. |
| 5126 // Use of this source code is goverened by a BSD-style |
| 5127 // license that can be found in the LICENSE file. |
| 5128 |
| 5129 (function(scope) { |
| 5130 'use strict'; |
| 5131 |
| 5132 var EventTarget = scope.wrappers.EventTarget; |
| 5133 var mixin = scope.mixin; |
| 5134 var registerWrapper = scope.registerWrapper; |
| 5135 var wrap = scope.wrap; |
| 5136 |
| 5137 var OriginalSVGElementInstance = window.SVGElementInstance; |
| 5138 if (!OriginalSVGElementInstance) |
| 5139 return; |
| 5140 |
| 5141 function SVGElementInstance(impl) { |
| 5142 EventTarget.call(this, impl); |
| 5143 } |
| 5144 |
| 5145 SVGElementInstance.prototype = Object.create(EventTarget.prototype); |
| 5146 mixin(SVGElementInstance.prototype, { |
| 5147 /** @type {SVGElement} */ |
| 5148 get correspondingElement() { |
| 5149 return wrap(this.impl.correspondingElement); |
| 5150 }, |
| 5151 |
| 5152 /** @type {SVGUseElement} */ |
| 5153 get correspondingUseElement() { |
| 5154 return wrap(this.impl.correspondingUseElement); |
| 5155 }, |
| 5156 |
| 5157 /** @type {SVGElementInstance} */ |
| 5158 get parentNode() { |
| 5159 return wrap(this.impl.parentNode); |
| 5160 }, |
| 5161 |
| 5162 /** @type {SVGElementInstanceList} */ |
| 5163 get childNodes() { |
| 5164 throw new Error('Not implemented'); |
| 5165 }, |
| 5166 |
| 5167 /** @type {SVGElementInstance} */ |
| 5168 get firstChild() { |
| 5169 return wrap(this.impl.firstChild); |
| 5170 }, |
| 5171 |
| 5172 /** @type {SVGElementInstance} */ |
| 5173 get lastChild() { |
| 5174 return wrap(this.impl.lastChild); |
| 5175 }, |
| 5176 |
| 5177 /** @type {SVGElementInstance} */ |
| 5178 get previousSibling() { |
| 5179 return wrap(this.impl.previousSibling); |
| 5180 }, |
| 5181 |
| 5182 /** @type {SVGElementInstance} */ |
| 5183 get nextSibling() { |
| 5184 return wrap(this.impl.nextSibling); |
| 5185 } |
| 5186 }); |
| 5187 |
| 5188 registerWrapper(OriginalSVGElementInstance, SVGElementInstance); |
| 5189 |
| 5190 scope.wrappers.SVGElementInstance = SVGElementInstance; |
| 5191 })(window.ShadowDOMPolyfill); |
| 5192 |
| 4619 // Copyright 2013 The Polymer Authors. All rights reserved. | 5193 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 4620 // Use of this source code is goverened by a BSD-style | 5194 // Use of this source code is goverened by a BSD-style |
| 4621 // license that can be found in the LICENSE file. | 5195 // license that can be found in the LICENSE file. |
| 4622 | 5196 |
| 4623 (function(scope) { | 5197 (function(scope) { |
| 4624 'use strict'; | 5198 'use strict'; |
| 4625 | 5199 |
| 4626 var mixin = scope.mixin; | 5200 var mixin = scope.mixin; |
| 4627 var registerWrapper = scope.registerWrapper; | 5201 var registerWrapper = scope.registerWrapper; |
| 4628 var unwrap = scope.unwrap; | 5202 var unwrap = scope.unwrap; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4778 return wrap(this.impl.cloneRange()); | 5352 return wrap(this.impl.cloneRange()); |
| 4779 }, | 5353 }, |
| 4780 isPointInRange: function(node, offset) { | 5354 isPointInRange: function(node, offset) { |
| 4781 return this.impl.isPointInRange(unwrapIfNeeded(node), offset); | 5355 return this.impl.isPointInRange(unwrapIfNeeded(node), offset); |
| 4782 }, | 5356 }, |
| 4783 comparePoint: function(node, offset) { | 5357 comparePoint: function(node, offset) { |
| 4784 return this.impl.comparePoint(unwrapIfNeeded(node), offset); | 5358 return this.impl.comparePoint(unwrapIfNeeded(node), offset); |
| 4785 }, | 5359 }, |
| 4786 intersectsNode: function(node) { | 5360 intersectsNode: function(node) { |
| 4787 return this.impl.intersectsNode(unwrapIfNeeded(node)); | 5361 return this.impl.intersectsNode(unwrapIfNeeded(node)); |
| 5362 }, |
| 5363 toString: function() { |
| 5364 return this.impl.toString(); |
| 4788 } | 5365 } |
| 4789 }; | 5366 }; |
| 4790 | 5367 |
| 4791 // IE9 does not have createContextualFragment. | 5368 // IE9 does not have createContextualFragment. |
| 4792 if (OriginalRange.prototype.createContextualFragment) { | 5369 if (OriginalRange.prototype.createContextualFragment) { |
| 4793 Range.prototype.createContextualFragment = function(html) { | 5370 Range.prototype.createContextualFragment = function(html) { |
| 4794 return wrap(this.impl.createContextualFragment(html)); | 5371 return wrap(this.impl.createContextualFragment(html)); |
| 4795 }; | 5372 }; |
| 4796 } | 5373 } |
| 4797 | 5374 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4812 var ParentNodeInterface = scope.ParentNodeInterface; | 5389 var ParentNodeInterface = scope.ParentNodeInterface; |
| 4813 var SelectorsInterface = scope.SelectorsInterface; | 5390 var SelectorsInterface = scope.SelectorsInterface; |
| 4814 var mixin = scope.mixin; | 5391 var mixin = scope.mixin; |
| 4815 var registerObject = scope.registerObject; | 5392 var registerObject = scope.registerObject; |
| 4816 | 5393 |
| 4817 var DocumentFragment = registerObject(document.createDocumentFragment()); | 5394 var DocumentFragment = registerObject(document.createDocumentFragment()); |
| 4818 mixin(DocumentFragment.prototype, ParentNodeInterface); | 5395 mixin(DocumentFragment.prototype, ParentNodeInterface); |
| 4819 mixin(DocumentFragment.prototype, SelectorsInterface); | 5396 mixin(DocumentFragment.prototype, SelectorsInterface); |
| 4820 mixin(DocumentFragment.prototype, GetElementsByInterface); | 5397 mixin(DocumentFragment.prototype, GetElementsByInterface); |
| 4821 | 5398 |
| 4822 var Text = registerObject(document.createTextNode('')); | |
| 4823 var Comment = registerObject(document.createComment('')); | 5399 var Comment = registerObject(document.createComment('')); |
| 4824 | 5400 |
| 4825 scope.wrappers.Comment = Comment; | 5401 scope.wrappers.Comment = Comment; |
| 4826 scope.wrappers.DocumentFragment = DocumentFragment; | 5402 scope.wrappers.DocumentFragment = DocumentFragment; |
| 4827 scope.wrappers.Text = Text; | |
| 4828 | 5403 |
| 4829 })(window.ShadowDOMPolyfill); | 5404 })(window.ShadowDOMPolyfill); |
| 4830 | 5405 |
| 4831 // Copyright 2013 The Polymer Authors. All rights reserved. | 5406 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 4832 // Use of this source code is goverened by a BSD-style | 5407 // Use of this source code is goverened by a BSD-style |
| 4833 // license that can be found in the LICENSE file. | 5408 // license that can be found in the LICENSE file. |
| 4834 | 5409 |
| 4835 (function(scope) { | 5410 (function(scope) { |
| 4836 'use strict'; | 5411 'use strict'; |
| 4837 | 5412 |
| 4838 var DocumentFragment = scope.wrappers.DocumentFragment; | 5413 var DocumentFragment = scope.wrappers.DocumentFragment; |
| 4839 var elementFromPoint = scope.elementFromPoint; | 5414 var elementFromPoint = scope.elementFromPoint; |
| 4840 var getInnerHTML = scope.getInnerHTML; | 5415 var getInnerHTML = scope.getInnerHTML; |
| 4841 var mixin = scope.mixin; | 5416 var mixin = scope.mixin; |
| 4842 var rewrap = scope.rewrap; | 5417 var rewrap = scope.rewrap; |
| 4843 var setInnerHTML = scope.setInnerHTML; | 5418 var setInnerHTML = scope.setInnerHTML; |
| 4844 var unwrap = scope.unwrap; | 5419 var unwrap = scope.unwrap; |
| 4845 | 5420 |
| 4846 var shadowHostTable = new WeakMap(); | 5421 var shadowHostTable = new WeakMap(); |
| 4847 var nextOlderShadowTreeTable = new WeakMap(); | 5422 var nextOlderShadowTreeTable = new WeakMap(); |
| 4848 | 5423 |
| 5424 var spaceCharRe = /[ \t\n\r\f]/; |
| 5425 |
| 4849 function ShadowRoot(hostWrapper) { | 5426 function ShadowRoot(hostWrapper) { |
| 4850 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); | 5427 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); |
| 4851 DocumentFragment.call(this, node); | 5428 DocumentFragment.call(this, node); |
| 4852 | 5429 |
| 4853 // createDocumentFragment associates the node with a wrapper | 5430 // createDocumentFragment associates the node with a wrapper |
| 4854 // DocumentFragment instance. Override that. | 5431 // DocumentFragment instance. Override that. |
| 4855 rewrap(node, this); | 5432 rewrap(node, this); |
| 4856 | 5433 |
| 4857 var oldShadowRoot = hostWrapper.shadowRoot; | 5434 var oldShadowRoot = hostWrapper.shadowRoot; |
| 4858 nextOlderShadowTreeTable.set(this, oldShadowRoot); | 5435 nextOlderShadowTreeTable.set(this, oldShadowRoot); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4879 | 5456 |
| 4880 invalidateShadowRenderer: function() { | 5457 invalidateShadowRenderer: function() { |
| 4881 return shadowHostTable.get(this).invalidateShadowRenderer(); | 5458 return shadowHostTable.get(this).invalidateShadowRenderer(); |
| 4882 }, | 5459 }, |
| 4883 | 5460 |
| 4884 elementFromPoint: function(x, y) { | 5461 elementFromPoint: function(x, y) { |
| 4885 return elementFromPoint(this, this.ownerDocument, x, y); | 5462 return elementFromPoint(this, this.ownerDocument, x, y); |
| 4886 }, | 5463 }, |
| 4887 | 5464 |
| 4888 getElementById: function(id) { | 5465 getElementById: function(id) { |
| 4889 return this.querySelector('#' + id); | 5466 if (spaceCharRe.test(id)) |
| 5467 return null; |
| 5468 return this.querySelector('[id="' + id + '"]'); |
| 4890 } | 5469 } |
| 4891 }); | 5470 }); |
| 4892 | 5471 |
| 4893 scope.wrappers.ShadowRoot = ShadowRoot; | 5472 scope.wrappers.ShadowRoot = ShadowRoot; |
| 4894 | 5473 |
| 4895 })(window.ShadowDOMPolyfill); | 5474 })(window.ShadowDOMPolyfill); |
| 4896 | 5475 |
| 4897 // Copyright 2013 The Polymer Authors. All rights reserved. | 5476 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 4898 // Use of this source code is governed by a BSD-style | 5477 // Use of this source code is governed by a BSD-style |
| 4899 // license that can be found in the LICENSE file. | 5478 // license that can be found in the LICENSE file. |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5079 return true; | 5658 return true; |
| 5080 | 5659 |
| 5081 // Here we know the select attribute is a non empty string. | 5660 // Here we know the select attribute is a non empty string. |
| 5082 select = select.trim(); | 5661 select = select.trim(); |
| 5083 if (!select) | 5662 if (!select) |
| 5084 return true; | 5663 return true; |
| 5085 | 5664 |
| 5086 if (!(node instanceof Element)) | 5665 if (!(node instanceof Element)) |
| 5087 return false; | 5666 return false; |
| 5088 | 5667 |
| 5668 // The native matches function in IE9 does not correctly work with elements |
| 5669 // that are not in the document. |
| 5670 // TODO(arv): Implement matching in JS. |
| 5671 // https://github.com/Polymer/ShadowDOM/issues/361 |
| 5672 if (select === '*' || select === node.localName) |
| 5673 return true; |
| 5674 |
| 5089 // TODO(arv): This does not seem right. Need to check for a simple selector. | 5675 // TODO(arv): This does not seem right. Need to check for a simple selector. |
| 5090 if (!selectorMatchRegExp.test(select)) | 5676 if (!selectorMatchRegExp.test(select)) |
| 5091 return false; | 5677 return false; |
| 5092 | 5678 |
| 5679 // TODO(arv): This no longer matches the spec. |
| 5093 if (select[0] === ':' && !allowedPseudoRegExp.test(select)) | 5680 if (select[0] === ':' && !allowedPseudoRegExp.test(select)) |
| 5094 return false; | 5681 return false; |
| 5095 | 5682 |
| 5096 try { | 5683 try { |
| 5097 return node.matches(select); | 5684 return node.matches(select); |
| 5098 } catch (ex) { | 5685 } catch (ex) { |
| 5099 // Invalid selector. | 5686 // Invalid selector. |
| 5100 return false; | 5687 return false; |
| 5101 } | 5688 } |
| 5102 } | 5689 } |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5599 | 6186 |
| 5600 registerWrapper(window[name], GeneratedWrapper, | 6187 registerWrapper(window[name], GeneratedWrapper, |
| 5601 document.createElement(name.slice(4, -7))); | 6188 document.createElement(name.slice(4, -7))); |
| 5602 scope.wrappers[name] = GeneratedWrapper; | 6189 scope.wrappers[name] = GeneratedWrapper; |
| 5603 } | 6190 } |
| 5604 | 6191 |
| 5605 elementsWithFormProperty.forEach(createWrapperConstructor); | 6192 elementsWithFormProperty.forEach(createWrapperConstructor); |
| 5606 | 6193 |
| 5607 })(window.ShadowDOMPolyfill); | 6194 })(window.ShadowDOMPolyfill); |
| 5608 | 6195 |
| 6196 // Copyright 2014 The Polymer Authors. All rights reserved. |
| 6197 // Use of this source code is goverened by a BSD-style |
| 6198 // license that can be found in the LICENSE file. |
| 6199 |
| 6200 (function(scope) { |
| 6201 'use strict'; |
| 6202 |
| 6203 var registerWrapper = scope.registerWrapper; |
| 6204 var unwrap = scope.unwrap; |
| 6205 var unwrapIfNeeded = scope.unwrapIfNeeded; |
| 6206 var wrap = scope.wrap; |
| 6207 |
| 6208 var OriginalSelection = window.Selection; |
| 6209 |
| 6210 function Selection(impl) { |
| 6211 this.impl = impl; |
| 6212 } |
| 6213 Selection.prototype = { |
| 6214 get anchorNode() { |
| 6215 return wrap(this.impl.anchorNode); |
| 6216 }, |
| 6217 get focusNode() { |
| 6218 return wrap(this.impl.focusNode); |
| 6219 }, |
| 6220 addRange: function(range) { |
| 6221 this.impl.addRange(unwrap(range)); |
| 6222 }, |
| 6223 collapse: function(node, index) { |
| 6224 this.impl.collapse(unwrapIfNeeded(node), index); |
| 6225 }, |
| 6226 containsNode: function(node, allowPartial) { |
| 6227 return this.impl.containsNode(unwrapIfNeeded(node), allowPartial); |
| 6228 }, |
| 6229 extend: function(node, offset) { |
| 6230 this.impl.extend(unwrapIfNeeded(node), offset); |
| 6231 }, |
| 6232 getRangeAt: function(index) { |
| 6233 return wrap(this.impl.getRangeAt(index)); |
| 6234 }, |
| 6235 removeRange: function(range) { |
| 6236 this.impl.removeRange(unwrap(range)); |
| 6237 }, |
| 6238 selectAllChildren: function(node) { |
| 6239 this.impl.selectAllChildren(unwrapIfNeeded(node)); |
| 6240 }, |
| 6241 toString: function() { |
| 6242 return this.impl.toString(); |
| 6243 } |
| 6244 }; |
| 6245 |
| 6246 // WebKit extensions. Not implemented. |
| 6247 // readonly attribute Node baseNode; |
| 6248 // readonly attribute long baseOffset; |
| 6249 // readonly attribute Node extentNode; |
| 6250 // readonly attribute long extentOffset; |
| 6251 // [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node b
aseNode, |
| 6252 // [Default=Undefined] optional long baseOffset, |
| 6253 // [Default=Undefined] optional Node extentNode, |
| 6254 // [Default=Undefined] optional long extentOffset); |
| 6255 // [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefin
ed] optional Node node, |
| 6256 // [Default=Undefined] optional long offset); |
| 6257 |
| 6258 registerWrapper(window.Selection, Selection, window.getSelection()); |
| 6259 |
| 6260 scope.wrappers.Selection = Selection; |
| 6261 |
| 6262 })(window.ShadowDOMPolyfill); |
| 6263 |
| 5609 // Copyright 2013 The Polymer Authors. All rights reserved. | 6264 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 5610 // Use of this source code is goverened by a BSD-style | 6265 // Use of this source code is goverened by a BSD-style |
| 5611 // license that can be found in the LICENSE file. | 6266 // license that can be found in the LICENSE file. |
| 5612 | 6267 |
| 5613 (function(scope) { | 6268 (function(scope) { |
| 5614 'use strict'; | 6269 'use strict'; |
| 5615 | 6270 |
| 5616 var GetElementsByInterface = scope.GetElementsByInterface; | 6271 var GetElementsByInterface = scope.GetElementsByInterface; |
| 5617 var Node = scope.wrappers.Node; | 6272 var Node = scope.wrappers.Node; |
| 5618 var ParentNodeInterface = scope.ParentNodeInterface; | 6273 var ParentNodeInterface = scope.ParentNodeInterface; |
| 6274 var Selection = scope.wrappers.Selection; |
| 5619 var SelectorsInterface = scope.SelectorsInterface; | 6275 var SelectorsInterface = scope.SelectorsInterface; |
| 5620 var ShadowRoot = scope.wrappers.ShadowRoot; | 6276 var ShadowRoot = scope.wrappers.ShadowRoot; |
| 5621 var defineWrapGetter = scope.defineWrapGetter; | 6277 var defineWrapGetter = scope.defineWrapGetter; |
| 5622 var elementFromPoint = scope.elementFromPoint; | 6278 var elementFromPoint = scope.elementFromPoint; |
| 5623 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 6279 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
| 5624 var matchesName = scope.matchesName; | 6280 var matchesNames = scope.matchesNames; |
| 5625 var mixin = scope.mixin; | 6281 var mixin = scope.mixin; |
| 5626 var registerWrapper = scope.registerWrapper; | 6282 var registerWrapper = scope.registerWrapper; |
| 6283 var renderAllPending = scope.renderAllPending; |
| 6284 var rewrap = scope.rewrap; |
| 5627 var unwrap = scope.unwrap; | 6285 var unwrap = scope.unwrap; |
| 5628 var wrap = scope.wrap; | 6286 var wrap = scope.wrap; |
| 5629 var wrapEventTargetMethods = scope.wrapEventTargetMethods; | 6287 var wrapEventTargetMethods = scope.wrapEventTargetMethods; |
| 5630 var wrapNodeList = scope.wrapNodeList; | 6288 var wrapNodeList = scope.wrapNodeList; |
| 5631 | 6289 |
| 5632 var implementationTable = new WeakMap(); | 6290 var implementationTable = new WeakMap(); |
| 5633 | 6291 |
| 5634 function Document(node) { | 6292 function Document(node) { |
| 5635 Node.call(this, node); | 6293 Node.call(this, node); |
| 5636 } | 6294 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5655 | 6313 |
| 5656 [ | 6314 [ |
| 5657 'createComment', | 6315 'createComment', |
| 5658 'createDocumentFragment', | 6316 'createDocumentFragment', |
| 5659 'createElement', | 6317 'createElement', |
| 5660 'createElementNS', | 6318 'createElementNS', |
| 5661 'createEvent', | 6319 'createEvent', |
| 5662 'createEventNS', | 6320 'createEventNS', |
| 5663 'createRange', | 6321 'createRange', |
| 5664 'createTextNode', | 6322 'createTextNode', |
| 5665 'getElementById', | 6323 'getElementById' |
| 5666 ].forEach(wrapMethod); | 6324 ].forEach(wrapMethod); |
| 5667 | 6325 |
| 5668 var originalAdoptNode = document.adoptNode; | 6326 var originalAdoptNode = document.adoptNode; |
| 5669 | 6327 |
| 5670 function adoptNodeNoRemove(node, doc) { | 6328 function adoptNodeNoRemove(node, doc) { |
| 5671 originalAdoptNode.call(doc.impl, unwrap(node)); | 6329 originalAdoptNode.call(doc.impl, unwrap(node)); |
| 5672 adoptSubtree(node, doc); | 6330 adoptSubtree(node, doc); |
| 5673 } | 6331 } |
| 5674 | 6332 |
| 5675 function adoptSubtree(node, doc) { | 6333 function adoptSubtree(node, doc) { |
| 5676 if (node.shadowRoot) | 6334 if (node.shadowRoot) |
| 5677 doc.adoptNode(node.shadowRoot); | 6335 doc.adoptNode(node.shadowRoot); |
| 5678 if (node instanceof ShadowRoot) | 6336 if (node instanceof ShadowRoot) |
| 5679 adoptOlderShadowRoots(node, doc); | 6337 adoptOlderShadowRoots(node, doc); |
| 5680 for (var child = node.firstChild; child; child = child.nextSibling) { | 6338 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 5681 adoptSubtree(child, doc); | 6339 adoptSubtree(child, doc); |
| 5682 } | 6340 } |
| 5683 } | 6341 } |
| 5684 | 6342 |
| 5685 function adoptOlderShadowRoots(shadowRoot, doc) { | 6343 function adoptOlderShadowRoots(shadowRoot, doc) { |
| 5686 var oldShadowRoot = shadowRoot.olderShadowRoot; | 6344 var oldShadowRoot = shadowRoot.olderShadowRoot; |
| 5687 if (oldShadowRoot) | 6345 if (oldShadowRoot) |
| 5688 doc.adoptNode(oldShadowRoot); | 6346 doc.adoptNode(oldShadowRoot); |
| 5689 } | 6347 } |
| 5690 | 6348 |
| 5691 var originalImportNode = document.importNode; | 6349 var originalImportNode = document.importNode; |
| 6350 var originalGetSelection = document.getSelection; |
| 5692 | 6351 |
| 5693 mixin(Document.prototype, { | 6352 mixin(Document.prototype, { |
| 5694 adoptNode: function(node) { | 6353 adoptNode: function(node) { |
| 5695 if (node.parentNode) | 6354 if (node.parentNode) |
| 5696 node.parentNode.removeChild(node); | 6355 node.parentNode.removeChild(node); |
| 5697 adoptNodeNoRemove(node, this); | 6356 adoptNodeNoRemove(node, this); |
| 5698 return node; | 6357 return node; |
| 5699 }, | 6358 }, |
| 5700 elementFromPoint: function(x, y) { | 6359 elementFromPoint: function(x, y) { |
| 5701 return elementFromPoint(this, this, x, y); | 6360 return elementFromPoint(this, this, x, y); |
| 5702 }, | 6361 }, |
| 5703 importNode: function(node, deep) { | 6362 importNode: function(node, deep) { |
| 5704 // We need to manually walk the tree to ensure we do not include rendered | 6363 // We need to manually walk the tree to ensure we do not include rendered |
| 5705 // shadow trees. | 6364 // shadow trees. |
| 5706 var clone = wrap(originalImportNode.call(this.impl, unwrap(node), false)); | 6365 var clone = wrap(originalImportNode.call(this.impl, unwrap(node), false)); |
| 5707 if (deep) { | 6366 if (deep) { |
| 5708 for (var child = node.firstChild; child; child = child.nextSibling) { | 6367 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 5709 clone.appendChild(this.importNode(child, true)); | 6368 clone.appendChild(this.importNode(child, true)); |
| 5710 } | 6369 } |
| 5711 } | 6370 } |
| 5712 return clone; | 6371 return clone; |
| 6372 }, |
| 6373 getSelection: function() { |
| 6374 renderAllPending(); |
| 6375 return new Selection(originalGetSelection.call(unwrap(this))); |
| 5713 } | 6376 } |
| 5714 }); | 6377 }); |
| 5715 | 6378 |
| 5716 if (document.register) { | 6379 if (document.registerElement) { |
| 5717 var originalRegister = document.register; | 6380 var originalRegisterElement = document.registerElement; |
| 5718 Document.prototype.register = function(tagName, object) { | 6381 Document.prototype.registerElement = function(tagName, object) { |
| 5719 var prototype = object.prototype; | 6382 var prototype = object.prototype; |
| 5720 | 6383 |
| 5721 // If we already used the object as a prototype for another custom | 6384 // If we already used the object as a prototype for another custom |
| 5722 // element. | 6385 // element. |
| 5723 if (scope.nativePrototypeTable.get(prototype)) { | 6386 if (scope.nativePrototypeTable.get(prototype)) { |
| 5724 // TODO(arv): DOMException | 6387 // TODO(arv): DOMException |
| 5725 throw new Error('NotSupportedError'); | 6388 throw new Error('NotSupportedError'); |
| 5726 } | 6389 } |
| 5727 | 6390 |
| 5728 // Find first object on the prototype chain that already have a native | 6391 // Find first object on the prototype chain that already have a native |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5752 for (var i = prototypes.length - 1; i >= 0; i--) { | 6415 for (var i = prototypes.length - 1; i >= 0; i--) { |
| 5753 newPrototype = Object.create(newPrototype); | 6416 newPrototype = Object.create(newPrototype); |
| 5754 } | 6417 } |
| 5755 | 6418 |
| 5756 // Add callbacks if present. | 6419 // Add callbacks if present. |
| 5757 // Names are taken from: | 6420 // Names are taken from: |
| 5758 // https://code.google.com/p/chromium/codesearch#chromium/src/third_part
y/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chrom
ium&type=cs&l=156 | 6421 // https://code.google.com/p/chromium/codesearch#chromium/src/third_part
y/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp&sq=package:chrom
ium&type=cs&l=156 |
| 5759 // and not from the spec since the spec is out of date. | 6422 // and not from the spec since the spec is out of date. |
| 5760 [ | 6423 [ |
| 5761 'createdCallback', | 6424 'createdCallback', |
| 5762 'enteredViewCallback', | 6425 'attachedCallback', |
| 5763 'leftViewCallback', | 6426 'detachedCallback', |
| 5764 'attributeChangedCallback', | 6427 'attributeChangedCallback', |
| 5765 ].forEach(function(name) { | 6428 ].forEach(function(name) { |
| 5766 var f = prototype[name]; | 6429 var f = prototype[name]; |
| 5767 if (!f) | 6430 if (!f) |
| 5768 return; | 6431 return; |
| 5769 newPrototype[name] = function() { | 6432 newPrototype[name] = function() { |
| 6433 // if this element has been wrapped prior to registration, |
| 6434 // the wrapper is stale; in this case rewrap |
| 6435 if (!(wrap(this) instanceof CustomElementConstructor)) { |
| 6436 rewrap(this); |
| 6437 } |
| 5770 f.apply(wrap(this), arguments); | 6438 f.apply(wrap(this), arguments); |
| 5771 }; | 6439 }; |
| 5772 }); | 6440 }); |
| 5773 | 6441 |
| 5774 var p = {prototype: newPrototype}; | 6442 var p = {prototype: newPrototype}; |
| 5775 if (object.extends) | 6443 if (object.extends) |
| 5776 p.extends = object.extends; | 6444 p.extends = object.extends; |
| 5777 var nativeConstructor = originalRegister.call(unwrap(this), tagName, p); | |
| 5778 | 6445 |
| 5779 function GeneratedWrapper(node) { | 6446 function CustomElementConstructor(node) { |
| 5780 if (!node) { | 6447 if (!node) { |
| 5781 if (object.extends) { | 6448 if (object.extends) { |
| 5782 return document.createElement(object.extends, tagName); | 6449 return document.createElement(object.extends, tagName); |
| 5783 } else { | 6450 } else { |
| 5784 return document.createElement(tagName); | 6451 return document.createElement(tagName); |
| 5785 } | 6452 } |
| 5786 } | 6453 } |
| 5787 this.impl = node; | 6454 this.impl = node; |
| 5788 } | 6455 } |
| 5789 GeneratedWrapper.prototype = prototype; | 6456 CustomElementConstructor.prototype = prototype; |
| 5790 GeneratedWrapper.prototype.constructor = GeneratedWrapper; | 6457 CustomElementConstructor.prototype.constructor = CustomElementConstructor; |
| 5791 | 6458 |
| 5792 scope.constructorTable.set(newPrototype, GeneratedWrapper); | 6459 scope.constructorTable.set(newPrototype, CustomElementConstructor); |
| 5793 scope.nativePrototypeTable.set(prototype, newPrototype); | 6460 scope.nativePrototypeTable.set(prototype, newPrototype); |
| 5794 | 6461 |
| 5795 return GeneratedWrapper; | 6462 // registration is synchronous so do it last |
| 6463 var nativeConstructor = originalRegisterElement.call(unwrap(this), |
| 6464 tagName, p); |
| 6465 return CustomElementConstructor; |
| 5796 }; | 6466 }; |
| 5797 | 6467 |
| 5798 forwardMethodsToWrapper([ | 6468 forwardMethodsToWrapper([ |
| 5799 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocume
nt | 6469 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocume
nt |
| 5800 ], [ | 6470 ], [ |
| 5801 'register', | 6471 'registerElement', |
| 5802 ]); | 6472 ]); |
| 5803 } | 6473 } |
| 5804 | 6474 |
| 5805 // We also override some of the methods on document.body and document.head | 6475 // We also override some of the methods on document.body and document.head |
| 5806 // for convenience. | 6476 // for convenience. |
| 5807 forwardMethodsToWrapper([ | 6477 forwardMethodsToWrapper([ |
| 5808 window.HTMLBodyElement, | 6478 window.HTMLBodyElement, |
| 5809 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument | 6479 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument |
| 5810 window.HTMLHeadElement, | 6480 window.HTMLHeadElement, |
| 5811 window.HTMLHtmlElement, | 6481 window.HTMLHtmlElement, |
| 5812 ], [ | 6482 ], [ |
| 5813 'appendChild', | 6483 'appendChild', |
| 5814 'compareDocumentPosition', | 6484 'compareDocumentPosition', |
| 5815 'contains', | 6485 'contains', |
| 5816 'getElementsByClassName', | 6486 'getElementsByClassName', |
| 5817 'getElementsByTagName', | 6487 'getElementsByTagName', |
| 5818 'getElementsByTagNameNS', | 6488 'getElementsByTagNameNS', |
| 5819 'insertBefore', | 6489 'insertBefore', |
| 5820 'querySelector', | 6490 'querySelector', |
| 5821 'querySelectorAll', | 6491 'querySelectorAll', |
| 5822 'removeChild', | 6492 'removeChild', |
| 5823 'replaceChild', | 6493 'replaceChild', |
| 5824 matchesName, | 6494 ].concat(matchesNames)); |
| 5825 ]); | |
| 5826 | 6495 |
| 5827 forwardMethodsToWrapper([ | 6496 forwardMethodsToWrapper([ |
| 5828 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument | 6497 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument |
| 5829 ], [ | 6498 ], [ |
| 5830 'adoptNode', | 6499 'adoptNode', |
| 5831 'importNode', | 6500 'importNode', |
| 5832 'contains', | 6501 'contains', |
| 5833 'createComment', | 6502 'createComment', |
| 5834 'createDocumentFragment', | 6503 'createDocumentFragment', |
| 5835 'createElement', | 6504 'createElement', |
| 5836 'createElementNS', | 6505 'createElementNS', |
| 5837 'createEvent', | 6506 'createEvent', |
| 5838 'createEventNS', | 6507 'createEventNS', |
| 5839 'createRange', | 6508 'createRange', |
| 5840 'createTextNode', | 6509 'createTextNode', |
| 5841 'elementFromPoint', | 6510 'elementFromPoint', |
| 5842 'getElementById', | 6511 'getElementById', |
| 6512 'getSelection', |
| 5843 ]); | 6513 ]); |
| 5844 | 6514 |
| 5845 mixin(Document.prototype, GetElementsByInterface); | 6515 mixin(Document.prototype, GetElementsByInterface); |
| 5846 mixin(Document.prototype, ParentNodeInterface); | 6516 mixin(Document.prototype, ParentNodeInterface); |
| 5847 mixin(Document.prototype, SelectorsInterface); | 6517 mixin(Document.prototype, SelectorsInterface); |
| 5848 | 6518 |
| 5849 mixin(Document.prototype, { | 6519 mixin(Document.prototype, { |
| 5850 get implementation() { | 6520 get implementation() { |
| 5851 var implementation = implementationTable.get(this); | 6521 var implementation = implementationTable.get(this); |
| 5852 if (implementation) | 6522 if (implementation) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5913 })(window.ShadowDOMPolyfill); | 6583 })(window.ShadowDOMPolyfill); |
| 5914 | 6584 |
| 5915 // Copyright 2013 The Polymer Authors. All rights reserved. | 6585 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 5916 // Use of this source code is goverened by a BSD-style | 6586 // Use of this source code is goverened by a BSD-style |
| 5917 // license that can be found in the LICENSE file. | 6587 // license that can be found in the LICENSE file. |
| 5918 | 6588 |
| 5919 (function(scope) { | 6589 (function(scope) { |
| 5920 'use strict'; | 6590 'use strict'; |
| 5921 | 6591 |
| 5922 var EventTarget = scope.wrappers.EventTarget; | 6592 var EventTarget = scope.wrappers.EventTarget; |
| 6593 var Selection = scope.wrappers.Selection; |
| 5923 var mixin = scope.mixin; | 6594 var mixin = scope.mixin; |
| 5924 var registerWrapper = scope.registerWrapper; | 6595 var registerWrapper = scope.registerWrapper; |
| 6596 var renderAllPending = scope.renderAllPending; |
| 5925 var unwrap = scope.unwrap; | 6597 var unwrap = scope.unwrap; |
| 5926 var unwrapIfNeeded = scope.unwrapIfNeeded; | 6598 var unwrapIfNeeded = scope.unwrapIfNeeded; |
| 5927 var wrap = scope.wrap; | 6599 var wrap = scope.wrap; |
| 5928 var renderAllPending = scope.renderAllPending; | |
| 5929 | 6600 |
| 5930 var OriginalWindow = window.Window; | 6601 var OriginalWindow = window.Window; |
| 6602 var originalGetComputedStyle = window.getComputedStyle; |
| 6603 var originalGetSelection = window.getSelection; |
| 5931 | 6604 |
| 5932 function Window(impl) { | 6605 function Window(impl) { |
| 5933 EventTarget.call(this, impl); | 6606 EventTarget.call(this, impl); |
| 5934 } | 6607 } |
| 5935 Window.prototype = Object.create(EventTarget.prototype); | 6608 Window.prototype = Object.create(EventTarget.prototype); |
| 5936 | 6609 |
| 5937 var originalGetComputedStyle = window.getComputedStyle; | |
| 5938 OriginalWindow.prototype.getComputedStyle = function(el, pseudo) { | 6610 OriginalWindow.prototype.getComputedStyle = function(el, pseudo) { |
| 5939 renderAllPending(); | 6611 return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo); |
| 5940 return originalGetComputedStyle.call(this || window, unwrapIfNeeded(el), | |
| 5941 pseudo); | |
| 5942 }; | 6612 }; |
| 5943 | 6613 |
| 6614 OriginalWindow.prototype.getSelection = function() { |
| 6615 return wrap(this || window).getSelection(); |
| 6616 }; |
| 6617 |
| 6618 // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065 |
| 6619 delete window.getComputedStyle; |
| 6620 delete window.getSelection; |
| 6621 |
| 5944 ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach( | 6622 ['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach( |
| 5945 function(name) { | 6623 function(name) { |
| 5946 OriginalWindow.prototype[name] = function() { | 6624 OriginalWindow.prototype[name] = function() { |
| 5947 var w = wrap(this || window); | 6625 var w = wrap(this || window); |
| 5948 return w[name].apply(w, arguments); | 6626 return w[name].apply(w, arguments); |
| 5949 }; | 6627 }; |
| 6628 |
| 6629 // Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065 |
| 6630 delete window[name]; |
| 5950 }); | 6631 }); |
| 5951 | 6632 |
| 5952 mixin(Window.prototype, { | 6633 mixin(Window.prototype, { |
| 5953 getComputedStyle: function(el, pseudo) { | 6634 getComputedStyle: function(el, pseudo) { |
| 6635 renderAllPending(); |
| 5954 return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el), | 6636 return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el), |
| 5955 pseudo); | 6637 pseudo); |
| 5956 } | 6638 }, |
| 6639 getSelection: function() { |
| 6640 renderAllPending(); |
| 6641 return new Selection(originalGetSelection.call(unwrap(this))); |
| 6642 }, |
| 5957 }); | 6643 }); |
| 5958 | 6644 |
| 5959 registerWrapper(OriginalWindow, Window); | 6645 registerWrapper(OriginalWindow, Window); |
| 5960 | 6646 |
| 5961 scope.wrappers.Window = Window; | 6647 scope.wrappers.Window = Window; |
| 5962 | 6648 |
| 5963 })(window.ShadowDOMPolyfill); | 6649 })(window.ShadowDOMPolyfill); |
| 5964 | 6650 |
| 5965 // Copyright 2013 The Polymer Authors. All rights reserved. | 6651 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 5966 // Use of this source code is goverened by a BSD-style | 6652 // Use of this source code is goverened by a BSD-style |
| 5967 // license that can be found in the LICENSE file. | 6653 // license that can be found in the LICENSE file. |
| 5968 | 6654 |
| 5969 (function(scope) { | 6655 (function(scope) { |
| 5970 'use strict'; | 6656 'use strict'; |
| 5971 | 6657 |
| 5972 var isWrapperFor = scope.isWrapperFor; | 6658 var isWrapperFor = scope.isWrapperFor; |
| 5973 | 6659 |
| 5974 // This is a list of the elements we currently override the global constructor | 6660 // This is a list of the elements we currently override the global constructor |
| 5975 // for. | 6661 // for. |
| 5976 var elements = { | 6662 var elements = { |
| 5977 'a': 'HTMLAnchorElement', | 6663 'a': 'HTMLAnchorElement', |
| 5978 'applet': 'HTMLAppletElement', | 6664 |
| 6665 // Do not create an applet element by default since it shows a warning in |
| 6666 // IE. |
| 6667 // https://github.com/Polymer/polymer/issues/217 |
| 6668 // 'applet': 'HTMLAppletElement', |
| 6669 |
| 5979 'area': 'HTMLAreaElement', | 6670 'area': 'HTMLAreaElement', |
| 5980 'br': 'HTMLBRElement', | 6671 'br': 'HTMLBRElement', |
| 5981 'base': 'HTMLBaseElement', | 6672 'base': 'HTMLBaseElement', |
| 5982 'body': 'HTMLBodyElement', | 6673 'body': 'HTMLBodyElement', |
| 5983 'button': 'HTMLButtonElement', | 6674 'button': 'HTMLButtonElement', |
| 5984 // 'command': 'HTMLCommandElement', // Not fully implemented in Gecko. | 6675 // 'command': 'HTMLCommandElement', // Not fully implemented in Gecko. |
| 5985 'dl': 'HTMLDListElement', | 6676 'dl': 'HTMLDListElement', |
| 5986 'datalist': 'HTMLDataListElement', | 6677 'datalist': 'HTMLDataListElement', |
| 5987 'data': 'HTMLDataElement', | 6678 'data': 'HTMLDataElement', |
| 5988 'dir': 'HTMLDirectoryElement', | 6679 'dir': 'HTMLDirectoryElement', |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6076 // patch in prefixed name | 6767 // patch in prefixed name |
| 6077 Object.defineProperties(HTMLElement.prototype, { | 6768 Object.defineProperties(HTMLElement.prototype, { |
| 6078 //TODO(sjmiles): review accessor alias with Arv | 6769 //TODO(sjmiles): review accessor alias with Arv |
| 6079 webkitShadowRoot: { | 6770 webkitShadowRoot: { |
| 6080 get: function() { | 6771 get: function() { |
| 6081 return this.shadowRoot; | 6772 return this.shadowRoot; |
| 6082 } | 6773 } |
| 6083 } | 6774 } |
| 6084 }); | 6775 }); |
| 6085 | 6776 |
| 6777 // ShadowCSS needs this: |
| 6778 window.wrap = window.ShadowDOMPolyfill.wrap; |
| 6779 window.unwrap = window.ShadowDOMPolyfill.unwrap; |
| 6780 |
| 6086 //TODO(sjmiles): review method alias with Arv | 6781 //TODO(sjmiles): review method alias with Arv |
| 6087 HTMLElement.prototype.webkitCreateShadowRoot = | 6782 HTMLElement.prototype.webkitCreateShadowRoot = |
| 6088 HTMLElement.prototype.createShadowRoot; | 6783 HTMLElement.prototype.createShadowRoot; |
| 6089 | 6784 |
| 6090 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?) | 6785 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?) |
| 6091 window.dartExperimentalFixupGetTag = function(originalGetTag) { | 6786 window.dartExperimentalFixupGetTag = function(originalGetTag) { |
| 6092 var NodeList = ShadowDOMPolyfill.wrappers.NodeList; | 6787 var NodeList = ShadowDOMPolyfill.wrappers.NodeList; |
| 6093 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot; | 6788 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot; |
| 6094 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded; | 6789 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded; |
| 6095 function getTag(obj) { | 6790 function getTag(obj) { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6283 <div class="content-container"> | 6978 <div class="content-container"> |
| 6284 <content></content> | 6979 <content></content> |
| 6285 </div> | 6980 </div> |
| 6286 | 6981 |
| 6287 Note the use of @polyfill in the comment above a ShadowDOM specific style | 6982 Note the use of @polyfill in the comment above a ShadowDOM specific style |
| 6288 declaration. This is a directive to the styling shim to use the selector | 6983 declaration. This is a directive to the styling shim to use the selector |
| 6289 in comments in lieu of the next selector when running under polyfill. | 6984 in comments in lieu of the next selector when running under polyfill. |
| 6290 */ | 6985 */ |
| 6291 (function(scope) { | 6986 (function(scope) { |
| 6292 | 6987 |
| 6988 var loader = scope.loader; |
| 6989 |
| 6293 var ShadowCSS = { | 6990 var ShadowCSS = { |
| 6294 strictStyling: false, | 6991 strictStyling: false, |
| 6295 registry: {}, | 6992 registry: {}, |
| 6296 // Shim styles for a given root associated with a name and extendsName | 6993 // Shim styles for a given root associated with a name and extendsName |
| 6297 // 1. cache root styles by name | 6994 // 1. cache root styles by name |
| 6298 // 2. optionally tag root nodes with scope name | 6995 // 2. optionally tag root nodes with scope name |
| 6299 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ | 6996 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ |
| 6300 // 4. shim @host and scoping | 6997 // 4. shim @host and scoping |
| 6301 shimStyling: function(root, name, extendsName) { | 6998 shimStyling: function(root, name, extendsName) { |
| 6302 var typeExtension = this.isTypeExtension(extendsName); | 6999 var typeExtension = this.isTypeExtension(extendsName); |
| 6303 // use caching to make working with styles nodes easier and to facilitate | 7000 // use caching to make working with styles nodes easier and to facilitate |
| 6304 // lookup of extendee | 7001 // lookup of extendee |
| 6305 var def = this.registerDefinition(root, name, extendsName); | 7002 var def = this.registerDefinition(root, name, extendsName); |
| 6306 // find styles and apply shimming... | 7003 // find styles and apply shimming... |
| 6307 if (this.strictStyling) { | 7004 if (this.strictStyling) { |
| 6308 this.applyScopeToContent(root, name); | 7005 this.applyScopeToContent(root, name); |
| 6309 } | 7006 } |
| 6310 // insert @polyfill and @polyfill-rule rules into style elements | 7007 var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles, |
| 6311 // scoping process takes care of shimming these | 7008 name, typeExtension); |
| 6312 this.insertPolyfillDirectives(def.rootStyles); | |
| 6313 this.insertPolyfillRules(def.rootStyles); | |
| 6314 var cssText = this.stylesToShimmedCssText(def.scopeStyles, name, | |
| 6315 typeExtension); | |
| 6316 // note: we only need to do rootStyles since these are unscoped. | |
| 6317 cssText += this.extractPolyfillUnscopedRules(def.rootStyles); | |
| 6318 // provide shimmedStyle for user extensibility | 7009 // provide shimmedStyle for user extensibility |
| 6319 def.shimmedStyle = cssTextToStyle(cssText); | 7010 def.shimmedStyle = cssTextToStyle(cssText); |
| 6320 if (root) { | 7011 if (root) { |
| 6321 root.shimmedStyle = def.shimmedStyle; | 7012 root.shimmedStyle = def.shimmedStyle; |
| 6322 } | 7013 } |
| 6323 // remove existing style elements | 7014 // remove existing style elements |
| 6324 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); | 7015 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); |
| 6325 i++) { | 7016 i++) { |
| 6326 s.parentNode.removeChild(s); | 7017 s.parentNode.removeChild(s); |
| 6327 } | 7018 } |
| 6328 // add style to document | 7019 // add style to document |
| 6329 addCssToDocument(cssText); | 7020 addCssToDocument(cssText); |
| 6330 }, | 7021 }, |
| 7022 // apply @polyfill rules + @host and scope shimming |
| 7023 stylesToShimmedCssText: function(rootStyles, scopeStyles, name, |
| 7024 typeExtension) { |
| 7025 name = name || ''; |
| 7026 // insert @polyfill and @polyfill-rule rules into style elements |
| 7027 // scoping process takes care of shimming these |
| 7028 this.insertPolyfillDirectives(rootStyles); |
| 7029 this.insertPolyfillRules(rootStyles); |
| 7030 var cssText = this.shimAtHost(scopeStyles, name, typeExtension) + |
| 7031 this.shimScoping(scopeStyles, name, typeExtension); |
| 7032 // note: we only need to do rootStyles since these are unscoped. |
| 7033 cssText += this.extractPolyfillUnscopedRules(rootStyles); |
| 7034 return cssText; |
| 7035 }, |
| 6331 registerDefinition: function(root, name, extendsName) { | 7036 registerDefinition: function(root, name, extendsName) { |
| 6332 var def = this.registry[name] = { | 7037 var def = this.registry[name] = { |
| 6333 root: root, | 7038 root: root, |
| 6334 name: name, | 7039 name: name, |
| 6335 extendsName: extendsName | 7040 extendsName: extendsName |
| 6336 } | 7041 } |
| 6337 var styles = root ? root.querySelectorAll('style') : []; | 7042 var styles = root ? root.querySelectorAll('style') : []; |
| 6338 styles = styles ? Array.prototype.slice.call(styles, 0) : []; | 7043 styles = styles ? Array.prototype.slice.call(styles, 0) : []; |
| 6339 def.rootStyles = styles; | 7044 def.rootStyles = styles; |
| 6340 def.scopeStyles = def.rootStyles; | 7045 def.scopeStyles = def.rootStyles; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6439 } | 7144 } |
| 6440 return cssText; | 7145 return cssText; |
| 6441 }, | 7146 }, |
| 6442 extractPolyfillUnscopedRulesFromCssText: function(cssText) { | 7147 extractPolyfillUnscopedRulesFromCssText: function(cssText) { |
| 6443 var r = '', matches; | 7148 var r = '', matches; |
| 6444 while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) { | 7149 while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) { |
| 6445 r += matches[1].slice(0, -1) + '\n\n'; | 7150 r += matches[1].slice(0, -1) + '\n\n'; |
| 6446 } | 7151 } |
| 6447 return r; | 7152 return r; |
| 6448 }, | 7153 }, |
| 6449 // apply @host and scope shimming | |
| 6450 stylesToShimmedCssText: function(styles, name, typeExtension) { | |
| 6451 return this.shimAtHost(styles, name, typeExtension) + | |
| 6452 this.shimScoping(styles, name, typeExtension); | |
| 6453 }, | |
| 6454 // form: @host { .foo { declarations } } | 7154 // form: @host { .foo { declarations } } |
| 6455 // becomes: scopeName.foo { declarations } | 7155 // becomes: scopeName.foo { declarations } |
| 6456 shimAtHost: function(styles, name, typeExtension) { | 7156 shimAtHost: function(styles, name, typeExtension) { |
| 6457 if (styles) { | 7157 if (styles) { |
| 6458 return this.convertAtHostStyles(styles, name, typeExtension); | 7158 return this.convertAtHostStyles(styles, name, typeExtension); |
| 6459 } | 7159 } |
| 6460 }, | 7160 }, |
| 6461 convertAtHostStyles: function(styles, name, typeExtension) { | 7161 convertAtHostStyles: function(styles, name, typeExtension) { |
| 6462 var cssText = stylesToCssText(styles), self = this; | 7162 var cssText = stylesToCssText(styles), self = this; |
| 6463 cssText = cssText.replace(hostRuleRe, function(m, p1) { | 7163 cssText = cssText.replace(hostRuleRe, function(m, p1) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6512 */ | 7212 */ |
| 6513 shimScoping: function(styles, name, typeExtension) { | 7213 shimScoping: function(styles, name, typeExtension) { |
| 6514 if (styles) { | 7214 if (styles) { |
| 6515 return this.convertScopedStyles(styles, name, typeExtension); | 7215 return this.convertScopedStyles(styles, name, typeExtension); |
| 6516 } | 7216 } |
| 6517 }, | 7217 }, |
| 6518 convertScopedStyles: function(styles, name, typeExtension) { | 7218 convertScopedStyles: function(styles, name, typeExtension) { |
| 6519 var cssText = stylesToCssText(styles).replace(hostRuleRe, ''); | 7219 var cssText = stylesToCssText(styles).replace(hostRuleRe, ''); |
| 6520 cssText = this.insertPolyfillHostInCssText(cssText); | 7220 cssText = this.insertPolyfillHostInCssText(cssText); |
| 6521 cssText = this.convertColonHost(cssText); | 7221 cssText = this.convertColonHost(cssText); |
| 7222 cssText = this.convertColonAncestor(cssText); |
| 7223 // TODO(sorvell): deprecated, remove |
| 6522 cssText = this.convertPseudos(cssText); | 7224 cssText = this.convertPseudos(cssText); |
| 7225 // TODO(sorvell): deprecated, remove |
| 6523 cssText = this.convertParts(cssText); | 7226 cssText = this.convertParts(cssText); |
| 6524 cssText = this.convertCombinators(cssText); | 7227 cssText = this.convertCombinators(cssText); |
| 6525 var rules = cssToRules(cssText); | 7228 var rules = cssToRules(cssText); |
| 6526 cssText = this.scopeRules(rules, name, typeExtension); | 7229 if (name) { |
| 7230 cssText = this.scopeRules(rules, name, typeExtension); |
| 7231 } |
| 6527 return cssText; | 7232 return cssText; |
| 6528 }, | 7233 }, |
| 6529 convertPseudos: function(cssText) { | 7234 convertPseudos: function(cssText) { |
| 6530 return cssText.replace(cssPseudoRe, ' [pseudo=$1]'); | 7235 return cssText.replace(cssPseudoRe, ' [pseudo=$1]'); |
| 6531 }, | 7236 }, |
| 6532 convertParts: function(cssText) { | 7237 convertParts: function(cssText) { |
| 6533 return cssText.replace(cssPartRe, ' [part=$1]'); | 7238 return cssText.replace(cssPartRe, ' [part=$1]'); |
| 6534 }, | 7239 }, |
| 6535 /* | 7240 /* |
| 6536 * convert a rule like :host(.foo) > .bar { } | 7241 * convert a rule like :host(.foo) > .bar { } |
| 6537 * | 7242 * |
| 6538 * to | 7243 * to |
| 6539 * | 7244 * |
| 7245 * scopeName.foo > .bar |
| 7246 */ |
| 7247 convertColonHost: function(cssText) { |
| 7248 return this.convertColonRule(cssText, cssColonHostRe, |
| 7249 this.colonHostPartReplacer); |
| 7250 }, |
| 7251 /* |
| 7252 * convert a rule like :ancestor(.foo) > .bar { } |
| 7253 * |
| 7254 * to |
| 7255 * |
| 6540 * scopeName.foo > .bar, .foo scopeName > .bar { } | 7256 * scopeName.foo > .bar, .foo scopeName > .bar { } |
| 6541 * | 7257 * |
| 6542 * and | 7258 * and |
| 6543 * | 7259 * |
| 6544 * :host(.foo:host) .bar { ... } | 7260 * :ancestor(.foo:host) .bar { ... } |
| 6545 * | 7261 * |
| 6546 * to | 7262 * to |
| 6547 * | 7263 * |
| 6548 * scopeName.foo .bar { ... } | 7264 * scopeName.foo .bar { ... } |
| 6549 */ | 7265 */ |
| 6550 convertColonHost: function(cssText) { | 7266 convertColonAncestor: function(cssText) { |
| 7267 return this.convertColonRule(cssText, cssColonAncestorRe, |
| 7268 this.colonAncestorPartReplacer); |
| 7269 }, |
| 7270 convertColonRule: function(cssText, regExp, partReplacer) { |
| 6551 // p1 = :host, p2 = contents of (), p3 rest of rule | 7271 // p1 = :host, p2 = contents of (), p3 rest of rule |
| 6552 return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) { | 7272 return cssText.replace(regExp, function(m, p1, p2, p3) { |
| 6553 p1 = polyfillHostNoCombinator; | 7273 p1 = polyfillHostNoCombinator; |
| 6554 if (p2) { | 7274 if (p2) { |
| 6555 var parts = p2.split(','), r = []; | 7275 var parts = p2.split(','), r = []; |
| 6556 for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { | 7276 for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { |
| 6557 p = p.trim(); | 7277 p = p.trim(); |
| 6558 if (p.match(polyfillHost)) { | 7278 r.push(partReplacer(p1, p, p3)); |
| 6559 r.push(p1 + p.replace(polyfillHost, '') + p3); | |
| 6560 } else { | |
| 6561 r.push(p1 + p + p3 + ', ' + p + ' ' + p1 + p3); | |
| 6562 } | |
| 6563 } | 7279 } |
| 6564 return r.join(','); | 7280 return r.join(','); |
| 6565 } else { | 7281 } else { |
| 6566 return p1 + p3; | 7282 return p1 + p3; |
| 6567 } | 7283 } |
| 6568 }); | 7284 }); |
| 6569 }, | 7285 }, |
| 7286 colonAncestorPartReplacer: function(host, part, suffix) { |
| 7287 if (part.match(polyfillHost)) { |
| 7288 return this.colonHostPartReplacer(host, part, suffix); |
| 7289 } else { |
| 7290 return host + part + suffix + ', ' + part + ' ' + host + suffix; |
| 7291 } |
| 7292 }, |
| 7293 colonHostPartReplacer: function(host, part, suffix) { |
| 7294 return host + part.replace(polyfillHost, '') + suffix; |
| 7295 }, |
| 6570 /* | 7296 /* |
| 6571 * Convert ^ and ^^ combinators by replacing with space. | 7297 * Convert ^ and ^^ combinators by replacing with space. |
| 6572 */ | 7298 */ |
| 6573 convertCombinators: function(cssText) { | 7299 convertCombinators: function(cssText) { |
| 6574 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); | 7300 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); |
| 6575 }, | 7301 }, |
| 6576 // change a selector like 'div' to 'name div' | 7302 // change a selector like 'div' to 'name div' |
| 6577 scopeRules: function(cssRules, name, typeExtension) { | 7303 scopeRules: function(cssRules, name, typeExtension) { |
| 6578 var cssText = ''; | 7304 var cssText = ''; |
| 6579 Array.prototype.forEach.call(cssRules, function(rule) { | 7305 Array.prototype.forEach.call(cssRules, function(rule) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6636 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { | 7362 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { |
| 6637 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') | 7363 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') |
| 6638 } | 7364 } |
| 6639 return p; | 7365 return p; |
| 6640 }).join(sep); | 7366 }).join(sep); |
| 6641 }); | 7367 }); |
| 6642 return scoped; | 7368 return scoped; |
| 6643 }, | 7369 }, |
| 6644 insertPolyfillHostInCssText: function(selector) { | 7370 insertPolyfillHostInCssText: function(selector) { |
| 6645 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, | 7371 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, |
| 6646 polyfillHost); | 7372 polyfillHost).replace(colonAncestorRe, polyfillAncestor); |
| 6647 }, | 7373 }, |
| 6648 propertiesFromRule: function(rule) { | 7374 propertiesFromRule: function(rule) { |
| 7375 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
| 7376 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
| 7377 if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
| 7378 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
| 7379 rule.style.content + '\';'); |
| 7380 } |
| 6649 return rule.style.cssText; | 7381 return rule.style.cssText; |
| 6650 } | 7382 } |
| 6651 }; | 7383 }; |
| 6652 | 7384 |
| 6653 var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim, | 7385 var hostRuleRe = /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim, |
| 6654 selectorRe = /([^{]*)({[\s\S]*?})/gim, | 7386 selectorRe = /([^{]*)({[\s\S]*?})/gim, |
| 6655 hostElementRe = /(.*)((?:\*)|(?:\:scope))(.*)/, | 7387 hostElementRe = /(.*)((?:\*)|(?:\:scope))(.*)/, |
| 6656 hostFixableRe = /^[.\[:]/, | 7388 hostFixableRe = /^[.\[:]/, |
| 6657 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, | 7389 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, |
| 6658 cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?
){/gim, | 7390 cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?
){/gim, |
| 6659 cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\/
/gim, | 7391 cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\/
/gim, |
| 6660 cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([
^/*][^*]*\*+)*)\//gim, | 7392 cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([
^/*][^*]*\*+)*)\//gim, |
| 6661 cssPseudoRe = /::(x-[^\s{,(]*)/gim, | 7393 cssPseudoRe = /::(x-[^\s{,(]*)/gim, |
| 6662 cssPartRe = /::part\(([^)]*)\)/gim, | 7394 cssPartRe = /::part\(([^)]*)\)/gim, |
| 6663 // note: :host pre-processed to -shadowcsshost. | 7395 // note: :host pre-processed to -shadowcsshost. |
| 6664 polyfillHost = '-shadowcsshost', | 7396 polyfillHost = '-shadowcsshost', |
| 6665 cssColonHostRe = new RegExp('(' + polyfillHost + | 7397 // note: :ancestor pre-processed to -shadowcssancestor. |
| 6666 ')(?:\\((' + | 7398 polyfillAncestor = '-shadowcssancestor', |
| 7399 parenSuffix = ')(?:\\((' + |
| 6667 '(?:\\([^)(]*\\)|[^)(]*)+?' + | 7400 '(?:\\([^)(]*\\)|[^)(]*)+?' + |
| 6668 ')\\))?([^,{]*)', 'gim'), | 7401 ')\\))?([^,{]*)'; |
| 7402 cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), |
| 7403 cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim')
, |
| 6669 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', | 7404 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', |
| 6670 hostRe = /@host/gim, | 7405 hostRe = /@host/gim, |
| 6671 colonHostRe = /\:host/gim, | 7406 colonHostRe = /\:host/gim, |
| 7407 colonAncestorRe = /\:ancestor/gim, |
| 6672 /* host name without combinator */ | 7408 /* host name without combinator */ |
| 6673 polyfillHostNoCombinator = polyfillHost + '-no-combinator', | 7409 polyfillHostNoCombinator = polyfillHost + '-no-combinator', |
| 6674 polyfillHostRe = new RegExp(polyfillHost, 'gim'); | 7410 polyfillHostRe = new RegExp(polyfillHost, 'gim'); |
| 7411 polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim'); |
| 6675 | 7412 |
| 6676 function stylesToCssText(styles, preserveComments) { | 7413 function stylesToCssText(styles, preserveComments) { |
| 6677 var cssText = ''; | 7414 var cssText = ''; |
| 6678 Array.prototype.forEach.call(styles, function(s) { | 7415 Array.prototype.forEach.call(styles, function(s) { |
| 6679 cssText += s.textContent + '\n\n'; | 7416 cssText += s.textContent + '\n\n'; |
| 6680 }); | 7417 }); |
| 6681 // strip comments for easier processing | 7418 // strip comments for easier processing |
| 6682 if (!preserveComments) { | 7419 if (!preserveComments) { |
| 6683 cssText = cssText.replace(cssCommentRe, ''); | 7420 cssText = cssText.replace(cssCommentRe, ''); |
| 6684 } | 7421 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 6710 if (cssText) { | 7447 if (cssText) { |
| 6711 getSheet().appendChild(document.createTextNode(cssText)); | 7448 getSheet().appendChild(document.createTextNode(cssText)); |
| 6712 } | 7449 } |
| 6713 } | 7450 } |
| 6714 | 7451 |
| 6715 var sheet; | 7452 var sheet; |
| 6716 function getSheet() { | 7453 function getSheet() { |
| 6717 if (!sheet) { | 7454 if (!sheet) { |
| 6718 sheet = document.createElement("style"); | 7455 sheet = document.createElement("style"); |
| 6719 sheet.setAttribute('ShadowCSSShim', ''); | 7456 sheet.setAttribute('ShadowCSSShim', ''); |
| 7457 sheet.shadowCssShim = true; |
| 6720 } | 7458 } |
| 6721 return sheet; | 7459 return sheet; |
| 6722 } | 7460 } |
| 6723 | 7461 |
| 6724 // add polyfill stylesheet to document | 7462 // add polyfill stylesheet to document |
| 6725 if (window.ShadowDOMPolyfill) { | 7463 if (window.ShadowDOMPolyfill) { |
| 6726 addCssToDocument('style { display: none !important; }\n'); | 7464 addCssToDocument('style { display: none !important; }\n'); |
| 6727 var head = document.querySelector('head'); | 7465 var doc = wrap(document); |
| 7466 var head = doc.querySelector('head'); |
| 6728 head.insertBefore(getSheet(), head.childNodes[0]); | 7467 head.insertBefore(getSheet(), head.childNodes[0]); |
| 7468 |
| 7469 document.addEventListener('DOMContentLoaded', function() { |
| 7470 if (window.HTMLImports && !HTMLImports.useNative) { |
| 7471 HTMLImports.importer.preloadSelectors += |
| 7472 ', link[rel=stylesheet]:not([nopolyfill])'; |
| 7473 HTMLImports.parser.parseGeneric = function(elt) { |
| 7474 if (elt.shadowCssShim) { |
| 7475 return; |
| 7476 } |
| 7477 var style = elt; |
| 7478 if (!elt.hasAttribute('nopolyfill')) { |
| 7479 if (elt.__resource) { |
| 7480 style = elt.ownerDocument.createElement('style'); |
| 7481 style.textContent = Platform.loader.resolveUrlsInCssText( |
| 7482 elt.__resource, elt.href); |
| 7483 // remove links from main document |
| 7484 if (elt.ownerDocument === doc) { |
| 7485 elt.parentNode.removeChild(elt); |
| 7486 } |
| 7487 } else { |
| 7488 Platform.loader.resolveUrlsInStyle(style); |
| 7489 } |
| 7490 var styles = [style]; |
| 7491 style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles); |
| 7492 style.shadowCssShim = true; |
| 7493 } |
| 7494 // place in document |
| 7495 if (style.parentNode !== head) { |
| 7496 head.appendChild(style); |
| 7497 } |
| 7498 } |
| 7499 } |
| 7500 }); |
| 6729 } | 7501 } |
| 6730 | 7502 |
| 6731 // exports | 7503 // exports |
| 6732 scope.ShadowCSS = ShadowCSS; | 7504 scope.ShadowCSS = ShadowCSS; |
| 6733 | 7505 |
| 6734 })(window.Platform); | 7506 })(window.Platform); |
| 6735 } | 7507 } |
| OLD | NEW |