| OLD | NEW |
| 1 if ((!HTMLElement.prototype.createShadowRoot && | 1 if ((!HTMLElement.prototype.createShadowRoot && |
| 2 !HTMLElement.prototype.webkitCreateShadowRoot) || | 2 !HTMLElement.prototype.webkitCreateShadowRoot) || |
| 3 window.__forceShadowDomPolyfill) { | 3 window.__forceShadowDomPolyfill) { |
| 4 | 4 |
| 5 /* | 5 /* |
| 6 * Copyright 2013 The Polymer Authors. All rights reserved. | 6 * Copyright 2013 The Polymer Authors. All rights reserved. |
| 7 * Use of this source code is governed by a BSD-style | 7 * Use of this source code is governed by a BSD-style |
| 8 * license that can be found in the LICENSE file. | 8 * license that can be found in the LICENSE file. |
| 9 */ | 9 */ |
| 10 (function() { | 10 (function() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 // SideTable is a weak map where possible. If WeakMap is not available the | 25 // SideTable is a weak map where possible. If WeakMap is not available the |
| 26 // association is stored as an expando property. | 26 // association is stored as an expando property. |
| 27 var SideTable; | 27 var SideTable; |
| 28 // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox | 28 // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox |
| 29 if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
0) { | 29 if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') <
0) { |
| 30 SideTable = WeakMap; | 30 SideTable = WeakMap; |
| 31 } else { | 31 } else { |
| 32 (function() { | 32 (function() { |
| 33 var defineProperty = Object.defineProperty; | 33 var defineProperty = Object.defineProperty; |
| 34 var hasOwnProperty = Object.hasOwnProperty; | 34 var counter = Date.now() % 1e9; |
| 35 var counter = new Date().getTime() % 1e9; | |
| 36 | 35 |
| 37 SideTable = function() { | 36 SideTable = function() { |
| 38 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); | 37 this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); |
| 39 }; | 38 }; |
| 40 | 39 |
| 41 SideTable.prototype = { | 40 SideTable.prototype = { |
| 42 set: function(key, value) { | 41 set: function(key, value) { |
| 43 defineProperty(key, this.name, {value: value, writable: true}); | 42 var entry = key[this.name]; |
| 43 if (entry && entry[0] === key) |
| 44 entry[1] = value; |
| 45 else |
| 46 defineProperty(key, this.name, {value: [key, value], writable: true}); |
| 44 }, | 47 }, |
| 45 get: function(key) { | 48 get: function(key) { |
| 46 return hasOwnProperty.call(key, this.name) ? key[this.name] : undefined; | 49 var entry; |
| 50 return (entry = key[this.name]) && entry[0] === key ? |
| 51 entry[1] : undefined; |
| 47 }, | 52 }, |
| 48 delete: function(key) { | 53 delete: function(key) { |
| 49 this.set(key, undefined); | 54 this.set(key, undefined); |
| 50 } | 55 } |
| 51 } | 56 } |
| 52 })(); | 57 })(); |
| 53 } | 58 } |
| 54 | 59 |
| 55 // Copyright 2012 The Polymer Authors. All rights reserved. | 60 // Copyright 2012 The Polymer Authors. All rights reserved. |
| 56 // Use of this source code is goverened by a BSD-style | 61 // Use of this source code is goverened by a BSD-style |
| 57 // license that can be found in the LICENSE file. | 62 // license that can be found in the LICENSE file. |
| 58 | 63 |
| 59 var ShadowDOMPolyfill = {}; | 64 var ShadowDOMPolyfill = {}; |
| 60 | 65 |
| 61 (function(scope) { | 66 (function(scope) { |
| 62 'use strict'; | 67 'use strict'; |
| 63 | 68 |
| 64 var wrapperTable = new SideTable(); | 69 var wrapperTable = new SideTable(); |
| 65 var constructorTable = new SideTable(); | 70 var constructorTable = new SideTable(); |
| 71 var nativePrototypeTable = new SideTable(); |
| 66 var wrappers = Object.create(null); | 72 var wrappers = Object.create(null); |
| 67 | 73 |
| 68 function assert(b) { | 74 function assert(b) { |
| 69 if (!b) | 75 if (!b) |
| 70 throw new Error('Assertion failed'); | 76 throw new Error('Assertion failed'); |
| 71 }; | 77 }; |
| 72 | 78 |
| 73 function mixin(to, from) { | 79 function mixin(to, from) { |
| 74 Object.getOwnPropertyNames(from).forEach(function(name) { | 80 Object.getOwnPropertyNames(from).forEach(function(name) { |
| 75 Object.defineProperty(to, name, | 81 Object.defineProperty(to, name, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 88 case 'prototype': | 94 case 'prototype': |
| 89 case 'toString': | 95 case 'toString': |
| 90 return; | 96 return; |
| 91 } | 97 } |
| 92 Object.defineProperty(to, name, | 98 Object.defineProperty(to, name, |
| 93 Object.getOwnPropertyDescriptor(from, name)); | 99 Object.getOwnPropertyDescriptor(from, name)); |
| 94 }); | 100 }); |
| 95 return to; | 101 return to; |
| 96 }; | 102 }; |
| 97 | 103 |
| 104 function oneOf(object, propertyNames) { |
| 105 for (var i = 0; i < propertyNames.length; i++) { |
| 106 if (propertyNames[i] in object) |
| 107 return propertyNames[i]; |
| 108 } |
| 109 } |
| 110 |
| 98 // Mozilla's old DOM bindings are bretty busted: | 111 // Mozilla's old DOM bindings are bretty busted: |
| 99 // https://bugzilla.mozilla.org/show_bug.cgi?id=855844 | 112 // https://bugzilla.mozilla.org/show_bug.cgi?id=855844 |
| 100 // Make sure they are create before we start modifying things. | 113 // Make sure they are create before we start modifying things. |
| 101 Object.getOwnPropertyNames(window); | 114 Object.getOwnPropertyNames(window); |
| 102 | 115 |
| 103 function getWrapperConstructor(node) { | 116 function getWrapperConstructor(node) { |
| 104 var nativePrototype = node.__proto__ || Object.getPrototypeOf(node); | 117 var nativePrototype = node.__proto__ || Object.getPrototypeOf(node); |
| 105 var wrapperConstructor = constructorTable.get(nativePrototype); | 118 var wrapperConstructor = constructorTable.get(nativePrototype); |
| 106 if (wrapperConstructor) | 119 if (wrapperConstructor) |
| 107 return wrapperConstructor; | 120 return wrapperConstructor; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 126 | 139 |
| 127 // This is used as a fallback when getting the descriptor fails in | 140 // This is used as a fallback when getting the descriptor fails in |
| 128 // installProperty. | 141 // installProperty. |
| 129 var dummyDescriptor = { | 142 var dummyDescriptor = { |
| 130 get: function() {}, | 143 get: function() {}, |
| 131 set: function(v) {}, | 144 set: function(v) {}, |
| 132 configurable: true, | 145 configurable: true, |
| 133 enumerable: true | 146 enumerable: true |
| 134 }; | 147 }; |
| 135 | 148 |
| 149 function isEventHandlerName(name) { |
| 150 return /^on[a-z]+$/.test(name); |
| 151 } |
| 152 |
| 136 function installProperty(source, target, allowMethod) { | 153 function installProperty(source, target, allowMethod) { |
| 137 Object.getOwnPropertyNames(source).forEach(function(name) { | 154 Object.getOwnPropertyNames(source).forEach(function(name) { |
| 138 if (name in target) | 155 if (name in target) |
| 139 return; | 156 return; |
| 140 | 157 |
| 141 if (isFirefox) { | 158 if (isFirefox) { |
| 142 // Tickle Firefox's old bindings. | 159 // Tickle Firefox's old bindings. |
| 143 source.__lookupGetter__(name); | 160 source.__lookupGetter__(name); |
| 144 } | 161 } |
| 145 var descriptor; | 162 var descriptor; |
| 146 try { | 163 try { |
| 147 descriptor = Object.getOwnPropertyDescriptor(source, name); | 164 descriptor = Object.getOwnPropertyDescriptor(source, name); |
| 148 } catch (ex) { | 165 } catch (ex) { |
| 149 // JSC and V8 both use data properties instead accessors which can cause | 166 // JSC and V8 both use data properties instead of accessors which can |
| 150 // getting the property desciptor throw an exception. | 167 // cause getting the property desciptor to throw an exception. |
| 151 // https://bugs.webkit.org/show_bug.cgi?id=49739 | 168 // https://bugs.webkit.org/show_bug.cgi?id=49739 |
| 152 descriptor = dummyDescriptor; | 169 descriptor = dummyDescriptor; |
| 153 } | 170 } |
| 154 var getter, setter; | 171 var getter, setter; |
| 155 if (allowMethod && typeof descriptor.value === 'function') { | 172 if (allowMethod && typeof descriptor.value === 'function') { |
| 156 target[name] = function() { | 173 target[name] = function() { |
| 157 return this.impl[name].apply(this.impl, arguments); | 174 return this.impl[name].apply(this.impl, arguments); |
| 158 }; | 175 }; |
| 159 return; | 176 return; |
| 160 } | 177 } |
| 161 | 178 |
| 162 getter = function() { | 179 var isEvent = isEventHandlerName(name); |
| 163 return this.impl[name]; | 180 if (isEvent) { |
| 164 }; | 181 getter = scope.getEventHandlerGetter(name); |
| 165 | 182 } else { |
| 166 if (descriptor.writable || descriptor.set) { | 183 getter = function() { |
| 167 setter = function(value) { | 184 return this.impl[name]; |
| 168 this.impl[name] = value; | |
| 169 }; | 185 }; |
| 170 } | 186 } |
| 171 | 187 |
| 188 if (descriptor.writable || descriptor.set) { |
| 189 if (isEvent) { |
| 190 setter = scope.getEventHandlerSetter(name); |
| 191 } else { |
| 192 setter = function(value) { |
| 193 this.impl[name] = value; |
| 194 }; |
| 195 } |
| 196 } |
| 197 |
| 172 Object.defineProperty(target, name, { | 198 Object.defineProperty(target, name, { |
| 173 get: getter, | 199 get: getter, |
| 174 set: setter, | 200 set: setter, |
| 175 configurable: descriptor.configurable, | 201 configurable: descriptor.configurable, |
| 176 enumerable: descriptor.enumerable | 202 enumerable: descriptor.enumerable |
| 177 }); | 203 }); |
| 178 }); | 204 }); |
| 179 } | 205 } |
| 180 | 206 |
| 181 /** | 207 /** |
| 182 * @param {Function} nativeConstructor | 208 * @param {Function} nativeConstructor |
| 183 * @param {Function} wrapperConstructor | 209 * @param {Function} wrapperConstructor |
| 184 * @param {string|Object=} opt_instance If present, this is used to extract | 210 * @param {Object=} opt_instance If present, this is used to extract |
| 185 * properties from an instance object. If this is a string | 211 * properties from an instance object. |
| 186 * |document.createElement| is used to create an instance. | |
| 187 */ | 212 */ |
| 188 function register(nativeConstructor, wrapperConstructor, opt_instance) { | 213 function register(nativeConstructor, wrapperConstructor, opt_instance) { |
| 189 var nativePrototype = nativeConstructor.prototype; | 214 var nativePrototype = nativeConstructor.prototype; |
| 190 registerInternal(nativePrototype, wrapperConstructor, opt_instance); | 215 registerInternal(nativePrototype, wrapperConstructor, opt_instance); |
| 191 mixinStatics(wrapperConstructor, nativeConstructor); | 216 mixinStatics(wrapperConstructor, nativeConstructor); |
| 192 } | 217 } |
| 193 | 218 |
| 194 function registerInternal(nativePrototype, wrapperConstructor, opt_instance) { | 219 function registerInternal(nativePrototype, wrapperConstructor, opt_instance) { |
| 195 var wrapperPrototype = wrapperConstructor.prototype; | 220 var wrapperPrototype = wrapperConstructor.prototype; |
| 196 assert(constructorTable.get(nativePrototype) === undefined); | 221 assert(constructorTable.get(nativePrototype) === undefined); |
| 222 |
| 197 constructorTable.set(nativePrototype, wrapperConstructor); | 223 constructorTable.set(nativePrototype, wrapperConstructor); |
| 224 nativePrototypeTable.set(wrapperPrototype, nativePrototype); |
| 225 |
| 198 addForwardingProperties(nativePrototype, wrapperPrototype); | 226 addForwardingProperties(nativePrototype, wrapperPrototype); |
| 199 if (opt_instance) | 227 if (opt_instance) |
| 200 registerInstanceProperties(wrapperPrototype, opt_instance); | 228 registerInstanceProperties(wrapperPrototype, opt_instance); |
| 201 } | 229 } |
| 202 | 230 |
| 203 function isWrapperFor(wrapperConstructor, nativeConstructor) { | 231 function isWrapperFor(wrapperConstructor, nativeConstructor) { |
| 204 return constructorTable.get(nativeConstructor.prototype) === | 232 return constructorTable.get(nativeConstructor.prototype) === |
| 205 wrapperConstructor; | 233 wrapperConstructor; |
| 206 } | 234 } |
| 207 | 235 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 225 return GeneratedWrapper; | 253 return GeneratedWrapper; |
| 226 } | 254 } |
| 227 | 255 |
| 228 function createWrapperConstructor(superWrapperConstructor) { | 256 function createWrapperConstructor(superWrapperConstructor) { |
| 229 function GeneratedWrapper(node) { | 257 function GeneratedWrapper(node) { |
| 230 superWrapperConstructor.call(this, node); | 258 superWrapperConstructor.call(this, node); |
| 231 } | 259 } |
| 232 GeneratedWrapper.prototype = | 260 GeneratedWrapper.prototype = |
| 233 Object.create(superWrapperConstructor.prototype); | 261 Object.create(superWrapperConstructor.prototype); |
| 234 GeneratedWrapper.prototype.constructor = GeneratedWrapper; | 262 GeneratedWrapper.prototype.constructor = GeneratedWrapper; |
| 235 // We add this property to work around a Firefox bug where HTMLFormElement | |
| 236 // and HTMLInputElements sometimes have their constructor incorrectly | |
| 237 // attached to GeneratedWrapper. See lib/patches-shadowdom-polyfill.js | |
| 238 GeneratedWrapper._ShadowDOMPolyfill$isGeneratedWrapper = true; | |
| 239 | 263 |
| 240 return GeneratedWrapper; | 264 return GeneratedWrapper; |
| 241 } | 265 } |
| 242 | 266 |
| 243 var OriginalDOMImplementation = DOMImplementation; | 267 var OriginalDOMImplementation = DOMImplementation; |
| 244 var OriginalEvent = Event; | 268 var OriginalEvent = Event; |
| 245 var OriginalNode = Node; | 269 var OriginalNode = Node; |
| 246 var OriginalWindow = Window; | 270 var OriginalWindow = Window; |
| 271 var OriginalRange = Range; |
| 247 | 272 |
| 248 function isWrapper(object) { | 273 function isWrapper(object) { |
| 249 return object instanceof wrappers.EventTarget || | 274 return object instanceof wrappers.EventTarget || |
| 250 object instanceof wrappers.Event || | 275 object instanceof wrappers.Event || |
| 276 object instanceof wrappers.Range || |
| 251 object instanceof wrappers.DOMImplementation; | 277 object instanceof wrappers.DOMImplementation; |
| 252 } | 278 } |
| 253 | 279 |
| 254 function isNative(object) { | 280 function isNative(object) { |
| 255 return object instanceof OriginalNode || | 281 return object instanceof OriginalNode || |
| 256 object instanceof OriginalEvent || | 282 object instanceof OriginalEvent || |
| 257 object instanceof OriginalWindow || | 283 object instanceof OriginalWindow || |
| 284 object instanceof OriginalRange || |
| 258 object instanceof OriginalDOMImplementation; | 285 object instanceof OriginalDOMImplementation; |
| 259 } | 286 } |
| 260 | 287 |
| 261 /** | 288 /** |
| 262 * Wraps a node in a WrapperNode. If there already exists a wrapper for the | 289 * Wraps a node in a WrapperNode. If there already exists a wrapper for the |
| 263 * |node| that wrapper is returned instead. | 290 * |node| that wrapper is returned instead. |
| 264 * @param {Node} node | 291 * @param {Node} node |
| 265 * @return {WrapperNode} | 292 * @return {WrapperNode} |
| 266 */ | 293 */ |
| 267 function wrap(impl) { | 294 function wrap(impl) { |
| 268 if (impl === null) | 295 if (impl === null) |
| 269 return null; | 296 return null; |
| 270 | 297 |
| 271 assert(isNative(impl)); | 298 assert(isNative(impl)); |
| 272 var wrapper = wrapperTable.get(impl); | 299 var wrapper = wrapperTable.get(impl); |
| 273 if (!wrapper) { | 300 if (!wrapper) |
| 274 var wrapperConstructor = getWrapperConstructor(impl); | 301 wrapperTable.set(impl, wrapper = new (getWrapperConstructor(impl))(impl)); |
| 275 wrapper = new wrapperConstructor(impl); | |
| 276 wrapperTable.set(impl, wrapper); | |
| 277 } | |
| 278 return wrapper; | 302 return wrapper; |
| 279 } | 303 } |
| 280 | 304 |
| 281 /** | 305 /** |
| 282 * Unwraps a wrapper and returns the node it is wrapping. | 306 * Unwraps a wrapper and returns the node it is wrapping. |
| 283 * @param {WrapperNode} wrapper | 307 * @param {WrapperNode} wrapper |
| 284 * @return {Node} | 308 * @return {Node} |
| 285 */ | 309 */ |
| 286 function unwrap(wrapper) { | 310 function unwrap(wrapper) { |
| 287 if (wrapper === null) | 311 if (wrapper === null) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 * Forwards existing methods on the native object to the wrapper methods. | 364 * Forwards existing methods on the native object to the wrapper methods. |
| 341 * This does not wrap any of the arguments or the return value since the | 365 * This does not wrap any of the arguments or the return value since the |
| 342 * wrapper implementation already takes care of that. | 366 * wrapper implementation already takes care of that. |
| 343 * @param {Array.<Function>} constructors | 367 * @param {Array.<Function>} constructors |
| 344 * @parem {Array.<string>} names | 368 * @parem {Array.<string>} names |
| 345 */ | 369 */ |
| 346 function forwardMethodsToWrapper(constructors, names) { | 370 function forwardMethodsToWrapper(constructors, names) { |
| 347 constructors.forEach(function(constructor) { | 371 constructors.forEach(function(constructor) { |
| 348 names.forEach(function(name) { | 372 names.forEach(function(name) { |
| 349 constructor.prototype[name] = function() { | 373 constructor.prototype[name] = function() { |
| 350 var w = wrap(this); | 374 var w = wrapIfNeeded(this); |
| 351 return w[name].apply(w, arguments); | 375 return w[name].apply(w, arguments); |
| 352 }; | 376 }; |
| 353 }); | 377 }); |
| 354 }); | 378 }); |
| 355 } | 379 } |
| 356 | 380 |
| 357 scope.assert = assert; | 381 scope.assert = assert; |
| 382 scope.constructorTable = constructorTable; |
| 358 scope.defineGetter = defineGetter; | 383 scope.defineGetter = defineGetter; |
| 359 scope.defineWrapGetter = defineWrapGetter; | 384 scope.defineWrapGetter = defineWrapGetter; |
| 360 scope.forwardMethodsToWrapper = forwardMethodsToWrapper; | 385 scope.forwardMethodsToWrapper = forwardMethodsToWrapper; |
| 361 scope.isWrapper = isWrapper; | |
| 362 scope.isWrapperFor = isWrapperFor; | 386 scope.isWrapperFor = isWrapperFor; |
| 363 scope.mixin = mixin; | 387 scope.mixin = mixin; |
| 388 scope.nativePrototypeTable = nativePrototypeTable; |
| 389 scope.oneOf = oneOf; |
| 364 scope.registerObject = registerObject; | 390 scope.registerObject = registerObject; |
| 365 scope.registerWrapper = register; | 391 scope.registerWrapper = register; |
| 366 scope.rewrap = rewrap; | 392 scope.rewrap = rewrap; |
| 367 scope.unwrap = unwrap; | 393 scope.unwrap = unwrap; |
| 368 scope.unwrapIfNeeded = unwrapIfNeeded; | 394 scope.unwrapIfNeeded = unwrapIfNeeded; |
| 369 scope.wrap = wrap; | 395 scope.wrap = wrap; |
| 370 scope.wrapIfNeeded = wrapIfNeeded; | 396 scope.wrapIfNeeded = wrapIfNeeded; |
| 371 scope.wrappers = wrappers; | 397 scope.wrappers = wrappers; |
| 372 | 398 |
| 373 })(this.ShadowDOMPolyfill); | 399 })(this.ShadowDOMPolyfill); |
| 374 | |
| 375 // Copyright 2013 The Polymer Authors. All rights reserved. | 400 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 376 // Use of this source code is goverened by a BSD-style | 401 // Use of this source code is goverened by a BSD-style |
| 377 // license that can be found in the LICENSE file. | 402 // license that can be found in the LICENSE file. |
| 378 | 403 |
| 379 (function(scope) { | 404 (function(scope) { |
| 380 'use strict'; | 405 'use strict'; |
| 381 | 406 |
| 382 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 407 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
| 383 var mixin = scope.mixin; | 408 var mixin = scope.mixin; |
| 384 var registerWrapper = scope.registerWrapper; | 409 var registerWrapper = scope.registerWrapper; |
| 385 var unwrap = scope.unwrap; | 410 var unwrap = scope.unwrap; |
| 386 var wrap = scope.wrap; | 411 var wrap = scope.wrap; |
| 387 var wrappers = scope.wrappers; | 412 var wrappers = scope.wrappers; |
| 388 | 413 |
| 389 var wrappedFuns = new SideTable(); | 414 var wrappedFuns = new SideTable(); |
| 390 var listenersTable = new SideTable(); | 415 var listenersTable = new SideTable(); |
| 391 var handledEventsTable = new SideTable(); | 416 var handledEventsTable = new SideTable(); |
| 392 var targetTable = new SideTable(); | 417 var targetTable = new SideTable(); |
| 393 var currentTargetTable = new SideTable(); | 418 var currentTargetTable = new SideTable(); |
| 394 var relatedTargetTable = new SideTable(); | 419 var relatedTargetTable = new SideTable(); |
| 395 var eventPhaseTable = new SideTable(); | 420 var eventPhaseTable = new SideTable(); |
| 396 var stopPropagationTable = new SideTable(); | 421 var stopPropagationTable = new SideTable(); |
| 397 var stopImmediatePropagationTable = new SideTable(); | 422 var stopImmediatePropagationTable = new SideTable(); |
| 423 var eventHandlersTable = new SideTable(); |
| 424 var eventPathTable = new SideTable(); |
| 398 | 425 |
| 399 function isShadowRoot(node) { | 426 function isShadowRoot(node) { |
| 400 return node instanceof wrappers.ShadowRoot; | 427 return node instanceof wrappers.ShadowRoot; |
| 401 } | 428 } |
| 402 | 429 |
| 403 function isInsertionPoint(node) { | 430 function isInsertionPoint(node) { |
| 404 var localName = node.localName; | 431 var localName = node.localName; |
| 405 return localName === 'content' || localName === 'shadow'; | 432 return localName === 'content' || localName === 'shadow'; |
| 406 } | 433 } |
| 407 | 434 |
| 408 function isShadowHost(node) { | 435 function isShadowHost(node) { |
| 409 return !!node.shadowRoot; | 436 return !!node.shadowRoot; |
| 410 } | 437 } |
| 411 | 438 |
| 412 function getEventParent(node) { | 439 function getEventParent(node) { |
| 413 var dv; | 440 var dv; |
| 414 return node.parentNode || (dv = node.defaultView) && wrap(dv) || null; | 441 return node.parentNode || (dv = node.defaultView) && wrap(dv) || null; |
| 415 } | 442 } |
| 416 | 443 |
| 417 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#df
n-adjusted-parent | 444 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#df
n-adjusted-parent |
| 418 function calculateParents(node, context, ancestors) { | 445 function calculateParents(node, context, ancestors) { |
| 419 if (ancestors.length) | 446 if (ancestors.length) |
| 420 return ancestors.shift(); | 447 return ancestors.shift(); |
| 421 | 448 |
| 422 // 1. | 449 // 1. |
| 423 if (isShadowRoot(node)) | 450 if (isShadowRoot(node)) |
| 424 return node.insertionParent || scope.getHostForShadowRoot(node); | 451 return getInsertionParent(node) || scope.getHostForShadowRoot(node); |
| 425 | 452 |
| 426 // 2. | 453 // 2. |
| 427 var eventParents = scope.eventParentsTable.get(node); | 454 var eventParents = scope.eventParentsTable.get(node); |
| 428 if (eventParents) { | 455 if (eventParents) { |
| 429 // Copy over the remaining event parents for next iteration. | 456 // Copy over the remaining event parents for next iteration. |
| 430 for (var i = 1; i < eventParents.length; i++) { | 457 for (var i = 1; i < eventParents.length; i++) { |
| 431 ancestors[i - 1] = eventParents[i]; | 458 ancestors[i - 1] = eventParents[i]; |
| 432 } | 459 } |
| 433 return eventParents[0]; | 460 return eventParents[0]; |
| 434 } | 461 } |
| 435 | 462 |
| 436 // 3. | 463 // 3. |
| 437 if (context && isInsertionPoint(node)) { | 464 if (context && isInsertionPoint(node)) { |
| 438 var parentNode = node.parentNode; | 465 var parentNode = node.parentNode; |
| 439 if (parentNode && isShadowHost(parentNode)) { | 466 if (parentNode && isShadowHost(parentNode)) { |
| 440 var trees = scope.getShadowTrees(parentNode); | 467 var trees = scope.getShadowTrees(parentNode); |
| 441 var p = context.insertionParent; | 468 var p = getInsertionParent(context); |
| 442 for (var i = 0; i < trees.length; i++) { | 469 for (var i = 0; i < trees.length; i++) { |
| 443 if (trees[i].contains(p)) | 470 if (trees[i].contains(p)) |
| 444 return p; | 471 return p; |
| 445 } | 472 } |
| 446 } | 473 } |
| 447 } | 474 } |
| 448 | 475 |
| 449 return getEventParent(node); | 476 return getEventParent(node); |
| 450 } | 477 } |
| 451 | 478 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 last = ancestor; // 3.4.6. | 543 last = ancestor; // 3.4.6. |
| 517 ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7. | 544 ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7. |
| 518 } | 545 } |
| 519 if (isShadowRoot(target)) // 3.5. | 546 if (isShadowRoot(target)) // 3.5. |
| 520 target = scope.getHostForShadowRoot(target); | 547 target = scope.getHostForShadowRoot(target); |
| 521 else | 548 else |
| 522 target = target.parentNode; // 3.6. | 549 target = target.parentNode; // 3.6. |
| 523 } | 550 } |
| 524 } | 551 } |
| 525 | 552 |
| 553 function getInsertionParent(node) { |
| 554 return scope.insertionParentTable.get(node); |
| 555 } |
| 556 |
| 526 function isDistributed(node) { | 557 function isDistributed(node) { |
| 527 return node.insertionParent; | 558 return getInsertionParent(node); |
| 528 } | 559 } |
| 529 | 560 |
| 530 function rootOfNode(node) { | 561 function rootOfNode(node) { |
| 531 var p; | 562 var p; |
| 532 while (p = node.parentNode) { | 563 while (p = node.parentNode) { |
| 533 node = p; | 564 node = p; |
| 534 } | 565 } |
| 535 return node; | 566 return node; |
| 536 } | 567 } |
| 537 | 568 |
| 538 function inSameTree(a, b) { | 569 function inSameTree(a, b) { |
| 539 return rootOfNode(a) === rootOfNode(b); | 570 return rootOfNode(a) === rootOfNode(b); |
| 540 } | 571 } |
| 541 | 572 |
| 573 function enclosedBy(a, b) { |
| 574 if (a === b) |
| 575 return true; |
| 576 if (a instanceof wrappers.ShadowRoot) { |
| 577 var host = scope.getHostForShadowRoot(a); |
| 578 return enclosedBy(rootOfNode(host), b); |
| 579 } |
| 580 return false; |
| 581 |
| 582 } |
| 583 |
| 542 function isMutationEvent(type) { | 584 function isMutationEvent(type) { |
| 543 switch (type) { | 585 switch (type) { |
| 544 case 'DOMAttrModified': | 586 case 'DOMAttrModified': |
| 545 case 'DOMAttributeNameChanged': | 587 case 'DOMAttributeNameChanged': |
| 546 case 'DOMCharacterDataModified': | 588 case 'DOMCharacterDataModified': |
| 547 case 'DOMElementNameChanged': | 589 case 'DOMElementNameChanged': |
| 548 case 'DOMNodeInserted': | 590 case 'DOMNodeInserted': |
| 549 case 'DOMNodeInsertedIntoDocument': | 591 case 'DOMNodeInsertedIntoDocument': |
| 550 case 'DOMNodeRemoved': | 592 case 'DOMNodeRemoved': |
| 551 case 'DOMNodeRemovedFromDocument': | 593 case 'DOMNodeRemovedFromDocument': |
| (...skipping 21 matching lines...) Expand all Loading... |
| 573 } | 615 } |
| 574 | 616 |
| 575 function dispatchEvent(event, originalWrapperTarget) { | 617 function dispatchEvent(event, originalWrapperTarget) { |
| 576 var eventPath = retarget(originalWrapperTarget); | 618 var eventPath = retarget(originalWrapperTarget); |
| 577 | 619 |
| 578 // For window load events the load event is dispatched at the window but | 620 // For window load events the load event is dispatched at the window but |
| 579 // the target is set to the document. | 621 // the target is set to the document. |
| 580 // | 622 // |
| 581 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end | 623 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end |
| 582 // | 624 // |
| 583 // TODO(arv): Find a loess hacky way to do this. | 625 // TODO(arv): Find a less hacky way to do this. |
| 584 if (event.type === 'load' && | 626 if (event.type === 'load' && |
| 585 eventPath.length === 2 && | 627 eventPath.length === 2 && |
| 586 eventPath[0].target instanceof wrappers.Document) { | 628 eventPath[0].target instanceof wrappers.Document) { |
| 587 eventPath.shift(); | 629 eventPath.shift(); |
| 588 } | 630 } |
| 589 | 631 |
| 632 eventPathTable.set(event, eventPath); |
| 633 |
| 590 if (dispatchCapturing(event, eventPath)) { | 634 if (dispatchCapturing(event, eventPath)) { |
| 591 if (dispatchAtTarget(event, eventPath)) { | 635 if (dispatchAtTarget(event, eventPath)) { |
| 592 dispatchBubbling(event, eventPath); | 636 dispatchBubbling(event, eventPath); |
| 593 } | 637 } |
| 594 } | 638 } |
| 595 | 639 |
| 596 eventPhaseTable.set(event, Event.NONE); | 640 eventPhaseTable.set(event, Event.NONE); |
| 597 currentTargetTable.set(event, null); | 641 currentTargetTable.set(event, null); |
| 598 | 642 |
| 599 return event.defaultPrevented; | 643 return event.defaultPrevented; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 Event.prototype = { | 787 Event.prototype = { |
| 744 get target() { | 788 get target() { |
| 745 return targetTable.get(this); | 789 return targetTable.get(this); |
| 746 }, | 790 }, |
| 747 get currentTarget() { | 791 get currentTarget() { |
| 748 return currentTargetTable.get(this); | 792 return currentTargetTable.get(this); |
| 749 }, | 793 }, |
| 750 get eventPhase() { | 794 get eventPhase() { |
| 751 return eventPhaseTable.get(this); | 795 return eventPhaseTable.get(this); |
| 752 }, | 796 }, |
| 797 get path() { |
| 798 var nodeList = new wrappers.NodeList(); |
| 799 var eventPath = eventPathTable.get(this); |
| 800 if (eventPath) { |
| 801 var index = 0; |
| 802 var lastIndex = eventPath.length - 1; |
| 803 var baseRoot = rootOfNode(currentTargetTable.get(this)); |
| 804 |
| 805 for (var i = 0; i <= lastIndex; i++) { |
| 806 var currentTarget = eventPath[i].currentTarget; |
| 807 var currentRoot = rootOfNode(currentTarget); |
| 808 if (enclosedBy(baseRoot, currentRoot) && |
| 809 // Make sure we do not add Window to the path. |
| 810 (i !== lastIndex || currentTarget instanceof wrappers.Node)) { |
| 811 nodeList[index++] = currentTarget; |
| 812 } |
| 813 } |
| 814 nodeList.length = index; |
| 815 } |
| 816 return nodeList; |
| 817 }, |
| 753 stopPropagation: function() { | 818 stopPropagation: function() { |
| 754 stopPropagationTable.set(this, true); | 819 stopPropagationTable.set(this, true); |
| 755 }, | 820 }, |
| 756 stopImmediatePropagation: function() { | 821 stopImmediatePropagation: function() { |
| 757 stopPropagationTable.set(this, true); | 822 stopPropagationTable.set(this, true); |
| 758 stopImmediatePropagationTable.set(this, true); | 823 stopImmediatePropagationTable.set(this, true); |
| 759 } | 824 } |
| 760 }; | 825 }; |
| 761 registerWrapper(OriginalEvent, Event, document.createEvent('Event')); | 826 registerWrapper(OriginalEvent, Event, document.createEvent('Event')); |
| 762 | 827 |
| 763 function unwrapOptions(options) { | 828 function unwrapOptions(options) { |
| 764 if (!options || !options.relatedTarget) | 829 if (!options || !options.relatedTarget) |
| 765 return options; | 830 return options; |
| 766 return Object.create(options, { | 831 return Object.create(options, { |
| 767 relatedTarget: {value: unwrap(options.relatedTarget)} | 832 relatedTarget: {value: unwrap(options.relatedTarget)} |
| 768 }); | 833 }); |
| 769 } | 834 } |
| 770 | 835 |
| 771 function registerGenericEvent(name, SuperEvent, prototype) { | 836 function registerGenericEvent(name, SuperEvent, prototype) { |
| 772 var OriginalEvent = window[name]; | 837 var OriginalEvent = window[name]; |
| 773 var GenericEvent = function(type, options) { | 838 var GenericEvent = function(type, options) { |
| 774 if (type instanceof OriginalEvent) | 839 if (type instanceof OriginalEvent) |
| 775 this.impl = type; | 840 this.impl = type; |
| 776 else | 841 else |
| 777 return wrap(constructEvent(OriginalEvent, name, type, options)); | 842 return wrap(constructEvent(OriginalEvent, name, type, options)); |
| 778 }; | 843 }; |
| 779 GenericEvent.prototype = Object.create(SuperEvent.prototype); | 844 GenericEvent.prototype = Object.create(SuperEvent.prototype); |
| 780 if (prototype) | 845 if (prototype) |
| 781 mixin(GenericEvent.prototype, prototype); | 846 mixin(GenericEvent.prototype, prototype); |
| 782 // Firefox does not support FocusEvent | 847 if (OriginalEvent) { |
| 783 // https://bugzilla.mozilla.org/show_bug.cgi?id=855741 | 848 // IE does not support event constructors but FocusEvent can only be |
| 784 if (OriginalEvent) | 849 // created using new FocusEvent in Firefox. |
| 785 registerWrapper(OriginalEvent, GenericEvent, document.createEvent(name)); | 850 // https://bugzilla.mozilla.org/show_bug.cgi?id=882165 |
| 851 if (OriginalEvent.prototype['init' + name]) { |
| 852 registerWrapper(OriginalEvent, GenericEvent, |
| 853 document.createEvent(name)); |
| 854 } else { |
| 855 registerWrapper(OriginalEvent, GenericEvent, new OriginalEvent('temp')); |
| 856 } |
| 857 } |
| 786 return GenericEvent; | 858 return GenericEvent; |
| 787 } | 859 } |
| 788 | 860 |
| 789 var UIEvent = registerGenericEvent('UIEvent', Event); | 861 var UIEvent = registerGenericEvent('UIEvent', Event); |
| 790 var CustomEvent = registerGenericEvent('CustomEvent', Event); | 862 var CustomEvent = registerGenericEvent('CustomEvent', Event); |
| 791 | 863 |
| 792 var relatedTargetProto = { | 864 var relatedTargetProto = { |
| 793 get relatedTarget() { | 865 get relatedTarget() { |
| 794 return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget); | 866 return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget); |
| 795 } | 867 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 } | 977 } |
| 906 | 978 |
| 907 // Node and Window have different internal type checks in WebKit so we cannot | 979 // Node and Window have different internal type checks in WebKit so we cannot |
| 908 // use the same method as the original function. | 980 // use the same method as the original function. |
| 909 var methodNames = [ | 981 var methodNames = [ |
| 910 'addEventListener', | 982 'addEventListener', |
| 911 'removeEventListener', | 983 'removeEventListener', |
| 912 'dispatchEvent' | 984 'dispatchEvent' |
| 913 ]; | 985 ]; |
| 914 | 986 |
| 915 [Element, Window, Document].forEach(function(constructor) { | 987 [Node, Window].forEach(function(constructor) { |
| 916 var p = constructor.prototype; | 988 var p = constructor.prototype; |
| 917 methodNames.forEach(function(name) { | 989 methodNames.forEach(function(name) { |
| 918 Object.defineProperty(p, name + '_', {value: p[name]}); | 990 Object.defineProperty(p, name + '_', {value: p[name]}); |
| 919 }); | 991 }); |
| 920 }); | 992 }); |
| 921 | 993 |
| 922 function getTargetToListenAt(wrapper) { | 994 function getTargetToListenAt(wrapper) { |
| 923 if (wrapper instanceof wrappers.ShadowRoot) | 995 if (wrapper instanceof wrappers.ShadowRoot) |
| 924 wrapper = scope.getHostForShadowRoot(wrapper); | 996 wrapper = scope.getHostForShadowRoot(wrapper); |
| 925 return unwrap(wrapper); | 997 return unwrap(wrapper); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 var element = wrap(originalElementFromPoint.call(document.impl, x, y)); | 1064 var element = wrap(originalElementFromPoint.call(document.impl, x, y)); |
| 993 var targets = retarget(element, this) | 1065 var targets = retarget(element, this) |
| 994 for (var i = 0; i < targets.length; i++) { | 1066 for (var i = 0; i < targets.length; i++) { |
| 995 var target = targets[i]; | 1067 var target = targets[i]; |
| 996 if (target.currentTarget === self) | 1068 if (target.currentTarget === self) |
| 997 return target.target; | 1069 return target.target; |
| 998 } | 1070 } |
| 999 return null; | 1071 return null; |
| 1000 } | 1072 } |
| 1001 | 1073 |
| 1074 /** |
| 1075 * Returns a function that is to be used as a getter for `onfoo` properties. |
| 1076 * @param {string} name |
| 1077 * @return {Function} |
| 1078 */ |
| 1079 function getEventHandlerGetter(name) { |
| 1080 return function() { |
| 1081 var inlineEventHandlers = eventHandlersTable.get(this); |
| 1082 return inlineEventHandlers && inlineEventHandlers[name] && |
| 1083 inlineEventHandlers[name].value || null; |
| 1084 }; |
| 1085 } |
| 1086 |
| 1087 /** |
| 1088 * Returns a function that is to be used as a setter for `onfoo` properties. |
| 1089 * @param {string} name |
| 1090 * @return {Function} |
| 1091 */ |
| 1092 function getEventHandlerSetter(name) { |
| 1093 var eventType = name.slice(2); |
| 1094 return function(value) { |
| 1095 var inlineEventHandlers = eventHandlersTable.get(this); |
| 1096 if (!inlineEventHandlers) { |
| 1097 inlineEventHandlers = Object.create(null); |
| 1098 eventHandlersTable.set(this, inlineEventHandlers); |
| 1099 } |
| 1100 |
| 1101 var old = inlineEventHandlers[name]; |
| 1102 if (old) |
| 1103 this.removeEventListener(eventType, old.wrapped, false); |
| 1104 |
| 1105 if (typeof value === 'function') { |
| 1106 var wrapped = function(e) { |
| 1107 var rv = value.call(this, e); |
| 1108 if (rv === false) |
| 1109 e.preventDefault(); |
| 1110 else if (name === 'onbeforeunload' && typeof rv === 'string') |
| 1111 e.returnValue = rv; |
| 1112 // mouseover uses true for preventDefault but preventDefault for |
| 1113 // mouseover is ignored by browsers these day. |
| 1114 }; |
| 1115 |
| 1116 this.addEventListener(eventType, wrapped, false); |
| 1117 inlineEventHandlers[name] = { |
| 1118 value: value, |
| 1119 wrapped: wrapped |
| 1120 }; |
| 1121 } |
| 1122 }; |
| 1123 } |
| 1124 |
| 1002 scope.adjustRelatedTarget = adjustRelatedTarget; | 1125 scope.adjustRelatedTarget = adjustRelatedTarget; |
| 1003 scope.elementFromPoint = elementFromPoint; | 1126 scope.elementFromPoint = elementFromPoint; |
| 1127 scope.getEventHandlerGetter = getEventHandlerGetter; |
| 1128 scope.getEventHandlerSetter = getEventHandlerSetter; |
| 1004 scope.wrapEventTargetMethods = wrapEventTargetMethods; | 1129 scope.wrapEventTargetMethods = wrapEventTargetMethods; |
| 1005 scope.wrappers.CustomEvent = CustomEvent; | 1130 scope.wrappers.CustomEvent = CustomEvent; |
| 1006 scope.wrappers.Event = Event; | 1131 scope.wrappers.Event = Event; |
| 1007 scope.wrappers.EventTarget = EventTarget; | 1132 scope.wrappers.EventTarget = EventTarget; |
| 1008 scope.wrappers.FocusEvent = FocusEvent; | 1133 scope.wrappers.FocusEvent = FocusEvent; |
| 1009 scope.wrappers.MouseEvent = MouseEvent; | 1134 scope.wrappers.MouseEvent = MouseEvent; |
| 1010 scope.wrappers.MutationEvent = MutationEvent; | 1135 scope.wrappers.MutationEvent = MutationEvent; |
| 1011 scope.wrappers.UIEvent = UIEvent; | 1136 scope.wrappers.UIEvent = UIEvent; |
| 1012 | 1137 |
| 1013 })(this.ShadowDOMPolyfill); | 1138 })(this.ShadowDOMPolyfill); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1066 'use strict'; | 1191 'use strict'; |
| 1067 | 1192 |
| 1068 var EventTarget = scope.wrappers.EventTarget; | 1193 var EventTarget = scope.wrappers.EventTarget; |
| 1069 var NodeList = scope.wrappers.NodeList; | 1194 var NodeList = scope.wrappers.NodeList; |
| 1070 var defineWrapGetter = scope.defineWrapGetter; | 1195 var defineWrapGetter = scope.defineWrapGetter; |
| 1071 var assert = scope.assert; | 1196 var assert = scope.assert; |
| 1072 var mixin = scope.mixin; | 1197 var mixin = scope.mixin; |
| 1073 var registerWrapper = scope.registerWrapper; | 1198 var registerWrapper = scope.registerWrapper; |
| 1074 var unwrap = scope.unwrap; | 1199 var unwrap = scope.unwrap; |
| 1075 var wrap = scope.wrap; | 1200 var wrap = scope.wrap; |
| 1201 var wrapIfNeeded = scope.wrapIfNeeded; |
| 1076 | 1202 |
| 1077 function assertIsNodeWrapper(node) { | 1203 function assertIsNodeWrapper(node) { |
| 1078 assert(node instanceof Node); | 1204 assert(node instanceof Node); |
| 1079 } | 1205 } |
| 1080 | 1206 |
| 1081 /** | 1207 /** |
| 1082 * Collects nodes from a DocumentFragment or a Node for removal followed | 1208 * Collects nodes from a DocumentFragment or a Node for removal followed |
| 1083 * by an insertion. | 1209 * by an insertion. |
| 1084 * | 1210 * |
| 1085 * This updates the internal pointers for node, previousNode and nextNode. | 1211 * This updates the internal pointers for node, previousNode and nextNode. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1112 } | 1238 } |
| 1113 | 1239 |
| 1114 if (previousNode) | 1240 if (previousNode) |
| 1115 previousNode.nextSibling_ = nodes[0]; | 1241 previousNode.nextSibling_ = nodes[0]; |
| 1116 if (nextNode) | 1242 if (nextNode) |
| 1117 nextNode.previousSibling_ = nodes[nodes.length - 1]; | 1243 nextNode.previousSibling_ = nodes[nodes.length - 1]; |
| 1118 | 1244 |
| 1119 return nodes; | 1245 return nodes; |
| 1120 } | 1246 } |
| 1121 | 1247 |
| 1122 function unwrapNodesForInsertion(nodes) { | 1248 function ensureSameOwnerDocument(parent, child) { |
| 1123 if (nodes.length === 1) | 1249 var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ? |
| 1250 parent : parent.ownerDocument; |
| 1251 if (ownerDoc !== child.ownerDocument) |
| 1252 ownerDoc.adoptNode(child); |
| 1253 } |
| 1254 |
| 1255 function adoptNodesIfNeeded(owner, nodes) { |
| 1256 if (!nodes.length) |
| 1257 return; |
| 1258 |
| 1259 var ownerDoc = owner.ownerDocument; |
| 1260 |
| 1261 // All nodes have the same ownerDocument when we get here. |
| 1262 if (ownerDoc === nodes[0].ownerDocument) |
| 1263 return; |
| 1264 |
| 1265 for (var i = 0; i < nodes.length; i++) { |
| 1266 scope.adoptNodeNoRemove(nodes[i], ownerDoc); |
| 1267 } |
| 1268 } |
| 1269 |
| 1270 function unwrapNodesForInsertion(owner, nodes) { |
| 1271 adoptNodesIfNeeded(owner, nodes); |
| 1272 var length = nodes.length; |
| 1273 |
| 1274 if (length === 1) |
| 1124 return unwrap(nodes[0]); | 1275 return unwrap(nodes[0]); |
| 1125 | 1276 |
| 1126 var df = unwrap(document.createDocumentFragment()); | 1277 var df = unwrap(owner.ownerDocument.createDocumentFragment()); |
| 1127 for (var i = 0; i < nodes.length; i++) { | 1278 for (var i = 0; i < length; i++) { |
| 1128 df.appendChild(unwrap(nodes[i])); | 1279 df.appendChild(unwrap(nodes[i])); |
| 1129 } | 1280 } |
| 1130 return df; | 1281 return df; |
| 1131 } | 1282 } |
| 1132 | 1283 |
| 1133 function removeAllChildNodes(wrapper) { | 1284 function removeAllChildNodes(wrapper) { |
| 1134 var childWrapper = wrapper.firstChild; | 1285 if (wrapper.invalidateShadowRenderer()) { |
| 1135 while (childWrapper) { | 1286 var childWrapper = wrapper.firstChild; |
| 1136 assert(childWrapper.parentNode === wrapper); | 1287 while (childWrapper) { |
| 1137 var nextSibling = childWrapper.nextSibling; | 1288 assert(childWrapper.parentNode === wrapper); |
| 1138 var childNode = unwrap(childWrapper); | 1289 var nextSibling = childWrapper.nextSibling; |
| 1139 var parentNode = childNode.parentNode; | 1290 var childNode = unwrap(childWrapper); |
| 1140 if (parentNode) | 1291 var parentNode = childNode.parentNode; |
| 1141 originalRemoveChild.call(parentNode, childNode); | 1292 if (parentNode) |
| 1142 childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.p
arentNode_ = null; | 1293 originalRemoveChild.call(parentNode, childNode); |
| 1143 childWrapper = nextSibling; | 1294 childWrapper.previousSibling_ = childWrapper.nextSibling_ = |
| 1295 childWrapper.parentNode_ = null; |
| 1296 childWrapper = nextSibling; |
| 1297 } |
| 1298 wrapper.firstChild_ = wrapper.lastChild_ = null; |
| 1299 } else { |
| 1300 var node = unwrap(wrapper); |
| 1301 var child = node.firstChild; |
| 1302 var nextSibling; |
| 1303 while (child) { |
| 1304 nextSibling = child.nextSibling; |
| 1305 originalRemoveChild.call(node, child); |
| 1306 child = nextSibling; |
| 1307 } |
| 1144 } | 1308 } |
| 1145 wrapper.firstChild_ = wrapper.lastChild_ = null; | 1309 } |
| 1310 |
| 1311 function invalidateParent(node) { |
| 1312 var p = node.parentNode; |
| 1313 return p && p.invalidateShadowRenderer(); |
| 1146 } | 1314 } |
| 1147 | 1315 |
| 1148 var OriginalNode = window.Node; | 1316 var OriginalNode = window.Node; |
| 1149 | 1317 |
| 1150 /** | 1318 /** |
| 1151 * This represents a wrapper of a native DOM node. | 1319 * This represents a wrapper of a native DOM node. |
| 1152 * @param {!Node} original The original DOM node, aka, the visual DOM node. | 1320 * @param {!Node} original The original DOM node, aka, the visual DOM node. |
| 1153 * @constructor | 1321 * @constructor |
| 1154 * @extends {EventTarget} | 1322 * @extends {EventTarget} |
| 1155 */ | 1323 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 var originalReplaceChild = OriginalNode.prototype.replaceChild; | 1366 var originalReplaceChild = OriginalNode.prototype.replaceChild; |
| 1199 var originalRemoveChild = OriginalNode.prototype.removeChild; | 1367 var originalRemoveChild = OriginalNode.prototype.removeChild; |
| 1200 var originalCompareDocumentPosition = | 1368 var originalCompareDocumentPosition = |
| 1201 OriginalNode.prototype.compareDocumentPosition; | 1369 OriginalNode.prototype.compareDocumentPosition; |
| 1202 | 1370 |
| 1203 Node.prototype = Object.create(EventTarget.prototype); | 1371 Node.prototype = Object.create(EventTarget.prototype); |
| 1204 mixin(Node.prototype, { | 1372 mixin(Node.prototype, { |
| 1205 appendChild: function(childWrapper) { | 1373 appendChild: function(childWrapper) { |
| 1206 assertIsNodeWrapper(childWrapper); | 1374 assertIsNodeWrapper(childWrapper); |
| 1207 | 1375 |
| 1208 this.invalidateShadowRenderer(); | 1376 if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) { |
| 1377 var previousNode = this.lastChild; |
| 1378 var nextNode = null; |
| 1379 var nodes = collectNodes(childWrapper, this, previousNode, nextNode); |
| 1209 | 1380 |
| 1210 var previousNode = this.lastChild; | 1381 this.lastChild_ = nodes[nodes.length - 1]; |
| 1211 var nextNode = null; | 1382 if (!previousNode) |
| 1212 var nodes = collectNodes(childWrapper, this, | 1383 this.firstChild_ = nodes[0]; |
| 1213 previousNode, nextNode); | |
| 1214 | 1384 |
| 1215 this.lastChild_ = nodes[nodes.length - 1]; | 1385 originalAppendChild.call(this.impl, unwrapNodesForInsertion(this, nodes)
); |
| 1216 if (!previousNode) | 1386 } else { |
| 1217 this.firstChild_ = nodes[0]; | 1387 ensureSameOwnerDocument(this, childWrapper); |
| 1388 originalAppendChild.call(this.impl, unwrap(childWrapper)); |
| 1389 } |
| 1218 | 1390 |
| 1219 // TODO(arv): It is unclear if we need to update the visual DOM here. | 1391 childWrapper.nodeWasAdded_(); |
| 1220 // A better aproach might be to make sure we only get here for nodes that | |
| 1221 // are related to a shadow host and then invalidate that and re-render | |
| 1222 // the host (on reflow?). | |
| 1223 originalAppendChild.call(this.impl, unwrapNodesForInsertion(nodes)); | |
| 1224 | 1392 |
| 1225 return childWrapper; | 1393 return childWrapper; |
| 1226 }, | 1394 }, |
| 1227 | 1395 |
| 1228 insertBefore: function(childWrapper, refWrapper) { | 1396 insertBefore: function(childWrapper, refWrapper) { |
| 1229 // TODO(arv): Unify with appendChild | 1397 // TODO(arv): Unify with appendChild |
| 1230 if (!refWrapper) | 1398 if (!refWrapper) |
| 1231 return this.appendChild(childWrapper); | 1399 return this.appendChild(childWrapper); |
| 1232 | 1400 |
| 1233 assertIsNodeWrapper(childWrapper); | 1401 assertIsNodeWrapper(childWrapper); |
| 1234 assertIsNodeWrapper(refWrapper); | 1402 assertIsNodeWrapper(refWrapper); |
| 1235 assert(refWrapper.parentNode === this); | 1403 assert(refWrapper.parentNode === this); |
| 1236 | 1404 |
| 1237 this.invalidateShadowRenderer(); | 1405 if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) { |
| 1406 var previousNode = refWrapper.previousSibling; |
| 1407 var nextNode = refWrapper; |
| 1408 var nodes = collectNodes(childWrapper, this, previousNode, nextNode); |
| 1238 | 1409 |
| 1239 var previousNode = refWrapper.previousSibling; | 1410 if (this.firstChild === refWrapper) |
| 1240 var nextNode = refWrapper; | 1411 this.firstChild_ = nodes[0]; |
| 1241 var nodes = collectNodes(childWrapper, this, | |
| 1242 previousNode, nextNode); | |
| 1243 | 1412 |
| 1413 // insertBefore refWrapper no matter what the parent is? |
| 1414 var refNode = unwrap(refWrapper); |
| 1415 var parentNode = refNode.parentNode; |
| 1244 | 1416 |
| 1245 if (this.firstChild === refWrapper) | 1417 if (parentNode) { |
| 1246 this.firstChild_ = nodes[0]; | 1418 originalInsertBefore.call( |
| 1419 parentNode, |
| 1420 unwrapNodesForInsertion(this, nodes), |
| 1421 refNode); |
| 1422 } else { |
| 1423 adoptNodesIfNeeded(this, nodes); |
| 1424 } |
| 1425 } else { |
| 1426 ensureSameOwnerDocument(this, childWrapper); |
| 1427 originalInsertBefore.call(this.impl, unwrap(childWrapper), |
| 1428 unwrap(refWrapper)); |
| 1429 } |
| 1247 | 1430 |
| 1248 // insertBefore refWrapper no matter what the parent is? | 1431 childWrapper.nodeWasAdded_(); |
| 1249 var refNode = unwrap(refWrapper); | |
| 1250 var parentNode = refNode.parentNode; | |
| 1251 if (parentNode) { | |
| 1252 originalInsertBefore.call( | |
| 1253 parentNode, | |
| 1254 unwrapNodesForInsertion(nodes), | |
| 1255 refNode); | |
| 1256 } | |
| 1257 | 1432 |
| 1258 return childWrapper; | 1433 return childWrapper; |
| 1259 }, | 1434 }, |
| 1260 | 1435 |
| 1261 removeChild: function(childWrapper) { | 1436 removeChild: function(childWrapper) { |
| 1262 assertIsNodeWrapper(childWrapper); | 1437 assertIsNodeWrapper(childWrapper); |
| 1263 if (childWrapper.parentNode !== this) { | 1438 if (childWrapper.parentNode !== this) { |
| 1264 // TODO(arv): DOMException | 1439 // TODO(arv): DOMException |
| 1265 throw new Error('NotFoundError'); | 1440 throw new Error('NotFoundError'); |
| 1266 } | 1441 } |
| 1267 | 1442 |
| 1268 this.invalidateShadowRenderer(); | 1443 var childNode = unwrap(childWrapper); |
| 1444 if (this.invalidateShadowRenderer()) { |
| 1269 | 1445 |
| 1270 // We need to remove the real node from the DOM before updating the | 1446 // We need to remove the real node from the DOM before updating the |
| 1271 // pointers. This is so that that mutation event is dispatched before | 1447 // pointers. This is so that that mutation event is dispatched before |
| 1272 // the pointers have changed. | 1448 // the pointers have changed. |
| 1273 var thisFirstChild = this.firstChild; | 1449 var thisFirstChild = this.firstChild; |
| 1274 var thisLastChild = this.lastChild; | 1450 var thisLastChild = this.lastChild; |
| 1275 var childWrapperNextSibling = childWrapper.nextSibling; | 1451 var childWrapperNextSibling = childWrapper.nextSibling; |
| 1276 var childWrapperPreviousSibling = childWrapper.previousSibling; | 1452 var childWrapperPreviousSibling = childWrapper.previousSibling; |
| 1277 | 1453 |
| 1278 var childNode = unwrap(childWrapper); | 1454 var parentNode = childNode.parentNode; |
| 1279 var parentNode = childNode.parentNode; | 1455 if (parentNode) |
| 1280 if (parentNode) | 1456 originalRemoveChild.call(parentNode, childNode); |
| 1281 originalRemoveChild.call(parentNode, childNode); | |
| 1282 | 1457 |
| 1283 if (thisFirstChild === childWrapper) | 1458 if (thisFirstChild === childWrapper) |
| 1284 this.firstChild_ = childWrapperNextSibling; | 1459 this.firstChild_ = childWrapperNextSibling; |
| 1285 if (thisLastChild === childWrapper) | 1460 if (thisLastChild === childWrapper) |
| 1286 this.lastChild_ = childWrapperPreviousSibling; | 1461 this.lastChild_ = childWrapperPreviousSibling; |
| 1287 if (childWrapperPreviousSibling) | 1462 if (childWrapperPreviousSibling) |
| 1288 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; | 1463 childWrapperPreviousSibling.nextSibling_ = childWrapperNextSibling; |
| 1289 if (childWrapperNextSibling) | 1464 if (childWrapperNextSibling) { |
| 1290 childWrapperNextSibling.previousSibling_ = childWrapperPreviousSibling; | 1465 childWrapperNextSibling.previousSibling_ = |
| 1466 childWrapperPreviousSibling; |
| 1467 } |
| 1291 | 1468 |
| 1292 childWrapper.previousSibling_ = childWrapper.nextSibling_ = childWrapper.p
arentNode_ = null; | 1469 childWrapper.previousSibling_ = childWrapper.nextSibling_ = |
| 1470 childWrapper.parentNode_ = undefined; |
| 1471 } else { |
| 1472 originalRemoveChild.call(this.impl, childNode); |
| 1473 } |
| 1293 | 1474 |
| 1294 return childWrapper; | 1475 return childWrapper; |
| 1295 }, | 1476 }, |
| 1296 | 1477 |
| 1297 replaceChild: function(newChildWrapper, oldChildWrapper) { | 1478 replaceChild: function(newChildWrapper, oldChildWrapper) { |
| 1298 assertIsNodeWrapper(newChildWrapper); | 1479 assertIsNodeWrapper(newChildWrapper); |
| 1299 assertIsNodeWrapper(oldChildWrapper); | 1480 assertIsNodeWrapper(oldChildWrapper); |
| 1300 | 1481 |
| 1301 if (oldChildWrapper.parentNode !== this) { | 1482 if (oldChildWrapper.parentNode !== this) { |
| 1302 // TODO(arv): DOMException | 1483 // TODO(arv): DOMException |
| 1303 throw new Error('NotFoundError'); | 1484 throw new Error('NotFoundError'); |
| 1304 } | 1485 } |
| 1305 | 1486 |
| 1306 this.invalidateShadowRenderer(); | 1487 var oldChildNode = unwrap(oldChildWrapper); |
| 1307 | 1488 |
| 1308 var previousNode = oldChildWrapper.previousSibling; | 1489 if (this.invalidateShadowRenderer() || |
| 1309 var nextNode = oldChildWrapper.nextSibling; | 1490 invalidateParent(newChildWrapper)) { |
| 1310 if (nextNode === newChildWrapper) | 1491 var previousNode = oldChildWrapper.previousSibling; |
| 1311 nextNode = newChildWrapper.nextSibling; | 1492 var nextNode = oldChildWrapper.nextSibling; |
| 1312 var nodes = collectNodes(newChildWrapper, this, | 1493 if (nextNode === newChildWrapper) |
| 1313 previousNode, nextNode); | 1494 nextNode = newChildWrapper.nextSibling; |
| 1495 var nodes = collectNodes(newChildWrapper, this, |
| 1496 previousNode, nextNode); |
| 1314 | 1497 |
| 1315 if (this.firstChild === oldChildWrapper) | 1498 if (this.firstChild === oldChildWrapper) |
| 1316 this.firstChild_ = nodes[0]; | 1499 this.firstChild_ = nodes[0]; |
| 1317 if (this.lastChild === oldChildWrapper) | 1500 if (this.lastChild === oldChildWrapper) |
| 1318 this.lastChild_ = nodes[nodes.length - 1]; | 1501 this.lastChild_ = nodes[nodes.length - 1]; |
| 1319 | 1502 |
| 1320 oldChildWrapper.previousSibling_ = null; | 1503 oldChildWrapper.previousSibling_ = oldChildWrapper.nextSibling_ = |
| 1321 oldChildWrapper.nextSibling_ = null; | 1504 oldChildWrapper.parentNode_ = undefined; |
| 1322 oldChildWrapper.parentNode_ = null; | |
| 1323 | 1505 |
| 1324 // replaceChild no matter what the parent is? | 1506 // replaceChild no matter what the parent is? |
| 1325 var oldChildNode = unwrap(oldChildWrapper); | 1507 if (oldChildNode.parentNode) { |
| 1326 if (oldChildNode.parentNode) { | 1508 originalReplaceChild.call( |
| 1327 originalReplaceChild.call( | 1509 oldChildNode.parentNode, |
| 1328 oldChildNode.parentNode, | 1510 unwrapNodesForInsertion(this, nodes), |
| 1329 unwrapNodesForInsertion(nodes), | 1511 oldChildNode); |
| 1330 oldChildNode); | 1512 } |
| 1513 } else { |
| 1514 ensureSameOwnerDocument(this, newChildWrapper); |
| 1515 originalReplaceChild.call(this.impl, unwrap(newChildWrapper), |
| 1516 oldChildNode); |
| 1331 } | 1517 } |
| 1332 | 1518 |
| 1519 newChildWrapper.nodeWasAdded_(); |
| 1520 |
| 1333 return oldChildWrapper; | 1521 return oldChildWrapper; |
| 1334 }, | 1522 }, |
| 1335 | 1523 |
| 1524 /** |
| 1525 * Called after a node was added. Subclasses override this to invalidate |
| 1526 * the renderer as needed. |
| 1527 * @private |
| 1528 */ |
| 1529 nodeWasAdded_: function() {}, |
| 1530 |
| 1336 hasChildNodes: function() { | 1531 hasChildNodes: function() { |
| 1337 return this.firstChild === null; | 1532 return this.firstChild === null; |
| 1338 }, | 1533 }, |
| 1339 | 1534 |
| 1340 /** @type {Node} */ | 1535 /** @type {Node} */ |
| 1341 get parentNode() { | 1536 get parentNode() { |
| 1342 // If the parentNode has not been overridden, use the original parentNode. | 1537 // If the parentNode has not been overridden, use the original parentNode. |
| 1343 return this.parentNode_ !== undefined ? | 1538 return this.parentNode_ !== undefined ? |
| 1344 this.parentNode_ : wrap(this.impl.parentNode); | 1539 this.parentNode_ : wrap(this.impl.parentNode); |
| 1345 }, | 1540 }, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 get textContent() { | 1574 get textContent() { |
| 1380 // TODO(arv): This should fallback to this.impl.textContent if there | 1575 // TODO(arv): This should fallback to this.impl.textContent if there |
| 1381 // are no shadow trees below or above the context node. | 1576 // are no shadow trees below or above the context node. |
| 1382 var s = ''; | 1577 var s = ''; |
| 1383 for (var child = this.firstChild; child; child = child.nextSibling) { | 1578 for (var child = this.firstChild; child; child = child.nextSibling) { |
| 1384 s += child.textContent; | 1579 s += child.textContent; |
| 1385 } | 1580 } |
| 1386 return s; | 1581 return s; |
| 1387 }, | 1582 }, |
| 1388 set textContent(textContent) { | 1583 set textContent(textContent) { |
| 1389 removeAllChildNodes(this); | 1584 if (this.invalidateShadowRenderer()) { |
| 1390 this.invalidateShadowRenderer(); | 1585 removeAllChildNodes(this); |
| 1391 if (textContent !== '') { | 1586 if (textContent !== '') { |
| 1392 var textNode = this.impl.ownerDocument.createTextNode(textContent); | 1587 var textNode = this.impl.ownerDocument.createTextNode(textContent); |
| 1393 this.appendChild(textNode); | 1588 this.appendChild(textNode); |
| 1589 } |
| 1590 } else { |
| 1591 this.impl.textContent = textContent; |
| 1394 } | 1592 } |
| 1395 }, | 1593 }, |
| 1396 | 1594 |
| 1397 get childNodes() { | 1595 get childNodes() { |
| 1398 var wrapperList = new NodeList(); | 1596 var wrapperList = new NodeList(); |
| 1399 var i = 0; | 1597 var i = 0; |
| 1400 for (var child = this.firstChild; child; child = child.nextSibling) { | 1598 for (var child = this.firstChild; child; child = child.nextSibling) { |
| 1401 wrapperList[i++] = child; | 1599 wrapperList[i++] = child; |
| 1402 } | 1600 } |
| 1403 wrapperList.length = i; | 1601 wrapperList.length = i; |
| 1404 return wrapperList; | 1602 return wrapperList; |
| 1405 }, | 1603 }, |
| 1406 | 1604 |
| 1407 cloneNode: function(deep) { | 1605 cloneNode: function(deep) { |
| 1408 if (!this.invalidateShadowRenderer()) | 1606 if (!this.invalidateShadowRenderer()) |
| 1409 return wrap(this.impl.cloneNode(deep)); | 1607 return wrap(this.impl.cloneNode(deep)); |
| 1410 | 1608 |
| 1411 var clone = wrap(this.impl.cloneNode(false)); | 1609 var clone = wrap(this.impl.cloneNode(false)); |
| 1412 if (deep) { | 1610 if (deep) { |
| 1413 for (var child = this.firstChild; child; child = child.nextSibling) { | 1611 for (var child = this.firstChild; child; child = child.nextSibling) { |
| 1414 clone.appendChild(child.cloneNode(true)); | 1612 clone.appendChild(child.cloneNode(true)); |
| 1415 } | 1613 } |
| 1416 } | 1614 } |
| 1417 // TODO(arv): Some HTML elements also clone other data like value. | 1615 // TODO(arv): Some HTML elements also clone other data like value. |
| 1418 return clone; | 1616 return clone; |
| 1419 }, | 1617 }, |
| 1420 | 1618 |
| 1421 // insertionParent is added in ShadowRender.js | |
| 1422 | |
| 1423 contains: function(child) { | 1619 contains: function(child) { |
| 1424 if (!child) | 1620 if (!child) |
| 1425 return false; | 1621 return false; |
| 1426 | 1622 |
| 1623 child = wrapIfNeeded(child); |
| 1624 |
| 1427 // TODO(arv): Optimize using ownerDocument etc. | 1625 // TODO(arv): Optimize using ownerDocument etc. |
| 1428 if (child === this) | 1626 if (child === this) |
| 1429 return true; | 1627 return true; |
| 1430 var parentNode = child.parentNode; | 1628 var parentNode = child.parentNode; |
| 1431 if (!parentNode) | 1629 if (!parentNode) |
| 1432 return false; | 1630 return false; |
| 1433 return this.contains(parentNode); | 1631 return this.contains(parentNode); |
| 1434 }, | 1632 }, |
| 1435 | 1633 |
| 1436 compareDocumentPosition: function(otherNode) { | 1634 compareDocumentPosition: function(otherNode) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1591 return wrapperList; | 1789 return wrapperList; |
| 1592 } | 1790 } |
| 1593 }; | 1791 }; |
| 1594 | 1792 |
| 1595 var ChildNodeInterface = { | 1793 var ChildNodeInterface = { |
| 1596 get nextElementSibling() { | 1794 get nextElementSibling() { |
| 1597 return forwardElement(this.nextSibling); | 1795 return forwardElement(this.nextSibling); |
| 1598 }, | 1796 }, |
| 1599 | 1797 |
| 1600 get previousElementSibling() { | 1798 get previousElementSibling() { |
| 1601 return backwardsElement(this.nextSibling); | 1799 return backwardsElement(this.previousSibling); |
| 1602 } | 1800 } |
| 1603 }; | 1801 }; |
| 1604 | 1802 |
| 1605 scope.ChildNodeInterface = ChildNodeInterface; | 1803 scope.ChildNodeInterface = ChildNodeInterface; |
| 1606 scope.ParentNodeInterface = ParentNodeInterface; | 1804 scope.ParentNodeInterface = ParentNodeInterface; |
| 1607 | 1805 |
| 1608 })(this.ShadowDOMPolyfill); | 1806 })(this.ShadowDOMPolyfill); |
| 1609 | 1807 |
| 1610 // Copyright 2013 The Polymer Authors. All rights reserved. | 1808 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 1611 // Use of this source code is goverened by a BSD-style | 1809 // Use of this source code is goverened by a BSD-style |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 (function(scope) { | 1847 (function(scope) { |
| 1650 'use strict'; | 1848 'use strict'; |
| 1651 | 1849 |
| 1652 var ChildNodeInterface = scope.ChildNodeInterface; | 1850 var ChildNodeInterface = scope.ChildNodeInterface; |
| 1653 var GetElementsByInterface = scope.GetElementsByInterface; | 1851 var GetElementsByInterface = scope.GetElementsByInterface; |
| 1654 var Node = scope.wrappers.Node; | 1852 var Node = scope.wrappers.Node; |
| 1655 var ParentNodeInterface = scope.ParentNodeInterface; | 1853 var ParentNodeInterface = scope.ParentNodeInterface; |
| 1656 var SelectorsInterface = scope.SelectorsInterface; | 1854 var SelectorsInterface = scope.SelectorsInterface; |
| 1657 var addWrapNodeListMethod = scope.addWrapNodeListMethod; | 1855 var addWrapNodeListMethod = scope.addWrapNodeListMethod; |
| 1658 var mixin = scope.mixin; | 1856 var mixin = scope.mixin; |
| 1857 var oneOf = scope.oneOf; |
| 1659 var registerWrapper = scope.registerWrapper; | 1858 var registerWrapper = scope.registerWrapper; |
| 1660 var wrappers = scope.wrappers; | 1859 var wrappers = scope.wrappers; |
| 1661 | 1860 |
| 1662 var shadowRootTable = new SideTable(); | 1861 var shadowRootTable = new SideTable(); |
| 1663 var OriginalElement = window.Element; | 1862 var OriginalElement = window.Element; |
| 1664 | 1863 |
| 1665 var originalMatches = | 1864 |
| 1666 OriginalElement.prototype.matches || | 1865 var matchesName = oneOf(OriginalElement.prototype, [ |
| 1667 OriginalElement.prototype.mozMatchesSelector || | 1866 'matches', |
| 1668 OriginalElement.prototype.msMatchesSelector || | 1867 'mozMatchesSelector', |
| 1669 OriginalElement.prototype.webkitMatchesSelector; | 1868 'msMatchesSelector', |
| 1869 'webkitMatchesSelector', |
| 1870 ]); |
| 1871 |
| 1872 var originalMatches = OriginalElement.prototype[matchesName]; |
| 1873 |
| 1874 function invalidateRendererBasedOnAttribute(element, name) { |
| 1875 // Only invalidate if parent node is a shadow host. |
| 1876 var p = element.parentNode; |
| 1877 if (!p || !p.shadowRoot) |
| 1878 return; |
| 1879 |
| 1880 var renderer = scope.getRendererForHost(p); |
| 1881 if (renderer.dependsOnAttribute(name)) |
| 1882 renderer.invalidate(); |
| 1883 } |
| 1670 | 1884 |
| 1671 function Element(node) { | 1885 function Element(node) { |
| 1672 Node.call(this, node); | 1886 Node.call(this, node); |
| 1673 } | 1887 } |
| 1674 Element.prototype = Object.create(Node.prototype); | 1888 Element.prototype = Object.create(Node.prototype); |
| 1675 mixin(Element.prototype, { | 1889 mixin(Element.prototype, { |
| 1676 createShadowRoot: function() { | 1890 createShadowRoot: function() { |
| 1677 var newShadowRoot = new wrappers.ShadowRoot(this); | 1891 var newShadowRoot = new wrappers.ShadowRoot(this); |
| 1678 shadowRootTable.set(this, newShadowRoot); | 1892 shadowRootTable.set(this, newShadowRoot); |
| 1679 | 1893 |
| 1680 scope.getRendererForHost(this); | 1894 var renderer = scope.getRendererForHost(this); |
| 1681 | 1895 renderer.invalidate(); |
| 1682 this.invalidateShadowRenderer(true); | |
| 1683 | 1896 |
| 1684 return newShadowRoot; | 1897 return newShadowRoot; |
| 1685 }, | 1898 }, |
| 1686 | 1899 |
| 1687 get shadowRoot() { | 1900 get shadowRoot() { |
| 1688 return shadowRootTable.get(this) || null; | 1901 return shadowRootTable.get(this) || null; |
| 1689 }, | 1902 }, |
| 1690 | 1903 |
| 1691 setAttribute: function(name, value) { | 1904 setAttribute: function(name, value) { |
| 1692 this.impl.setAttribute(name, value); | 1905 this.impl.setAttribute(name, value); |
| 1693 // This is a bit agressive. We need to invalidate if it affects | 1906 invalidateRendererBasedOnAttribute(this, name); |
| 1694 // the rendering content[select] or if it effects the value of a content | 1907 }, |
| 1695 // select. | 1908 |
| 1696 this.invalidateShadowRenderer(); | 1909 removeAttribute: function(name) { |
| 1910 this.impl.removeAttribute(name); |
| 1911 invalidateRendererBasedOnAttribute(this, name); |
| 1697 }, | 1912 }, |
| 1698 | 1913 |
| 1699 matches: function(selector) { | 1914 matches: function(selector) { |
| 1700 return originalMatches.call(this.impl, selector); | 1915 return originalMatches.call(this.impl, selector); |
| 1701 } | 1916 } |
| 1702 }); | 1917 }); |
| 1703 | 1918 |
| 1919 Element.prototype[matchesName] = function(selector) { |
| 1920 return this.matches(selector); |
| 1921 }; |
| 1922 |
| 1923 if (OriginalElement.prototype.webkitCreateShadowRoot) { |
| 1924 Element.prototype.webkitCreateShadowRoot = |
| 1925 Element.prototype.createShadowRoot; |
| 1926 } |
| 1927 |
| 1928 /** |
| 1929 * Useful for generating the accessor pair for a property that reflects an |
| 1930 * attribute. |
| 1931 */ |
| 1932 function setterDirtiesAttribute(prototype, propertyName, opt_attrName) { |
| 1933 var attrName = opt_attrName || propertyName; |
| 1934 Object.defineProperty(prototype, propertyName, { |
| 1935 get: function() { |
| 1936 return this.impl[propertyName]; |
| 1937 }, |
| 1938 set: function(v) { |
| 1939 this.impl[propertyName] = v; |
| 1940 invalidateRendererBasedOnAttribute(this, attrName); |
| 1941 }, |
| 1942 configurable: true, |
| 1943 enumerable: true |
| 1944 }); |
| 1945 } |
| 1946 |
| 1947 setterDirtiesAttribute(Element.prototype, 'id'); |
| 1948 setterDirtiesAttribute(Element.prototype, 'className', 'class'); |
| 1949 |
| 1704 mixin(Element.prototype, ChildNodeInterface); | 1950 mixin(Element.prototype, ChildNodeInterface); |
| 1705 mixin(Element.prototype, GetElementsByInterface); | 1951 mixin(Element.prototype, GetElementsByInterface); |
| 1706 mixin(Element.prototype, ParentNodeInterface); | 1952 mixin(Element.prototype, ParentNodeInterface); |
| 1707 mixin(Element.prototype, SelectorsInterface); | 1953 mixin(Element.prototype, SelectorsInterface); |
| 1708 | 1954 |
| 1709 registerWrapper(OriginalElement, Element); | 1955 registerWrapper(OriginalElement, Element); |
| 1710 | 1956 |
| 1957 // TODO(arv): Export setterDirtiesAttribute and apply it to more bindings |
| 1958 // that reflect attributes. |
| 1959 scope.matchesName = matchesName; |
| 1711 scope.wrappers.Element = Element; | 1960 scope.wrappers.Element = Element; |
| 1712 })(this.ShadowDOMPolyfill); | 1961 })(this.ShadowDOMPolyfill); |
| 1713 | 1962 |
| 1714 // Copyright 2013 The Polymer Authors. All rights reserved. | 1963 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 1715 // Use of this source code is goverened by a BSD-style | 1964 // Use of this source code is goverened by a BSD-style |
| 1716 // license that can be found in the LICENSE file. | 1965 // license that can be found in the LICENSE file. |
| 1717 | 1966 |
| 1718 (function(scope) { | 1967 (function(scope) { |
| 1719 'use strict'; | 1968 'use strict'; |
| 1720 | 1969 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 var s = ''; | 2044 var s = ''; |
| 1796 for (var child = node.firstChild; child; child = child.nextSibling) { | 2045 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 1797 s += getOuterHTML(child); | 2046 s += getOuterHTML(child); |
| 1798 } | 2047 } |
| 1799 return s; | 2048 return s; |
| 1800 } | 2049 } |
| 1801 | 2050 |
| 1802 function setInnerHTML(node, value, opt_tagName) { | 2051 function setInnerHTML(node, value, opt_tagName) { |
| 1803 var tagName = opt_tagName || 'div'; | 2052 var tagName = opt_tagName || 'div'; |
| 1804 node.textContent = ''; | 2053 node.textContent = ''; |
| 1805 var tempElement =unwrap(node.ownerDocument.createElement(tagName)); | 2054 var tempElement = unwrap(node.ownerDocument.createElement(tagName)); |
| 1806 tempElement.innerHTML = value; | 2055 tempElement.innerHTML = value; |
| 1807 var firstChild; | 2056 var firstChild; |
| 1808 while (firstChild = tempElement.firstChild) { | 2057 while (firstChild = tempElement.firstChild) { |
| 1809 node.appendChild(wrap(firstChild)); | 2058 node.appendChild(wrap(firstChild)); |
| 1810 } | 2059 } |
| 1811 } | 2060 } |
| 1812 | 2061 |
| 1813 var OriginalHTMLElement = window.HTMLElement; | 2062 var OriginalHTMLElement = window.HTMLElement; |
| 1814 | 2063 |
| 1815 function HTMLElement(node) { | 2064 function HTMLElement(node) { |
| 1816 Element.call(this, node); | 2065 Element.call(this, node); |
| 1817 } | 2066 } |
| 1818 HTMLElement.prototype = Object.create(Element.prototype); | 2067 HTMLElement.prototype = Object.create(Element.prototype); |
| 1819 mixin(HTMLElement.prototype, { | 2068 mixin(HTMLElement.prototype, { |
| 1820 get innerHTML() { | 2069 get innerHTML() { |
| 1821 // TODO(arv): This should fallback to this.impl.innerHTML if there | 2070 // TODO(arv): This should fallback to this.impl.innerHTML if there |
| 1822 // are no shadow trees below or above the context node. | 2071 // are no shadow trees below or above the context node. |
| 1823 return getInnerHTML(this); | 2072 return getInnerHTML(this); |
| 1824 }, | 2073 }, |
| 1825 set innerHTML(value) { | 2074 set innerHTML(value) { |
| 1826 setInnerHTML(this, value, this.tagName); | 2075 if (this.invalidateShadowRenderer()) |
| 2076 setInnerHTML(this, value, this.tagName); |
| 2077 else |
| 2078 this.impl.innerHTML = value; |
| 1827 }, | 2079 }, |
| 1828 | 2080 |
| 1829 get outerHTML() { | 2081 get outerHTML() { |
| 1830 // TODO(arv): This should fallback to HTMLElement_prototype.outerHTML if t
here | 2082 // TODO(arv): This should fallback to HTMLElement_prototype.outerHTML if t
here |
| 1831 // are no shadow trees below or above the context node. | 2083 // are no shadow trees below or above the context node. |
| 1832 return getOuterHTML(this); | 2084 return getOuterHTML(this); |
| 1833 }, | 2085 }, |
| 1834 set outerHTML(value) { | 2086 set outerHTML(value) { |
| 1835 if (!this.invalidateShadowRenderer()) { | 2087 var p = this.parentNode; |
| 2088 if (p) { |
| 2089 p.invalidateShadowRenderer(); |
| 1836 this.impl.outerHTML = value; | 2090 this.impl.outerHTML = value; |
| 1837 } else { | |
| 1838 throw new Error('not implemented'); | |
| 1839 } | 2091 } |
| 1840 } | 2092 } |
| 1841 }); | 2093 }); |
| 1842 | 2094 |
| 1843 function getterRequiresRendering(name) { | 2095 function getterRequiresRendering(name) { |
| 1844 defineGetter(HTMLElement, name, function() { | 2096 defineGetter(HTMLElement, name, function() { |
| 1845 scope.renderAllPending(); | 2097 scope.renderAllPending(); |
| 1846 return this.impl[name]; | 2098 return this.impl[name]; |
| 1847 }); | 2099 }); |
| 1848 } | 2100 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1938 'use strict'; | 2190 'use strict'; |
| 1939 | 2191 |
| 1940 var HTMLElement = scope.wrappers.HTMLElement; | 2192 var HTMLElement = scope.wrappers.HTMLElement; |
| 1941 var mixin = scope.mixin; | 2193 var mixin = scope.mixin; |
| 1942 var registerWrapper = scope.registerWrapper; | 2194 var registerWrapper = scope.registerWrapper; |
| 1943 | 2195 |
| 1944 var OriginalHTMLShadowElement = window.HTMLShadowElement; | 2196 var OriginalHTMLShadowElement = window.HTMLShadowElement; |
| 1945 | 2197 |
| 1946 function HTMLShadowElement(node) { | 2198 function HTMLShadowElement(node) { |
| 1947 HTMLElement.call(this, node); | 2199 HTMLElement.call(this, node); |
| 1948 this.olderShadowRoot_ = null; | |
| 1949 } | 2200 } |
| 1950 HTMLShadowElement.prototype = Object.create(HTMLElement.prototype); | 2201 HTMLShadowElement.prototype = Object.create(HTMLElement.prototype); |
| 1951 mixin(HTMLShadowElement.prototype, { | 2202 mixin(HTMLShadowElement.prototype, { |
| 1952 get olderShadowRoot() { | |
| 1953 return this.olderShadowRoot_; | |
| 1954 }, | |
| 1955 | |
| 1956 invalidateShadowRenderer: function() { | |
| 1957 HTMLElement.prototype.invalidateShadowRenderer.call(this, true); | |
| 1958 }, | |
| 1959 | |
| 1960 // TODO: attribute boolean resetStyleInheritance; | 2203 // TODO: attribute boolean resetStyleInheritance; |
| 1961 }); | 2204 }); |
| 1962 | 2205 |
| 1963 if (OriginalHTMLShadowElement) | 2206 if (OriginalHTMLShadowElement) |
| 1964 registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement); | 2207 registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement); |
| 1965 | 2208 |
| 1966 scope.wrappers.HTMLShadowElement = HTMLShadowElement; | 2209 scope.wrappers.HTMLShadowElement = HTMLShadowElement; |
| 1967 })(this.ShadowDOMPolyfill); | 2210 })(this.ShadowDOMPolyfill); |
| 2211 |
| 1968 // Copyright 2013 The Polymer Authors. All rights reserved. | 2212 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 1969 // Use of this source code is goverened by a BSD-style | 2213 // Use of this source code is goverened by a BSD-style |
| 1970 // license that can be found in the LICENSE file. | 2214 // license that can be found in the LICENSE file. |
| 1971 | 2215 |
| 1972 (function(scope) { | 2216 (function(scope) { |
| 1973 'use strict'; | 2217 'use strict'; |
| 1974 | 2218 |
| 1975 var HTMLElement = scope.wrappers.HTMLElement; | 2219 var HTMLElement = scope.wrappers.HTMLElement; |
| 1976 var getInnerHTML = scope.getInnerHTML; | 2220 var getInnerHTML = scope.getInnerHTML; |
| 1977 var mixin = scope.mixin; | 2221 var mixin = scope.mixin; |
| 1978 var registerWrapper = scope.registerWrapper; | 2222 var registerWrapper = scope.registerWrapper; |
| 1979 var setInnerHTML = scope.setInnerHTML; | 2223 var setInnerHTML = scope.setInnerHTML; |
| 2224 var unwrap = scope.unwrap; |
| 1980 var wrap = scope.wrap; | 2225 var wrap = scope.wrap; |
| 1981 | 2226 |
| 1982 var contentTable = new SideTable(); | 2227 var contentTable = new SideTable(); |
| 1983 var templateContentsOwnerTable = new SideTable(); | 2228 var templateContentsOwnerTable = new SideTable(); |
| 1984 | 2229 |
| 1985 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner | 2230 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner |
| 1986 function getTemplateContentsOwner(doc) { | 2231 function getTemplateContentsOwner(doc) { |
| 1987 if (!doc.defaultView) | 2232 if (!doc.defaultView) |
| 1988 return doc; | 2233 return doc; |
| 1989 var d = templateContentsOwnerTable.get(doc); | 2234 var d = templateContentsOwnerTable.get(doc); |
| 1990 if (!d) { | 2235 if (!d) { |
| 1991 // TODO(arv): This should either be a Document or HTMLDocument depending | 2236 // TODO(arv): This should either be a Document or HTMLDocument depending |
| 1992 // on doc. | 2237 // on doc. |
| 1993 d = doc.implementation.createHTMLDocument(''); | 2238 d = doc.implementation.createHTMLDocument(''); |
| 1994 while (d.lastChild) { | 2239 while (d.lastChild) { |
| 1995 d.removeChild(d.lastChild); | 2240 d.removeChild(d.lastChild); |
| 1996 } | 2241 } |
| 1997 templateContentsOwnerTable.set(doc, d); | 2242 templateContentsOwnerTable.set(doc, d); |
| 1998 } | 2243 } |
| 1999 return d; | 2244 return d; |
| 2000 } | 2245 } |
| 2001 | 2246 |
| 2002 function extractContent(templateElement) { | 2247 function extractContent(templateElement) { |
| 2248 // templateElement is not a wrapper here. |
| 2003 var doc = getTemplateContentsOwner(templateElement.ownerDocument); | 2249 var doc = getTemplateContentsOwner(templateElement.ownerDocument); |
| 2004 var df = doc.createDocumentFragment(); | 2250 var df = unwrap(doc.createDocumentFragment()); |
| 2005 var nextSibling; | |
| 2006 var child; | 2251 var child; |
| 2007 while (child = templateElement.firstChild) { | 2252 while (child = templateElement.firstChild) { |
| 2008 df.appendChild(child); | 2253 df.appendChild(child); |
| 2009 } | 2254 } |
| 2010 return df; | 2255 return df; |
| 2011 } | 2256 } |
| 2012 | 2257 |
| 2013 var OriginalHTMLTemplateElement = window.HTMLTemplateElement; | 2258 var OriginalHTMLTemplateElement = window.HTMLTemplateElement; |
| 2014 | 2259 |
| 2015 function HTMLTemplateElement(node) { | 2260 function HTMLTemplateElement(node) { |
| 2016 HTMLElement.call(this, node); | 2261 HTMLElement.call(this, node); |
| 2262 if (!OriginalHTMLTemplateElement) { |
| 2263 var content = extractContent(node); |
| 2264 contentTable.set(this, wrap(content)); |
| 2265 } |
| 2017 } | 2266 } |
| 2018 HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype); | 2267 HTMLTemplateElement.prototype = Object.create(HTMLElement.prototype); |
| 2019 | 2268 |
| 2020 mixin(HTMLTemplateElement.prototype, { | 2269 mixin(HTMLTemplateElement.prototype, { |
| 2021 get content() { | 2270 get content() { |
| 2022 if (OriginalHTMLTemplateElement) | 2271 if (OriginalHTMLTemplateElement) |
| 2023 return wrap(this.impl.content); | 2272 return wrap(this.impl.content); |
| 2024 | 2273 return contentTable.get(this); |
| 2025 // TODO(arv): This should be done in createCallback. I initially tried to | |
| 2026 // do this in the constructor but the wrapper is not yet created at that | |
| 2027 // point in time so we hit an iloop. | |
| 2028 var content = contentTable.get(this); | |
| 2029 if (!content) { | |
| 2030 content = extractContent(this); | |
| 2031 contentTable.set(this, content); | |
| 2032 } | |
| 2033 return content; | |
| 2034 }, | 2274 }, |
| 2035 | 2275 |
| 2036 get innerHTML() { | 2276 get innerHTML() { |
| 2037 return getInnerHTML(this.content); | 2277 return getInnerHTML(this.content); |
| 2038 }, | 2278 }, |
| 2039 set innerHTML(value) { | 2279 set innerHTML(value) { |
| 2040 setInnerHTML(this.content, value); | 2280 setInnerHTML(this.content, value); |
| 2041 this.invalidateShadowRenderer(); | |
| 2042 } | 2281 } |
| 2043 | 2282 |
| 2044 // TODO(arv): cloneNode needs to clone content. | 2283 // TODO(arv): cloneNode needs to clone content. |
| 2045 | 2284 |
| 2046 }); | 2285 }); |
| 2047 | 2286 |
| 2048 if (OriginalHTMLTemplateElement) | 2287 if (OriginalHTMLTemplateElement) |
| 2049 registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement); | 2288 registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement); |
| 2050 | 2289 |
| 2051 scope.wrappers.HTMLTemplateElement = HTMLTemplateElement; | 2290 scope.wrappers.HTMLTemplateElement = HTMLTemplateElement; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 | 2356 |
| 2118 var DocumentFragment = scope.wrappers.DocumentFragment; | 2357 var DocumentFragment = scope.wrappers.DocumentFragment; |
| 2119 var elementFromPoint = scope.elementFromPoint; | 2358 var elementFromPoint = scope.elementFromPoint; |
| 2120 var getInnerHTML = scope.getInnerHTML; | 2359 var getInnerHTML = scope.getInnerHTML; |
| 2121 var mixin = scope.mixin; | 2360 var mixin = scope.mixin; |
| 2122 var rewrap = scope.rewrap; | 2361 var rewrap = scope.rewrap; |
| 2123 var setInnerHTML = scope.setInnerHTML; | 2362 var setInnerHTML = scope.setInnerHTML; |
| 2124 var unwrap = scope.unwrap; | 2363 var unwrap = scope.unwrap; |
| 2125 | 2364 |
| 2126 var shadowHostTable = new SideTable(); | 2365 var shadowHostTable = new SideTable(); |
| 2366 var nextOlderShadowTreeTable = new SideTable(); |
| 2127 | 2367 |
| 2128 function ShadowRoot(hostWrapper) { | 2368 function ShadowRoot(hostWrapper) { |
| 2129 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); | 2369 var node = unwrap(hostWrapper.impl.ownerDocument.createDocumentFragment()); |
| 2130 DocumentFragment.call(this, node); | 2370 DocumentFragment.call(this, node); |
| 2131 | 2371 |
| 2132 // createDocumentFragment associates the node with a wrapper | 2372 // createDocumentFragment associates the node with a wrapper |
| 2133 // DocumentFragment instance. Override that. | 2373 // DocumentFragment instance. Override that. |
| 2134 rewrap(node, this); | 2374 rewrap(node, this); |
| 2135 | 2375 |
| 2136 var oldShadowRoot = hostWrapper.shadowRoot; | 2376 var oldShadowRoot = hostWrapper.shadowRoot; |
| 2137 scope.nextOlderShadowTreeTable.set(this, oldShadowRoot); | 2377 nextOlderShadowTreeTable.set(this, oldShadowRoot); |
| 2138 | 2378 |
| 2139 shadowHostTable.set(this, hostWrapper); | 2379 shadowHostTable.set(this, hostWrapper); |
| 2140 } | 2380 } |
| 2141 ShadowRoot.prototype = Object.create(DocumentFragment.prototype); | 2381 ShadowRoot.prototype = Object.create(DocumentFragment.prototype); |
| 2142 mixin(ShadowRoot.prototype, { | 2382 mixin(ShadowRoot.prototype, { |
| 2143 get innerHTML() { | 2383 get innerHTML() { |
| 2144 return getInnerHTML(this); | 2384 return getInnerHTML(this); |
| 2145 }, | 2385 }, |
| 2146 set innerHTML(value) { | 2386 set innerHTML(value) { |
| 2147 setInnerHTML(this, value); | 2387 setInnerHTML(this, value); |
| 2148 this.invalidateShadowRenderer(); | 2388 this.invalidateShadowRenderer(); |
| 2149 }, | 2389 }, |
| 2150 | 2390 |
| 2391 get olderShadowRoot() { |
| 2392 return nextOlderShadowTreeTable.get(this) || null; |
| 2393 }, |
| 2394 |
| 2151 invalidateShadowRenderer: function() { | 2395 invalidateShadowRenderer: function() { |
| 2152 return shadowHostTable.get(this).invalidateShadowRenderer(); | 2396 return shadowHostTable.get(this).invalidateShadowRenderer(); |
| 2153 }, | 2397 }, |
| 2154 | 2398 |
| 2155 elementFromPoint: function(x, y) { | 2399 elementFromPoint: function(x, y) { |
| 2156 return elementFromPoint(this, this.ownerDocument, x, y); | 2400 return elementFromPoint(this, this.ownerDocument, x, y); |
| 2157 }, | 2401 }, |
| 2158 | 2402 |
| 2159 getElementById: function(id) { | 2403 getElementById: function(id) { |
| 2160 return this.querySelector('#' + id); | 2404 return this.querySelector('#' + id); |
| 2161 } | 2405 } |
| 2162 }); | 2406 }); |
| 2163 | 2407 |
| 2164 scope.wrappers.ShadowRoot = ShadowRoot; | 2408 scope.wrappers.ShadowRoot = ShadowRoot; |
| 2165 scope.getHostForShadowRoot = function(node) { | 2409 scope.getHostForShadowRoot = function(node) { |
| 2166 return shadowHostTable.get(node); | 2410 return shadowHostTable.get(node); |
| 2167 }; | 2411 }; |
| 2168 })(this.ShadowDOMPolyfill); | 2412 })(this.ShadowDOMPolyfill); |
| 2169 // Copyright 2013 The Polymer Authors. All rights reserved. | 2413 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 2170 // Use of this source code is governed by a BSD-style | 2414 // Use of this source code is governed by a BSD-style |
| 2171 // license that can be found in the LICENSE file. | 2415 // license that can be found in the LICENSE file. |
| 2172 | 2416 |
| 2173 (function(scope) { | 2417 (function(scope) { |
| 2174 'use strict'; | 2418 'use strict'; |
| 2175 | 2419 |
| 2176 var HTMLContentElement = scope.wrappers.HTMLContentElement; | 2420 var HTMLContentElement = scope.wrappers.HTMLContentElement; |
| 2421 var HTMLShadowElement = scope.wrappers.HTMLShadowElement; |
| 2177 var Node = scope.wrappers.Node; | 2422 var Node = scope.wrappers.Node; |
| 2423 var ShadowRoot = scope.wrappers.ShadowRoot; |
| 2178 var assert = scope.assert; | 2424 var assert = scope.assert; |
| 2425 var getHostForShadowRoot = scope.getHostForShadowRoot; |
| 2179 var mixin = scope.mixin; | 2426 var mixin = scope.mixin; |
| 2427 var oneOf = scope.oneOf; |
| 2180 var unwrap = scope.unwrap; | 2428 var unwrap = scope.unwrap; |
| 2181 var wrap = scope.wrap; | 2429 var wrap = scope.wrap; |
| 2182 | 2430 |
| 2183 /** | 2431 /** |
| 2184 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. | 2432 * Updates the fields of a wrapper to a snapshot of the logical DOM as needed. |
| 2185 * Up means parentNode | 2433 * Up means parentNode |
| 2186 * Sideways means previous and next sibling. | 2434 * Sideways means previous and next sibling. |
| 2187 * @param {!Node} wrapper | 2435 * @param {!Node} wrapper |
| 2188 */ | 2436 */ |
| 2189 function updateWrapperUpAndSideways(wrapper) { | 2437 function updateWrapperUpAndSideways(wrapper) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2212 updateWrapperDown(parentNodeWrapper); | 2460 updateWrapperDown(parentNodeWrapper); |
| 2213 } | 2461 } |
| 2214 | 2462 |
| 2215 // This object groups DOM operations. This is supposed to be the DOM as the | 2463 // This object groups DOM operations. This is supposed to be the DOM as the |
| 2216 // browser/render tree sees it. | 2464 // browser/render tree sees it. |
| 2217 // When changes are done to the visual DOM the logical DOM needs to be updated | 2465 // When changes are done to the visual DOM the logical DOM needs to be updated |
| 2218 // to reflect the correct tree. | 2466 // to reflect the correct tree. |
| 2219 function removeAllChildNodes(parentNodeWrapper) { | 2467 function removeAllChildNodes(parentNodeWrapper) { |
| 2220 var parentNode = unwrap(parentNodeWrapper); | 2468 var parentNode = unwrap(parentNodeWrapper); |
| 2221 updateAllChildNodes(parentNodeWrapper); | 2469 updateAllChildNodes(parentNodeWrapper); |
| 2222 parentNode.textContent = ''; | 2470 if (parentNode.firstChild) |
| 2471 parentNode.textContent = ''; |
| 2223 } | 2472 } |
| 2224 | 2473 |
| 2225 function appendChild(parentNodeWrapper, childWrapper) { | 2474 function appendChild(parentNodeWrapper, childWrapper) { |
| 2226 var parentNode = unwrap(parentNodeWrapper); | 2475 var parentNode = unwrap(parentNodeWrapper); |
| 2227 var child = unwrap(childWrapper); | 2476 var child = unwrap(childWrapper); |
| 2228 if (child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | 2477 if (child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { |
| 2229 updateAllChildNodes(childWrapper); | 2478 updateAllChildNodes(childWrapper); |
| 2230 | 2479 |
| 2231 } else { | 2480 } else { |
| 2232 remove(childWrapper); | 2481 remove(childWrapper); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2267 function remove(nodeWrapper) { | 2516 function remove(nodeWrapper) { |
| 2268 var node = unwrap(nodeWrapper) | 2517 var node = unwrap(nodeWrapper) |
| 2269 var parentNode = node.parentNode; | 2518 var parentNode = node.parentNode; |
| 2270 if (parentNode) | 2519 if (parentNode) |
| 2271 removeChild(wrap(parentNode), nodeWrapper); | 2520 removeChild(wrap(parentNode), nodeWrapper); |
| 2272 } | 2521 } |
| 2273 | 2522 |
| 2274 var distributedChildNodesTable = new SideTable(); | 2523 var distributedChildNodesTable = new SideTable(); |
| 2275 var eventParentsTable = new SideTable(); | 2524 var eventParentsTable = new SideTable(); |
| 2276 var insertionParentTable = new SideTable(); | 2525 var insertionParentTable = new SideTable(); |
| 2277 var nextOlderShadowTreeTable = new SideTable(); | |
| 2278 var rendererForHostTable = new SideTable(); | 2526 var rendererForHostTable = new SideTable(); |
| 2279 var shadowDOMRendererTable = new SideTable(); | 2527 var shadowDOMRendererTable = new SideTable(); |
| 2280 | 2528 |
| 2281 var reprCounter = 0; | 2529 var reprCounter = 0; |
| 2282 | 2530 |
| 2283 function repr(node) { | 2531 function repr(node) { |
| 2284 if (!node.displayName) | 2532 if (!node.displayName) |
| 2285 node.displayName = node.nodeName + '-' + ++reprCounter; | 2533 node.displayName = node.nodeName + '-' + ++reprCounter; |
| 2286 return node.displayName; | 2534 return node.displayName; |
| 2287 } | 2535 } |
| 2288 | 2536 |
| 2289 function distributeChildToInsertionPoint(child, insertionPoint) { | 2537 function distributeChildToInsertionPoint(child, insertionPoint) { |
| 2290 getDistributedChildNodes(insertionPoint).push(child); | 2538 getDistributedChildNodes(insertionPoint).push(child); |
| 2291 insertionParentTable.set(child, insertionPoint); | 2539 assignToInsertionPoint(child, insertionPoint); |
| 2292 | 2540 |
| 2293 var eventParents = eventParentsTable.get(child); | 2541 var eventParents = eventParentsTable.get(child); |
| 2294 if (!eventParents) | 2542 if (!eventParents) |
| 2295 eventParentsTable.set(child, eventParents = []); | 2543 eventParentsTable.set(child, eventParents = []); |
| 2296 eventParents.push(insertionPoint); | 2544 eventParents.push(insertionPoint); |
| 2297 } | 2545 } |
| 2298 | 2546 |
| 2299 function resetDistributedChildNodes(insertionPoint) { | 2547 function resetDistributedChildNodes(insertionPoint) { |
| 2300 distributedChildNodesTable.set(insertionPoint, []); | 2548 distributedChildNodesTable.set(insertionPoint, []); |
| 2301 } | 2549 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2326 var node = nodes[i]; | 2574 var node = nodes[i]; |
| 2327 if (predicate(node)) { | 2575 if (predicate(node)) { |
| 2328 if (visitor(node) === false) | 2576 if (visitor(node) === false) |
| 2329 return; | 2577 return; |
| 2330 } else { | 2578 } else { |
| 2331 visit(node, predicate, visitor); | 2579 visit(node, predicate, visitor); |
| 2332 } | 2580 } |
| 2333 } | 2581 } |
| 2334 } | 2582 } |
| 2335 | 2583 |
| 2336 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn
-distribution-algorithm | |
| 2337 function distribute(tree, pool) { | |
| 2338 var anyRemoved = false; | |
| 2339 | |
| 2340 visit(tree, isActiveInsertionPoint, | |
| 2341 function(insertionPoint) { | |
| 2342 resetDistributedChildNodes(insertionPoint); | |
| 2343 for (var i = 0; i < pool.length; i++) { // 1.2 | |
| 2344 var node = pool[i]; // 1.2.1 | |
| 2345 if (node === undefined) // removed | |
| 2346 continue; | |
| 2347 if (matchesCriteria(node, insertionPoint)) { // 1.2.2 | |
| 2348 distributeChildToInsertionPoint(node, insertionPoint); // 1.2.2.1 | |
| 2349 pool[i] = undefined; // 1.2.2.2 | |
| 2350 anyRemoved = true; | |
| 2351 } | |
| 2352 } | |
| 2353 }); | |
| 2354 | |
| 2355 if (!anyRemoved) | |
| 2356 return pool; | |
| 2357 | |
| 2358 return pool.filter(function(item) { | |
| 2359 return item !== undefined; | |
| 2360 }); | |
| 2361 } | |
| 2362 | |
| 2363 // Matching Insertion Points | 2584 // Matching Insertion Points |
| 2364 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#mat
ching-insertion-points | 2585 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#mat
ching-insertion-points |
| 2365 | 2586 |
| 2366 // TODO(arv): Verify this... I don't remember why I picked this regexp. | 2587 // TODO(arv): Verify this... I don't remember why I picked this regexp. |
| 2367 var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/; | 2588 var selectorMatchRegExp = /^[*.:#[a-zA-Z_|]/; |
| 2368 | 2589 |
| 2369 var allowedPseudoRegExp = new RegExp('^:(' + [ | 2590 var allowedPseudoRegExp = new RegExp('^:(' + [ |
| 2370 'link', | 2591 'link', |
| 2371 'visited', | 2592 'visited', |
| 2372 'target', | 2593 'target', |
| 2373 'enabled', | 2594 'enabled', |
| 2374 'disabled', | 2595 'disabled', |
| 2375 'checked', | 2596 'checked', |
| 2376 'indeterminate', | 2597 'indeterminate', |
| 2377 'nth-child', | 2598 'nth-child', |
| 2378 'nth-last-child', | 2599 'nth-last-child', |
| 2379 'nth-of-type', | 2600 'nth-of-type', |
| 2380 'nth-last-of-type', | 2601 'nth-last-of-type', |
| 2381 'first-child', | 2602 'first-child', |
| 2382 'last-child', | 2603 'last-child', |
| 2383 'first-of-type', | 2604 'first-of-type', |
| 2384 'last-of-type', | 2605 'last-of-type', |
| 2385 'only-of-type', | 2606 'only-of-type', |
| 2386 ].join('|') + ')'); | 2607 ].join('|') + ')'); |
| 2387 | 2608 |
| 2388 | 2609 |
| 2389 function oneOf(object, propertyNames) { | |
| 2390 for (var i = 0; i < propertyNames.length; i++) { | |
| 2391 if (propertyNames[i] in object) | |
| 2392 return propertyNames[i]; | |
| 2393 } | |
| 2394 } | |
| 2395 | |
| 2396 /** | 2610 /** |
| 2397 * @param {Element} node | 2611 * @param {Element} node |
| 2398 * @oaram {Element} point The insertion point element. | 2612 * @oaram {Element} point The insertion point element. |
| 2399 * @return {boolean} Whether the node matches the insertion point. | 2613 * @return {boolean} Whether the node matches the insertion point. |
| 2400 */ | 2614 */ |
| 2401 function matchesCriteria(node, point) { | 2615 function matchesCriteria(node, point) { |
| 2402 var select = point.getAttribute('select'); | 2616 var select = point.getAttribute('select'); |
| 2403 if (!select) | 2617 if (!select) |
| 2404 return true; | 2618 return true; |
| 2405 | 2619 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2440 renderTimer = null; | 2654 renderTimer = null; |
| 2441 pendingDirtyRenderers.forEach(function(owner) { | 2655 pendingDirtyRenderers.forEach(function(owner) { |
| 2442 owner.render(); | 2656 owner.render(); |
| 2443 }); | 2657 }); |
| 2444 pendingDirtyRenderers = []; | 2658 pendingDirtyRenderers = []; |
| 2445 } | 2659 } |
| 2446 | 2660 |
| 2447 function ShadowRenderer(host) { | 2661 function ShadowRenderer(host) { |
| 2448 this.host = host; | 2662 this.host = host; |
| 2449 this.dirty = false; | 2663 this.dirty = false; |
| 2664 this.invalidateAttributes(); |
| 2450 this.associateNode(host); | 2665 this.associateNode(host); |
| 2451 } | 2666 } |
| 2452 | 2667 |
| 2668 /** |
| 2669 * Returns existing shadow renderer for a host or creates it if it is needed. |
| 2670 * @params {!Element} host |
| 2671 * @return {!ShadowRenderer} |
| 2672 */ |
| 2453 function getRendererForHost(host) { | 2673 function getRendererForHost(host) { |
| 2454 var renderer = rendererForHostTable.get(host); | 2674 var renderer = rendererForHostTable.get(host); |
| 2455 if (!renderer) { | 2675 if (!renderer) { |
| 2456 renderer = new ShadowRenderer(host); | 2676 renderer = new ShadowRenderer(host); |
| 2457 rendererForHostTable.set(host, renderer); | 2677 rendererForHostTable.set(host, renderer); |
| 2458 } | 2678 } |
| 2459 return renderer; | 2679 return renderer; |
| 2460 } | 2680 } |
| 2461 | 2681 |
| 2682 function getShadowRootAncestor(node) { |
| 2683 for (; node; node = node.parentNode) { |
| 2684 if (node instanceof ShadowRoot) |
| 2685 return node; |
| 2686 } |
| 2687 return null; |
| 2688 } |
| 2689 |
| 2690 function getRendererForShadowRoot(shadowRoot) { |
| 2691 return getRendererForHost(getHostForShadowRoot(shadowRoot)); |
| 2692 } |
| 2693 |
| 2462 ShadowRenderer.prototype = { | 2694 ShadowRenderer.prototype = { |
| 2695 |
| 2463 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#r
endering-shadow-trees | 2696 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#r
endering-shadow-trees |
| 2464 render: function() { | 2697 render: function() { |
| 2465 if (!this.dirty) | 2698 if (!this.dirty) |
| 2466 return; | 2699 return; |
| 2467 | 2700 |
| 2701 this.invalidateAttributes(); |
| 2702 this.treeComposition(); |
| 2703 |
| 2468 var host = this.host; | 2704 var host = this.host; |
| 2469 this.treeComposition(); | |
| 2470 var shadowDOM = host.shadowRoot; | 2705 var shadowDOM = host.shadowRoot; |
| 2471 if (!shadowDOM) | |
| 2472 return; | |
| 2473 | 2706 |
| 2474 this.removeAllChildNodes(this.host); | 2707 this.removeAllChildNodes(this.host); |
| 2475 | 2708 |
| 2476 var shadowDOMChildNodes = getChildNodesSnapshot(shadowDOM); | 2709 var shadowDOMChildNodes = getChildNodesSnapshot(shadowDOM); |
| 2477 shadowDOMChildNodes.forEach(function(node) { | 2710 shadowDOMChildNodes.forEach(function(node) { |
| 2478 this.renderNode(host, shadowDOM, node, false); | 2711 this.renderNode(host, shadowDOM, node, false); |
| 2479 }, this); | 2712 }, this); |
| 2480 | 2713 |
| 2481 this.dirty = false; | 2714 this.dirty = false; |
| 2482 }, | 2715 }, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2499 renderer.render(); | 2732 renderer.render(); |
| 2500 } else if (isInsertionPoint(node)) { | 2733 } else if (isInsertionPoint(node)) { |
| 2501 this.renderInsertionPoint(visualParent, tree, node, isNested); | 2734 this.renderInsertionPoint(visualParent, tree, node, isNested); |
| 2502 } else if (isShadowInsertionPoint(node)) { | 2735 } else if (isShadowInsertionPoint(node)) { |
| 2503 this.renderShadowInsertionPoint(visualParent, tree, node); | 2736 this.renderShadowInsertionPoint(visualParent, tree, node); |
| 2504 } else { | 2737 } else { |
| 2505 this.renderAsAnyDomTree(visualParent, tree, node, isNested); | 2738 this.renderAsAnyDomTree(visualParent, tree, node, isNested); |
| 2506 } | 2739 } |
| 2507 }, | 2740 }, |
| 2508 | 2741 |
| 2509 renderAsAnyDomTree: function(visualParent, tree, child, isNested) { | 2742 renderAsAnyDomTree: function(visualParent, tree, node, isNested) { |
| 2510 this.appendChild(visualParent, child); | 2743 this.appendChild(visualParent, node); |
| 2511 | 2744 |
| 2512 if (isShadowHost(child)) { | 2745 if (isShadowHost(node)) { |
| 2513 render(child); | 2746 render(node); |
| 2514 } else { | 2747 } else { |
| 2515 var parent = child; | 2748 var parent = node; |
| 2516 var logicalChildNodes = getChildNodesSnapshot(parent); | 2749 var logicalChildNodes = getChildNodesSnapshot(parent); |
| 2750 // We associate the parent of a content/shadow with the renderer |
| 2751 // because we may need to remove stale childNodes. |
| 2752 if (shadowDOMRendererTable.get(parent)) |
| 2753 this.removeAllChildNodes(parent); |
| 2517 logicalChildNodes.forEach(function(node) { | 2754 logicalChildNodes.forEach(function(node) { |
| 2518 this.renderNode(parent, tree, node, isNested); | 2755 this.renderNode(parent, tree, node, isNested); |
| 2519 }, this); | 2756 }, this); |
| 2520 } | 2757 } |
| 2521 }, | 2758 }, |
| 2522 | 2759 |
| 2523 renderInsertionPoint: function(visualParent, tree, insertionPoint, isNested)
{ | 2760 renderInsertionPoint: function(visualParent, tree, insertionPoint, isNested)
{ |
| 2524 var distributedChildNodes = getDistributedChildNodes(insertionPoint); | 2761 var distributedChildNodes = getDistributedChildNodes(insertionPoint); |
| 2525 if (distributedChildNodes.length) { | 2762 if (distributedChildNodes.length) { |
| 2526 this.removeAllChildNodes(insertionPoint); | 2763 this.removeAllChildNodes(insertionPoint); |
| 2527 | 2764 |
| 2528 distributedChildNodes.forEach(function(child) { | 2765 distributedChildNodes.forEach(function(child) { |
| 2529 if (isInsertionPoint(child) && isNested) | 2766 if (isInsertionPoint(child) && isNested) |
| 2530 this.renderInsertionPoint(visualParent, tree, child, isNested); | 2767 this.renderInsertionPoint(visualParent, tree, child, isNested); |
| 2531 else | 2768 else |
| 2532 this.renderAsAnyDomTree(visualParent, tree, child, isNested); | 2769 this.renderAsAnyDomTree(visualParent, tree, child, isNested); |
| 2533 }, this); | 2770 }, this); |
| 2534 } else { | 2771 } else { |
| 2535 this.renderFallbackContent(visualParent, insertionPoint); | 2772 this.renderFallbackContent(visualParent, insertionPoint); |
| 2536 } | 2773 } |
| 2537 this.remove(insertionPoint); | 2774 this.remove(insertionPoint); |
| 2538 }, | 2775 }, |
| 2539 | 2776 |
| 2540 renderShadowInsertionPoint: function(visualParent, tree, shadowInsertionPoin
t) { | 2777 renderShadowInsertionPoint: function(visualParent, tree, shadowInsertionPoin
t) { |
| 2541 var nextOlderTree = getNextOlderTree(tree); | 2778 var nextOlderTree = tree.olderShadowRoot; |
| 2542 if (nextOlderTree) { | 2779 if (nextOlderTree) { |
| 2543 // This makes ShadowRoot have its insertionParent be the <shadow>. | 2780 assignToInsertionPoint(nextOlderTree, shadowInsertionPoint); |
| 2544 insertionParentTable.set(nextOlderTree, shadowInsertionPoint); | |
| 2545 shadowInsertionPoint.olderShadowRoot_ = nextOlderTree; | |
| 2546 this.remove(shadowInsertionPoint); | 2781 this.remove(shadowInsertionPoint); |
| 2547 var shadowDOMChildNodes = getChildNodesSnapshot(nextOlderTree); | 2782 var shadowDOMChildNodes = getChildNodesSnapshot(nextOlderTree); |
| 2548 shadowDOMChildNodes.forEach(function(node) { | 2783 shadowDOMChildNodes.forEach(function(node) { |
| 2549 this.renderNode(visualParent, nextOlderTree, node, true); | 2784 this.renderNode(visualParent, nextOlderTree, node, true); |
| 2550 }, this); | 2785 }, this); |
| 2551 } else { | 2786 } else { |
| 2552 this.renderFallbackContent(visualParent, shadowInsertionPoint); | 2787 this.renderFallbackContent(visualParent, shadowInsertionPoint); |
| 2553 } | 2788 } |
| 2554 }, | 2789 }, |
| 2555 | 2790 |
| 2556 renderFallbackContent: function (visualParent, fallbackHost) { | 2791 renderFallbackContent: function (visualParent, fallbackHost) { |
| 2557 var logicalChildNodes = getChildNodesSnapshot(fallbackHost); | 2792 var logicalChildNodes = getChildNodesSnapshot(fallbackHost); |
| 2793 this.associateNode(fallbackHost); |
| 2794 this.remove(fallbackHost); |
| 2558 logicalChildNodes.forEach(function(node) { | 2795 logicalChildNodes.forEach(function(node) { |
| 2559 this.appendChild(visualParent, node); | 2796 this.appendChild(visualParent, node); |
| 2560 }, this); | 2797 }, this); |
| 2561 }, | 2798 }, |
| 2562 | 2799 |
| 2800 /** |
| 2801 * Invalidates the attributes used to keep track of which attributes may |
| 2802 * cause the renderer to be invalidated. |
| 2803 */ |
| 2804 invalidateAttributes: function() { |
| 2805 this.attributes = Object.create(null); |
| 2806 }, |
| 2807 |
| 2808 /** |
| 2809 * Parses the selector and makes this renderer dependent on the attribute |
| 2810 * being used in the selector. |
| 2811 * @param {string} selector |
| 2812 */ |
| 2813 updateDependentAttributes: function(selector) { |
| 2814 if (!selector) |
| 2815 return; |
| 2816 |
| 2817 var attributes = this.attributes; |
| 2818 |
| 2819 // .class |
| 2820 if (/\.\w+/.test(selector)) |
| 2821 attributes['class'] = true; |
| 2822 |
| 2823 // #id |
| 2824 if (/#\w+/.test(selector)) |
| 2825 attributes['id'] = true; |
| 2826 |
| 2827 selector.replace(/\[\s*([^\s=\|~\]]+)/g, function(_, name) { |
| 2828 attributes[name] = true; |
| 2829 }); |
| 2830 |
| 2831 // Pseudo selectors have been removed from the spec. |
| 2832 }, |
| 2833 |
| 2834 dependsOnAttribute: function(name) { |
| 2835 return this.attributes[name]; |
| 2836 }, |
| 2837 |
| 2838 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#d
fn-distribution-algorithm |
| 2839 distribute: function(tree, pool) { |
| 2840 var anyRemoved = false; |
| 2841 var self = this; |
| 2842 |
| 2843 visit(tree, isActiveInsertionPoint, |
| 2844 function(insertionPoint) { |
| 2845 resetDistributedChildNodes(insertionPoint); |
| 2846 self.updateDependentAttributes( |
| 2847 insertionPoint.getAttribute('select')); |
| 2848 |
| 2849 for (var i = 0; i < pool.length; i++) { // 1.2 |
| 2850 var node = pool[i]; // 1.2.1 |
| 2851 if (node === undefined) // removed |
| 2852 continue; |
| 2853 if (matchesCriteria(node, insertionPoint)) { // 1.2.2 |
| 2854 distributeChildToInsertionPoint(node, insertionPoint); // 1.2.2
.1 |
| 2855 pool[i] = undefined; // 1.2.2.2 |
| 2856 anyRemoved = true; |
| 2857 } |
| 2858 } |
| 2859 }); |
| 2860 |
| 2861 if (!anyRemoved) |
| 2862 return pool; |
| 2863 |
| 2864 return pool.filter(function(item) { |
| 2865 return item !== undefined; |
| 2866 }); |
| 2867 }, |
| 2868 |
| 2563 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#d
fn-tree-composition | 2869 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#d
fn-tree-composition |
| 2564 treeComposition: function () { | 2870 treeComposition: function () { |
| 2565 var shadowHost = this.host; | 2871 var shadowHost = this.host; |
| 2566 var tree = shadowHost.shadowRoot; // 1. | 2872 var tree = shadowHost.shadowRoot; // 1. |
| 2567 var pool = []; // 2. | 2873 var pool = []; // 2. |
| 2568 var shadowHostChildNodes = getChildNodesSnapshot(shadowHost); | 2874 var shadowHostChildNodes = getChildNodesSnapshot(shadowHost); |
| 2569 shadowHostChildNodes.forEach(function(child) { // 3. | 2875 shadowHostChildNodes.forEach(function(child) { // 3. |
| 2570 if (isInsertionPoint(child)) { // 3.2. | 2876 if (isInsertionPoint(child)) { // 3.2. |
| 2571 var reprojected = getDistributedChildNodes(child); // 3.2.1. | 2877 var reprojected = getDistributedChildNodes(child); // 3.2.1. |
| 2572 // if reprojected is undef... reset it? | 2878 // if reprojected is undef... reset it? |
| 2573 if (!reprojected || !reprojected.length) // 3.2.2. | 2879 if (!reprojected || !reprojected.length) // 3.2.2. |
| 2574 reprojected = getChildNodesSnapshot(child); | 2880 reprojected = getChildNodesSnapshot(child); |
| 2575 pool.push.apply(pool, reprojected); // 3.2.3. | 2881 pool.push.apply(pool, reprojected); // 3.2.3. |
| 2576 } else { | 2882 } else { |
| 2577 pool.push(child); // 3.3. | 2883 pool.push(child); // 3.3. |
| 2578 } | 2884 } |
| 2579 }); | 2885 }); |
| 2580 | 2886 |
| 2581 var shadowInsertionPoint, point; | 2887 var shadowInsertionPoint, point; |
| 2582 while (tree) { // 4. | 2888 while (tree) { // 4. |
| 2583 // 4.1. | 2889 // 4.1. |
| 2584 shadowInsertionPoint = undefined; // Reset every iteration. | 2890 shadowInsertionPoint = undefined; // Reset every iteration. |
| 2585 visit(tree, isActiveShadowInsertionPoint, function(point) { | 2891 visit(tree, isActiveShadowInsertionPoint, function(point) { |
| 2586 shadowInsertionPoint = point; | 2892 shadowInsertionPoint = point; |
| 2587 return false; | 2893 return false; |
| 2588 }); | 2894 }); |
| 2589 point = shadowInsertionPoint; | 2895 point = shadowInsertionPoint; |
| 2590 | 2896 |
| 2591 pool = distribute(tree, pool); // 4.2. | 2897 pool = this.distribute(tree, pool); // 4.2. |
| 2592 if (point) { // 4.3. | 2898 if (point) { // 4.3. |
| 2593 var nextOlderTree = getNextOlderTree(tree); // 4.3.1. | 2899 var nextOlderTree = tree.olderShadowRoot; // 4.3.1. |
| 2594 if (!nextOlderTree) { | 2900 if (!nextOlderTree) { |
| 2595 break; // 4.3.1.1. | 2901 break; // 4.3.1.1. |
| 2596 } else { | 2902 } else { |
| 2597 tree = nextOlderTree; // 4.3.2.2. | 2903 tree = nextOlderTree; // 4.3.2.2. |
| 2598 assignShadowTreeToShadowInsertionPoint(tree, point); // 4.3.2.2. | 2904 assignToInsertionPoint(tree, point); // 4.3.2.2. |
| 2599 continue; // 4.3.2.3. | 2905 continue; // 4.3.2.3. |
| 2600 } | 2906 } |
| 2601 } else { | 2907 } else { |
| 2602 break; // 4.4. | 2908 break; // 4.4. |
| 2603 } | 2909 } |
| 2604 } | 2910 } |
| 2605 }, | 2911 }, |
| 2606 | 2912 |
| 2607 // Visual DOM mutation. | |
| 2608 appendChild: function(parent, child) { | 2913 appendChild: function(parent, child) { |
| 2914 // this.associateNode(child); |
| 2915 this.associateNode(parent); |
| 2609 appendChild(parent, child); | 2916 appendChild(parent, child); |
| 2610 this.associateNode(child); | |
| 2611 }, | 2917 }, |
| 2612 | 2918 |
| 2613 remove: function(node) { | 2919 remove: function(node) { |
| 2920 // this.associateNode(node); |
| 2921 this.associateNode(node.parentNode); |
| 2614 remove(node); | 2922 remove(node); |
| 2615 this.associateNode(node); | |
| 2616 }, | 2923 }, |
| 2617 | 2924 |
| 2618 removeAllChildNodes: function(parent) { | 2925 removeAllChildNodes: function(parent) { |
| 2926 this.associateNode(parent); |
| 2619 removeAllChildNodes(parent); | 2927 removeAllChildNodes(parent); |
| 2620 // TODO(arv): Does this need to associate all the nodes with this renderer
? | |
| 2621 }, | 2928 }, |
| 2622 | 2929 |
| 2623 associateNode: function(node) { | 2930 associateNode: function(node) { |
| 2624 // TODO: Clear when moved out of shadow tree. | |
| 2625 shadowDOMRendererTable.set(node, this); | 2931 shadowDOMRendererTable.set(node, this); |
| 2626 } | 2932 } |
| 2627 }; | 2933 }; |
| 2628 | 2934 |
| 2629 function isInsertionPoint(node) { | 2935 function isInsertionPoint(node) { |
| 2630 // Should this include <shadow>? | 2936 // Should this include <shadow>? |
| 2631 return node.localName === 'content'; | 2937 return node.localName === 'content'; |
| 2632 } | 2938 } |
| 2633 | 2939 |
| 2634 function isActiveInsertionPoint(node) { | 2940 function isActiveInsertionPoint(node) { |
| 2635 // <content> inside another <content> or <shadow> is considered inactive. | 2941 // <content> inside another <content> or <shadow> is considered inactive. |
| 2636 return node.localName === 'content'; | 2942 return node.localName === 'content'; |
| 2637 } | 2943 } |
| 2638 | 2944 |
| 2639 function isShadowInsertionPoint(node) { | 2945 function isShadowInsertionPoint(node) { |
| 2640 return node.localName === 'shadow'; | 2946 return node.localName === 'shadow'; |
| 2641 } | 2947 } |
| 2642 | 2948 |
| 2643 function isActiveShadowInsertionPoint(node) { | 2949 function isActiveShadowInsertionPoint(node) { |
| 2644 // <shadow> inside another <content> or <shadow> is considered inactive. | 2950 // <shadow> inside another <content> or <shadow> is considered inactive. |
| 2645 return node.localName === 'shadow'; | 2951 return node.localName === 'shadow'; |
| 2646 } | 2952 } |
| 2647 | 2953 |
| 2648 function isShadowHost(shadowHost) { | 2954 function isShadowHost(shadowHost) { |
| 2649 return !!shadowHost.shadowRoot; | 2955 return shadowHost.shadowRoot; |
| 2650 } | |
| 2651 | |
| 2652 /** | |
| 2653 * @param {WrapperShadowRoot} tree | |
| 2654 */ | |
| 2655 function getNextOlderTree(tree) { | |
| 2656 return nextOlderShadowTreeTable.get(tree); | |
| 2657 } | 2956 } |
| 2658 | 2957 |
| 2659 function getShadowTrees(host) { | 2958 function getShadowTrees(host) { |
| 2660 var trees = []; | 2959 var trees = []; |
| 2661 | 2960 |
| 2662 for (var tree = host.shadowRoot; | 2961 for (var tree = host.shadowRoot; tree; tree = tree.olderShadowRoot) { |
| 2663 tree; | |
| 2664 tree = nextOlderShadowTreeTable.get(tree)) { | |
| 2665 trees.push(tree); | 2962 trees.push(tree); |
| 2666 } | 2963 } |
| 2667 return trees; | 2964 return trees; |
| 2668 } | 2965 } |
| 2669 | 2966 |
| 2670 function assignShadowTreeToShadowInsertionPoint(tree, point) { | 2967 function assignToInsertionPoint(tree, point) { |
| 2671 insertionParentTable.set(tree, point); | 2968 insertionParentTable.set(tree, point); |
| 2672 } | 2969 } |
| 2673 | 2970 |
| 2674 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#ren
dering-shadow-trees | 2971 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#ren
dering-shadow-trees |
| 2675 function render(host) { | 2972 function render(host) { |
| 2676 new ShadowRenderer(host).render(); | 2973 new ShadowRenderer(host).render(); |
| 2677 }; | 2974 }; |
| 2678 | 2975 |
| 2976 // Need to rerender shadow host when: |
| 2977 // |
| 2978 // - a direct child to the ShadowRoot is added or removed |
| 2979 // - a direct child to the host is added or removed |
| 2980 // - a new shadow root is created |
| 2981 // - a direct child to a content/shadow element is added or removed |
| 2982 // - a sibling to a content/shadow element is added or removed |
| 2983 // - content[select] is changed |
| 2984 // - an attribute in a direct child to a host is modified |
| 2985 |
| 2986 /** |
| 2987 * This gets called when a node was added or removed to it. |
| 2988 */ |
| 2679 Node.prototype.invalidateShadowRenderer = function(force) { | 2989 Node.prototype.invalidateShadowRenderer = function(force) { |
| 2680 // TODO: If this is in light DOM we only need to invalidate renderer if this | |
| 2681 // is a direct child of a ShadowRoot. | |
| 2682 // Maybe we should only associate renderers with direct child nodes of a | |
| 2683 // shadow root (and all nodes in the shadow dom). | |
| 2684 var renderer = shadowDOMRendererTable.get(this); | 2990 var renderer = shadowDOMRendererTable.get(this); |
| 2685 if (!renderer) | 2991 if (renderer) { |
| 2686 return false; | |
| 2687 | |
| 2688 var p; | |
| 2689 if (force || this.shadowRoot || | |
| 2690 (p = this.parentNode) && (p.shadowRoot || p instanceof ShadowRoot)) { | |
| 2691 renderer.invalidate(); | 2992 renderer.invalidate(); |
| 2993 return true; |
| 2692 } | 2994 } |
| 2693 | 2995 |
| 2694 return true; | 2996 return false; |
| 2695 }; | 2997 }; |
| 2696 | 2998 |
| 2697 HTMLContentElement.prototype.getDistributedNodes = function() { | 2999 HTMLContentElement.prototype.getDistributedNodes = function() { |
| 2698 // TODO(arv): We should associate the element with the shadow root so we | 3000 var renderer = shadowDOMRendererTable.get(this); |
| 2699 // only have to rerender this ShadowRenderer. | 3001 if (renderer) |
| 2700 renderAllPending(); | 3002 renderer.render(); |
| 2701 return getDistributedChildNodes(this); | 3003 return getDistributedChildNodes(this); |
| 2702 }; | 3004 }; |
| 2703 | 3005 |
| 2704 mixin(Node.prototype, { | 3006 HTMLShadowElement.prototype.nodeWasAdded_ = |
| 2705 get insertionParent() { | 3007 HTMLContentElement.prototype.nodeWasAdded_ = function() { |
| 2706 return insertionParentTable.get(this) || null; | 3008 // Invalidate old renderer if any. |
| 2707 } | 3009 this.invalidateShadowRenderer(); |
| 2708 }); | 3010 |
| 3011 var shadowRoot = getShadowRootAncestor(this); |
| 3012 var renderer; |
| 3013 if (shadowRoot) |
| 3014 renderer = getRendererForShadowRoot(shadowRoot); |
| 3015 shadowDOMRendererTable.set(this, renderer); |
| 3016 if (renderer) |
| 3017 renderer.invalidate(); |
| 3018 }; |
| 2709 | 3019 |
| 2710 scope.eventParentsTable = eventParentsTable; | 3020 scope.eventParentsTable = eventParentsTable; |
| 2711 scope.getRendererForHost = getRendererForHost; | 3021 scope.getRendererForHost = getRendererForHost; |
| 2712 scope.getShadowTrees = getShadowTrees; | 3022 scope.getShadowTrees = getShadowTrees; |
| 2713 scope.nextOlderShadowTreeTable = nextOlderShadowTreeTable; | 3023 scope.insertionParentTable = insertionParentTable; |
| 2714 scope.renderAllPending = renderAllPending; | 3024 scope.renderAllPending = renderAllPending; |
| 2715 | 3025 |
| 2716 // Exposed for testing | 3026 // Exposed for testing |
| 2717 scope.visual = { | 3027 scope.visual = { |
| 2718 removeAllChildNodes: removeAllChildNodes, | 3028 removeAllChildNodes: removeAllChildNodes, |
| 2719 appendChild: appendChild, | 3029 appendChild: appendChild, |
| 2720 removeChild: removeChild | 3030 removeChild: removeChild |
| 2721 }; | 3031 }; |
| 2722 | 3032 |
| 2723 })(this.ShadowDOMPolyfill); | 3033 })(this.ShadowDOMPolyfill); |
| 2724 // Copyright 2013 The Polymer Authors. All rights reserved. | 3034 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 2725 // Use of this source code is goverened by a BSD-style | 3035 // Use of this source code is goverened by a BSD-style |
| 2726 // license that can be found in the LICENSE file. | 3036 // license that can be found in the LICENSE file. |
| 2727 | 3037 |
| 2728 (function(scope) { | 3038 (function(scope) { |
| 2729 'use strict'; | 3039 'use strict'; |
| 2730 | 3040 |
| 3041 var HTMLElement = scope.wrappers.HTMLElement; |
| 3042 var assert = scope.assert; |
| 3043 var mixin = scope.mixin; |
| 3044 var registerWrapper = scope.registerWrapper; |
| 3045 var unwrap = scope.unwrap; |
| 3046 var wrap = scope.wrap; |
| 3047 |
| 3048 var elementsWithFormProperty = [ |
| 3049 'HTMLButtonElement', |
| 3050 'HTMLFieldSetElement', |
| 3051 'HTMLInputElement', |
| 3052 'HTMLKeygenElement', |
| 3053 'HTMLLabelElement', |
| 3054 'HTMLLegendElement', |
| 3055 'HTMLObjectElement', |
| 3056 'HTMLOptionElement', |
| 3057 'HTMLOutputElement', |
| 3058 'HTMLSelectElement', |
| 3059 'HTMLTextAreaElement', |
| 3060 ]; |
| 3061 |
| 3062 function createWrapperConstructor(name) { |
| 3063 if (!window[name]) |
| 3064 return; |
| 3065 |
| 3066 // Ensure we are not overriding an already existing constructor. |
| 3067 assert(!scope.wrappers[name]); |
| 3068 |
| 3069 var GeneratedWrapper = function(node) { |
| 3070 // At this point all of them extend HTMLElement. |
| 3071 HTMLElement.call(this, node); |
| 3072 } |
| 3073 GeneratedWrapper.prototype = Object.create(HTMLElement.prototype); |
| 3074 mixin(GeneratedWrapper.prototype, { |
| 3075 get form() { |
| 3076 return wrap(unwrap(this).form); |
| 3077 }, |
| 3078 }); |
| 3079 |
| 3080 registerWrapper(window[name], GeneratedWrapper, |
| 3081 document.createElement(name.slice(4, -7))); |
| 3082 scope.wrappers[name] = GeneratedWrapper; |
| 3083 } |
| 3084 |
| 3085 elementsWithFormProperty.forEach(createWrapperConstructor); |
| 3086 |
| 3087 })(this.ShadowDOMPolyfill); |
| 3088 |
| 3089 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3090 // Use of this source code is goverened by a BSD-style |
| 3091 // license that can be found in the LICENSE file. |
| 3092 |
| 3093 (function(scope) { |
| 3094 'use strict'; |
| 3095 |
| 2731 var GetElementsByInterface = scope.GetElementsByInterface; | 3096 var GetElementsByInterface = scope.GetElementsByInterface; |
| 2732 var Node = scope.wrappers.Node; | 3097 var Node = scope.wrappers.Node; |
| 2733 var ParentNodeInterface = scope.ParentNodeInterface; | 3098 var ParentNodeInterface = scope.ParentNodeInterface; |
| 2734 var SelectorsInterface = scope.SelectorsInterface; | 3099 var SelectorsInterface = scope.SelectorsInterface; |
| 3100 var ShadowRoot = scope.wrappers.ShadowRoot; |
| 2735 var defineWrapGetter = scope.defineWrapGetter; | 3101 var defineWrapGetter = scope.defineWrapGetter; |
| 2736 var elementFromPoint = scope.elementFromPoint; | 3102 var elementFromPoint = scope.elementFromPoint; |
| 2737 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; | 3103 var forwardMethodsToWrapper = scope.forwardMethodsToWrapper; |
| 3104 var matchesName = scope.matchesName; |
| 2738 var mixin = scope.mixin; | 3105 var mixin = scope.mixin; |
| 2739 var registerWrapper = scope.registerWrapper; | 3106 var registerWrapper = scope.registerWrapper; |
| 2740 var unwrap = scope.unwrap; | 3107 var unwrap = scope.unwrap; |
| 2741 var wrap = scope.wrap; | 3108 var wrap = scope.wrap; |
| 2742 var wrapEventTargetMethods = scope.wrapEventTargetMethods; | 3109 var wrapEventTargetMethods = scope.wrapEventTargetMethods; |
| 2743 var wrapNodeList = scope.wrapNodeList; | 3110 var wrapNodeList = scope.wrapNodeList; |
| 2744 | 3111 |
| 2745 var implementationTable = new SideTable(); | 3112 var implementationTable = new SideTable(); |
| 2746 | 3113 |
| 2747 function Document(node) { | 3114 function Document(node) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2760 // directly on the instance. | 3127 // directly on the instance. |
| 2761 | 3128 |
| 2762 function wrapMethod(name) { | 3129 function wrapMethod(name) { |
| 2763 var original = document[name]; | 3130 var original = document[name]; |
| 2764 Document.prototype[name] = function() { | 3131 Document.prototype[name] = function() { |
| 2765 return wrap(original.apply(this.impl, arguments)); | 3132 return wrap(original.apply(this.impl, arguments)); |
| 2766 }; | 3133 }; |
| 2767 } | 3134 } |
| 2768 | 3135 |
| 2769 [ | 3136 [ |
| 2770 'getElementById', | 3137 'createComment', |
| 3138 'createDocumentFragment', |
| 2771 'createElement', | 3139 'createElement', |
| 2772 'createElementNS', | 3140 'createElementNS', |
| 2773 'createTextNode', | |
| 2774 'createDocumentFragment', | |
| 2775 'createEvent', | 3141 'createEvent', |
| 2776 'createEventNS', | 3142 'createEventNS', |
| 3143 'createRange', |
| 3144 'createTextNode', |
| 3145 'getElementById', |
| 2777 ].forEach(wrapMethod); | 3146 ].forEach(wrapMethod); |
| 2778 | 3147 |
| 2779 var originalAdoptNode = document.adoptNode; | 3148 var originalAdoptNode = document.adoptNode; |
| 2780 var originalWrite = document.write; | 3149 |
| 3150 function adoptNodeNoRemove(node, doc) { |
| 3151 originalAdoptNode.call(doc.impl, unwrap(node)); |
| 3152 adoptSubtree(node, doc); |
| 3153 } |
| 3154 |
| 3155 function adoptSubtree(node, doc) { |
| 3156 if (node.shadowRoot) |
| 3157 doc.adoptNode(node.shadowRoot); |
| 3158 if (node instanceof ShadowRoot) |
| 3159 adoptOlderShadowRoots(node, doc); |
| 3160 for (var child = node.firstChild; child; child = child.nextSibling) { |
| 3161 adoptSubtree(child, doc); |
| 3162 } |
| 3163 } |
| 3164 |
| 3165 function adoptOlderShadowRoots(shadowRoot, doc) { |
| 3166 var oldShadowRoot = shadowRoot.olderShadowRoot; |
| 3167 if (oldShadowRoot) |
| 3168 doc.adoptNode(oldShadowRoot); |
| 3169 } |
| 2781 | 3170 |
| 2782 mixin(Document.prototype, { | 3171 mixin(Document.prototype, { |
| 2783 adoptNode: function(node) { | 3172 adoptNode: function(node) { |
| 2784 originalAdoptNode.call(this.impl, unwrap(node)); | 3173 if (node.parentNode) |
| 3174 node.parentNode.removeChild(node); |
| 3175 adoptNodeNoRemove(node, this); |
| 2785 return node; | 3176 return node; |
| 2786 }, | 3177 }, |
| 2787 elementFromPoint: function(x, y) { | 3178 elementFromPoint: function(x, y) { |
| 2788 return elementFromPoint(this, this, x, y); | 3179 return elementFromPoint(this, this, x, y); |
| 2789 }, | |
| 2790 write: function(s) { | |
| 2791 var all = this.querySelectorAll('*'); | |
| 2792 var last = all[all.length - 1]; | |
| 2793 while (last.nextSibling) { | |
| 2794 last = last.nextSibling; | |
| 2795 } | |
| 2796 var p = last.parentNode; | |
| 2797 p.lastChild_ = undefined; | |
| 2798 last.nextSibling_ = undefined; | |
| 2799 originalWrite.call(this.impl, s); | |
| 2800 } | 3180 } |
| 2801 }); | 3181 }); |
| 2802 | 3182 |
| 3183 if (document.register) { |
| 3184 var originalRegister = document.register; |
| 3185 Document.prototype.register = function(tagName, object) { |
| 3186 var prototype = object.prototype; |
| 3187 |
| 3188 // If we already used the object as a prototype for another custom |
| 3189 // element. |
| 3190 if (scope.nativePrototypeTable.get(prototype)) { |
| 3191 // TODO(arv): DOMException |
| 3192 throw new Error('NotSupportedError'); |
| 3193 } |
| 3194 |
| 3195 // Find first object on the prototype chain that already have a native |
| 3196 // prototype. Keep track of all the objects before that so we can create |
| 3197 // a similar structure for the native case. |
| 3198 var proto = Object.getPrototypeOf(prototype); |
| 3199 var nativePrototype; |
| 3200 var prototypes = []; |
| 3201 while (proto) { |
| 3202 nativePrototype = scope.nativePrototypeTable.get(proto); |
| 3203 if (nativePrototype) |
| 3204 break; |
| 3205 prototypes.push(proto); |
| 3206 proto = Object.getPrototypeOf(proto); |
| 3207 } |
| 3208 |
| 3209 if (!nativePrototype) { |
| 3210 // TODO(arv): DOMException |
| 3211 throw new Error('NotSupportedError'); |
| 3212 } |
| 3213 |
| 3214 // This works by creating a new prototype object that is empty, but has |
| 3215 // the native prototype as its proto. The original prototype object |
| 3216 // passed into register is used as the wrapper prototype. |
| 3217 |
| 3218 var newPrototype = Object.create(nativePrototype); |
| 3219 for (var i = prototypes.length - 1; i >= 0; i--) { |
| 3220 newPrototype = Object.create(newPrototype); |
| 3221 } |
| 3222 |
| 3223 // Add callbacks if present. |
| 3224 // Names are taken from: |
| 3225 // 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 |
| 3226 // and not from the spec since the spec is out of date. |
| 3227 [ |
| 3228 'createdCallback', |
| 3229 'enteredDocumentCallback', |
| 3230 'leftDocumentCallback', |
| 3231 'attributeChangedCallback', |
| 3232 ].forEach(function(name) { |
| 3233 var f = prototype[name]; |
| 3234 if (!f) |
| 3235 return; |
| 3236 newPrototype[name] = function() { |
| 3237 f.apply(wrap(this), arguments); |
| 3238 }; |
| 3239 }); |
| 3240 |
| 3241 var nativeConstructor = originalRegister.call(unwrap(this), tagName, |
| 3242 {prototype: newPrototype}); |
| 3243 |
| 3244 function GeneratedWrapper(node) { |
| 3245 if (!node) |
| 3246 return document.createElement(tagName); |
| 3247 this.impl = node; |
| 3248 } |
| 3249 GeneratedWrapper.prototype = prototype; |
| 3250 GeneratedWrapper.prototype.constructor = GeneratedWrapper; |
| 3251 |
| 3252 scope.constructorTable.set(newPrototype, GeneratedWrapper); |
| 3253 scope.nativePrototypeTable.set(prototype, newPrototype); |
| 3254 |
| 3255 return GeneratedWrapper; |
| 3256 }; |
| 3257 |
| 3258 forwardMethodsToWrapper([ |
| 3259 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocume
nt |
| 3260 ], [ |
| 3261 'register', |
| 3262 ]); |
| 3263 } |
| 3264 |
| 2803 // We also override some of the methods on document.body and document.head | 3265 // We also override some of the methods on document.body and document.head |
| 2804 // for convenience. | 3266 // for convenience. |
| 2805 forwardMethodsToWrapper([ | 3267 forwardMethodsToWrapper([ |
| 2806 window.HTMLBodyElement, | 3268 window.HTMLBodyElement, |
| 2807 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument | 3269 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument |
| 2808 window.HTMLHeadElement, | 3270 window.HTMLHeadElement, |
| 3271 window.HTMLHtmlElement, |
| 2809 ], [ | 3272 ], [ |
| 2810 'appendChild', | 3273 'appendChild', |
| 2811 'compareDocumentPosition', | 3274 'compareDocumentPosition', |
| 3275 'contains', |
| 2812 'getElementsByClassName', | 3276 'getElementsByClassName', |
| 2813 'getElementsByTagName', | 3277 'getElementsByTagName', |
| 2814 'getElementsByTagNameNS', | 3278 'getElementsByTagNameNS', |
| 2815 'insertBefore', | 3279 'insertBefore', |
| 2816 'querySelector', | 3280 'querySelector', |
| 2817 'querySelectorAll', | 3281 'querySelectorAll', |
| 2818 'removeChild', | 3282 'removeChild', |
| 2819 'replaceChild', | 3283 'replaceChild', |
| 3284 matchesName, |
| 2820 ]); | 3285 ]); |
| 2821 | 3286 |
| 2822 forwardMethodsToWrapper([ | 3287 forwardMethodsToWrapper([ |
| 2823 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument | 3288 window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument |
| 2824 ], [ | 3289 ], [ |
| 2825 'adoptNode', | 3290 'adoptNode', |
| 3291 'contains', |
| 3292 'createComment', |
| 2826 'createDocumentFragment', | 3293 'createDocumentFragment', |
| 2827 'createElement', | 3294 'createElement', |
| 2828 'createElementNS', | 3295 'createElementNS', |
| 2829 'createEvent', | 3296 'createEvent', |
| 2830 'createEventNS', | 3297 'createEventNS', |
| 3298 'createRange', |
| 2831 'createTextNode', | 3299 'createTextNode', |
| 2832 'elementFromPoint', | 3300 'elementFromPoint', |
| 2833 'getElementById', | 3301 'getElementById', |
| 2834 'write', | |
| 2835 ]); | 3302 ]); |
| 2836 | 3303 |
| 2837 mixin(Document.prototype, GetElementsByInterface); | 3304 mixin(Document.prototype, GetElementsByInterface); |
| 2838 mixin(Document.prototype, ParentNodeInterface); | 3305 mixin(Document.prototype, ParentNodeInterface); |
| 2839 mixin(Document.prototype, SelectorsInterface); | 3306 mixin(Document.prototype, SelectorsInterface); |
| 2840 | 3307 |
| 2841 mixin(Document.prototype, { | 3308 mixin(Document.prototype, { |
| 2842 get implementation() { | 3309 get implementation() { |
| 2843 var implementation = implementationTable.get(this); | 3310 var implementation = implementationTable.get(this); |
| 2844 if (implementation) | 3311 if (implementation) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2891 | 3358 |
| 2892 forwardMethodsToWrapper([ | 3359 forwardMethodsToWrapper([ |
| 2893 window.DOMImplementation, | 3360 window.DOMImplementation, |
| 2894 ], [ | 3361 ], [ |
| 2895 'createDocumentType', | 3362 'createDocumentType', |
| 2896 'createDocument', | 3363 'createDocument', |
| 2897 'createHTMLDocument', | 3364 'createHTMLDocument', |
| 2898 'hasFeature', | 3365 'hasFeature', |
| 2899 ]); | 3366 ]); |
| 2900 | 3367 |
| 3368 scope.adoptNodeNoRemove = adoptNodeNoRemove; |
| 3369 scope.wrappers.DOMImplementation = DOMImplementation; |
| 2901 scope.wrappers.Document = Document; | 3370 scope.wrappers.Document = Document; |
| 2902 scope.wrappers.DOMImplementation = DOMImplementation; | |
| 2903 | 3371 |
| 2904 })(this.ShadowDOMPolyfill); | 3372 })(this.ShadowDOMPolyfill); |
| 2905 | 3373 |
| 2906 // Copyright 2013 The Polymer Authors. All rights reserved. | 3374 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 2907 // Use of this source code is goverened by a BSD-style | 3375 // Use of this source code is goverened by a BSD-style |
| 2908 // license that can be found in the LICENSE file. | 3376 // license that can be found in the LICENSE file. |
| 2909 | 3377 |
| 2910 (function(scope) { | 3378 (function(scope) { |
| 2911 'use strict'; | 3379 'use strict'; |
| 2912 | 3380 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3039 | 3507 |
| 3040 })(this.ShadowDOMPolyfill); | 3508 })(this.ShadowDOMPolyfill); |
| 3041 | 3509 |
| 3042 // Copyright 2013 The Polymer Authors. All rights reserved. | 3510 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3043 // Use of this source code is goverened by a BSD-style | 3511 // Use of this source code is goverened by a BSD-style |
| 3044 // license that can be found in the LICENSE file. | 3512 // license that can be found in the LICENSE file. |
| 3045 | 3513 |
| 3046 (function(scope) { | 3514 (function(scope) { |
| 3047 'use strict'; | 3515 'use strict'; |
| 3048 | 3516 |
| 3517 var registerWrapper = scope.registerWrapper; |
| 3518 var unwrap = scope.unwrap; |
| 3519 var unwrapIfNeeded = scope.unwrapIfNeeded; |
| 3520 var wrap = scope.wrap; |
| 3521 |
| 3522 var OriginalRange = window.Range; |
| 3523 |
| 3524 function Range(impl) { |
| 3525 this.impl = impl; |
| 3526 } |
| 3527 Range.prototype = { |
| 3528 get startContainer() { |
| 3529 return wrap(this.impl.startContainer); |
| 3530 }, |
| 3531 get endContainer() { |
| 3532 return wrap(this.impl.endContainer); |
| 3533 }, |
| 3534 get commonAncestorContainer() { |
| 3535 return wrap(this.impl.commonAncestorContainer); |
| 3536 }, |
| 3537 setStart: function(refNode,offset) { |
| 3538 this.impl.setStart(unwrapIfNeeded(refNode), offset); |
| 3539 }, |
| 3540 setEnd: function(refNode,offset) { |
| 3541 this.impl.setEnd(unwrapIfNeeded(refNode), offset); |
| 3542 }, |
| 3543 setStartBefore: function(refNode) { |
| 3544 this.impl.setStartBefore(unwrapIfNeeded(refNode)); |
| 3545 }, |
| 3546 setStartAfter: function(refNode) { |
| 3547 this.impl.setStartAfter(unwrapIfNeeded(refNode)); |
| 3548 }, |
| 3549 setEndBefore: function(refNode) { |
| 3550 this.impl.setEndBefore(unwrapIfNeeded(refNode)); |
| 3551 }, |
| 3552 setEndAfter: function(refNode) { |
| 3553 this.impl.setEndAfter(unwrapIfNeeded(refNode)); |
| 3554 }, |
| 3555 selectNode: function(refNode) { |
| 3556 this.impl.selectNode(unwrapIfNeeded(refNode)); |
| 3557 }, |
| 3558 selectNodeContents: function(refNode) { |
| 3559 this.impl.selectNodeContents(unwrapIfNeeded(refNode)); |
| 3560 }, |
| 3561 compareBoundaryPoints: function(how, sourceRange) { |
| 3562 return this.impl.compareBoundaryPoints(how, unwrap(sourceRange)); |
| 3563 }, |
| 3564 extractContents: function() { |
| 3565 return wrap(this.impl.extractContents()); |
| 3566 }, |
| 3567 cloneContents: function() { |
| 3568 return wrap(this.impl.cloneContents()); |
| 3569 }, |
| 3570 insertNode: function(node) { |
| 3571 this.impl.insertNode(unwrapIfNeeded(node)); |
| 3572 }, |
| 3573 surroundContents: function(newParent) { |
| 3574 this.impl.surroundContents(unwrapIfNeeded(newParent)); |
| 3575 }, |
| 3576 cloneRange: function() { |
| 3577 return wrap(this.impl.cloneRange()); |
| 3578 }, |
| 3579 isPointInRange: function(node, offset) { |
| 3580 return this.impl.isPointInRange(unwrapIfNeeded(node), offset); |
| 3581 }, |
| 3582 comparePoint: function(node, offset) { |
| 3583 return this.impl.comparePoint(unwrapIfNeeded(node), offset); |
| 3584 }, |
| 3585 intersectsNode: function(node) { |
| 3586 return this.impl.intersectsNode(unwrapIfNeeded(node)); |
| 3587 } |
| 3588 }; |
| 3589 |
| 3590 // IE9 does not have createContextualFragment. |
| 3591 if (OriginalRange.prototype.createContextualFragment) { |
| 3592 Range.prototype.createContextualFragment = function(html) { |
| 3593 return wrap(this.impl.createContextualFragment(html)); |
| 3594 }; |
| 3595 } |
| 3596 |
| 3597 registerWrapper(window.Range, Range); |
| 3598 |
| 3599 scope.wrappers.Range = Range; |
| 3600 |
| 3601 })(this.ShadowDOMPolyfill); |
| 3602 |
| 3603 // Copyright 2013 The Polymer Authors. All rights reserved. |
| 3604 // Use of this source code is goverened by a BSD-style |
| 3605 // license that can be found in the LICENSE file. |
| 3606 |
| 3607 (function(scope) { |
| 3608 'use strict'; |
| 3609 |
| 3049 var isWrapperFor = scope.isWrapperFor; | 3610 var isWrapperFor = scope.isWrapperFor; |
| 3050 | 3611 |
| 3051 // This is a list of the elements we currently override the global constructor | 3612 // This is a list of the elements we currently override the global constructor |
| 3052 // for. | 3613 // for. |
| 3053 var elements = { | 3614 var elements = { |
| 3054 'a': 'HTMLAnchorElement', | 3615 'a': 'HTMLAnchorElement', |
| 3055 'applet': 'HTMLAppletElement', | 3616 'applet': 'HTMLAppletElement', |
| 3056 'area': 'HTMLAreaElement', | 3617 'area': 'HTMLAreaElement', |
| 3057 'audio': 'HTMLAudioElement', | 3618 'audio': 'HTMLAudioElement', |
| 3058 'br': 'HTMLBRElement', | 3619 'br': 'HTMLBRElement', |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 }); | 3725 }); |
| 3165 | 3726 |
| 3166 //TODO(sjmiles): review method alias with Arv | 3727 //TODO(sjmiles): review method alias with Arv |
| 3167 HTMLElement.prototype.webkitCreateShadowRoot = | 3728 HTMLElement.prototype.webkitCreateShadowRoot = |
| 3168 HTMLElement.prototype.createShadowRoot; | 3729 HTMLElement.prototype.createShadowRoot; |
| 3169 | 3730 |
| 3170 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?) | 3731 // TODO(jmesserly): we need to wrap document somehow (a dart:html hook?) |
| 3171 window.dartExperimentalFixupGetTag = function(originalGetTag) { | 3732 window.dartExperimentalFixupGetTag = function(originalGetTag) { |
| 3172 var NodeList = ShadowDOMPolyfill.wrappers.NodeList; | 3733 var NodeList = ShadowDOMPolyfill.wrappers.NodeList; |
| 3173 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot; | 3734 var ShadowRoot = ShadowDOMPolyfill.wrappers.ShadowRoot; |
| 3174 var isWrapper = ShadowDOMPolyfill.isWrapper; | 3735 var unwrapIfNeeded = ShadowDOMPolyfill.unwrapIfNeeded; |
| 3175 var unwrap = ShadowDOMPolyfill.unwrap; | |
| 3176 function getTag(obj) { | 3736 function getTag(obj) { |
| 3737 // TODO(jmesserly): do we still need these? |
| 3177 if (obj instanceof NodeList) return 'NodeList'; | 3738 if (obj instanceof NodeList) return 'NodeList'; |
| 3178 if (obj instanceof ShadowRoot) return 'ShadowRoot'; | 3739 if (obj instanceof ShadowRoot) return 'ShadowRoot'; |
| 3179 if (obj instanceof MutationRecord) return 'MutationRecord'; | 3740 if (obj instanceof MutationRecord) return 'MutationRecord'; |
| 3180 if (obj instanceof MutationObserver) return 'MutationObserver'; | 3741 if (obj instanceof MutationObserver) return 'MutationObserver'; |
| 3181 | 3742 |
| 3182 if (isWrapper(obj)) { | 3743 var unwrapped = unwrapIfNeeded(obj); |
| 3183 obj = unwrap(obj); | 3744 if (obj !== unwrapped) { |
| 3184 | 3745 // Fix up class names for Firefox. |
| 3185 // Fix up class names for Firefox. For some of them like | 3746 // For some of them (like HTMLFormElement and HTMLInputElement), |
| 3186 // HTMLFormElement and HTMLInputElement, the "constructor" property of | 3747 // the "constructor" property of the unwrapped nodes points at the |
| 3187 // the unwrapped nodes points at the wrapper for some reason. | 3748 // wrapper. |
| 3188 // TODO(jmesserly): figure out why this is happening. | 3749 // Note: it is safe to check for the GeneratedWrapper string because |
| 3750 // we know it is some kind of Shadow DOM wrapper object. |
| 3189 var ctor = obj.constructor; | 3751 var ctor = obj.constructor; |
| 3190 if (ctor && ctor._ShadowDOMPolyfill$isGeneratedWrapper) { | 3752 if (ctor && ctor.name == 'GeneratedWrapper') { |
| 3191 var name = ctor._ShadowDOMPolyfill$cacheTag_; | 3753 var name = ctor._ShadowDOMPolyfill$cacheTag_; |
| 3192 if (!name) { | 3754 if (!name) { |
| 3193 name = Object.prototype.toString.call(obj); | 3755 name = Object.prototype.toString.call(unwrapped); |
| 3194 name = name.substring(8, name.length - 1); | 3756 name = name.substring(8, name.length - 1); |
| 3195 ctor._ShadowDOMPolyfill$cacheTag_ = name; | 3757 ctor._ShadowDOMPolyfill$cacheTag_ = name; |
| 3196 } | 3758 } |
| 3197 return name; | 3759 return name; |
| 3198 } | 3760 } |
| 3761 |
| 3762 obj = unwrapped; |
| 3199 } | 3763 } |
| 3200 return originalGetTag(obj); | 3764 return originalGetTag(obj); |
| 3201 } | 3765 } |
| 3202 | 3766 |
| 3203 return getTag; | 3767 return getTag; |
| 3204 }; | 3768 }; |
| 3205 })(); | 3769 })(); |
| 3206 | 3770 |
| 3207 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3771 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 3208 // for details. All rights reserved. Use of this source code is governed by a | 3772 // for details. All rights reserved. Use of this source code is governed by a |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3722 css.push(cssRules[i].cssText); | 4286 css.push(cssRules[i].cssText); |
| 3723 } | 4287 } |
| 3724 return css.join('\n\n'); | 4288 return css.join('\n\n'); |
| 3725 } | 4289 } |
| 3726 | 4290 |
| 3727 // exports | 4291 // exports |
| 3728 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2; | 4292 scope.ShadowCSS.shimShadowDOMStyling2 = shimShadowDOMStyling2; |
| 3729 })(window.Platform); | 4293 })(window.Platform); |
| 3730 | 4294 |
| 3731 } | 4295 } |
| OLD | NEW |