Index: client/html/release/htmlimpl.dart |
diff --git a/client/html/release/htmlimpl.dart b/client/html/release/htmlimpl.dart |
index 6a5f9f397c4dcb5467724b9cfa514c961d86e279..11bb5348f60129aff0395f99958502a5f0a30b1c 100644 |
--- a/client/html/release/htmlimpl.dart |
+++ b/client/html/release/htmlimpl.dart |
@@ -18601,7 +18601,7 @@ class CompositionEventWrappingImplementation extends UIEventWrappingImplementati |
String get data() => _ptr.data; |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -18708,7 +18708,6 @@ class _CssClassSet implements Set<String> { |
* className property of this element. |
*/ |
void _modify( f(Set<String> s)) { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_element)); |
Set<String> s = _read(); |
f(s); |
_write(s); |
@@ -18741,7 +18740,6 @@ class _CssClassSet implements Set<String> { |
* back to the element. |
*/ |
void _write(Set s) { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_element)); |
_element.className = _formatSet(s); |
} |
@@ -18753,7 +18751,7 @@ class _CssClassSet implements Set<String> { |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -18767,18 +18765,8 @@ class _CssClassSet implements Set<String> { |
class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implements CSSStyleDeclaration { |
static String _cachedBrowserPrefix; |
- /** |
- * The element this style declaration is associated with if any. This |
- * should only be set to a non-null value if modifying this object |
- * will change the associated element. Thus this should not be set for |
- * computed styles. |
- */ |
- final ElementWrappingImplementation _element; |
- |
- CSSStyleDeclarationWrappingImplementation._wrap(ptr) |
- : super._wrap(ptr), _element = null; |
- CSSStyleDeclarationWrappingImplementation._wrapWithElement( |
- ptr, this._element) : super._wrap(ptr); |
+ |
+ CSSStyleDeclarationWrappingImplementation._wrap(ptr) : super._wrap(ptr) {} |
factory CSSStyleDeclarationWrappingImplementation.css(String css) { |
var style = new Element.tag('div').style; |
@@ -18797,21 +18785,14 @@ class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implement |
} else { |
_cachedBrowserPrefix = '-webkit-'; |
} |
- // TODO(jacobr): support IE and Opera as well. |
+ // TODO(jacobr): support IE 9.0 and Opera as well. |
} |
return _cachedBrowserPrefix; |
} |
- String get cssText() => _ptr.cssText; |
- |
- bool get _inDocument() { |
- return _element !== null && _element._inDocument; |
- } |
+ String get cssText() { return _ptr.cssText; } |
- void set cssText(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.cssText = value; |
- } |
+ void set cssText(String value) { _ptr.cssText = value; } |
int get length() { return _ptr.length; } |
@@ -18842,15 +18823,16 @@ class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implement |
} |
String removeProperty(String propertyName) { |
- assert(!_inMeasurementFrame || !_inDocument); |
return _ptr.removeProperty(propertyName); |
} |
void setProperty(String propertyName, var value, [String priority = '']) { |
- assert(!_inMeasurementFrame || !_inDocument); |
_ptr.setProperty(propertyName, '$value', priority); |
} |
+ String get typeName() { return "CSSStyleDeclaration"; } |
+ |
+ |
/** Gets the value of "animation" */ |
String get animation() => |
getPropertyValue('${_browserPrefix}animation'); |
@@ -21770,7 +21752,7 @@ class DeviceOrientationEventWrappingImplementation extends EventWrappingImplemen |
num get gamma() => _ptr.gamma; |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -21904,6 +21886,11 @@ class EmptyStyleDeclaration extends CSSStyleDeclarationWrappingImplementation { |
} |
} |
+Future<CSSStyleDeclaration> _emptyStyleFuture() { |
+ return _createMeasurementFuture(() => new EmptyStyleDeclaration(), |
+ new Completer<CSSStyleDeclaration>()); |
+} |
+ |
class EmptyElementRect implements ElementRect { |
final ClientRect client = const SimpleClientRect(0, 0, 0, 0); |
final ClientRect offset = const SimpleClientRect(0, 0, 0, 0); |
@@ -22001,10 +21988,9 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation |
return _on; |
} |
- ElementRect get rect() { |
- // A document fragment can never be attached to a Document so it always |
- // safe to measure. |
- return const EmptyElementRect(); |
+ Future<ElementRect> get rect() { |
+ return _createMeasurementFuture(() => const EmptyElementRect(), |
+ new Completer<ElementRect>()); |
} |
Element query(String selectors) => |
@@ -22037,9 +22023,10 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation |
Set<String> get classes() => new Set<String>(); |
Map<String, String> get dataAttributes() => const {}; |
CSSStyleDeclaration get style() => new EmptyStyleDeclaration(); |
- CSSStyleDeclaration get computedStyle() => new EmptyStyleDeclaration(); |
- CSSStyleDeclaration getComputedStyle(String pseudoElement) => |
- new EmptyStyleDeclaration(); |
+ Future<CSSStyleDeclaration> get computedStyle() => |
+ _emptyStyleFuture(); |
+ Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) => |
+ _emptyStyleFuture(); |
bool matchesSelector([String selectors]) => false; |
// Imperative Element methods are made into no-ops, as they are on parentless |
@@ -22139,7 +22126,7 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation |
DocumentFragment clone(bool deep) => super.clone(deep); |
} |
-// Copyright (c) 2012 the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -22223,9 +22210,10 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple |
String get webkitVisibilityState() => _documentPtr.webkitVisibilityState; |
/** @domName caretRangeFromPoint */ |
- Range caretRangeFromPoint([int x = null, int y = null]) { |
- assert(_inMeasurementFrame); |
- return LevelDom.wrapRange(_documentPtr.caretRangeFromPoint(x, y)); |
+ Future<Range> caretRangeFromPoint([int x = null, int y = null]) { |
+ return _createMeasurementFuture( |
+ () => LevelDom.wrapRange(_documentPtr.caretRangeFromPoint(x, y)), |
+ new Completer<Range>()); |
} |
/** @domName createEvent */ |
@@ -22234,14 +22222,14 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple |
} |
/** @domName elementFromPoint */ |
- Element elementFromPoint([int x = null, int y = null]) { |
- assert(_inMeasurementFrame); |
- return LevelDom.wrapElement(_documentPtr.elementFromPoint(x, y)); |
+ Future<Element> elementFromPoint([int x = null, int y = null]) { |
+ return _createMeasurementFuture( |
+ () => LevelDom.wrapElement(_documentPtr.elementFromPoint(x, y)), |
+ new Completer<Element>()); |
} |
/** @domName execCommand */ |
bool execCommand([String command = null, bool userInterface = null, String value = null]) { |
- assert(!_inMeasurementFrame); |
return _documentPtr.execCommand(command, userInterface, value); |
} |
@@ -22280,10 +22268,7 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple |
String get manifest() => _ptr.manifest; |
/** @domName HTMLHtmlElement.manifest */ |
- void set manifest(String value) { |
- assert(!_inMeasurementFrame); |
- _ptr.manifest = value; |
- } |
+ void set manifest(String value) { _ptr.manifest = value; } |
DocumentEvents get on() { |
if (_on === null) { |
@@ -22347,7 +22332,7 @@ class DOMWrapperBase { |
/** This function is provided for unittest purposes only. */ |
unwrapDomObject(DOMWrapperBase wrapper) { |
return wrapper._ptr; |
-}// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+}// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -22361,7 +22346,6 @@ class _ChildrenElementList implements ElementList { |
: _childElements = element.children, |
_element = element; |
- bool get _inDocument() => _nodeInDocument(_element); |
List<Element> _toList() { |
final output = new List(_childElements.length); |
for (int i = 0, len = _childElements.length; i < len; i++) { |
@@ -22411,7 +22395,6 @@ class _ChildrenElementList implements ElementList { |
} |
void operator []=(int index, Element value) { |
- assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument)); |
_element.replaceChild(LevelDom.unwrap(value), _childElements.item(index)); |
} |
@@ -22421,7 +22404,6 @@ class _ChildrenElementList implements ElementList { |
} |
Element add(Element value) { |
- assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument)); |
_element.appendChild(LevelDom.unwrap(value)); |
return value; |
} |
@@ -22431,9 +22413,7 @@ class _ChildrenElementList implements ElementList { |
Iterator<Element> iterator() => _toList().iterator(); |
void addAll(Collection<Element> collection) { |
- assert(!_inMeasurementFrame || !_inDocument); |
for (Element element in collection) { |
- assert(!_inMeasurementFrame || !element._inDocument); |
_element.appendChild(LevelDom.unwrap(element)); |
} |
} |
@@ -22468,13 +22448,11 @@ class _ChildrenElementList implements ElementList { |
} |
void clear() { |
- assert(!_inMeasurementFrame || !_inDocument); |
// It is unclear if we want to keep non element nodes? |
_element.textContent = ''; |
} |
Element removeLast() { |
- assert(!_inMeasurementFrame || !_inDocument); |
final last = this.last(); |
if (last != null) { |
_element.removeChild(LevelDom.unwrap(last)); |
@@ -22668,12 +22646,10 @@ class ElementAttributeMap implements Map<String, String> { |
} |
String remove(String key) { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_element)); |
_element.removeAttribute(key); |
} |
void clear() { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_element)); |
final attributes = _element.attributes; |
for (int i = attributes.length - 1; i >= 0; i--) { |
_element.removeAttribute(attributes.item(i).name); |
@@ -22792,52 +22768,48 @@ class SimpleClientRect implements ClientRect { |
String toString() => "($left, $top, $width, $height)"; |
} |
+// TODO(jacobr): we cannot currently be lazy about calculating the client |
+// rects as we must perform all measurement queries at a safe point to avoid |
+// triggering unneeded layouts. |
/** |
- * All your element measurement needs in one place. |
- * All members of this class can only be cassed when inside a measurement |
- * frame or when the element is not attached to the DOM. |
+ * All your element measurement needs in one place |
* @domName none |
*/ |
class ElementRectWrappingImplementation implements ElementRect { |
- final dom.HTMLElement _element; |
- |
- ElementRectWrappingImplementation(this._element); |
- |
- ClientRect get client() { |
- assert(window.inMeasurementFrame || !_nodeInDocument(_element)); |
- return new SimpleClientRect(_element.clientLeft, |
- _element.clientTop, |
- _element.clientWidth, |
- _element.clientHeight); |
- } |
- |
- ClientRect get offset() { |
- assert(window.inMeasurementFrame || !_nodeInDocument(_element)); |
- return new SimpleClientRect(_element.offsetLeft, |
- _element.offsetTop, |
- _element.offsetWidth, |
- _element.offsetHeight); |
- } |
- |
- ClientRect get scroll() { |
- assert(window.inMeasurementFrame || !_nodeInDocument(_element)); |
- return new SimpleClientRect(_element.scrollLeft, |
- _element.scrollTop, |
- _element.scrollWidth, |
- _element.scrollHeight); |
- } |
- |
- ClientRect get bounding() { |
- assert(window.inMeasurementFrame || !_nodeInDocument(_element)); |
- return LevelDom.wrapClientRect(_element.getBoundingClientRect()); |
- } |
+ final ClientRect client; |
+ final ClientRect offset; |
+ final ClientRect scroll; |
+ |
+ // TODO(jacobr): should we move these outside of ElementRect to avoid the |
+ // overhead of computing them every time even though they are rarely used. |
+ // This should be type dom.ClientRect but that fails on dartium. b/5522629 |
+ final _boundingClientRect; |
+ // an exception due to a dartium bug. |
+ final _clientRects; // TODO(jacobr): should be dom.ClientRectList |
+ |
+ ElementRectWrappingImplementation(dom.HTMLElement element) : |
+ client = new SimpleClientRect(element.clientLeft, |
+ element.clientTop, |
+ element.clientWidth, |
+ element.clientHeight), |
+ offset = new SimpleClientRect(element.offsetLeft, |
+ element.offsetTop, |
+ element.offsetWidth, |
+ element.offsetHeight), |
+ scroll = new SimpleClientRect(element.scrollLeft, |
+ element.scrollTop, |
+ element.scrollWidth, |
+ element.scrollHeight), |
+ _boundingClientRect = element.getBoundingClientRect(), |
+ _clientRects = element.getClientRects(); |
+ |
+ ClientRect get bounding() => |
+ LevelDom.wrapClientRect(_boundingClientRect); |
List<ClientRect> get clientRects() { |
- assert(window.inMeasurementFrame || !_nodeInDocument(_element)); |
- final clientRects = _element.getClientRects(); |
- final out = new List(clientRects.length); |
- for (num i = 0, len = clientRects.length; i < len; i++) { |
- out[i] = LevelDom.wrapClientRect(clientRects.item(i)); |
+ final out = new List(_clientRects.length); |
+ for (num i = 0; i < _clientRects.length; i++) { |
+ out[i] = LevelDom.wrapClientRect(_clientRects.item(i)); |
} |
return out; |
} |
@@ -22921,7 +22893,6 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
} |
void set attributes(Map<String, String> value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
Map<String, String> attributes = this.attributes; |
attributes.clear(); |
for (String key in value.getKeys()) { |
@@ -22930,7 +22901,6 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
} |
void set elements(Collection<Element> value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
final elements = this.elements; |
elements.clear(); |
elements.addAll(value); |
@@ -22956,7 +22926,6 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
} |
void set classes(Collection<String> value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
_CssClassSet classSet = classes; |
classSet.clear(); |
classSet.addAll(value); |
@@ -22970,7 +22939,6 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
} |
void set dataAttributes(Map<String, String> value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
Map<String, String> dataAttributes = this.dataAttributes; |
dataAttributes.clear(); |
for (String key in value.getKeys()) { |
@@ -22980,17 +22948,11 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
String get contentEditable() => _ptr.contentEditable; |
- void set contentEditable(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.contentEditable = value; |
- } |
+ void set contentEditable(String value) { _ptr.contentEditable = value; } |
String get dir() => _ptr.dir; |
- void set dir(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.dir = value; |
- } |
+ void set dir(String value) { _ptr.dir = value; } |
bool get draggable() => _ptr.draggable; |
@@ -23000,33 +22962,21 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
bool get hidden() => _ptr.hidden; |
- void set hidden(bool value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.hidden = value; |
- } |
+ void set hidden(bool value) { _ptr.hidden = value; } |
String get id() => _ptr.id; |
- void set id(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.id = value; |
- } |
+ void set id(String value) { _ptr.id = value; } |
String get innerHTML() => _ptr.innerHTML; |
- void set innerHTML(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.innerHTML = value; |
- } |
+ void set innerHTML(String value) { _ptr.innerHTML = value; } |
bool get isContentEditable() => _ptr.isContentEditable; |
String get lang() => _ptr.lang; |
- void set lang(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.lang = value; |
- } |
+ void set lang(String value) { _ptr.lang = value; } |
Element get lastElementChild() => LevelDom.wrapElement(_ptr.lastElementChild); |
@@ -23040,46 +22990,25 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
bool get spellcheck() => _ptr.spellcheck; |
- void set spellcheck(bool value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.spellcheck = value; |
- } |
+ void set spellcheck(bool value) { _ptr.spellcheck = value; } |
- CSSStyleDeclaration get style() { |
- // Changes to this CSSStyleDeclaration dirty the layout so we must pass |
- // the associated Element to the CSSStyleDeclaration constructor so that |
- // we can compute whether the current element is attached to the document |
- // which is required to decide whether modification inside a measurement |
- // frame is allowed. |
- final raw = _ptr.style; |
- return raw.dartObjectLocalStorage !== null ? |
- raw.dartObjectLocalStorage : |
- new CSSStyleDeclarationWrappingImplementation._wrapWithElement( |
- raw, this); |
- } |
+ CSSStyleDeclaration get style() => LevelDom.wrapCSSStyleDeclaration(_ptr.style); |
int get tabIndex() => _ptr.tabIndex; |
- void set tabIndex(int value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.tabIndex = value; |
- } |
+ void set tabIndex(int value) { _ptr.tabIndex = value; } |
String get tagName() => _ptr.tagName; |
String get title() => _ptr.title; |
- void set title(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.title = value; |
- } |
+ void set title(String value) { _ptr.title = value; } |
String get webkitdropzone() => _ptr.webkitdropzone; |
void set webkitdropzone(String value) { _ptr.webkitdropzone = value; } |
void blur() { |
- assert(!_inMeasurementFrame || !_inDocument); |
_ptr.blur(); |
} |
@@ -23088,22 +23017,18 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
} |
void focus() { |
- assert(!_inMeasurementFrame || !_inDocument); |
_ptr.focus(); |
} |
Element insertAdjacentElement([String where = null, Element element = null]) { |
- assert(!_inMeasurementFrame || !_inDocument); |
return LevelDom.wrapElement(_ptr.insertAdjacentElement(where, LevelDom.unwrap(element))); |
} |
void insertAdjacentHTML([String position_OR_where = null, String text = null]) { |
- assert(!_inMeasurementFrame || !_inDocument); |
_ptr.insertAdjacentHTML(position_OR_where, text); |
} |
void insertAdjacentText([String where = null, String text = null]) { |
- assert(!_inMeasurementFrame || !_inDocument); |
_ptr.insertAdjacentText(where, text); |
} |
@@ -23148,21 +23073,24 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement |
* clientTop, clientLeft, offsetHeight, offsetWidth, offsetTop, offsetLeft, |
* scrollHeight, scrollWidth, scrollTop, scrollLeft |
*/ |
- ElementRect get rect() { |
- return new ElementRectWrappingImplementation(_ptr); |
+ Future<ElementRect> get rect() { |
+ return _createMeasurementFuture( |
+ () => new ElementRectWrappingImplementation(_ptr), |
+ new Completer<ElementRect>()); |
} |
/** @domName Window.getComputedStyle */ |
- CSSStyleDeclaration get computedStyle() { |
+ Future<CSSStyleDeclaration> get computedStyle() { |
// TODO(jacobr): last param should be null, see b/5045788 |
- return getComputedStyle(''); |
+ return getComputedStyle(''); |
} |
/** @domName Window.getComputedStyle */ |
- CSSStyleDeclaration getComputedStyle(String pseudoElement) { |
- assert(window.inMeasurementFrame || !_inDocument); |
- return LevelDom.wrapCSSStyleDeclaration( |
- dom.window.getComputedStyle(_ptr, pseudoElement)); |
+ Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) { |
+ return _createMeasurementFuture(() => |
+ LevelDom.wrapCSSStyleDeclaration( |
+ dom.window.getComputedStyle(_ptr, pseudoElement)), |
+ new Completer<CSSStyleDeclaration>()); |
} |
ElementEvents get on() { |
@@ -23225,7 +23153,7 @@ class EventSourceWrappingImplementation extends EventTargetWrappingImplementatio |
return _on; |
} |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -23238,7 +23166,7 @@ class EventsImplementation implements Events { |
EventsImplementation._wrap(this._ptr) { |
// TODO(sigmund): the key type (String) yields a warning in frog and the vm, |
// but it is currently necessary to compile with dartc. |
- _listenerMap = new Map<String, EventListenerList>(); |
+ _listenerMap = <String, EventListenerList>{}; |
} |
EventListenerList operator [](String type) { |
@@ -23472,15 +23400,23 @@ class LoseContextWrappingImplementation extends DOMWrapperBase implements LoseCo |
return; |
} |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
-bool _inMeasurementFrame = false; |
+typedef Object ComputeValue(); |
-final _MEASUREMENT_MESSAGE = "DART-MEASURE"; |
+class _MeasurementRequest<T> { |
+ final ComputeValue computeValue; |
+ final Completer<T> completer; |
+ Object value; |
+ bool exception = false; |
+ _MeasurementRequest(this.computeValue, this.completer); |
+} |
-Queue<MeasurementCallback> _pendingMeasurementFrameCallbacks; |
+final _MEASUREMENT_MESSAGE = "DART-MEASURE"; |
+List<_MeasurementRequest> _pendingRequests; |
+List<TimeoutHandler> _pendingMeasurementFrameCallbacks; |
bool _nextMeasurementFrameScheduled = false; |
bool _firstMeasurementRequest = true; |
@@ -23493,9 +23429,9 @@ void _maybeScheduleMeasurementFrame() { |
if (_firstMeasurementRequest) { |
// Messages from other windows do not cause a security risk as |
// all we care about is that _onCompleteMeasurementRequests is called |
- // after the current event loop is unwound and calling |
- // _runMeasurementFrames is a noop when zero requests are pending. |
- window.on.message.add((e) => _runMeasurementFrames()); |
+ // after the current event loop is unwound and calling the function is |
+ // a noop when zero requests are pending. |
+ window.on.message.add((e) => _completeMeasurementFutures()); |
_firstMeasurementRequest = false; |
} |
@@ -23512,52 +23448,75 @@ void _maybeScheduleMeasurementFrame() { |
* when they would have completed to avoid confusing bugs if it happened that |
* no measurements were actually requested. |
*/ |
-void _addMeasurementFrameCallback(MeasurementCallback callback) { |
- assert(callback != null); |
+void _addMeasurementFrameCallback(TimeoutHandler callback) { |
if (_pendingMeasurementFrameCallbacks === null) { |
- _pendingMeasurementFrameCallbacks = new Queue<MeasurementCallback>(); |
+ _pendingMeasurementFrameCallbacks = <TimeoutHandler>[]; |
+ _maybeScheduleMeasurementFrame(); |
} |
- _maybeScheduleMeasurementFrame(); |
_pendingMeasurementFrameCallbacks.add(callback); |
} |
/** |
- * Run all pending measurement frames evaluating them in a single batch |
+ * Returns a [Future] whose value will be the result of evaluating |
+ * [computeValue] during the next safe measurement interval. |
+ * The next safe measurement interval is after the current event loop has |
+ * unwound but before the browser has rendered the page. |
+ * It is important that the [computeValue] function only queries the html |
+ * layout and html in any way. |
+ */ |
+Future _createMeasurementFuture(ComputeValue computeValue, |
+ Completer completer) { |
+ if (_pendingRequests === null) { |
+ _pendingRequests = <_MeasurementRequest>[]; |
+ _maybeScheduleMeasurementFrame(); |
+ } |
+ _pendingRequests.add(new _MeasurementRequest(computeValue, completer)); |
+ return completer.future; |
+} |
+ |
+/** |
+ * Complete all pending measurement futures evaluating them in a single batch |
* so that the the browser is guaranteed to avoid multiple layouts. |
*/ |
-void _runMeasurementFrames() { |
- if (_nextMeasurementFrameScheduled == false || _inMeasurementFrame) { |
+void _completeMeasurementFutures() { |
+ if (_nextMeasurementFrameScheduled == false) { |
// Ignore spurious call to this function. |
return; |
} |
- _inMeasurementFrame = true; |
- |
- final layoutCallbacks = <LayoutCallback>[]; |
- while (!_pendingMeasurementFrameCallbacks.isEmpty()) { |
- MeasurementCallback measurementCallback = |
- _pendingMeasurementFrameCallbacks.removeFirst(); |
- try { |
- final layoutCallback = measurementCallback(); |
- if (layoutCallback != null) { |
- layoutCallbacks.add(layoutCallback); |
+ _nextMeasurementFrameScheduled = false; |
+ // We must compute all new values before fulfilling the futures as |
+ // the onComplete callbacks for the futures could modify the DOM making |
+ // subsequent measurement calculations expensive to compute. |
+ if (_pendingRequests !== null) { |
+ for (_MeasurementRequest request in _pendingRequests) { |
+ try { |
+ request.value = request.computeValue(); |
+ } catch(var e) { |
+ request.value = e; |
+ request.exception = true; |
} |
- } catch (Object e) { |
- window.console.error( |
- 'Caught exception in measurement frame callback: ${e}'); |
- // TODO(jacobr): throw this exception again in the correct way. |
} |
} |
- _inMeasurementFrame = false; |
- _nextMeasurementFrameScheduled = false; |
+ final completedRequests = _pendingRequests; |
+ final readyMeasurementFrameCallbacks = _pendingMeasurementFrameCallbacks; |
+ _pendingRequests = null; |
+ _pendingMeasurementFrameCallbacks = null; |
+ if (completedRequests !== null) { |
+ for (_MeasurementRequest request in completedRequests) { |
+ if (request.exception) { |
+ request.completer.completeException(request.value); |
+ } else { |
+ request.completer.complete(request.value); |
+ } |
+ } |
+ } |
- for (LayoutCallback layoutCallback in layoutCallbacks) { |
- try { |
- layoutCallback(); |
- } catch (Object e) { |
- window.console.error('Caught exception in layout callback: ${e}'); |
- // TODO(jacobr): throw this exception again in the correct way. |
+ if (readyMeasurementFrameCallbacks !== null) { |
+ for (TimeoutHandler handler in readyMeasurementFrameCallbacks) { |
+ // TODO(jacobr): wrap each call to a handler in a try-catch block. |
+ handler(); |
} |
} |
} |
@@ -23672,19 +23631,10 @@ class MutationEventWrappingImplementation extends EventWrappingImplementation im |
Node get relatedNode() => LevelDom.wrapNode(_ptr.relatedNode); |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
-// TODO(jacobr): we could write this method more efficiently if we wanted to |
-// however performance isn't crucial as it is only called when a method is |
-// called from an atypical context (e.g. measurement method called outside of |
-// requestMeasurementFrame or dom manipulation called within |
-// requestMeasurementFrame). |
-bool _nodeInDocument(dom.Node node) { |
- return LevelDom.wrapNode(node)._inDocument; |
-} |
- |
class _ChildrenNodeList implements NodeList { |
// Raw node. |
final _node; |
@@ -23753,16 +23703,12 @@ class _ChildrenNodeList implements NodeList { |
/** @domName Node.appendChild */ |
Node add(Node value) { |
- assert(!_inMeasurementFrame |
- || (!_nodeInDocument(_node) && !value._inDocument)); |
_node.appendChild(LevelDom.unwrap(value)); |
return value; |
} |
Node addLast(Node value) { |
- assert(!_inMeasurementFrame |
- || (!_nodeInDocument(_node) && !value._inDocument)); |
- _node.appendChild(LevelDom.unwrap(value)); |
+ _node.appendChild(LevelDom.unwrap(value)); |
return value; |
} |
@@ -23771,9 +23717,7 @@ class _ChildrenNodeList implements NodeList { |
} |
void addAll(Collection<Node> collection) { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_node)); |
for (Node node in collection) { |
- assert(!_inMeasurementFrame || !node._inDocument); |
_node.appendChild(LevelDom.unwrap(node)); |
} |
} |
@@ -23808,12 +23752,10 @@ class _ChildrenNodeList implements NodeList { |
} |
void clear() { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_node)); |
_node.textContent = ''; |
} |
Node removeLast() { |
- assert(!_inMeasurementFrame || !_nodeInDocument(_node)); |
final last = this.last(); |
if (last != null) { |
_node.removeChild(LevelDom.unwrap(last)); |
@@ -23832,7 +23774,6 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple |
NodeWrappingImplementation._wrap(ptr) : super._wrap(ptr); |
void set nodes(Collection<Node> value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
// Copy list first since we don't want liveness during iteration. |
List copy = new List.from(value); |
nodes.clear(); |
@@ -23856,14 +23797,10 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple |
String get text() => _ptr.textContent; |
- void set text(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.textContent = value; |
- } |
+ void set text(String value) { _ptr.textContent = value; } |
// New methods implemented. |
Node replaceWith(Node otherNode) { |
- assert(!_inMeasurementFrame || !_inDocument); |
try { |
_ptr.parentNode.replaceChild(LevelDom.unwrap(otherNode), _ptr); |
} catch(var e) { |
@@ -23873,7 +23810,6 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple |
} |
Node remove() { |
- assert(!_inMeasurementFrame || !_inDocument); |
// TODO(jacobr): should we throw an exception if parent is already null? |
if (_ptr.parentNode !== null) { |
_ptr.parentNode.removeChild(_ptr); |
@@ -23894,7 +23830,6 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple |
// insertBefore or we switch NodeList to implement LinkedList rather than |
// array. |
Node insertBefore(Node newChild, Node refChild) { |
- assert(!_inMeasurementFrame || !_inDocument); |
return LevelDom.wrapNode(_ptr.insertBefore( |
LevelDom.unwrap(newChild), LevelDom.unwrap(refChild))); |
} |
@@ -23902,8 +23837,6 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple |
Node clone(bool deep) { |
return LevelDom.wrapNode(_ptr.cloneNode(deep)); |
} |
- |
- bool get _inDocument() => document.contains(this); |
} |
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
@@ -24160,7 +24093,7 @@ class StorageEventWrappingImplementation extends EventWrappingImplementation imp |
class SVGDocumentWrappingImplementation extends DocumentWrappingImplementation implements SVGDocument { |
SVGDocumentWrappingImplementation._wrap(dom.SVGDocument ptr) : super._wrap(ptr, ptr.rootElement); |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -24206,10 +24139,7 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp |
String get id() { return _ptr.id; } |
- void set id(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.id = value; |
- } |
+ void set id(String value) { _ptr.id = value; } |
SVGSVGElement get ownerSVGElement() { return LevelDom.wrapSVGSVGElement(_ptr.ownerSVGElement); } |
@@ -24217,10 +24147,7 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp |
String get xmlbase() { return _ptr.xmlbase; } |
- void set xmlbase(String value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
- _ptr.xmlbase = value; |
- } |
+ void set xmlbase(String value) { _ptr.xmlbase = value; } |
ElementList get elements() { |
if (_elements == null) { |
@@ -24231,7 +24158,6 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp |
// TODO: The type of value should be Collection<Element>. See http://b/5392897 |
void set elements(value) { |
- assert(!_inMeasurementFrame || !_inDocument); |
final elements = this.elements; |
elements.clear(); |
elements.addAll(value); |
@@ -24250,7 +24176,6 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp |
} |
void set innerHTML(String svg) { |
- assert(!_inMeasurementFrame || !_inDocument); |
var container = new Element.tag("div"); |
// Wrap the SVG string in <svg> so that SVGElements are created, rather than |
// HTMLElements. |
@@ -24521,7 +24446,7 @@ class TextEventWrappingImplementation extends UIEventWrappingImplementation impl |
String get data() => _ptr.data; |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -24537,7 +24462,6 @@ class TextWrappingImplementation extends CharacterDataWrappingImplementation imp |
String get wholeText() => _ptr.wholeText; |
Text replaceWholeText([String content = null]) { |
- assert(!_inMeasurementFrame || !_inDocument); |
if (content === null) { |
return LevelDom.wrapText(_ptr.replaceWholeText()); |
} else { |
@@ -24546,7 +24470,6 @@ class TextWrappingImplementation extends CharacterDataWrappingImplementation imp |
} |
Text splitText([int offset = null]) { |
- assert(!_inMeasurementFrame || !_inDocument); |
if (offset === null) { |
return LevelDom.wrapText(_ptr.splitText()); |
} else { |
@@ -24745,7 +24668,7 @@ class WheelEventWrappingImplementation extends UIEventWrappingImplementation imp |
int get y() => _ptr.y; |
} |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -25550,7 +25473,6 @@ class WindowWrappingImplementation extends EventTargetWrappingImplementation imp |
} |
Point webkitConvertPointFromNodeToPage([Node node = null, Point p = null]) { |
- assert(_inMeasurementFrame); |
if (node === null) { |
if (p === null) { |
return LevelDom.wrapPoint(_ptr.webkitConvertPointFromNodeToPage()); |
@@ -25566,7 +25488,6 @@ class WindowWrappingImplementation extends EventTargetWrappingImplementation imp |
} |
Point webkitConvertPointFromPageToNode([Node node = null, Point p = null]) { |
- assert(_inMeasurementFrame); |
if (node === null) { |
if (p === null) { |
return LevelDom.wrapPoint(_ptr.webkitConvertPointFromPageToNode()); |
@@ -25585,12 +25506,10 @@ class WindowWrappingImplementation extends EventTargetWrappingImplementation imp |
return _ptr.webkitRequestAnimationFrame(callback, LevelDom.unwrap(element)); |
} |
- void requestMeasurementFrame(MeasurementCallback callback) { |
+ void requestLayoutFrame(TimeoutHandler callback) { |
_addMeasurementFrameCallback(callback); |
} |
- bool get inMeasurementFrame() => _inMeasurementFrame; |
- |
WindowEvents get on() { |
if (_on === null) { |
_on = new WindowEventsImplementation._wrap(_ptr); |