| 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);
|
|
|