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

Side by Side Diff: lib/dom/templates/html/impl/impl_Element.darttemplate

Issue 9732019: dart:html perf optimization based on runing Dromaeo benchmarks (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // TODO(jacobr): use _Lists.dart to remove some of the duplicated 5 // TODO(jacobr): use _Lists.dart to remove some of the duplicated
6 // functionality. 6 // functionality.
7 class _ChildrenElementList implements ElementList { 7 class _ChildrenElementList implements ElementList {
8 // Raw Element. 8 // Raw Element.
9 final _ElementImpl _element; 9 final _ElementImpl _element;
10 final _HTMLCollectionImpl _childElements; 10 final _HTMLCollectionImpl _childElements;
11 11
12 _ChildrenElementList._wrap(_ElementImpl element) 12 _ChildrenElementList._wrap(_ElementImpl element)
13 : _childElements = element._children, 13 : _childElements = element.$dom_children,
14 _element = element; 14 _element = element;
15 15
16 List<Element> _toList() { 16 List<Element> _toList() {
17 final output = new List(_childElements.length); 17 final output = new List(_childElements.length);
18 for (int i = 0, len = _childElements.length; i < len; i++) { 18 for (int i = 0, len = _childElements.length; i < len; i++) {
19 output[i] = _childElements[i]; 19 output[i] = _childElements[i];
20 } 20 }
21 return output; 21 return output;
22 } 22 }
23 23
24 _ElementImpl get first() { 24 _ElementImpl get first() {
25 return _element._firstElementChild; 25 return _element.$dom_firstElementChild;
26 } 26 }
27 27
28 void forEach(void f(Element element)) { 28 void forEach(void f(Element element)) {
29 for (_ElementImpl element in _childElements) { 29 for (_ElementImpl element in _childElements) {
30 f(element); 30 f(element);
31 } 31 }
32 } 32 }
33 33
34 ElementList filter(bool f(Element element)) { 34 ElementList filter(bool f(Element element)) {
35 final output = <Element>[]; 35 final output = <Element>[];
(...skipping 25 matching lines...) Expand all
61 61
62 Collection map(f(Element element)) { 62 Collection map(f(Element element)) {
63 final out = []; 63 final out = [];
64 for (Element el in this) { 64 for (Element el in this) {
65 out.add(f(el)); 65 out.add(f(el));
66 } 66 }
67 return out; 67 return out;
68 } 68 }
69 69
70 bool isEmpty() { 70 bool isEmpty() {
71 return _element._firstElementChild == null; 71 return _element.$dom_firstElementChild == null;
72 } 72 }
73 73
74 int get length() { 74 int get length() {
75 return _childElements.length; 75 return _childElements.length;
76 } 76 }
77 77
78 _ElementImpl operator [](int index) { 78 _ElementImpl operator [](int index) {
79 return _childElements[index]; 79 return _childElements[index];
80 } 80 }
81 81
82 void operator []=(int index, _ElementImpl value) { 82 void operator []=(int index, _ElementImpl value) {
83 _element._replaceChild(value, _childElements[index]); 83 _element.$dom_replaceChild(value, _childElements[index]);
84 } 84 }
85 85
86 void set length(int newLength) { 86 void set length(int newLength) {
87 // TODO(jacobr): remove children when length is reduced. 87 // TODO(jacobr): remove children when length is reduced.
88 throw const UnsupportedOperationException(''); 88 throw const UnsupportedOperationException('');
89 } 89 }
90 90
91 Element add(_ElementImpl value) { 91 Element add(_ElementImpl value) {
92 _element._appendChild(value); 92 _element.$dom_appendChild(value);
93 return value; 93 return value;
94 } 94 }
95 95
96 Element addLast(_ElementImpl value) => add(value); 96 Element addLast(_ElementImpl value) => add(value);
97 97
98 Iterator<Element> iterator() => _toList().iterator(); 98 Iterator<Element> iterator() => _toList().iterator();
99 99
100 void addAll(Collection<Element> collection) { 100 void addAll(Collection<Element> collection) {
101 for (_ElementImpl element in collection) { 101 for (_ElementImpl element in collection) {
102 _element._appendChild(element); 102 _element.$dom_appendChild(element);
103 } 103 }
104 } 104 }
105 105
106 void sort(int compare(Element a, Element b)) { 106 void sort(int compare(Element a, Element b)) {
107 throw const UnsupportedOperationException('TODO(jacobr): should we impl?'); 107 throw const UnsupportedOperationException('TODO(jacobr): should we impl?');
108 } 108 }
109 109
110 void copyFrom(List<Object> src, int srcStart, int dstStart, int count) { 110 void copyFrom(List<Object> src, int srcStart, int dstStart, int count) {
111 throw 'Not impl yet. todo(jacobr)'; 111 throw 'Not impl yet. todo(jacobr)';
112 } 112 }
(...skipping 24 matching lines...) Expand all
137 } 137 }
138 138
139 void clear() { 139 void clear() {
140 // It is unclear if we want to keep non element nodes? 140 // It is unclear if we want to keep non element nodes?
141 _element.text = ''; 141 _element.text = '';
142 } 142 }
143 143
144 Element removeLast() { 144 Element removeLast() {
145 final last = this.last(); 145 final last = this.last();
146 if (last != null) { 146 if (last != null) {
147 _element._removeChild(last); 147 _element.$dom_removeChild(last);
148 } 148 }
149 return last; 149 return last;
150 } 150 }
151 151
152 Element last() { 152 Element last() {
153 return _element.lastElementChild; 153 return _element.$dom_lastElementChild;
154 } 154 }
155 } 155 }
156 156
157 // TODO(jacobr): this is an inefficient implementation but it is hard to see 157 // TODO(jacobr): this is an inefficient implementation but it is hard to see
158 // a better option given that we cannot quite force NodeList to be an 158 // a better option given that we cannot quite force NodeList to be an
159 // ElementList as there are valid cases where a NodeList JavaScript object 159 // ElementList as there are valid cases where a NodeList JavaScript object
160 // contains Node objects that are not Elements. 160 // contains Node objects that are not Elements.
161 class _FrozenElementList implements ElementList { 161 class _FrozenElementList implements ElementList {
162 final List<Node> _nodeList; 162 final List<Node> _nodeList;
163 163
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 new _ElementList(super.getRange(start, length)); 305 new _ElementList(super.getRange(start, length));
306 } 306 }
307 307
308 class ElementAttributeMap implements Map<String, String> { 308 class ElementAttributeMap implements Map<String, String> {
309 309
310 final _ElementImpl _element; 310 final _ElementImpl _element;
311 311
312 ElementAttributeMap._wrap(this._element); 312 ElementAttributeMap._wrap(this._element);
313 313
314 bool containsValue(String value) { 314 bool containsValue(String value) {
315 final attributes = _element._attributes; 315 final attributes = _element.$dom_attributes;
316 for (int i = 0, len = attributes.length; i < len; i++) { 316 for (int i = 0, len = attributes.length; i < len; i++) {
317 if(value == attributes[i].value) { 317 if(value == attributes[i].value) {
318 return true; 318 return true;
319 } 319 }
320 } 320 }
321 return false; 321 return false;
322 } 322 }
323 323
324 bool containsKey(String key) { 324 bool containsKey(String key) {
325 return _element._hasAttribute(key); 325 return _element.$dom_hasAttribute(key);
326 } 326 }
327 327
328 String operator [](String key) { 328 String operator [](String key) {
329 return _element._getAttribute(key); 329 return _element.$dom_getAttribute(key);
330 } 330 }
331 331
332 void operator []=(String key, String value) { 332 void operator []=(String key, String value) {
333 _element._setAttribute(key, value); 333 _element.$dom_setAttribute(key, value);
334 } 334 }
335 335
336 String putIfAbsent(String key, String ifAbsent()) { 336 String putIfAbsent(String key, String ifAbsent()) {
337 if (!containsKey(key)) { 337 if (!containsKey(key)) {
338 this[key] = ifAbsent(); 338 this[key] = ifAbsent();
339 } 339 }
340 } 340 }
341 341
342 String remove(String key) { 342 String remove(String key) {
343 _element._removeAttribute(key); 343 _element.$dom_removeAttribute(key);
344 } 344 }
345 345
346 void clear() { 346 void clear() {
347 final attributes = _element._attributes; 347 final attributes = _element.$dom_attributes;
348 for (int i = attributes.length - 1; i >= 0; i--) { 348 for (int i = attributes.length - 1; i >= 0; i--) {
349 remove(attributes[i].name); 349 remove(attributes[i].name);
350 } 350 }
351 } 351 }
352 352
353 void forEach(void f(String key, String value)) { 353 void forEach(void f(String key, String value)) {
354 final attributes = _element._attributes; 354 final attributes = _element.$dom_attributes;
355 for (int i = 0, len = attributes.length; i < len; i++) { 355 for (int i = 0, len = attributes.length; i < len; i++) {
356 final item = attributes[i]; 356 final item = attributes[i];
357 f(item.name, item.value); 357 f(item.name, item.value);
358 } 358 }
359 } 359 }
360 360
361 Collection<String> getKeys() { 361 Collection<String> getKeys() {
362 // TODO(jacobr): generate a lazy collection instead. 362 // TODO(jacobr): generate a lazy collection instead.
363 final attributes = _element._attributes; 363 final attributes = _element.$dom_attributes;
364 final keys = new List<String>(attributes.length); 364 final keys = new List<String>(attributes.length);
365 for (int i = 0, len = attributes.length; i < len; i++) { 365 for (int i = 0, len = attributes.length; i < len; i++) {
366 keys[i] = attributes[i].name; 366 keys[i] = attributes[i].name;
367 } 367 }
368 return keys; 368 return keys;
369 } 369 }
370 370
371 Collection<String> getValues() { 371 Collection<String> getValues() {
372 // TODO(jacobr): generate a lazy collection instead. 372 // TODO(jacobr): generate a lazy collection instead.
373 final attributes = _element._attributes; 373 final attributes = _element.$dom_attributes;
374 final values = new List<String>(attributes.length); 374 final values = new List<String>(attributes.length);
375 for (int i = 0, len = attributes.length; i < len; i++) { 375 for (int i = 0, len = attributes.length; i < len; i++) {
376 values[i] = attributes[i].value; 376 values[i] = attributes[i].value;
377 } 377 }
378 return values; 378 return values;
379 } 379 }
380 380
381 /** 381 /**
382 * The number of {key, value} pairs in the map. 382 * The number of {key, value} pairs in the map.
383 */ 383 */
384 int get length() { 384 int get length() {
385 return _element._attributes.length; 385 return _element.$dom_attributes.length;
386 } 386 }
387 387
388 /** 388 /**
389 * Returns true if there is no {key, value} pair in the map. 389 * Returns true if there is no {key, value} pair in the map.
390 */ 390 */
391 bool isEmpty() { 391 bool isEmpty() {
392 return length == 0; 392 return length == 0;
393 } 393 }
394 } 394 }
395 395
(...skipping 26 matching lines...) Expand all
422 final ClientRect client; 422 final ClientRect client;
423 final ClientRect offset; 423 final ClientRect offset;
424 final ClientRect scroll; 424 final ClientRect scroll;
425 425
426 // TODO(jacobr): should we move these outside of ElementRect to avoid the 426 // TODO(jacobr): should we move these outside of ElementRect to avoid the
427 // overhead of computing them every time even though they are rarely used. 427 // overhead of computing them every time even though they are rarely used.
428 final _ClientRectImpl _boundingClientRect; 428 final _ClientRectImpl _boundingClientRect;
429 final _ClientRectListImpl _clientRects; 429 final _ClientRectListImpl _clientRects;
430 430
431 _ElementRectImpl(_ElementImpl element) : 431 _ElementRectImpl(_ElementImpl element) :
432 client = new _SimpleClientRect(element._clientLeft, 432 client = new _SimpleClientRect(element.$dom_clientLeft,
433 element._clientTop, 433 element.$dom_clientTop,
434 element._clientWidth, 434 element.$dom_clientWidth,
435 element._clientHeight), 435 element.$dom_clientHeight),
436 offset = new _SimpleClientRect(element._offsetLeft, 436 offset = new _SimpleClientRect(element.$dom_offsetLeft,
437 element._offsetTop, 437 element.$dom_offsetTop,
438 element._offsetWidth, 438 element.$dom_offsetWidth,
439 element._offsetHeight), 439 element.$dom_offsetHeight),
440 scroll = new _SimpleClientRect(element._scrollLeft, 440 scroll = new _SimpleClientRect(element.$dom_scrollLeft,
441 element._scrollTop, 441 element.$dom_scrollTop,
442 element._scrollWidth, 442 element.$dom_scrollWidth,
443 element._scrollHeight), 443 element.$dom_scrollHeight),
444 _boundingClientRect = element._getBoundingClientRect(), 444 _boundingClientRect = element.$dom_getBoundingClientRect(),
445 _clientRects = element._getClientRects(); 445 _clientRects = element.$dom_getClientRects();
446 446
447 _ClientRectImpl get bounding() => _boundingClientRect; 447 _ClientRectImpl get bounding() => _boundingClientRect;
448 448
449 // TODO(jacobr): cleanup. 449 // TODO(jacobr): cleanup.
450 List<ClientRect> get clientRects() { 450 List<ClientRect> get clientRects() {
451 final out = new List(_clientRects.length); 451 final out = new List(_clientRects.length);
452 for (num i = 0; i < _clientRects.length; i++) { 452 for (num i = 0; i < _clientRects.length; i++) {
453 out[i] = _clientRects.item(i); 453 out[i] = _clientRects.item(i);
454 } 454 }
455 return out; 455 return out;
(...skipping 28 matching lines...) Expand all
484 484
485 void set elements(Collection<Element> value) { 485 void set elements(Collection<Element> value) {
486 final elements = this.elements; 486 final elements = this.elements;
487 elements.clear(); 487 elements.clear();
488 elements.addAll(value); 488 elements.addAll(value);
489 } 489 }
490 490
491 ElementList get elements() => new _ChildrenElementList._wrap(this); 491 ElementList get elements() => new _ChildrenElementList._wrap(this);
492 492
493 ElementList queryAll(String selectors) => 493 ElementList queryAll(String selectors) =>
494 new _FrozenElementList._wrap(_querySelectorAll(selectors)); 494 new _FrozenElementList._wrap($dom_querySelectorAll(selectors));
495 495
496 Set<String> get classes() { 496 Set<String> get classes() {
497 if (_cssClassSet === null) { 497 if (_cssClassSet === null) {
498 _cssClassSet = new _CssClassSet(this); 498 _cssClassSet = new _CssClassSet(this);
499 } 499 }
500 return _cssClassSet; 500 return _cssClassSet;
501 } 501 }
502 502
503 void set classes(Collection<String> value) { 503 void set classes(Collection<String> value) {
504 _CssClassSet classSet = classes; 504 _CssClassSet classSet = classes;
(...skipping 22 matching lines...) Expand all
527 new Completer<ElementRect>()); 527 new Completer<ElementRect>());
528 } 528 }
529 529
530 Future<CSSStyleDeclaration> get computedStyle() { 530 Future<CSSStyleDeclaration> get computedStyle() {
531 // TODO(jacobr): last param should be null, see b/5045788 531 // TODO(jacobr): last param should be null, see b/5045788
532 return getComputedStyle(''); 532 return getComputedStyle('');
533 } 533 }
534 534
535 Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) { 535 Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) {
536 return _createMeasurementFuture( 536 return _createMeasurementFuture(
537 () => _window._getComputedStyle(this, pseudoElement), 537 () => _window.$dom_getComputedStyle(this, pseudoElement),
538 new Completer<CSSStyleDeclaration>()); 538 new Completer<CSSStyleDeclaration>());
539 } 539 }
540 $!MEMBERS 540 $!MEMBERS
541 } 541 }
542
543 final _START_TAG_REGEXP = const RegExp('<(\\w+)');
544 class _ElementFactoryProvider {
545 static final _CUSTOM_PARENT_TAG_MAP = const {
546 'body' : 'html',
547 'head' : 'html',
548 'caption' : 'table',
549 'td': 'tr',
550 'colgroup': 'table',
551 'col' : 'colgroup',
552 'tr' : 'tbody',
553 'tbody' : 'table',
554 'tfoot' : 'table',
555 'thead' : 'table',
556 'track' : 'audio',
557 };
558
559 /** @domName Document.createElement */
560 factory Element.html(String html) {
561 // TODO(jacobr): this method can be made more robust and performant.
562 // 1) Cache the dummy parent elements required to use innerHTML rather than
563 // creating them every call.
564 // 2) Verify that the html does not contain leading or trailing text nodes.
565 // 3) Verify that the html does not contain both <head> and <body> tags.
566 // 4) Detatch the created element from its dummy parent.
567 String parentTag = 'div';
568 String tag;
569 final match = _START_TAG_REGEXP.firstMatch(html);
570 if (match !== null) {
571 tag = match.group(1).toLowerCase();
572 if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) {
573 parentTag = _CUSTOM_PARENT_TAG_MAP[tag];
574 }
575 }
576 final _ElementImpl temp = new Element.tag(parentTag);
577 temp.innerHTML = html;
578
579 Element element;
580 if (temp.elements.length == 1) {
581 element = temp.elements.first;
582 } else if (parentTag == 'html' && temp.elements.length == 2) {
583 // Work around for edge case in WebKit and possibly other browsers where
584 // both body and head elements are created even though the inner html
585 // only contains a head or body element.
586 element = temp.elements[tag == 'head' ? 0 : 1];
587 } else {
588 throw new IllegalArgumentException('HTML had ${temp.elements.length} ' +
589 'top level elements but 1 expected');
590 }
591 element.remove();
592 return element;
593 }
594
595 /** @domName Document.createElement */
596 $if FROG
597 // Optimization to improve performance until the frog compiler inlines this
598 // method.
599 factory Element.tag(String tag) native "return document.createElement(tag)";
600 $else
601 factory Element.tag(String tag) => _document.$dom_createElement(tag);
602 $endif
603 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698