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

Unified Diff: client/html/release/htmlimpl.dart

Side-by-side diff isn't available for this file because of its large size.
Issue 9148015: Example showing alternate async measurement solution (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Final version Created 8 years, 11 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:
Download patch
Index: client/html/release/htmlimpl.dart
diff --git a/client/html/release/htmlimpl.dart b/client/html/release/htmlimpl.dart
index 11bb5348f60129aff0395f99958502a5f0a30b1c..6a5f9f397c4dcb5467724b9cfa514c961d86e279 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) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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,6 +18708,7 @@ 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);
@@ -18740,6 +18741,7 @@ class _CssClassSet implements Set<String> {
* back to the element.
*/
void _write(Set s) {
+ assert(!_inMeasurementFrame || !_nodeInDocument(_element));
_element.className = _formatSet(s);
}
@@ -18751,7 +18753,7 @@ class _CssClassSet implements Set<String> {
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -18765,8 +18767,18 @@ class _CssClassSet implements Set<String> {
class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implements CSSStyleDeclaration {
static String _cachedBrowserPrefix;
-
- CSSStyleDeclarationWrappingImplementation._wrap(ptr) : super._wrap(ptr) {}
+ /**
+ * 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);
factory CSSStyleDeclarationWrappingImplementation.css(String css) {
var style = new Element.tag('div').style;
@@ -18785,14 +18797,21 @@ class CSSStyleDeclarationWrappingImplementation extends DOMWrapperBase implement
} else {
_cachedBrowserPrefix = '-webkit-';
}
- // TODO(jacobr): support IE 9.0 and Opera as well.
+ // TODO(jacobr): support IE and Opera as well.
}
return _cachedBrowserPrefix;
}
- String get cssText() { return _ptr.cssText; }
+ String get cssText() => _ptr.cssText;
- void set cssText(String value) { _ptr.cssText = value; }
+ bool get _inDocument() {
+ return _element !== null && _element._inDocument;
+ }
+
+ void set cssText(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.cssText = value;
+ }
int get length() { return _ptr.length; }
@@ -18823,16 +18842,15 @@ 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');
@@ -21752,7 +21770,7 @@ class DeviceOrientationEventWrappingImplementation extends EventWrappingImplemen
num get gamma() => _ptr.gamma;
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -21886,11 +21904,6 @@ 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);
@@ -21988,9 +22001,10 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation
return _on;
}
- Future<ElementRect> get rect() {
- return _createMeasurementFuture(() => const EmptyElementRect(),
- new Completer<ElementRect>());
+ ElementRect get rect() {
+ // A document fragment can never be attached to a Document so it always
+ // safe to measure.
+ return const EmptyElementRect();
}
Element query(String selectors) =>
@@ -22023,10 +22037,9 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation
Set<String> get classes() => new Set<String>();
Map<String, String> get dataAttributes() => const {};
CSSStyleDeclaration get style() => new EmptyStyleDeclaration();
- Future<CSSStyleDeclaration> get computedStyle() =>
- _emptyStyleFuture();
- Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) =>
- _emptyStyleFuture();
+ CSSStyleDeclaration get computedStyle() => new EmptyStyleDeclaration();
+ CSSStyleDeclaration getComputedStyle(String pseudoElement) =>
+ new EmptyStyleDeclaration();
bool matchesSelector([String selectors]) => false;
// Imperative Element methods are made into no-ops, as they are on parentless
@@ -22126,7 +22139,7 @@ class DocumentFragmentWrappingImplementation extends NodeWrappingImplementation
DocumentFragment clone(bool deep) => super.clone(deep);
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012 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.
@@ -22210,10 +22223,9 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple
String get webkitVisibilityState() => _documentPtr.webkitVisibilityState;
/** @domName caretRangeFromPoint */
- Future<Range> caretRangeFromPoint([int x = null, int y = null]) {
- return _createMeasurementFuture(
- () => LevelDom.wrapRange(_documentPtr.caretRangeFromPoint(x, y)),
- new Completer<Range>());
+ Range caretRangeFromPoint([int x = null, int y = null]) {
+ assert(_inMeasurementFrame);
+ return LevelDom.wrapRange(_documentPtr.caretRangeFromPoint(x, y));
}
/** @domName createEvent */
@@ -22222,14 +22234,14 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple
}
/** @domName elementFromPoint */
- Future<Element> elementFromPoint([int x = null, int y = null]) {
- return _createMeasurementFuture(
- () => LevelDom.wrapElement(_documentPtr.elementFromPoint(x, y)),
- new Completer<Element>());
+ Element elementFromPoint([int x = null, int y = null]) {
+ assert(_inMeasurementFrame);
+ return LevelDom.wrapElement(_documentPtr.elementFromPoint(x, y));
}
/** @domName execCommand */
bool execCommand([String command = null, bool userInterface = null, String value = null]) {
+ assert(!_inMeasurementFrame);
return _documentPtr.execCommand(command, userInterface, value);
}
@@ -22268,7 +22280,10 @@ class DocumentWrappingImplementation extends ElementWrappingImplementation imple
String get manifest() => _ptr.manifest;
/** @domName HTMLHtmlElement.manifest */
- void set manifest(String value) { _ptr.manifest = value; }
+ void set manifest(String value) {
+ assert(!_inMeasurementFrame);
+ _ptr.manifest = value;
+ }
DocumentEvents get on() {
if (_on === null) {
@@ -22332,7 +22347,7 @@ class DOMWrapperBase {
/** This function is provided for unittest purposes only. */
unwrapDomObject(DOMWrapperBase wrapper) {
return wrapper._ptr;
-}// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+}// Copyright (c) 2012, 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.
@@ -22346,6 +22361,7 @@ 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++) {
@@ -22395,6 +22411,7 @@ class _ChildrenElementList implements ElementList {
}
void operator []=(int index, Element value) {
+ assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument));
_element.replaceChild(LevelDom.unwrap(value), _childElements.item(index));
}
@@ -22404,6 +22421,7 @@ class _ChildrenElementList implements ElementList {
}
Element add(Element value) {
+ assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument));
_element.appendChild(LevelDom.unwrap(value));
return value;
}
@@ -22413,7 +22431,9 @@ 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));
}
}
@@ -22448,11 +22468,13 @@ 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));
@@ -22646,10 +22668,12 @@ 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);
@@ -22768,48 +22792,52 @@ 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 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.
* @domName none
*/
class ElementRectWrappingImplementation implements ElementRect {
- 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);
+ 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());
+ }
List<ClientRect> get clientRects() {
- final out = new List(_clientRects.length);
- for (num i = 0; i < _clientRects.length; i++) {
- out[i] = LevelDom.wrapClientRect(_clientRects.item(i));
+ 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));
}
return out;
}
@@ -22893,6 +22921,7 @@ 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()) {
@@ -22901,6 +22930,7 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
}
void set elements(Collection<Element> value) {
+ assert(!_inMeasurementFrame || !_inDocument);
final elements = this.elements;
elements.clear();
elements.addAll(value);
@@ -22926,6 +22956,7 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
}
void set classes(Collection<String> value) {
+ assert(!_inMeasurementFrame || !_inDocument);
_CssClassSet classSet = classes;
classSet.clear();
classSet.addAll(value);
@@ -22939,6 +22970,7 @@ 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()) {
@@ -22948,11 +22980,17 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
String get contentEditable() => _ptr.contentEditable;
- void set contentEditable(String value) { _ptr.contentEditable = value; }
+ void set contentEditable(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.contentEditable = value;
+ }
String get dir() => _ptr.dir;
- void set dir(String value) { _ptr.dir = value; }
+ void set dir(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.dir = value;
+ }
bool get draggable() => _ptr.draggable;
@@ -22962,21 +23000,33 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
bool get hidden() => _ptr.hidden;
- void set hidden(bool value) { _ptr.hidden = value; }
+ void set hidden(bool value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.hidden = value;
+ }
String get id() => _ptr.id;
- void set id(String value) { _ptr.id = value; }
+ void set id(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.id = value;
+ }
String get innerHTML() => _ptr.innerHTML;
- void set innerHTML(String value) { _ptr.innerHTML = value; }
+ void set innerHTML(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.innerHTML = value;
+ }
bool get isContentEditable() => _ptr.isContentEditable;
String get lang() => _ptr.lang;
- void set lang(String value) { _ptr.lang = value; }
+ void set lang(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.lang = value;
+ }
Element get lastElementChild() => LevelDom.wrapElement(_ptr.lastElementChild);
@@ -22990,25 +23040,46 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
bool get spellcheck() => _ptr.spellcheck;
- void set spellcheck(bool value) { _ptr.spellcheck = value; }
+ void set spellcheck(bool value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.spellcheck = value;
+ }
- CSSStyleDeclaration get style() => LevelDom.wrapCSSStyleDeclaration(_ptr.style);
+ 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);
+ }
int get tabIndex() => _ptr.tabIndex;
- void set tabIndex(int value) { _ptr.tabIndex = value; }
+ void set tabIndex(int value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.tabIndex = value;
+ }
String get tagName() => _ptr.tagName;
String get title() => _ptr.title;
- void set title(String value) { _ptr.title = value; }
+ void set title(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.title = value;
+ }
String get webkitdropzone() => _ptr.webkitdropzone;
void set webkitdropzone(String value) { _ptr.webkitdropzone = value; }
void blur() {
+ assert(!_inMeasurementFrame || !_inDocument);
_ptr.blur();
}
@@ -23017,18 +23088,22 @@ 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);
}
@@ -23073,24 +23148,21 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
* clientTop, clientLeft, offsetHeight, offsetWidth, offsetTop, offsetLeft,
* scrollHeight, scrollWidth, scrollTop, scrollLeft
*/
- Future<ElementRect> get rect() {
- return _createMeasurementFuture(
- () => new ElementRectWrappingImplementation(_ptr),
- new Completer<ElementRect>());
+ ElementRect get rect() {
+ return new ElementRectWrappingImplementation(_ptr);
}
/** @domName Window.getComputedStyle */
- Future<CSSStyleDeclaration> get computedStyle() {
+ CSSStyleDeclaration get computedStyle() {
// TODO(jacobr): last param should be null, see b/5045788
- return getComputedStyle('');
+ return getComputedStyle('');
}
/** @domName Window.getComputedStyle */
- Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) {
- return _createMeasurementFuture(() =>
- LevelDom.wrapCSSStyleDeclaration(
- dom.window.getComputedStyle(_ptr, pseudoElement)),
- new Completer<CSSStyleDeclaration>());
+ CSSStyleDeclaration getComputedStyle(String pseudoElement) {
+ assert(window.inMeasurementFrame || !_inDocument);
+ return LevelDom.wrapCSSStyleDeclaration(
+ dom.window.getComputedStyle(_ptr, pseudoElement));
}
ElementEvents get on() {
@@ -23153,7 +23225,7 @@ class EventSourceWrappingImplementation extends EventTargetWrappingImplementatio
return _on;
}
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -23166,7 +23238,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 = <String, EventListenerList>{};
+ _listenerMap = new Map<String, EventListenerList>();
}
EventListenerList operator [](String type) {
@@ -23400,23 +23472,15 @@ class LoseContextWrappingImplementation extends DOMWrapperBase implements LoseCo
return;
}
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
-typedef Object ComputeValue();
-
-class _MeasurementRequest<T> {
- final ComputeValue computeValue;
- final Completer<T> completer;
- Object value;
- bool exception = false;
- _MeasurementRequest(this.computeValue, this.completer);
-}
+bool _inMeasurementFrame = false;
final _MEASUREMENT_MESSAGE = "DART-MEASURE";
-List<_MeasurementRequest> _pendingRequests;
-List<TimeoutHandler> _pendingMeasurementFrameCallbacks;
+
+Queue<MeasurementCallback> _pendingMeasurementFrameCallbacks;
bool _nextMeasurementFrameScheduled = false;
bool _firstMeasurementRequest = true;
@@ -23429,9 +23493,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 the function is
- // a noop when zero requests are pending.
- window.on.message.add((e) => _completeMeasurementFutures());
+ // after the current event loop is unwound and calling
+ // _runMeasurementFrames is a noop when zero requests are pending.
+ window.on.message.add((e) => _runMeasurementFrames());
_firstMeasurementRequest = false;
}
@@ -23448,75 +23512,52 @@ void _maybeScheduleMeasurementFrame() {
* when they would have completed to avoid confusing bugs if it happened that
* no measurements were actually requested.
*/
-void _addMeasurementFrameCallback(TimeoutHandler callback) {
+void _addMeasurementFrameCallback(MeasurementCallback callback) {
+ assert(callback != null);
if (_pendingMeasurementFrameCallbacks === null) {
- _pendingMeasurementFrameCallbacks = <TimeoutHandler>[];
- _maybeScheduleMeasurementFrame();
+ _pendingMeasurementFrameCallbacks = new Queue<MeasurementCallback>();
}
+ _maybeScheduleMeasurementFrame();
_pendingMeasurementFrameCallbacks.add(callback);
}
/**
- * 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
+ * Run all pending measurement frames evaluating them in a single batch
* so that the the browser is guaranteed to avoid multiple layouts.
*/
-void _completeMeasurementFutures() {
- if (_nextMeasurementFrameScheduled == false) {
+void _runMeasurementFrames() {
+ if (_nextMeasurementFrameScheduled == false || _inMeasurementFrame) {
// Ignore spurious call to this function.
return;
}
- _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;
- }
- }
- }
+ _inMeasurementFrame = true;
- 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);
+ final layoutCallbacks = <LayoutCallback>[];
+ while (!_pendingMeasurementFrameCallbacks.isEmpty()) {
+ MeasurementCallback measurementCallback =
+ _pendingMeasurementFrameCallbacks.removeFirst();
+ try {
+ final layoutCallback = measurementCallback();
+ if (layoutCallback != null) {
+ layoutCallbacks.add(layoutCallback);
}
+ } catch (Object e) {
+ window.console.error(
+ 'Caught exception in measurement frame 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();
+ _inMeasurementFrame = false;
+ _nextMeasurementFrameScheduled = false;
+
+ 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.
}
}
}
@@ -23631,10 +23672,19 @@ class MutationEventWrappingImplementation extends EventWrappingImplementation im
Node get relatedNode() => LevelDom.wrapNode(_ptr.relatedNode);
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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;
@@ -23703,12 +23753,16 @@ 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) {
- _node.appendChild(LevelDom.unwrap(value));
+ assert(!_inMeasurementFrame
+ || (!_nodeInDocument(_node) && !value._inDocument));
+ _node.appendChild(LevelDom.unwrap(value));
return value;
}
@@ -23717,7 +23771,9 @@ 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));
}
}
@@ -23752,10 +23808,12 @@ 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));
@@ -23774,6 +23832,7 @@ 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();
@@ -23797,10 +23856,14 @@ class NodeWrappingImplementation extends EventTargetWrappingImplementation imple
String get text() => _ptr.textContent;
- void set text(String value) { _ptr.textContent = value; }
+ void set text(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.textContent = value;
+ }
// New methods implemented.
Node replaceWith(Node otherNode) {
+ assert(!_inMeasurementFrame || !_inDocument);
try {
_ptr.parentNode.replaceChild(LevelDom.unwrap(otherNode), _ptr);
} catch(var e) {
@@ -23810,6 +23873,7 @@ 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);
@@ -23830,6 +23894,7 @@ 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)));
}
@@ -23837,6 +23902,8 @@ 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
@@ -24093,7 +24160,7 @@ class StorageEventWrappingImplementation extends EventWrappingImplementation imp
class SVGDocumentWrappingImplementation extends DocumentWrappingImplementation implements SVGDocument {
SVGDocumentWrappingImplementation._wrap(dom.SVGDocument ptr) : super._wrap(ptr, ptr.rootElement);
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -24139,7 +24206,10 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp
String get id() { return _ptr.id; }
- void set id(String value) { _ptr.id = value; }
+ void set id(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.id = value;
+ }
SVGSVGElement get ownerSVGElement() { return LevelDom.wrapSVGSVGElement(_ptr.ownerSVGElement); }
@@ -24147,7 +24217,10 @@ class SVGElementWrappingImplementation extends ElementWrappingImplementation imp
String get xmlbase() { return _ptr.xmlbase; }
- void set xmlbase(String value) { _ptr.xmlbase = value; }
+ void set xmlbase(String value) {
+ assert(!_inMeasurementFrame || !_inDocument);
+ _ptr.xmlbase = value;
+ }
ElementList get elements() {
if (_elements == null) {
@@ -24158,6 +24231,7 @@ 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);
@@ -24176,6 +24250,7 @@ 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.
@@ -24446,7 +24521,7 @@ class TextEventWrappingImplementation extends UIEventWrappingImplementation impl
String get data() => _ptr.data;
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -24462,6 +24537,7 @@ 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 {
@@ -24470,6 +24546,7 @@ class TextWrappingImplementation extends CharacterDataWrappingImplementation imp
}
Text splitText([int offset = null]) {
+ assert(!_inMeasurementFrame || !_inDocument);
if (offset === null) {
return LevelDom.wrapText(_ptr.splitText());
} else {
@@ -24668,7 +24745,7 @@ class WheelEventWrappingImplementation extends UIEventWrappingImplementation imp
int get y() => _ptr.y;
}
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2012, 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.
@@ -25473,6 +25550,7 @@ 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());
@@ -25488,6 +25566,7 @@ 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());
@@ -25506,10 +25585,12 @@ class WindowWrappingImplementation extends EventTargetWrappingImplementation imp
return _ptr.webkitRequestAnimationFrame(callback, LevelDom.unwrap(element));
}
- void requestLayoutFrame(TimeoutHandler callback) {
+ void requestMeasurementFrame(MeasurementCallback callback) {
_addMeasurementFrameCallback(callback);
}
+ bool get inMeasurementFrame() => _inMeasurementFrame;
+
WindowEvents get on() {
if (_on === null) {
_on = new WindowEventsImplementation._wrap(_ptr);

Powered by Google App Engine
This is Rietveld 408576698