| Index: client/html/src/ElementWrappingImplementation.dart
|
| diff --git a/client/html/src/ElementWrappingImplementation.dart b/client/html/src/ElementWrappingImplementation.dart
|
| index 8f9abb72c0912f01c9f612180b4ec7d5751087e5..5220caaa8dc97e9e282ddfeb85c385bf3267c48e 100644
|
| --- a/client/html/src/ElementWrappingImplementation.dart
|
| +++ b/client/html/src/ElementWrappingImplementation.dart
|
| @@ -1,4 +1,4 @@
|
| -// 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.
|
|
|
| @@ -12,6 +12,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++) {
|
| @@ -61,6 +62,7 @@ class _ChildrenElementList implements ElementList {
|
| }
|
|
|
| void operator []=(int index, Element value) {
|
| + assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument));
|
| _element.replaceChild(LevelDom.unwrap(value), _childElements.item(index));
|
| }
|
|
|
| @@ -70,6 +72,7 @@ class _ChildrenElementList implements ElementList {
|
| }
|
|
|
| Element add(Element value) {
|
| + assert(!_inMeasurementFrame || (!_inDocument && !value._inDocument));
|
| _element.appendChild(LevelDom.unwrap(value));
|
| return value;
|
| }
|
| @@ -79,7 +82,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));
|
| }
|
| }
|
| @@ -114,11 +119,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));
|
| @@ -312,10 +319,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);
|
| @@ -434,48 +443,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;
|
| }
|
| @@ -559,6 +572,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()) {
|
| @@ -567,6 +581,7 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
|
| }
|
|
|
| void set elements(Collection<Element> value) {
|
| + assert(!_inMeasurementFrame || !_inDocument);
|
| final elements = this.elements;
|
| elements.clear();
|
| elements.addAll(value);
|
| @@ -592,6 +607,7 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
|
| }
|
|
|
| void set classes(Collection<String> value) {
|
| + assert(!_inMeasurementFrame || !_inDocument);
|
| _CssClassSet classSet = classes;
|
| classSet.clear();
|
| classSet.addAll(value);
|
| @@ -605,6 +621,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()) {
|
| @@ -614,11 +631,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;
|
|
|
| @@ -628,21 +651,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);
|
|
|
| @@ -656,25 +691,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();
|
| }
|
|
|
| @@ -683,18 +739,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);
|
| }
|
|
|
| @@ -739,24 +799,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() {
|
|
|