Version 0.3.7.1
svn merge -r 18570:18571 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@18593 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/compiler/implementation/lib/web.dart b/lib/compiler/implementation/lib/web.dart
new file mode 100644
index 0000000..a75db7b
--- /dev/null
+++ b/lib/compiler/implementation/lib/web.dart
@@ -0,0 +1,9 @@
+// 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.
+
+#library("web");
+
+String htmlEscape(String text) {
+ throw "Unimplemented: web::htmlEscape(String).";
+}
diff --git a/lib/compiler/implementation/lib/web.dartp b/lib/compiler/implementation/lib/web.dartp
new file mode 100644
index 0000000..c3ba2ad
--- /dev/null
+++ b/lib/compiler/implementation/lib/web.dartp
@@ -0,0 +1,13 @@
+// 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.
+
+// Patch file for dart:web
+
+/*patch*/ String htmlEscape(String text) {
+ return text.replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'"); // Different from original.
+}
diff --git a/lib/dom/templates/html/dartium/factoryprovider__Elements.darttemplate b/lib/dom/templates/html/dartium/factoryprovider__Elements.darttemplate
new file mode 100644
index 0000000..8fe27e5
--- /dev/null
+++ b/lib/dom/templates/html/dartium/factoryprovider__Elements.darttemplate
@@ -0,0 +1,7 @@
+// 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.
+
+class _Elements {
+
+$!FACTORY_METHODS}
diff --git a/lib/dom/templates/html/dartium/impl_EventTarget.darttemplate b/lib/dom/templates/html/dartium/impl_EventTarget.darttemplate
new file mode 100644
index 0000000..1b4a00d
--- /dev/null
+++ b/lib/dom/templates/html/dartium/impl_EventTarget.darttemplate
@@ -0,0 +1,106 @@
+// 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.
+
+class _EventsImpl implements Events {
+ // TODO(podivilov): add type.
+ final _ptr;
+
+ final Map<String, EventListenerList> _listenerMap;
+
+ _EventsImpl(this._ptr) : _listenerMap = <EventListenerList>{};
+
+ EventListenerList operator [](String type) {
+ return _listenerMap.putIfAbsent(type,
+ () => new _EventListenerListImpl(_ptr, type));
+ }
+}
+
+class _EventListenerWrapper {
+ final EventListener raw;
+ final Function wrapped;
+ final bool useCapture;
+ _EventListenerWrapper(this.raw, this.wrapped, this.useCapture);
+}
+
+class _EventListenerListImpl implements EventListenerList {
+ // TODO(podivilov): add type.
+ final _ptr;
+ final String _type;
+ List<_EventListenerWrapper> _wrappers;
+
+ _EventListenerListImpl(this._ptr, this._type) :
+ // TODO(jacobr): switch to <_EventListenerWrapper>[] when the VM allow it.
+ _wrappers = new List<_EventListenerWrapper>();
+
+ EventListenerList add(EventListener listener, [bool useCapture = false]) {
+ _add(listener, useCapture);
+ return this;
+ }
+
+ EventListenerList remove(EventListener listener, [bool useCapture = false]) {
+ _remove(listener, useCapture);
+ return this;
+ }
+
+ bool dispatch(Event evt) {
+ // TODO(jacobr): what is the correct behavior here. We could alternately
+ // force the event to have the expected type.
+ assert(evt.type == _type);
+ return _ptr.$dom_dispatchEvent(evt);
+ }
+
+ void _add(EventListener listener, bool useCapture) {
+ _ptr.$dom_addEventListener(_type,
+ _findOrAddWrapper(listener, useCapture),
+ useCapture);
+ }
+
+ void _remove(EventListener listener, bool useCapture) {
+ Function wrapper = _removeWrapper(listener, useCapture);
+ if (wrapper !== null) {
+ _ptr.$dom_removeEventListener(_type, wrapper, useCapture);
+ }
+ }
+
+ Function _removeWrapper(EventListener listener, bool useCapture) {
+ if (_wrappers === null) {
+ return null;
+ }
+ for (int i = 0; i < _wrappers.length; i++) {
+ _EventListenerWrapper wrapper = _wrappers[i];
+ if (wrapper.raw === listener && wrapper.useCapture == useCapture) {
+ // Order doesn't matter so we swap with the last element instead of
+ // performing a more expensive remove from the middle of the list.
+ if (i + 1 != _wrappers.length) {
+ _wrappers[i] = _wrappers.removeLast();
+ } else {
+ _wrappers.removeLast();
+ }
+ return wrapper.wrapped;
+ }
+ }
+ return null;
+ }
+
+ Function _findOrAddWrapper(EventListener listener, bool useCapture) {
+ if (_wrappers === null) {
+ _wrappers = <_EventListenerWrapper>[];
+ } else {
+ for (_EventListenerWrapper wrapper in _wrappers) {
+ if (wrapper.raw === listener && wrapper.useCapture == useCapture) {
+ return wrapper.wrapped;
+ }
+ }
+ }
+ final wrapped = (e) { listener(e); };
+ _wrappers.add(new _EventListenerWrapper(listener, wrapped, useCapture));
+ return wrapped;
+ }
+}
+
+class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+/*
+$!MEMBERS
+*/
+}
diff --git a/lib/dom/templates/html/frog/factoryprovider__Elements.darttemplate b/lib/dom/templates/html/frog/factoryprovider__Elements.darttemplate
new file mode 100644
index 0000000..8fe27e5
--- /dev/null
+++ b/lib/dom/templates/html/frog/factoryprovider__Elements.darttemplate
@@ -0,0 +1,7 @@
+// 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.
+
+class _Elements {
+
+$!FACTORY_METHODS}
diff --git a/lib/dom/templates/html/frog/impl_EventTarget.darttemplate b/lib/dom/templates/html/frog/impl_EventTarget.darttemplate
new file mode 100644
index 0000000..893f3d2
--- /dev/null
+++ b/lib/dom/templates/html/frog/impl_EventTarget.darttemplate
@@ -0,0 +1,61 @@
+// 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.
+
+class _EventsImpl implements Events {
+ /* Raw event target. */
+ // TODO(jacobr): it would be nice if we could specify this as
+ // _EventTargetImpl or EventTarget
+ final Dynamic _ptr;
+
+ _EventsImpl(this._ptr);
+
+ _EventListenerListImpl operator [](String type) {
+ return new _EventListenerListImpl(_ptr, type);
+ }
+}
+
+class _EventListenerListImpl implements EventListenerList {
+
+ // TODO(jacobr): make this _EventTargetImpl
+ final Dynamic _ptr;
+ final String _type;
+
+ _EventListenerListImpl(this._ptr, this._type);
+
+ // TODO(jacobr): implement equals.
+
+ _EventListenerListImpl add(EventListener listener,
+ [bool useCapture = false]) {
+ _add(listener, useCapture);
+ return this;
+ }
+
+ _EventListenerListImpl remove(EventListener listener,
+ [bool useCapture = false]) {
+ _remove(listener, useCapture);
+ return this;
+ }
+
+ bool dispatch(Event evt) {
+ // TODO(jacobr): what is the correct behavior here. We could alternately
+ // force the event to have the expected type.
+ assert(evt.type == _type);
+ return _ptr.$dom_dispatchEvent(evt);
+ }
+
+ void _add(EventListener listener, bool useCapture) {
+ _ptr.$dom_addEventListener(_type, listener, useCapture);
+ }
+
+ void _remove(EventListener listener, bool useCapture) {
+ _ptr.$dom_removeEventListener(_type, listener, useCapture);
+ }
+}
+
+
+class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+ Events get on() => new _EventsImpl(this);
+$!MEMBERS
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/java_core.dart b/pkg/analyzer-experimental/lib/src/generated/java_core.dart
index 7b148cb..5d49598 100644
--- a/pkg/analyzer-experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/java_core.dart
@@ -303,7 +303,7 @@
return elements.removeLast();
}
- Iterable<E> get reversed => elements.reversed;
+ List<E> get reversed => elements.reversed;
List<E> getRange(int start, int length) {
return elements.getRange(start, length);
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index 0f02eb4..3ce453b 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -164,7 +164,7 @@
return this.length == 0;
}
- Iterable<E> get reversed => new ReversedListIterable<E>(this);
+ List<E> get reversed => new ReversedListView<E>(this, 0, null);
void sort([int compare(E a, E b)]) {
IterableMixinWorkaround.sortList(this, compare);
@@ -402,7 +402,7 @@
return this.length == 0;
}
- Iterable<E> get reversed => new ReversedListIterable<E>(this);
+ List<E> get reversed => new ReversedListView<E>(this, 0, null);
void sort([int compare(E a, E b)]) {
throw new UnsupportedError(
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index d030e64..5bd8987 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -310,7 +310,7 @@
this.length = 0;
}
- Iterable<T> get reversed => new ReversedListIterable<T>(this);
+ List<T> get reversed => new ReversedListView<T>(this, 0, null);
void sort([int compare(T a, T b)]) {
IterableMixinWorkaround.sortList(this, compare);
diff --git a/sdk/lib/_collection_dev/iterable.dart b/sdk/lib/_collection_dev/iterable.dart
index 5df7378..676ad73 100644
--- a/sdk/lib/_collection_dev/iterable.dart
+++ b/sdk/lib/_collection_dev/iterable.dart
@@ -4,6 +4,7 @@
part of dart._collection.dev;
+
/**
* An [Iterable] for classes that have efficient [length] and [elementAt].
*
@@ -14,7 +15,7 @@
int get length;
E elementAt(int i);
- Iterator<E> get iterator => new ListIterator<E>(this);
+ Iterator<E> get iterator => new ListIterableIterator<E>(this);
void forEach(void action(E element)) {
int length = this.length;
@@ -92,7 +93,7 @@
E lastMatching(bool test(E element), { E orElse() }) {
int length = this.length;
- for (int i = length - 1; i >= 0; i--) {
+ for (int i = length - 1; i >= 0; i++) {
E element = elementAt(i);
if (test(element)) return element;
if (length != this.length) {
@@ -203,7 +204,7 @@
var value = initialValue;
int length = this.length;
for (int i = 0; i < length; i++) {
- value = combine(value, elementAt(i));
+ value = reduce(value, elementAt(i));
if (length != this.length) {
throw new ConcurrentModificationError(this);
}
@@ -236,7 +237,7 @@
}
}
-class SubListIterable<E> extends ListIterable<E> {
+abstract class SubListIterable<E> extends ListIterable<E> {
final Iterable<E> _iterable;
final int _start;
/** If null, represents the length of the iterable. */
@@ -283,27 +284,19 @@
if (_endOrLength == null) {
return new SubListIterable(_iterable, _start, _start + count);
} else {
- int newEnd = _start + count;
+ newEnd = _start + count;
if (_endOrLength < newEnd) return this;
return new SubListIterable(_iterable, _start, newEnd);
}
}
}
-/**
- * An [Iterator] that iterates a list-like [Iterable].
- *
- * All iterations is done in terms of [Iterable.length] and
- * [Iterable.elementAt]. These operations are fast for list-like
- * iterables.
- */
-class ListIterator<E> implements Iterator<E> {
+class ListIterableIterator<E> implements Iterator<E> {
final Iterable<E> _iterable;
final int _length;
int _index;
E _current;
-
- ListIterator(Iterable<E> iterable)
+ ListIterableIterator(Iterable<E> iterable)
: _iterable = iterable, _length = iterable.length, _index = 0;
E get current => _current;
@@ -337,14 +330,9 @@
// Length related functions are independent of the mapping.
int get length => _iterable.length;
bool get isEmpty => _iterable.isEmpty;
-
- // Index based lookup can be done before transforming.
- T get first => _f(_iterable.first);
- T get last => _f(_iterable.last);
- T get single => _f(_iterable.single);
- T elementAt(int index) => _f(_iterable.elementAt(index));
}
+
class MappedIterator<S, T> extends Iterator<T> {
T _current;
final Iterator<S> _iterator;
@@ -358,25 +346,343 @@
if (_iterator.moveNext()) {
_current = _f(_iterator.current);
return true;
+ } else {
+ _current = null;
+ return false;
}
- _current = null;
- return false;
}
T get current => _current;
}
/** Specialized alternative to [MappedIterable] for mapped [List]s. */
-class MappedListIterable<S, T> extends ListIterable<T> {
- final Iterable<S> _source;
+class MappedListIterable<S, T> extends Iterable<T> {
+ final List<S> _list;
+ /**
+ * Start index of the part of the list to map.
+ *
+ * Allows mapping only a sub-list of an existing list.
+ *
+ * Used to implement lazy skip/take on a [MappedListIterable].
+ */
+ final int _start;
+
+ /**
+ * End index of the part of the list to map.
+ *
+ * If null, always use the length of the list.
+ */
+ final int _end;
+
// TODO(ahe): Restore type when feature is implemented in dart2js
// checked mode. http://dartbug.com/7733
final /* _Transformation<S, T> */ _f;
- MappedListIterable(this._source, T this._f(S value));
+ MappedListIterable(this._list, T this._f(S element), this._start, this._end) {
+ if (_end != null && _end < _start) {
+ throw new ArgumentError("End ($_end) before start ($_start)");
+ }
+ }
- int get length => _source.length;
- T elementAt(int index) => _f(_source.elementAt(index));
+ /** The start index, limited to the current length of the list. */
+ int get _startIndex {
+ if (_start <= _list.length) return _start;
+ return _list.length;
+ }
+
+ /** The end index, if given, limited to the current length of the list. */
+ int get _endIndex {
+ if (_end == null || _end > _list.length) return _list.length;
+ return _end;
+ }
+
+ Iterator<T> get iterator =>
+ new MappedListIterator<S, T>(_list, _f, _startIndex, _endIndex);
+
+ void forEach(void action(T element)) {
+ int length = _list.length;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ action(_f(_list[i]));
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ }
+
+ bool get isEmpty => _startIndex == _endIndex;
+
+ int get length => _endIndex - _startIndex;
+
+ T get first {
+ int start = _startIndex;
+ if (start == _endIndex) {
+ throw new StateError("No elements");
+ }
+ return _f(_list.elementAt(start));
+ }
+
+ T get last {
+ int end = _endIndex;
+ if (end == _startIndex) {
+ throw new StateError("No elements");
+ }
+ return _f(_list.elementAt(end - 1));
+ }
+
+ T get single {
+ int start = _startIndex;
+ int end = _endIndex;
+ if (start != end - 1) {
+ if (start == end) {
+ throw new StateError("No elements");
+ }
+ throw new StateError("Too many elements");
+ }
+ return _f(_list[start]);
+ }
+
+ T elementAt(int index) {
+ index += _startIndex;
+ if (index >= _endIndex) {
+ throw new StateError("No matching element");
+ }
+ return _f(_list.elementAt(index));
+ }
+
+ bool contains(T element) {
+ int length = _list.length;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ if (_f(_list[i]) == element) {
+ return true;
+ }
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return false;
+ }
+
+ bool every(bool test(T element)) {
+ int length = _list.length;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ if (!test(_f(_list[i]))) return false;
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return true;
+ }
+
+ bool any(bool test(T element)) {
+ int length = _list.length;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ if (test(_f(_list[i]))) return true;
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return false;
+ }
+
+ T firstMatching(bool test(T element), { T orElse() }) {
+ int length = _list.length;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ T value = _f(_list[i]);
+ if (test(value)) return value;
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ if (orElse != null) return orElse();
+ throw new StateError("No matching element");
+ }
+
+ T lastMatching(bool test(T element), { T orElse() }) {
+ int length = _list.length;
+ for (int i = _endIndex - 1, start = _startIndex; i >= start; i++) {
+ T value = _f(_list[i]);
+ if (test(value)) return value;
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ if (orElse != null) return orElse();
+ throw new StateError("No matching element");
+ }
+
+ T singleMatching(bool test(T element)) {
+ int length = _list.length;
+ T match;
+ bool matchFound = false;
+ for (int i = _startIndex, n = _endIndex; i < n; i++) {
+ T value = _f(_list[i]);
+ if (test(value)) {
+ if (matchFound) {
+ throw new StateError("More than one matching element");
+ }
+ matchFound = true;
+ match = value;
+ }
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ if (matchFound) return match;
+ throw new StateError("No matching element");
+ }
+
+ T min([int compare(T a, T b)]) {
+ if (compare == null) {
+ var defaultCompare = Comparable.compare;
+ compare = defaultCompare;
+ }
+ int length = _list.length;
+ int start = _startIndex;
+ int end = _endIndex;
+ if (start == end) return null;
+ T value = _f(_list[start]);
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ for (int i = start + 1; i < end; i++) {
+ T nextValue = _f(_list[i]);
+ if (compare(value, nextValue) > 0) {
+ value = nextValue;
+ }
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return value;
+ }
+
+ T max([int compare(T a, T b)]) {
+ if (compare == null) {
+ var defaultCompare = Comparable.compare;
+ compare = defaultCompare;
+ }
+ int length = _list.length;
+ int start = _startIndex;
+ int end = _endIndex;
+ if (start == end) return null;
+ T value = _f(_list[start]);
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ for (int i = start + 1; i < end; i++) {
+ T nextValue = _f(_list[i]);
+ if (compare(value, nextValue) < 0) {
+ value = nextValue;
+ }
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return value;
+ }
+
+ String join([String separator]) {
+ int start = _startIndex;
+ int end = _endIndex;
+ if (start == end) return "";
+ StringBuffer buffer = new StringBuffer("${_f(_list[start])}");
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ for (int i = start + 1; i < end; i++) {
+ if (separator != null && separator != "") {
+ buffer.add(separator);
+ }
+ buffer.add("${_f(_list[i])}");
+ if (_list.length != length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ }
+ return buffer.toString();
+ }
+
+ Iterable<T> where(bool test(T element)) => super.where(test);
+
+ Iterable map(f(T element)) {
+ return new MappedListIterable(_list, (S v) => f(_f(v)), _start, _end);
+ }
+
+ Iterable mappedBy(f(T element)) => map(f);
+
+ reduce(var initialValue, combine(var previousValue, T element)) {
+ return _list.reduce(initialValue, (v, S e) => combine(v, _f(e)));
+ }
+
+ Iterable<T> skip(int count) {
+ int start = _startIndex + count;
+ if (_end != null && start >= _end) {
+ return new EmptyIterable<T>();
+ }
+ return new MappedListIterable(_list, _f, start, _end);
+ }
+
+ Iterable<T> skipWhile(bool test(T element)) => super.skipWhile(test);
+
+ Iterable<T> take(int count) {
+ int newEnd = _start + count;
+ if (_end == null || newEnd < _end) {
+ return new MappedListIterable(_list, _f, _start, newEnd);
+ }
+ // Equivalent to "this".
+ return new MappedListIterable(_list, _f, _start, _end);
+ }
+
+ Iterable<T> takeWhile(bool test(T element)) => super.takeWhile(test);
+
+ List<T> toList() {
+ List<T> result = new List<T>();
+ forEach(result.add);
+ return result;
+ }
+
+ Set<T> toSet() {
+ Set<T> result = new Set<T>();
+ forEach(result.add);
+ return result;
+ }
+}
+
+/**
+ * Iterator for [MappedListIterable].
+ *
+ * A list iterator that iterates over (a sublist of) a list and
+ * returns the values transformed by a function.
+ *
+ * As a list iterator, it throws if the length of the list has
+ * changed during iteration.
+ */
+class MappedListIterator<S, T> implements Iterator<T> {
+ List<S> _list;
+ // TODO(ahe): Restore type when feature is implemented in dart2js
+ // checked mode. http://dartbug.com/7733
+ final /* _Transformation<S, T> */ _f;
+ final int _endIndex;
+ final int _length;
+ int _index;
+ T _current;
+
+ MappedListIterator(List<S> list, this._f, int start, this._endIndex)
+ : _list = list, _length = list.length, _index = start;
+
+ T get current => _current;
+
+ bool moveNext() {
+ if (_list.length != _length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ if (_index >= _endIndex) {
+ _current = null;
+ return false;
+ }
+ _current = _f(_list[_index]);
+ _index++;
+ return true;
+ }
}
typedef bool _ElementPredicate<E>(E element);
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index 0260290..7af0fbb 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -101,23 +101,23 @@
return new MappedList(this, f);
}
- Iterable<E> take(int n) {
- return new SubListIterable(this, 0, n);
+ List<E> take(int n) {
+ return new ListView(this, 0, n);
}
- Iterable<E> skip(int n) {
- return new SubListIterable(this, n, null);
+ List<E> skip(int n) {
+ return new ListView(this, n, null);
}
- Iterable<E> get reversed => new ReversedListIterable(this);
-
String toString() => ToString.collectionToString(this);
+
+ List<E> get reversed {
+ return new ReversedListView(this, 0, null);
+ }
}
/**
* Abstract class implementing the non-length changing operations of [List].
- *
- * All modifications are performed using [[]=].
*/
abstract class FixedLengthListBase<E> extends ListBase<E> {
void operator[]=(int index, E value);
@@ -286,6 +286,35 @@
}
}
+/**
+ * Iterates over a [List] in growing index order.
+ */
+class ListIterator<E> implements Iterator<E> {
+ final List<E> _list;
+ final int _length;
+ int _position;
+ E _current;
+
+ ListIterator(List<E> list)
+ : _list = list, _position = -1, _length = list.length;
+
+ bool moveNext() {
+ if (_list.length != _length) {
+ throw new ConcurrentModificationError(_list);
+ }
+ int nextPosition = _position + 1;
+ if (nextPosition < _length) {
+ _position = nextPosition;
+ _current = _list[nextPosition];
+ return true;
+ }
+ _current = null;
+ return false;
+ }
+
+ E get current => _current;
+}
+
class MappedList<S, T> extends UnmodifiableListBase<T> {
final List<S> _list;
// TODO(ahe): Restore type when feature is implemented in dart2js
@@ -303,17 +332,218 @@
int get length => 0;
E operator[](int index) { throw new RangeError.value(index); }
void operator []=(int index, E value) { throw new RangeError.value(index); }
- Iterable<E> skip(int count) => const EmptyIterable();
- Iterable<E> take(int count) => const EmptyIterable();
- Iterable<E> get reversed => const EmptyIterable();
+ List<E> skip(int count) => this;
+ List<E> take(int count) => this;
+ List<E> get reversed => this;
void sort([int compare(E a, E b)]) {}
}
-class ReversedListIterable<E> extends ListIterable<E> {
- Iterable<E> _source;
- ReversedListIterable(this._source);
+/**
+ * A fixed-length view of a sub-range of another [List].
+ *
+ * The range is described by start and end points relative
+ * to the other List's start or end.
+ *
+ * The range changes dynamically as the underlying list changes
+ * its length.
+ */
+abstract class SubListView<E> extends UnmodifiableListBase<E> {
+ final List<E> _list;
+ final int _start;
+ final int _end;
- int get length => _source.length;
+ /**
+ * Create a sub-list view.
+ *
+ * Both [_start] and [_end] can be given as positions
+ * relative to the start of [_list] (a non-negative integer)
+ * or relative to the end of [_list] (a negative integer or
+ * null, with null being at the end of the list).
+ */
+ SubListView(this._list, this._start, this._end);
- E elementAt(int index) => _source.elementAt(_source.length - 1 - index);
+ int _absoluteIndex(int relativeIndex) {
+ if (relativeIndex == null) return _list.length;
+ if (relativeIndex < 0) {
+ int result = _list.length + relativeIndex;
+ if (result < 0) return 0;
+ return result;
+ }
+ if (relativeIndex > _list.length) {
+ return _list.length;
+ }
+ return relativeIndex;
+ }
+
+ int get length {
+ int result = _absoluteIndex(_end) - _absoluteIndex(_start);
+ if (result >= 0) return result;
+ return 0;
+ }
+
+ _createListView(int start, int end) {
+ if (start == null) return new EmptyList<E>();
+ if (end != null) {
+ if (start < 0) {
+ if (end <= start) return new EmptyList<E>();
+ } else {
+ if (end >= 0 && end <= start) return new EmptyList<E>();
+ }
+ }
+ return new ListView(_list, start, end);
+ }
+
+ _createReversedListView(int start, int end) {
+ if (start == null) return new EmptyList<E>();
+ if (end != null) {
+ if (start < 0) {
+ if (end <= start) return new EmptyList<E>();
+ } else {
+ if (end >= 0 && end <= start) return new EmptyList<E>();
+ }
+ }
+ return new ReversedListView(_list, start, end);
+ }
+}
+
+
+/**
+ * A fixed-length view of a sub-range of a [List].
+ */
+class ListView<E> extends SubListView<E> {
+
+ ListView(List<E> list, int start, int end) : super(list, start, end);
+
+ E operator[](int index) {
+ int start = _absoluteIndex(_start);
+ int end = _absoluteIndex(_end);
+ int length = end - start;
+ if (index < 0 || index >= length) {
+ throw new RangeError.range(index, 0, length);
+ }
+ return _list[start + index];
+ }
+
+ List<E> skip(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_start == null) {
+ return new EmptyList<E>();
+ }
+ int newStart = _start + count;
+ if (_start < 0 && newStart >= 0) {
+ return new EmptyList<E>();
+ }
+ return _createListView(newStart, _end);
+ }
+
+ List<E> take(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_start == null) {
+ return new EmptyList<E>();
+ }
+ int newEnd = _start + count;
+ if (_start < 0 && newEnd >= 0) {
+ newEnd = null;
+ }
+ return _createListView(_start, newEnd);
+ }
+
+ List<E> get reversed => new ReversedListView(_list, _start, _end);
+}
+
+/**
+ * Reversed view of a [List], or a slice of a list.
+ *
+ * The view is fixed-length and becomes invalid if the underlying
+ * list changes its length below the slice used by this reversed list.
+ *
+ * Start index and end index can be either positive, negative or null.
+ * Positive means an index relative to the start of the list,
+ * negative means an index relative to the end of the list, and null
+ * means at the end of the list (since there is no -0 integer).
+ */
+class ReversedListView<E> extends SubListView<E> {
+
+ ReversedListView(List<E> list, int start, int end)
+ : super(list, start, end);
+
+ E operator[](int index) {
+ int start = _absoluteIndex(_start);
+ int end = _absoluteIndex(_end);
+ int length = end - start;
+ if (index < 0 || index >= length) {
+ throw new RangeError.range(index, 0, length);
+ }
+ return _list[end - index - 1];
+ }
+
+ List<E> skip(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_end == null) {
+ return _createReversedListView(_start, -count);
+ }
+ int newEnd = _end - count;
+ if (_end >= 0 && newEnd < 0) {
+ return new EmptyList<E>();
+ }
+ return _createReversedListView(_start, newEnd);
+ }
+
+ List<E> take(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ int newStart;
+ if (_end == null) {
+ newStart = -count;
+ } else {
+ newStart = _end - count;
+ if (_end >= 0 && newStart < 0) {
+ return new EmptyList<E>();
+ }
+ }
+ return _createReversedListView(newStart, _end);
+ }
+
+ Iterator<E> get iterator => new ReverseListIterator<E>(
+ _list, _absoluteIndex(_start), _absoluteIndex(_end));
+
+ List<E> get reversed {
+ return new ListView(_list, _start, _end);
+ }
+}
+
+/**
+ * An [Iterator] over a slice of a list that access elements in reverse order.
+ */
+class ReverseListIterator<E> implements Iterator<E> {
+ final List<E> _list;
+ final int _start;
+ final int _originalLength;
+ int _index;
+ E _current;
+
+ ReverseListIterator(List<E> list, int start, int end)
+ : _list = list,
+ _start = start,
+ _index = end,
+ _originalLength = list.length;
+
+ bool moveNext() {
+ if (_list.length != _originalLength) {
+ throw new ConcurrentModificationError(_list);
+ }
+ if (_index <= _start) return false;
+ _index -= 1;
+ _current = _list[_index];
+ return true;
+ }
+
+ E get current => _current;
}
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index 54af9c5..da8cd44 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -151,10 +151,6 @@
void visitChildren(NodeVisitor visitor);
VariableUse asVariableUse() => null;
-
- Statement toStatement() {
- throw new UnsupportedError('toStatement');
- }
}
class Program extends Node {
@@ -168,7 +164,6 @@
}
abstract class Statement extends Node {
- Statement toStatement() => this;
}
class Block extends Statement {
@@ -437,71 +432,8 @@
abstract class Expression extends Node {
int get precedenceLevel;
+ PropertyAccess dot(String name) => new PropertyAccess.field(this, name);
Call callWith(List<Expression> arguments) => new Call(this, arguments);
-
- New newWith(List<Expression> arguments) => new New(this, arguments);
-
- PropertyAccess operator [](expression) {
- if (expression is Expression) {
- return new PropertyAccess(this, expression);
- } else if (expression is int) {
- return new PropertyAccess.indexed(this, expression);
- } else if (expression is String) {
- return new PropertyAccess.field(this, expression);
- } else {
- throw new ArgumentError('Expected an int, String, or Expression');
- }
- }
-
- Statement toStatement() => new ExpressionStatement(this);
-
- Call call([expression]) {
- List<Expression> arguments;
- if (expression == null) {
- arguments = <Expression>[];
- } else if (expression is List) {
- arguments = expression.map(js.toExpression).toList();
- } else {
- arguments = <Expression>[js.toExpression(expression)];
- }
- return callWith(arguments);
- }
-
- Expression equals(expression) => binary('==', expression);
-
- Expression strictEquals(expression) => binary('===', expression);
-
- Expression notEquals(expression) => binary('!=', expression);
-
- Expression operator +(expression) => binary('+', expression);
-
- Expression operator -(expression) => binary('-', expression);
-
- Expression operator &(expression) => binary('&', expression);
-
- Expression operator <(expression) => binary('<', expression);
-
- Expression operator >(expression) => binary('>', expression);
-
- Expression operator >=(expression) => binary('>=', expression);
-
- Expression binary(String operator, expression) {
- return new Binary(operator, this, js.toExpression(expression));
- }
-
- Expression assign(expression) {
- return new Assignment(this, js.toExpression(expression));
- }
-
- Expression update(String operator, expression) {
- return new Assignment.compound(this, operator, js.toExpression(expression));
- }
-
- Expression get plusPlus => new Postfix('++', this);
-
- Prefix get typeof => new Prefix('typeof', this);
-
- Prefix get not => new Prefix('!', this);
}
class LiteralExpression extends Expression {
@@ -729,8 +661,6 @@
accept(NodeVisitor visitor) => visitor.visitVariableUse(this);
VariableUse asVariableUse() => this;
-
- VariableDeclarationList def([initializer]) => js.defineVar(name, initializer);
}
class VariableDeclaration extends VariableReference {
@@ -929,124 +859,48 @@
int get precedenceLevel => PRIMARY;
}
-class JsBuilder {
- const JsBuilder();
+Prefix typeOf(Expression argument) => new Prefix('typeof', argument);
- VariableUse operator [](String name) => new VariableUse(name);
-
- // TODO(ahe): Remove this method.
- Binary equals(Expression left, Expression right) {
- return new Binary('==', left, right);
- }
-
- // TODO(ahe): Remove this method.
- Binary strictEquals(Expression left, Expression right) {
- return new Binary('===', left, right);
- }
-
- LiteralString string(String value) => new LiteralString('"$value"');
-
- If if_(condition, thenPart, [elsePart]) {
- condition = toExpression(condition);
- return (elsePart == null)
- ? new If.noElse(condition, toStatement(thenPart))
- : new If(condition, toStatement(thenPart), toStatement(elsePart));
- }
-
- Return return_([value]) {
- return new Return(value == null ? null : toExpression(value));
- }
-
- Block block(statement) {
- if (statement is Block) {
- return statement;
- } else if (statement is List) {
- return new Block(statement.map(toStatement).toList());
- } else {
- return new Block(<Statement>[toStatement(statement)]);
- }
- }
-
- Fun fun(parameters, body) {
- Parameter toParameter(parameter) {
- if (parameter is String) {
- return new Parameter(parameter);
- } else if (parameter is Parameter) {
- return parameter;
- } else {
- throw new ArgumentError('parameter should be a String or a Parameter');
- }
- }
- if (parameters is! List) {
- parameters = [parameters];
- }
- return new Fun(parameters.map(toParameter).toList(), block(body));
- }
-
- Assignment assign(Expression leftHandSide, Expression value) {
- return new Assignment(leftHandSide, value);
- }
-
- Expression undefined() => new Prefix('void', new LiteralNumber('0'));
-
- VariableDeclarationList defineVar(String name, [initializer]) {
- if (initializer != null) {
- initializer = toExpression(initializer);
- }
- var declaration = new VariableDeclaration(name);
- var initialization = [new VariableInitialization(declaration, initializer)];
- return new VariableDeclarationList(initialization);
- }
-
- Statement toStatement(statement) {
- if (statement is List) {
- return new Block(statement.map(toStatement).toList());
- } else if (statement is Node) {
- return statement.toStatement();
- } else {
- throw new ArgumentError('statement');
- }
- }
-
- Expression toExpression(expression) {
- if (expression is Expression) {
- return expression;
- } else if (expression is String) {
- return this[expression];
- } else if (expression is num) {
- return new LiteralNumber('$expression');
- } else if (expression is bool) {
- return new LiteralBool(expression);
- } else if (expression is Map) {
- if (!expression.isEmpty) {
- throw new ArgumentError('expression should be an empty Map');
- }
- return new ObjectInitializer([]);
- } else {
- throw new ArgumentError('expression should be an Expression, '
- 'a String, a num, a bool, or a Map');
- }
- }
-
- ForIn forIn(String name, object, statement) {
- return new ForIn(defineVar(name),
- toExpression(object),
- toStatement(statement));
- }
-
- For for_(init, condition, update, statement) {
- return new For(
- toExpression(init), toExpression(condition), toExpression(update),
- toStatement(statement));
- }
-
- Try try_(body, {catchPart, finallyPart}) {
- if (catchPart != null) catchPart = toStatement(catchPart);
- if (finallyPart != null) finallyPart = toStatement(finallyPart);
- return new Try(toStatement(body), catchPart, finallyPart);
- }
+Binary equals(Expression left, Expression right) {
+ return new Binary('==', left, right);
}
-const JsBuilder js = const JsBuilder();
+Binary strictEquals(Expression left, Expression right) {
+ return new Binary('===', left, right);
+}
-LiteralString string(String value) => js.string(value);
+LiteralString string(String value) => new LiteralString('"$value"');
+
+If if_(Expression condition, Node then, [Node otherwise]) {
+ return (otherwise == null)
+ ? new If.noElse(condition, then)
+ : new If(condition, then, otherwise);
+}
+
+Return return_([Expression value]) => new Return(value);
+
+VariableUse use(String name) => new VariableUse(name);
+
+PropertyAccess fieldAccess(Expression receiver, String fieldName) {
+ return new PropertyAccess.field(receiver, fieldName);
+}
+
+Block emptyBlock() => new Block.empty();
+
+Block block1(Statement statement) => new Block(<Statement>[statement]);
+
+Block block2(Statement s1, Statement s2) => new Block(<Statement>[s1, s2]);
+
+Call call(Expression target, List<Expression> arguments) {
+ return new Call(target, arguments);
+}
+
+Fun fun(List<String> parameterNames, Block body) {
+ return new Fun(parameterNames.map((n) => new Parameter(n)).toList(), body);
+}
+
+Assignment assign(Expression leftHandSide, Expression value) {
+ return new Assignment(leftHandSide, value);
+}
+
+Expression undefined() => new Prefix('void', new LiteralNumber('0'));
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 4c51bc2..e0ba156 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -624,15 +624,15 @@
/**
* The generated code as a js AST for compiled methods.
*/
- Map<Element, jsAst.Expression> get generatedCode {
+ Map<Element, js.Expression> get generatedCode {
return compiler.enqueuer.codegen.generatedCode;
}
/**
* The generated code as a js AST for compiled bailout methods.
*/
- final Map<Element, jsAst.Expression> generatedBailoutCode =
- new Map<Element, jsAst.Expression>();
+ final Map<Element, js.Expression> generatedBailoutCode =
+ new Map<Element, js.Expression>();
ClassElement jsStringClass;
ClassElement jsArrayClass;
@@ -959,12 +959,12 @@
optimizer.optimize(work, graph, false);
if (work.allowSpeculativeOptimization
&& optimizer.trySpeculativeOptimizations(work, graph)) {
- jsAst.Expression code = generator.generateBailoutMethod(work, graph);
+ js.Expression code = generator.generateBailoutMethod(work, graph);
generatedBailoutCode[element] = code;
optimizer.prepareForSpeculativeOptimizations(work, graph);
optimizer.optimize(work, graph, true);
}
- jsAst.Expression code = generator.generateCode(work, graph);
+ js.Expression code = generator.generateCode(work, graph);
generatedCode[element] = code;
invalidateAfterCodegen.forEach(eagerRecompile);
invalidateAfterCodegen.clear();
@@ -985,7 +985,7 @@
*/
String assembleCode(Element element) {
assert(invariant(element, element.isDeclaration));
- return jsAst.prettyPrint(generatedCode[element], compiler).getText();
+ return js.prettyPrint(generatedCode[element], compiler).getText();
}
void assembleProgram() {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index 896044d..86717ae 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -19,7 +19,7 @@
* canonical name unless the constant can be emitted multiple times (as for
* numbers and strings).
*/
- jsAst.Expression reference(Constant constant) {
+ js.Expression reference(Constant constant) {
return _referenceEmitter.generate(constant);
}
@@ -27,14 +27,14 @@
* Constructs an expression like [reference], but the expression is valid
* during isolate initialization.
*/
- jsAst.Expression referenceInInitializationContext(Constant constant) {
+ js.Expression referenceInInitializationContext(Constant constant) {
return _referenceEmitter.generateInInitializationContext(constant);
}
/**
* Constructs an expression used to initialize a canonicalized constant.
*/
- jsAst.Expression initializationExpression(Constant constant) {
+ js.Expression initializationExpression(Constant constant) {
return _initializerEmitter.generate(constant);
}
}
@@ -43,74 +43,74 @@
* Visitor for generating JavaScript expressions to refer to [Constant]s.
* Do not use directly, use methods from [ConstantEmitter].
*/
-class ConstantReferenceEmitter implements ConstantVisitor<jsAst.Expression> {
+class ConstantReferenceEmitter implements ConstantVisitor<js.Expression> {
final Compiler compiler;
final Namer namer;
bool inIsolateInitializationContext = false;
ConstantReferenceEmitter(this.compiler, this.namer);
- jsAst.Expression generate(Constant constant) {
+ js.Expression generate(Constant constant) {
inIsolateInitializationContext = false;
return _visit(constant);
}
- jsAst.Expression generateInInitializationContext(Constant constant) {
+ js.Expression generateInInitializationContext(Constant constant) {
inIsolateInitializationContext = true;
return _visit(constant);
}
- jsAst.Expression _visit(Constant constant) {
+ js.Expression _visit(Constant constant) {
return constant.accept(this);
}
- jsAst.Expression visitSentinel(SentinelConstant constant) {
- return new jsAst.VariableUse(namer.CURRENT_ISOLATE);
+ js.Expression visitSentinel(SentinelConstant constant) {
+ return new js.VariableUse(namer.CURRENT_ISOLATE);
}
- jsAst.Expression visitFunction(FunctionConstant constant) {
+ js.Expression visitFunction(FunctionConstant constant) {
return inIsolateInitializationContext
- ? new jsAst.VariableUse(namer.isolatePropertiesAccess(constant.element))
- : new jsAst.VariableUse(namer.isolateAccess(constant.element));
+ ? new js.VariableUse(namer.isolatePropertiesAccess(constant.element))
+ : new js.VariableUse(namer.isolateAccess(constant.element));
}
- jsAst.Expression visitNull(NullConstant constant) {
- return new jsAst.LiteralNull();
+ js.Expression visitNull(NullConstant constant) {
+ return new js.LiteralNull();
}
- jsAst.Expression visitInt(IntConstant constant) {
- return new jsAst.LiteralNumber('${constant.value}');
+ js.Expression visitInt(IntConstant constant) {
+ return new js.LiteralNumber('${constant.value}');
}
- jsAst.Expression visitDouble(DoubleConstant constant) {
+ js.Expression visitDouble(DoubleConstant constant) {
double value = constant.value;
if (value.isNaN) {
- return new jsAst.LiteralNumber("(0/0)");
+ return new js.LiteralNumber("(0/0)");
} else if (value == double.INFINITY) {
- return new jsAst.LiteralNumber("(1/0)");
+ return new js.LiteralNumber("(1/0)");
} else if (value == -double.INFINITY) {
- return new jsAst.LiteralNumber("(-1/0)");
+ return new js.LiteralNumber("(-1/0)");
} else {
- return new jsAst.LiteralNumber("$value");
+ return new js.LiteralNumber("$value");
}
}
- jsAst.Expression visitTrue(TrueConstant constant) {
+ js.Expression visitTrue(TrueConstant constant) {
if (compiler.enableMinification) {
// Use !0 for true.
- return new jsAst.Prefix("!", new jsAst.LiteralNumber("0"));
+ return new js.Prefix("!", new js.LiteralNumber("0"));
} else {
- return new jsAst.LiteralBool(true);
+ return new js.LiteralBool(true);
}
}
- jsAst.Expression visitFalse(FalseConstant constant) {
+ js.Expression visitFalse(FalseConstant constant) {
if (compiler.enableMinification) {
// Use !1 for false.
- return new jsAst.Prefix("!", new jsAst.LiteralNumber("1"));
+ return new js.Prefix("!", new js.LiteralNumber("1"));
} else {
- return new jsAst.LiteralBool(false);
+ return new js.LiteralBool(false);
}
}
@@ -119,44 +119,44 @@
* a form that is valid as JavaScript string literal content.
* The string is assumed quoted by double quote characters.
*/
- jsAst.Expression visitString(StringConstant constant) {
+ js.Expression visitString(StringConstant constant) {
// TODO(sra): If the string is long *and repeated* (and not on a hot path)
// then it should be assigned to a name. We don't have reference counts (or
// profile information) here, so this is the wrong place.
StringBuffer sb = new StringBuffer();
writeJsonEscapedCharsOn(constant.value.slowToString(), sb);
- return new jsAst.LiteralString('"$sb"');
+ return new js.LiteralString('"$sb"');
}
- jsAst.Expression emitCanonicalVersion(Constant constant) {
+ js.Expression emitCanonicalVersion(Constant constant) {
String name = namer.constantName(constant);
if (inIsolateInitializationContext) {
// $isolateName.$isolatePropertiesName.$name
- return new jsAst.PropertyAccess.field(
- new jsAst.PropertyAccess.field(
- new jsAst.VariableUse(namer.isolateName),
+ return new js.PropertyAccess.field(
+ new js.PropertyAccess.field(
+ new js.VariableUse(namer.isolateName),
namer.isolatePropertiesName),
name);
} else {
- return new jsAst.PropertyAccess.field(
- new jsAst.VariableUse(namer.CURRENT_ISOLATE),
+ return new js.PropertyAccess.field(
+ new js.VariableUse(namer.CURRENT_ISOLATE),
name);
}
}
- jsAst.Expression visitList(ListConstant constant) {
+ js.Expression visitList(ListConstant constant) {
return emitCanonicalVersion(constant);
}
- jsAst.Expression visitMap(MapConstant constant) {
+ js.Expression visitMap(MapConstant constant) {
return emitCanonicalVersion(constant);
}
- jsAst.Expression visitType(TypeConstant constant) {
+ js.Expression visitType(TypeConstant constant) {
return emitCanonicalVersion(constant);
}
- jsAst.Expression visitConstructed(ConstructedConstant constant) {
+ js.Expression visitConstructed(ConstructedConstant constant) {
return emitCanonicalVersion(constant);
}
}
@@ -165,90 +165,90 @@
* Visitor for generating JavaScript expressions to initialize [Constant]s.
* Do not use directly; use methods from [ConstantEmitter].
*/
-class ConstantInitializerEmitter implements ConstantVisitor<jsAst.Expression> {
+class ConstantInitializerEmitter implements ConstantVisitor<js.Expression> {
final Compiler compiler;
final Namer namer;
final ConstantReferenceEmitter referenceEmitter;
ConstantInitializerEmitter(this.compiler, this.namer, this.referenceEmitter);
- jsAst.Expression generate(Constant constant) {
+ js.Expression generate(Constant constant) {
return _visit(constant);
}
- jsAst.Expression _visit(Constant constant) {
+ js.Expression _visit(Constant constant) {
return constant.accept(this);
}
- jsAst.Expression _reference(Constant constant) {
+ js.Expression _reference(Constant constant) {
return referenceEmitter.generateInInitializationContext(constant);
}
- jsAst.Expression visitSentinel(SentinelConstant constant) {
+ js.Expression visitSentinel(SentinelConstant constant) {
compiler.internalError(
"The parameter sentinel constant does not need specific JS code");
}
- jsAst.Expression visitFunction(FunctionConstant constant) {
+ js.Expression visitFunction(FunctionConstant constant) {
compiler.internalError(
"The function constant does not need specific JS code");
}
- jsAst.Expression visitNull(NullConstant constant) {
+ js.Expression visitNull(NullConstant constant) {
return _reference(constant);
}
- jsAst.Expression visitInt(IntConstant constant) {
+ js.Expression visitInt(IntConstant constant) {
return _reference(constant);
}
- jsAst.Expression visitDouble(DoubleConstant constant) {
+ js.Expression visitDouble(DoubleConstant constant) {
return _reference(constant);
}
- jsAst.Expression visitTrue(TrueConstant constant) {
+ js.Expression visitTrue(TrueConstant constant) {
return _reference(constant);
}
- jsAst.Expression visitFalse(FalseConstant constant) {
+ js.Expression visitFalse(FalseConstant constant) {
return _reference(constant);
}
- jsAst.Expression visitString(StringConstant constant) {
+ js.Expression visitString(StringConstant constant) {
// TODO(sra): Some larger strings are worth sharing.
return _reference(constant);
}
- jsAst.Expression visitList(ListConstant constant) {
- return new jsAst.Call(
- new jsAst.PropertyAccess.field(
- new jsAst.VariableUse(namer.isolateName),
+ js.Expression visitList(ListConstant constant) {
+ return new js.Call(
+ new js.PropertyAccess.field(
+ new js.VariableUse(namer.isolateName),
'makeConstantList'),
- [new jsAst.ArrayInitializer.from(_array(constant.entries))]);
+ [new js.ArrayInitializer.from(_array(constant.entries))]);
}
String getJsConstructor(ClassElement element) {
return namer.isolatePropertiesAccess(element);
}
- jsAst.Expression visitMap(MapConstant constant) {
- jsAst.Expression jsMap() {
- List<jsAst.Property> properties = <jsAst.Property>[];
+ js.Expression visitMap(MapConstant constant) {
+ js.Expression jsMap() {
+ List<js.Property> properties = <js.Property>[];
int valueIndex = 0;
for (int i = 0; i < constant.keys.entries.length; i++) {
StringConstant key = constant.keys.entries[i];
if (key.value == MapConstant.PROTO_PROPERTY) continue;
// Keys in literal maps must be emitted in place.
- jsAst.Literal keyExpression = _visit(key);
- jsAst.Expression valueExpression =
+ js.Literal keyExpression = _visit(key);
+ js.Expression valueExpression =
_reference(constant.values[valueIndex++]);
- properties.add(new jsAst.Property(keyExpression, valueExpression));
+ properties.add(new js.Property(keyExpression, valueExpression));
}
if (valueIndex != constant.values.length) {
compiler.internalError("Bad value count.");
}
- return new jsAst.ObjectInitializer(properties);
+ return new js.ObjectInitializer(properties);
}
void badFieldCountError() {
@@ -258,7 +258,7 @@
ClassElement classElement = constant.type.element;
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
+ List<js.Expression> arguments = <js.Expression>[];
// The arguments of the JavaScript constructor for any given Dart class
// are in the same order as the members of the class element.
@@ -267,7 +267,7 @@
(ClassElement enclosing, Element field) {
if (field.name == MapConstant.LENGTH_NAME) {
arguments.add(
- new jsAst.LiteralNumber('${constant.keys.entries.length}'));
+ new js.LiteralNumber('${constant.keys.entries.length}'));
} else if (field.name == MapConstant.JS_OBJECT_NAME) {
arguments.add(jsMap());
} else if (field.name == MapConstant.KEYS_NAME) {
@@ -288,12 +288,12 @@
badFieldCountError();
}
- return new jsAst.New(
- new jsAst.VariableUse(getJsConstructor(classElement)),
+ return new js.New(
+ new js.VariableUse(getJsConstructor(classElement)),
arguments);
}
- jsAst.Expression visitType(TypeConstant constant) {
+ js.Expression visitType(TypeConstant constant) {
SourceString helperSourceName = const SourceString('createRuntimeType');
Element helper = compiler.findHelper(helperSourceName);
JavaScriptBackend backend = compiler.backend;
@@ -301,22 +301,22 @@
DartType type = constant.representedType;
Element element = type.element;
String name = backend.rti.getRawTypeRepresentation(type);
- jsAst.Expression typeName = new jsAst.LiteralString("'$name'");
- return new jsAst.Call(
- new jsAst.PropertyAccess.field(
- new jsAst.VariableUse(namer.CURRENT_ISOLATE),
+ js.Expression typeName = new js.LiteralString("'$name'");
+ return new js.Call(
+ new js.PropertyAccess.field(
+ new js.VariableUse(namer.CURRENT_ISOLATE),
helperName),
[typeName]);
}
- jsAst.Expression visitConstructed(ConstructedConstant constant) {
- return new jsAst.New(
- new jsAst.VariableUse(getJsConstructor(constant.type.element)),
+ js.Expression visitConstructed(ConstructedConstant constant) {
+ return new js.New(
+ new js.VariableUse(getJsConstructor(constant.type.element)),
_array(constant.fields));
}
- List<jsAst.Expression> _array(List<Constant> values) {
- List<jsAst.Expression> valueList = <jsAst.Expression>[];
+ List<js.Expression> _array(List<Constant> values) {
+ List<js.Expression> valueList = <js.Expression>[];
for (int i = 0; i < values.length; i++) {
valueList.add(_reference(values[i]));
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index c91a3c3..b238df6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -27,22 +27,20 @@
/**
* A convenient type alias for some functions that emit keyed values.
*/
-typedef void DefineStubFunction(String invocationName, jsAst.Expression value);
+typedef void DefineStubFunction(String invocationName, js.Expression value);
/**
* A data structure for collecting fragments of a class definition.
*/
class ClassBuilder {
- final List<jsAst.Property> properties = <jsAst.Property>[];
+ final List<js.Property> properties = <js.Property>[];
// Has the same signature as [DefineStubFunction].
- void addProperty(String name, jsAst.Expression value) {
- properties.add(new jsAst.Property(js.string(name), value));
+ void addProperty(String name, js.Expression value) {
+ properties.add(new js.Property(js.string(name), value));
}
- jsAst.Expression toObjectInitializer() {
- return new jsAst.ObjectInitializer(properties);
- }
+ js.Expression toObjectInitializer() => new js.ObjectInitializer(properties);
}
/**
@@ -128,11 +126,11 @@
});
}
- jsAst.Expression constantReference(Constant value) {
+ js.Expression constantReference(Constant value) {
return constantEmitter.reference(value);
}
- jsAst.Expression constantInitializerExpression(Constant value) {
+ js.Expression constantInitializerExpression(Constant value) {
return constantEmitter.initializationExpression(value);
}
@@ -174,100 +172,42 @@
const GETTER_SETTER_CODE = 0x3d;
const GETTER_CODE = 0x3e;
const RENAMING_FLAG = 0x40;
+ String needsGetterCode(String variable) => '($variable & 3) > 0';
+ String needsSetterCode(String variable) => '($variable & 2) == 0';
+ String isRenaming(String variable) => '($variable & $RENAMING_FLAG) != 0';
- jsAst.Expression needsGetterCode(String variable) {
- // ($variable & 3) > 0
- return (js[variable] & 3) > 0;
+ String get generateAccessorFunction {
+ return """
+function generateAccessor(field, prototype) {
+ var len = field.length;
+ var lastCharCode = field.charCodeAt(len - 1);
+ var needsAccessor = (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE;
+ if (needsAccessor) {
+ var needsGetter = ${needsGetterCode('lastCharCode')};
+ var needsSetter = ${needsSetterCode('lastCharCode')};
+ var renaming = ${isRenaming('lastCharCode')};
+ var accessorName = field = field.substring(0, len - 1);
+ if (renaming) {
+ var divider = field.indexOf(":");
+ accessorName = field.substring(0, divider);
+ field = field.substring(divider + 1);
+ }
+ if (needsGetter) {
+ var getterString = "return this." + field + ";";
+ prototype["${namer.getterPrefix}" + accessorName] =
+ new Function(getterString);
+ }
+ if (needsSetter) {
+ var setterString = "this." + field + " = v;";
+ prototype["${namer.setterPrefix}" + accessorName] =
+ new Function("v", setterString);
+ }
+ }
+ return field;
+}""";
}
- jsAst.Expression needsSetterCode(String variable) {
- // ($variable & 2) == 0
- return (js[variable] & 2).equals(0);
- }
-
- jsAst.Expression isRenaming(String variable) {
- // ($variable & $RENAMING_FLAG) != 0
- return (js[variable] & RENAMING_FLAG).notEquals(0);
- }
-
- jsAst.FunctionDeclaration get generateAccessorFunction {
- // function generateAccessor(field, prototype) {
- jsAst.Fun fun = js.fun(['field', 'prototype'], [
-
- // var len = field.length;
- js['len'].def(js['field']['length']),
-
- // var lastCharCode = field.charCodeAt(len - 1);
- js['lastCharCode'].def(js['field']['charCodeAt'](js['len'] - 1)),
-
- // var needsAccessor =
- // (lastCharCode & $SUFFIX_MASK) >= $FIRST_SUFFIX_CODE;
- js['needsAccessor'].def(
- (js['lastCharCode'] & SUFFIX_MASK) >= FIRST_SUFFIX_CODE),
-
- // if (needsAccessor) {
- js.if_('needsAccessor', [
- // var needsGetter = ${needsGetterCode('lastCharCode')};
- js['needsGetter'].def(needsGetterCode('lastCharCode')),
-
- // var needsSetter = ${needsSetterCode('lastCharCode')};
- js['needsSetter'].def(needsSetterCode('lastCharCode')),
-
- // var renaming = ${isRenaming('lastCharCode')};
- js['renaming'].def(isRenaming('lastCharCode')),
-
- // var accessorName = field = field.substring(0, len - 1);
- js['accessorName'].def(
- js['field'].assign(js['field']['substring']([0, js['len'] - 1]))),
-
- // if (renaming) {
- js.if_('renaming', [
- // var divider = field.indexOf(":");
- js['divider'].def(js['field']['indexOf'](js.string(':'))),
-
- // accessorName = field.substring(0, divider);
- js['accessorName'].assign(js['field']['substring']([0, 'divider'])),
-
- // field = field.substring(divider + 1);
- js['field'].assign(js['field']['substring'](js['divider'] + 1))
- ]),
-
- // if (needsGetter) {
- js.if_('needsGetter', [
- // var getterString = "return this." + field + ";";
- js['getterString'].def(js.string('return this.') + 'field'),
-
- // prototype["${namer.getterPrefix}" + accessorName] =
- // new Function(getterString);
- js['prototype'][js.string(namer.getterPrefix) + 'accessorName']
- .assign(js['Function'].newWith([js['getterString']]))
- ]),
-
- // if (needsSetter) {
- js.if_('needsSetter', [
- // var setterString = "this." + field + " = v;";
- js['setterString'].def(
- js.string('this.') + 'field' + js.string('$_=${_}v')),
-
- // prototype["${namer.setterPrefix}" + accessorName] =
- // new Function("v", setterString);
- js['prototype'][js.string(namer.setterPrefix) + 'accessorName']
- .assign(js['Function'].newWith([js.string('v'),
- js['setterString']]))
- ]),
-
- ]),
-
- // return field;
- js.return_('field')
- ]);
-
- return new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('generateAccessor'),
- fun);
- }
-
- jsAst.Fun get defineClassFunction {
+ String get defineClassFunction {
// First the class name, then the field names in an array and the members
// (inside an Object literal).
// The caller can also pass in the constructor as a function if needed.
@@ -281,68 +221,33 @@
// this.x = t - v;
// },
// });
-
- // function(cls, fields, prototype) {
- return js.fun(['cls', 'fields', 'prototype'], [
-
- // var constructor;
- js['constructor'].def(),
-
- // if (typeof fields == 'function') {
- js.if_(js['fields'].typeof.equals(js.string('function')), [
- // constructor = fields;
- js['constructor'].assign('fields')
- ], /* else */ [
- // var str = "function " + cls + "(";
- js['str'].def(js.string('function ') + 'cls' + js.string('(')),
-
- // var body = "";
- js['body'].def(js.string('')),
-
- // for (var i = 0; i < fields.length; i++) {
- js.for_(js['i'].def(0),
- js['i'] < js['fields']['length'],
- js['i'].plusPlus, [
- // if (i != 0) str += ", ";
- js.if_(js['i'].notEquals(0), js['str'].update('+', js.string(', '))),
-
- // var field = fields[i];
- js['field'].def(js['fields'][js['i']]),
-
- // field = generateAccessor(field, prototype);
- js['field'].assign(js['generateAccessor'](['field', 'prototype'])),
-
- // str += field;
- js['str'].update('+', 'field'),
-
- // body += "this." + field + " = " + field + ";\\n";
- js['body'].update('+',
- js.string('this.') + 'field' + js.string(" = ") +
- 'field' + js.string(r';\n'))
- ]),
-
- // str += ") {" + body + "}\\nreturn " + cls;
- js['str'].update(
- '+',
- js.string(') {') + 'body' + js.string(r'}\nreturn ') + 'cls'),
-
- // constructor = new Function(str)();
- js['constructor'].assign(js['Function'].newWith([js['str']])())
- ]),
-
- // constructor.prototype = prototype;
- js['constructor']['prototype'].assign('prototype'),
-
- // constructor.builtin\$cls = cls;
- js['constructor'][r'builtin$cls'].assign('cls'),
-
- // return constructor;
- js.return_('constructor')
- ]);
+ return """
+function(cls, fields, prototype) {
+ var constructor;
+ if (typeof fields == 'function') {
+ constructor = fields;
+ } else {
+ var str = "function " + cls + "(";
+ var body = "";
+ for (var i = 0; i < fields.length; i++) {
+ if (i != 0) str += ", ";
+ var field = fields[i];
+ field = generateAccessor(field, prototype);
+ str += field;
+ body += "this." + field + " = " + field + ";\\n";
+ }
+ str += ") {" + body + "}\\n";
+ str += "return " + cls + ";";
+ constructor = new Function(str)();
+ }
+ constructor.prototype = prototype;
+ constructor.builtin\$cls = cls;
+ return constructor;
+}""";
}
/** Needs defineClass to be defined. */
- List buildProtoSupportCheck() {
+ String get protoSupportCheck {
// On Firefox and Webkit browsers we can manipulate the __proto__
// directly. Opera claims to have __proto__ support, but it is buggy.
// So we have to do more checks.
@@ -351,33 +256,18 @@
// If the browser does not support __proto__ we need to instantiate an
// object with the correct (internal) prototype set up correctly, and then
// copy the members.
- // TODO(8541): Remove this work around.
- return [
- // var $supportsProtoName = false;
- js[supportsProtoName].def(false),
-
- // var tmp = $defineClassName('c', ['f?'], {}).prototype;
- js['tmp'].def(
- js[defineClassName](
- [js.string('c'),
- new jsAst.ArrayInitializer.from([js.string('f?')]),
- {}])['prototype']),
-
- // if (tmp.__proto__) {
- js.if_(js['tmp']['__proto__'], [
- // tmp.__proto__ = {};
- js['tmp']['__proto__'].assign({}),
-
- // if (typeof tmp.get\$f != 'undefined') $supportsProtoName = true;
- js.if_(js['tmp'][r'get$f'].typeof.notEquals(js.string('undefined')),
- js[supportsProtoName].assign(true))
-
- ])
- ];
+ return '''
+var $supportsProtoName = false;
+var tmp = $defineClassName('c', ['f?'], {}).prototype;
+if (tmp.__proto__) {
+ tmp.__proto__ = {};
+ if (typeof tmp.get\$f !== 'undefined') $supportsProtoName = true;
+}
+''';
}
- jsAst.Fun get finishClassesFunction {
+ String get finishClassesFunction {
// 'defineClass' does not require the classes to be constructed in order.
// Classes are initially just stored in the 'pendingClasses' field.
// 'finishClasses' takes all pending classes and sets up the prototype.
@@ -390,171 +280,67 @@
// For engines where we have access to the '__proto__' we can manipulate
// the object literal directly. For other engines we have to create a new
// object and copy over the members.
-
- // function(collectedClasses) {
- return js.fun(['collectedClasses'], [
-
- // var hasOwnProperty = Object.prototype.hasOwnProperty;
- js['hasOwnProperty'].def(js['Object']['prototype']['hasOwnProperty']),
-
- // for (var cls in collectedClasses) {
- js.forIn('cls', 'collectedClasses', [
- // if (hasOwnProperty.call(collectedClasses, cls)) {
- js.if_(js['hasOwnProperty']['call'](['collectedClasses', 'cls']),[
-
- // var desc = collectedClasses[cls];
- js['desc'].def(js['collectedClasses'][js['cls']]),
-
- /* The 'fields' are either a constructor function or a
- * string encoding fields, constructor and superclass. Get
- * the superclass and the fields in the format
- * Super;field1,field2 from the null-string property on the
- * descriptor.
- */
- // var fields = desc[''], supr;
- (() {
- var fields = js['desc'][''];
- var supr = js['supr'].def(null).declarations.single;
- var fieldsAndSupr = js['fields'].def(fields);
- fieldsAndSupr.declarations.add(supr);
- return fieldsAndSupr;
- })(),
-
- // if (typeof fields == 'string') {
- js.if_(js['fields'].typeof.equals(js.string('string')), [
- // var s = fields.split(';');
- js['s'].def(js['fields']['split'](js.string(';'))),
-
- // supr = s[0];
- js['supr'].assign(js['s'][0]),
-
- // fields = s[1] == '' ? [] : s[1].split(',');
- js['fields'].assign(
- new jsAst.Conditional(
- js['s'][1].equals(js.string('')),
- new jsAst.ArrayInitializer(0, []),
- js['s'][1]['split'](js.string(',')))),
- ], /* else */ [
- // supr = desc['super'];
- js['supr'].assign(js['desc']['super'])
- ]),
-
- // $isolatePropertiesName[cls] = $defineClassName(cls, fields, desc);
- js[isolatePropertiesName][js['cls']].assign(
- js[defineClassName](['cls', 'fields', 'desc'])),
-
- // if (supr) $pendingClassesName[cls] = supr;
- js.if_(js['supr'],
- js[pendingClassesName][js['cls']].assign(js['supr']))
- ])
- ]),
-
-
- // var pendingClasses = $pendingClassesName;
- js['pendingClasses'].def(js[pendingClassesName]),
-
- /* FinishClasses can be called multiple times. This means that we need to
- clear the pendingClasses property. */
- // $pendingClassesName = {};
- js[pendingClassesName].assign({}),
-
- // var finishedClasses = {};
- js['finishedClasses'].def({}),
-
- // function finishClass(cls) { ... }
- buildFinishClass(),
-
- // for (var cls in pendingClasses) finishClass(cls);
- js.forIn('cls', 'pendingClasses', js['finishClass']('cls'))
- ]);
+ return '''
+function(collectedClasses) {
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ for (var cls in collectedClasses) {
+ if (hasOwnProperty.call(collectedClasses, cls)) {
+ var desc = collectedClasses[cls];
+'''/* The 'fields' are either a constructor function or a string encoding
+ fields, constructor and superclass. Get the superclass and the fields
+ in the format Super;field1,field2 from the null-string property on the
+ descriptor. */'''
+ var fields = desc[''], supr;
+ if (typeof fields == 'string') {
+ var s = fields.split(';'); supr = s[0];
+ fields = s[1] == '' ? [] : s[1].split(',');
+ } else {
+ supr = desc['super'];
+ }
+ $isolatePropertiesName[cls] = $defineClassName(cls, fields, desc);
+ if (supr) $pendingClassesName[cls] = supr;
+ }
+ }
+ var pendingClasses = $pendingClassesName;
+'''/* FinishClasses can be called multiple times. This means that we need to
+ clear the pendingClasses property. */'''
+ $pendingClassesName = {};
+ var finishedClasses = {};
+ function finishClass(cls) {
+'''/* Opera does not support 'getOwnPropertyNames'. Therefore we use
+ hasOwnProperty instead. */'''
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ if (hasOwnProperty.call(finishedClasses, cls)) return;
+ finishedClasses[cls] = true;
+ var superclass = pendingClasses[cls];
+'''/* The superclass is only false (empty string) for Dart's Object class. */'''
+ if (!superclass) return;
+ finishClass(superclass);
+ var constructor = $isolatePropertiesName[cls];
+ var superConstructor = $isolatePropertiesName[superclass];
+ var prototype = constructor.prototype;
+ if ($supportsProtoName) {
+ prototype.__proto__ = superConstructor.prototype;
+ prototype.constructor = constructor;
+ } else {
+ function tmp() {};
+ tmp.prototype = superConstructor.prototype;
+ var newPrototype = new tmp();
+ constructor.prototype = newPrototype;
+ newPrototype.constructor = constructor;
+ for (var member in prototype) {
+ if (!member) continue; '''/* Short version of: if (member == '') */'''
+ if (hasOwnProperty.call(prototype, member)) {
+ newPrototype[member] = prototype[member];
+ }
+ }
+ }
+ }
+ for (var cls in pendingClasses) finishClass(cls);
+}''';
}
- jsAst.FunctionDeclaration buildFinishClass() {
- // function finishClass(cls) {
- jsAst.Fun fun = js.fun(['cls'], [
-
- // TODO(8540): Remove this work around.
- /* Opera does not support 'getOwnPropertyNames'. Therefore we use
- hasOwnProperty instead. */
-
- // var hasOwnProperty = Object.prototype.hasOwnProperty;
- js['hasOwnProperty'].def(js['Object']['prototype']['hasOwnProperty']),
-
- // if (hasOwnProperty.call(finishedClasses, cls)) return;
- js.if_(js['hasOwnProperty']['call'](['finishedClasses', 'cls']),
- js.return_()),
-
- // finishedClasses[cls] = true;
- js['finishedClasses'][js['cls']].assign(true),
-
- // var superclass = pendingClasses[cls];
- js['superclass'].def(js['pendingClasses'][js['cls']]),
-
- /* The superclass is only false (empty string) for Dart's Object class. */
- // if (!superclass) return;
- js.if_(js['superclass'].not, js.return_()),
-
- // finishClass(superclass);
- js['finishClass']('superclass'),
-
- // var constructor = $isolatePropertiesName[cls];
- js['constructor'].def(js[isolatePropertiesName][js['cls']]),
-
- // var superConstructor = $isolatePropertiesName[superclass];
- js['superConstructor'].def(js[isolatePropertiesName][js['superclass']]),
-
- // var prototype = constructor.prototype;
- js['prototype'].def(js['constructor']['prototype']),
-
- // if ($supportsProtoName) {
- js.if_(supportsProtoName, [
- // prototype.__proto__ = superConstructor.prototype;
- js['prototype']['__proto__'].assign(js['superConstructor']['prototype']),
-
- // prototype.constructor = constructor;
- js['prototype']['constructor'].assign('constructor')
-
- ], /* else */ [
- // function tmp() {};
- new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('tmp'),
- js.fun([], [])),
-
- // tmp.prototype = superConstructor.prototype;
- js['tmp']['prototype'].assign(js['superConstructor']['prototype']),
-
- // var newPrototype = new tmp();
- js['newPrototype'].def(js['tmp'].newWith([])),
-
- // constructor.prototype = newPrototype;
- js['constructor']['prototype'].assign('newPrototype'),
-
- // newPrototype.constructor = constructor;
- js['newPrototype']['constructor'].assign('constructor'),
-
- // for (var member in prototype) {
- js.forIn('member', 'prototype', [
- /* Short version of: if (member == '') */
- // if (!member) continue;
- js.if_(js['member'].not, new jsAst.Continue(null)),
-
- // if (hasOwnProperty.call(prototype, member)) {
- js.if_(js['hasOwnProperty']['call'](['prototype', 'member']), [
- // newPrototype[member] = prototype[member];
- js['newPrototype'][js['member']].assign(
- js['prototype'][js['member']])
- ])
- ])
-
- ])
- ]);
-
- return new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('finishClass'),
- fun);
- }
-
- jsAst.Fun get finishIsolateConstructorFunction {
+ String get finishIsolateConstructorFunction {
String isolate = namer.isolateName;
// We replace the old Isolate function with a new one that initializes
// all its field with the initial (and often final) value of all globals.
@@ -576,178 +362,91 @@
//
// We also copy over old values like the prototype, and the
// isolateProperties themselves.
-
- // function(oldIsolate) {
- return js.fun('oldIsolate', [
- // var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
- js['isolateProperties'].def(
- js['oldIsolate'][namer.isolatePropertiesName]),
-
- // var isolatePrototype = oldIsolate.prototype;
- js['isolatePrototype'].def(js['oldIsolate']['prototype']),
-
- // var str = "{\\n";
- js['str'].def(js.string(r'{\n')),
-
- // str += "var properties = $isolate.${namer.isolatePropertiesName};\\n";
- js['str'].update('+', js.string('var properties = '
- '$isolate.${namer.isolatePropertiesName};'
- r'\n')),
-
- // var hasOwnProperty = Object.prototype.hasOwnProperty;
- js['hasOwnProperty'].def(js['Object']['prototype']['hasOwnProperty']),
-
- // for (var staticName in isolateProperties) {
- js.forIn('staticName', 'isolateProperties', [
-
- // if (hasOwnProperty.call(isolateProperties, staticName)) {
- js.if_(js['hasOwnProperty']['call'](['isolateProperties',
- 'staticName']), [
-
- //str += "this." + staticName + "= properties." + staticName + ";\\n";
- js['str'].update(
- '+',
- js.string("this.") + 'staticName' + js.string("= properties.") +
- 'staticName' + js.string(r';\n'))
- ])
- ]),
-
- // str += "}\\n";
- js['str'].update('+', js.string(r'}\n')),
-
- // var newIsolate = new Function(str);
- js['newIsolate'].def(js['Function'].newWith([js['str']])),
-
- // newIsolate.prototype = isolatePrototype;
- js['newIsolate']['prototype'].assign('isolatePrototype'),
-
- // isolatePrototype.constructor = newIsolate;
- js['isolatePrototype']['constructor'].assign('newIsolate'),
-
- // newIsolate.${namer.isolatePropertiesName} = isolateProperties;
- js['newIsolate'][namer.isolatePropertiesName].assign('isolateProperties'),
-
- // return newIsolate;
- js.return_('newIsolate')
- ]);
+ return """function(oldIsolate) {
+ var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
+ var isolatePrototype = oldIsolate.prototype;
+ var str = "{\\n";
+ str += "var properties = $isolate.${namer.isolatePropertiesName};\\n";
+ for (var staticName in isolateProperties) {
+ if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
+ str += "this." + staticName + "= properties." + staticName + ";\\n";
+ }
+ }
+ str += "}\\n";
+ var newIsolate = new Function(str);
+ newIsolate.prototype = isolatePrototype;
+ isolatePrototype.constructor = newIsolate;
+ newIsolate.${namer.isolatePropertiesName} = isolateProperties;
+ return newIsolate;
+}""";
}
- jsAst.Fun get lazyInitializerFunction {
+ String get lazyInitializerFunction {
String isolate = namer.CURRENT_ISOLATE;
-
- // function(prototype, staticName, fieldName, getterName, lazyValue) {
- var parameters = <String>['prototype', 'staticName', 'fieldName',
- 'getterName', 'lazyValue'];
- return js.fun(parameters, [
- // var getter = new Function("{ return $isolate." + fieldName + ";}");
- js['getter'].def(js['Function'].newWith([
- js.string("{ return $isolate.") + 'fieldName' + js.string('}')]))
- ]..addAll(addLazyInitializerLogic())
- );
+ return """
+function(prototype, staticName, fieldName, getterName, lazyValue) {
+ var getter = new Function("{ return $isolate." + fieldName + ";}");
+$lazyInitializerLogic
+}""";
}
- List addLazyInitializerLogic() {
+ String get lazyInitializerLogic {
String isolate = namer.CURRENT_ISOLATE;
JavaScriptBackend backend = compiler.backend;
String cyclicThrow = namer.isolateAccess(backend.cyclicThrowHelper);
-
- return [
- // var sentinelUndefined = {};
- js['sentinelUndefined'].def({}),
-
- // var sentinelInProgress = {};
- js['sentinelInProgress'].def({}),
-
- // prototype[fieldName] = sentinelUndefined;
- js['prototype'][js['fieldName']].assign('sentinelUndefined'),
-
- // prototype[getterName] = function() {
- js['prototype'][js['getterName']].assign(js.fun([], [
- // var result = $isolate[fieldName];
- js['result'].def(js[isolate][js['fieldName']]),
-
- // try {
- js.try_([
- // if (result === sentinelUndefined) {
- js.if_(js['result'].strictEquals('sentinelUndefined'), [
-
- // $isolate[fieldName] = sentinelInProgress;
- js[isolate][js['fieldName']].assign('sentinelInProgress'),
-
- // try {
- js.try_([
- // result = $isolate[fieldName] = lazyValue();
- js['result'].assign(
- js[isolate][js['fieldName']].assign(js['lazyValue']()))
-
- ], finallyPart: [
- // Use try-finally, not try-catch/throw as it destroys the
- // stack trace.
-
- // if (result === sentinelUndefined) {
- js.if_(js['result'].strictEquals('sentinelUndefined'), [
- // if ($isolate[fieldName] === sentinelInProgress) {
- js.if_(js[isolate][js['fieldName']]
- .strictEquals('sentinelInProgress'), [
-
- // $isolate[fieldName] = null;
- js[isolate][js['fieldName']].assign(new jsAst.LiteralNull())
- ])
- ])
- ])
- ], /* else */ [
- // } else if (result === sentinelInProgress) {
- js.if_(js['result'].strictEquals('sentinelInProgress'),
- // $cyclicThrow(staticName);
- js[cyclicThrow]('staticName')
- )
- ]),
-
- // return result;
- js.return_('result')
-
- ], finallyPart: [
- // $isolate[getterName] = getter;
- js[isolate][js['getterName']].assign('getter')
- ])
- ]))
- ];
+ return """
+ var sentinelUndefined = {};
+ var sentinelInProgress = {};
+ prototype[fieldName] = sentinelUndefined;
+ prototype[getterName] = function() {
+ var result = $isolate[fieldName];
+ try {
+ if (result === sentinelUndefined) {
+ $isolate[fieldName] = sentinelInProgress;
+ try {
+ result = $isolate[fieldName] = lazyValue();
+ } finally {
+""" // Use try-finally, not try-catch/throw as it destroys the stack trace.
+"""
+ if (result === sentinelUndefined) {
+ if ($isolate[fieldName] === sentinelInProgress) {
+ $isolate[fieldName] = null;
+ }
+ }
+ }
+ } else if (result === sentinelInProgress) {
+ $cyclicThrow(staticName);
+ }
+ return result;
+ } finally {
+ $isolate[getterName] = getter;
+ }
+ };""";
}
- List buildDefineClassAndFinishClassFunctionsIfNecessary() {
- if (!needsDefineClass) return [];
- return [
- // Declare a function called "generateAccessor". This is used in
+ void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) {
+ if (needsDefineClass) {
+ // Declare function called generateAccessor. This is used in
// defineClassFunction (it's a local declaration in init()).
- generateAccessorFunction,
-
- // $generateAccessorHolder = generateAccessor;
- js[generateAccessorHolder].assign('generateAccessor'),
-
- // $defineClassName = $defineClassFunction;
- js[defineClassName].assign(defineClassFunction)
- ]
- ..addAll(buildProtoSupportCheck())
- ..addAll([
- // $pendingClassesName = {};
- js[pendingClassesName].assign({}),
-
- js[finishClassesName].assign(finishClassesFunction)
- ]);
+ buffer.add("$generateAccessorFunction$N");
+ buffer.add("$generateAccessorHolder = generateAccessor$N");
+ buffer.add("$defineClassName = $defineClassFunction$N");
+ buffer.add(protoSupportCheck);
+ buffer.add("$pendingClassesName = {}$N");
+ buffer.add("$finishClassesName = $finishClassesFunction$N");
+ }
}
- List buildLazyInitializerFunctionIfNecessary() {
- if (!needsLazyInitializer) return [];
-
- // $lazyInitializerName = $lazyInitializerFunction
- return [js[lazyInitializerName].assign(lazyInitializerFunction)];
+ void addLazyInitializerFunctionIfNecessary(CodeBuffer buffer) {
+ if (needsLazyInitializer) {
+ buffer.add("$lazyInitializerName = $lazyInitializerFunction$N");
+ }
}
- List buildFinishIsolateConstructor() {
- return [
- // $finishIsolateConstructorName = $finishIsolateConstructorFunction
- js[finishIsolateConstructorName].assign(finishIsolateConstructorFunction)
- ];
+ void emitFinishIsolateConstructor(CodeBuffer buffer) {
+ String name = finishIsolateConstructorName;
+ String value = finishIsolateConstructorFunction;
+ buffer.add("$name = $value$N");
}
void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) {
@@ -800,19 +499,19 @@
String receiverArgumentName = r'$receiver';
// The parameters that this stub takes.
- List<jsAst.Parameter> parametersBuffer =
- new List<jsAst.Parameter>.fixedLength(
+ List<js.Parameter> parametersBuffer =
+ new List<js.Parameter>.fixedLength(
selector.argumentCount + extraArgumentCount);
// The arguments that will be passed to the real method.
- List<jsAst.Expression> argumentsBuffer =
- new List<jsAst.Expression>.fixedLength(
+ List<js.Expression> argumentsBuffer =
+ new List<js.Expression>.fixedLength(
parameters.parameterCount + extraArgumentCount);
int count = 0;
if (isInterceptorClass) {
count++;
- parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
- argumentsBuffer[0] = js[receiverArgumentName];
+ parametersBuffer[0] = new js.Parameter(receiverArgumentName);
+ argumentsBuffer[0] = new js.VariableUse(receiverArgumentName);
}
int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1;
@@ -824,17 +523,17 @@
assert(jsName != receiverArgumentName);
int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
if (count < optionalParameterStart) {
- parametersBuffer[count] = new jsAst.Parameter(jsName);
- argumentsBuffer[count] = js[jsName];
+ parametersBuffer[count] = new js.Parameter(jsName);
+ argumentsBuffer[count] = new js.VariableUse(jsName);
} else {
int index = names.indexOf(element.name);
if (index != -1) {
indexOfLastOptionalArgumentInParameters = count;
// The order of the named arguments is not the same as the
// one in the real method (which is in Dart source order).
- argumentsBuffer[count] = js[jsName];
+ argumentsBuffer[count] = new js.VariableUse(jsName);
parametersBuffer[optionalParameterStart + index] =
- new jsAst.Parameter(jsName);
+ new js.Parameter(jsName);
// Note that [elements] may be null for a synthesized [member].
} else if (elements != null && elements.isParameterChecked(element)) {
argumentsBuffer[count] = constantReference(SentinelConstant.SENTINEL);
@@ -855,16 +554,20 @@
count++;
});
- List body;
+ List<js.Statement> body;
if (member.hasFixedBackendName()) {
body = nativeEmitter.generateParameterStubStatements(
member, invocationName, parametersBuffer, argumentsBuffer,
indexOfLastOptionalArgumentInParameters);
} else {
- body = [js.return_(js['this'][namer.getName(member)](argumentsBuffer))];
+ body = <js.Statement>[
+ new js.Return(
+ new js.VariableUse('this')
+ .dot(namer.getName(member))
+ .callWith(argumentsBuffer))];
}
- jsAst.Fun function = js.fun(parametersBuffer, body);
+ js.Fun function = new js.Fun(parametersBuffer, new js.Block(body));
defineStub(invocationName, function);
}
@@ -1023,7 +726,7 @@
|| member.isAccessor()) {
if (member.isAbstract(compiler)) return;
JavaScriptBackend backend = compiler.backend;
- jsAst.Expression code = backend.generatedCode[member];
+ js.Expression code = backend.generatedCode[member];
if (code == null) return;
builder.addProperty(namer.getName(member), code);
code = backend.generatedBailoutCode[member];
@@ -1085,12 +788,12 @@
includeSuperMembers: false);
void generateIsTest(Element other) {
- jsAst.Expression code;
+ js.Expression code;
if (compiler.objectClass == other) return;
if (nativeEmitter.requiresNativeIsCheck(other)) {
- code = js.fun([], [js.return_(true)]);
+ code = js.fun([], js.block1(js.return_(new js.LiteralBool(true))));
} else {
- code = new jsAst.LiteralBool(true);
+ code = new js.LiteralBool(true);
}
builder.addProperty(namer.operatorIs(other), code);
}
@@ -1098,20 +801,21 @@
void generateSubstitution(Element other, {bool emitNull: false}) {
RuntimeTypeInformation rti = backend.rti;
// TODO(karlklose): support typedefs with variables.
- jsAst.Expression expression;
+ js.Expression expression;
bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other);
if (other.kind == ElementKind.CLASS) {
String substitution = rti.getSupertypeSubstitution(classElement, other,
alwaysGenerateFunction: true);
if (substitution != null) {
- expression = new jsAst.LiteralExpression(substitution);
+ expression = new js.LiteralExpression(substitution);
} else if (emitNull || needsNativeCheck) {
- expression = new jsAst.LiteralNull();
+ expression = new js.LiteralNull();
}
}
if (expression != null) {
if (needsNativeCheck) {
- expression = js.fun([], js.return_(expression));
+ expression =
+ new js.Fun([], new js.Block([new js.Return(expression)]));
}
builder.addProperty(namer.substitutionName(other), expression);
}
@@ -1143,7 +847,7 @@
? js.equals
: js.strictEquals;
builder.addProperty(name, js.fun(['receiver', 'a'],
- js.block(js.return_(kind(js['receiver'], js['a'])))));
+ js.block1(js.return_(kind(js.use('receiver'), js.use('a'))))));
}
}
@@ -1305,14 +1009,17 @@
ClassBuilder builder) {
String getterName = namer.getterNameFromAccessorName(accessorName);
builder.addProperty(getterName,
- js.fun([], js.return_(js['this'][fieldName])));
+ js.fun([], js.block1(js.return_(js.use('this').dot(fieldName)))));
}
void generateSetter(Element member, String fieldName, String accessorName,
ClassBuilder builder) {
String setterName = namer.setterNameFromAccessorName(accessorName);
builder.addProperty(setterName,
- js.fun(['v'], js['this'][fieldName].assign('v')));
+ js.fun(['v'],
+ js.block1(
+ new js.ExpressionStatement(
+ js.assign(js.use('this').dot(fieldName), js.use('v'))))));
}
bool canGenerateCheckedSetter(Element member) {
@@ -1337,14 +1044,19 @@
SourceString helper = compiler.backend.getCheckedModeHelper(type);
FunctionElement helperElement = compiler.findHelper(helper);
String helperName = namer.isolateAccess(helperElement);
- List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']];
+ List<js.Expression> arguments = <js.Expression>[js.use('v')];
if (helperElement.computeSignature(compiler).parameterCount != 1) {
arguments.add(js.string(namer.operatorIs(type.element)));
}
String setterName = namer.setterNameFromAccessorName(accessorName);
builder.addProperty(setterName,
- js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments))));
+ js.fun(['v'],
+ js.block1(
+ new js.ExpressionStatement(
+ js.assign(
+ js.use('this').dot(fieldName),
+ js.call(js.use(helperName), arguments))))));
}
void emitClassConstructor(ClassElement classElement, ClassBuilder builder) {
@@ -1476,9 +1188,11 @@
emitClassGettersSetters(classElement, builder);
emitInstanceMembers(classElement, builder);
- jsAst.Expression init =
- js[classesCollector][className].assign(builder.toObjectInitializer());
- buffer.add(jsAst.prettyPrint(init, compiler));
+ js.Expression init =
+ js.assign(
+ js.use(classesCollector).dot(className),
+ builder.toObjectInitializer());
+ buffer.add(js.prettyPrint(init, compiler));
buffer.add('$N$n');
}
@@ -1504,23 +1218,29 @@
// emit all possible sends on intercepted methods.
for (Selector selector in
backend.usedInterceptors.toList()..sort(_compareSelectorNames)) {
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- parameters.add(new jsAst.Parameter('receiver'));
+ List<js.Parameter> parameters = <js.Parameter>[];
+ List<js.Expression> arguments = <js.Expression>[];
+ parameters.add(new js.Parameter('receiver'));
String name = backend.namer.invocationName(selector);
if (selector.isSetter()) {
- parameters.add(new jsAst.Parameter('value'));
- arguments.add(js['value']);
+ parameters.add(new js.Parameter('value'));
+ arguments.add(new js.VariableUse('value'));
} else {
for (int i = 0; i < selector.argumentCount; i++) {
String argName = 'a$i';
- parameters.add(new jsAst.Parameter(argName));
- arguments.add(js[argName]);
+ parameters.add(new js.Parameter(argName));
+ arguments.add(new js.VariableUse(argName));
}
}
- jsAst.Fun function =
- js.fun(parameters, js.return_(js['receiver'][name](arguments)));
+ js.Fun function =
+ new js.Fun(parameters,
+ new js.Block(
+ <js.Statement>[
+ new js.Return(
+ new js.VariableUse('receiver')
+ .dot(name)
+ .callWith(arguments))]));
builder.addProperty(name, function);
}
}
@@ -1750,10 +1470,10 @@
void emitStaticFunction(CodeBuffer buffer,
String name,
- jsAst.Expression functionExpression) {
- jsAst.Expression assignment =
- js[isolateProperties][name].assign(functionExpression);
- buffer.add(jsAst.prettyPrint(assignment, compiler));
+ js.Expression functionExpression) {
+ js.Expression assignment =
+ js.assign(js.use(isolateProperties).dot(name), functionExpression);
+ buffer.add(js.prettyPrint(assignment, compiler));
buffer.add('$N$n');
}
@@ -1770,9 +1490,9 @@
.toSet();
for (Element element in Elements.sortedByPosition(elements)) {
- jsAst.Expression code = backend.generatedCode[element];
+ js.Expression code = backend.generatedCode[element];
emitStaticFunction(buffer, namer.getName(element), code);
- jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
+ js.Expression bailoutCode = backend.generatedBailoutCode[element];
if (bailoutCode != null) {
pendingElementsWithBailouts.remove(element);
emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
@@ -1782,7 +1502,7 @@
// Is it possible the primary function was inlined but the bailout was not?
for (Element element in
Elements.sortedByPosition(pendingElementsWithBailouts)) {
- jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
+ js.Expression bailoutCode = backend.generatedBailoutCode[element];
emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
}
}
@@ -1804,11 +1524,13 @@
String fieldAccess = '$isolateProperties.$staticName';
buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N");
- addParameterStubs(callElement, (String name, jsAst.Expression value) {
- jsAst.Expression assignment =
- js[isolateProperties][staticName][name].assign(value);
+ addParameterStubs(callElement, (String name, js.Expression value) {
+ js.Expression assignment =
+ js.assign(
+ js.use(isolateProperties).dot(staticName).dot(name),
+ value);
buffer.add(
- jsAst.prettyPrint(assignment.toStatement(), compiler));
+ js.prettyPrint(new js.ExpressionStatement(assignment), compiler));
buffer.add('$N');
});
@@ -1927,32 +1649,37 @@
String invocationName = namer.instanceMethodName(callElement);
List<String> parameters = <String>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
+ List<js.Expression> arguments = <js.Expression>[];
if (inInterceptor) {
- arguments.add(js['this'][fieldNames[2]]);
+ arguments.add(js.use('this').dot(fieldNames[2]));
}
for (int i = 0; i < parameterCount; i++) {
String name = 'p$i';
parameters.add(name);
- arguments.add(js[name]);
+ arguments.add(js.use(name));
}
- jsAst.Expression fun = js.fun(
- parameters,
- js.return_(
- js['this'][fieldNames[0]][js['this'][fieldNames[1]]](arguments)));
+ js.Expression fun =
+ js.fun(parameters,
+ js.block1(
+ js.return_(
+ new js.PropertyAccess(
+ js.use('this').dot(fieldNames[0]),
+ js.use('this').dot(fieldNames[1]))
+ .callWith(arguments))));
boundClosureBuilder.addProperty(invocationName, fun);
addParameterStubs(callElement, boundClosureBuilder.addProperty);
typedefChecks.forEach((Element typedef) {
String operator = namer.operatorIs(typedef);
- boundClosureBuilder.addProperty(operator, new jsAst.LiteralBool(true));
+ boundClosureBuilder.addProperty(operator, new js.LiteralBool(true));
});
- jsAst.Expression init =
- js[classesCollector][mangledName].assign(
+ js.Expression init =
+ js.assign(
+ js.use(classesCollector).dot(mangledName),
boundClosureBuilder.toObjectInitializer());
- boundClosureBuffer.add(jsAst.prettyPrint(init, compiler));
+ boundClosureBuffer.add(js.prettyPrint(init, compiler));
boundClosureBuffer.add("$N");
closureClass = namer.isolateAccess(closureClassElement);
@@ -1968,17 +1695,19 @@
String targetName = namer.instanceMethodName(member);
List<String> parameters = <String>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- arguments.add(js['this']);
+ List<js.Expression> arguments = <js.Expression>[];
+ arguments.add(js.use('this'));
arguments.add(js.string(targetName));
if (inInterceptor) {
parameters.add(extraArg);
- arguments.add(js[extraArg]);
+ arguments.add(js.use(extraArg));
}
- jsAst.Expression getterFunction = js.fun(
- parameters,
- js.return_(js[closureClass].newWith(arguments)));
+ js.Expression getterFunction =
+ js.fun(parameters,
+ js.block1(
+ js.return_(
+ new js.New(js.use(closureClass), arguments))));
defineStub(getterName, getterFunction);
}
@@ -2001,18 +1730,18 @@
const String receiverArgumentName = r'$receiver';
- jsAst.Expression buildGetter() {
+ js.Expression buildGetter() {
if (member.isGetter()) {
String getterName = namer.getterName(member);
- return js['this'][getterName](
+ return new js.VariableUse('this').dot(getterName).callWith(
isInterceptorClass
- ? <jsAst.Expression>[js[receiverArgumentName]]
- : <jsAst.Expression>[]);
+ ? <js.Expression>[new js.VariableUse(receiverArgumentName)]
+ : <js.Expression>[]);
} else {
String fieldName = member.hasFixedBackendName()
? member.fixedBackendName()
: namer.instanceFieldName(member);
- return js['this'][fieldName];
+ return new js.VariableUse('this').dot(fieldName);
}
}
@@ -2031,21 +1760,25 @@
Selector callSelector = new Selector.callClosureFrom(selector);
String closureCallName = namer.invocationName(callSelector);
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
+ List<js.Parameter> parameters = <js.Parameter>[];
+ List<js.Expression> arguments = <js.Expression>[];
if (isInterceptorClass) {
- parameters.add(new jsAst.Parameter(receiverArgumentName));
+ parameters.add(new js.Parameter(receiverArgumentName));
}
for (int i = 0; i < selector.argumentCount; i++) {
String name = 'arg$i';
- parameters.add(new jsAst.Parameter(name));
- arguments.add(js[name]);
+ parameters.add(new js.Parameter(name));
+ arguments.add(new js.VariableUse(name));
}
- jsAst.Fun function = js.fun(
- parameters,
- js.return_(buildGetter()[closureCallName](arguments)));
+ js.Fun function =
+ new js.Fun(parameters,
+ new js.Block(
+ <js.Statement>[
+ new js.Return(
+ buildGetter().dot(closureCallName)
+ .callWith(arguments))]));
defineStub(invocationName, function);
}
@@ -2059,10 +1792,13 @@
for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
compiler.withCurrentElement(element, () {
Constant initialValue = handler.getInitialValueFor(element);
- jsAst.Expression init =
- js[isolateProperties][namer.getName(element)].assign(
- constantEmitter.referenceInInitializationContext(initialValue));
- buffer.add(jsAst.prettyPrint(init, compiler));
+ js.Expression init =
+ new js.Assignment(
+ new js.PropertyAccess.field(
+ new js.VariableUse(isolateProperties),
+ namer.getName(element)),
+ constantEmitter.referenceInInitializationContext(initialValue));
+ buffer.add(js.prettyPrint(init, compiler));
buffer.add('$N');
});
}
@@ -2077,31 +1813,31 @@
needsLazyInitializer = true;
for (VariableElement element in Elements.sortedByPosition(lazyFields)) {
assert(backend.generatedBailoutCode[element] == null);
- jsAst.Expression code = backend.generatedCode[element];
+ js.Expression code = backend.generatedCode[element];
assert(code != null);
// The code only computes the initial value. We build the lazy-check
// here:
// lazyInitializer(prototype, 'name', fieldName, getterName, initial);
// The name is used for error reporting. The 'initial' must be a
// closure that constructs the initial value.
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- arguments.add(js[isolateProperties]);
+ List<js.Expression> arguments = <js.Expression>[];
+ arguments.add(js.use(isolateProperties));
arguments.add(js.string(element.name.slowToString()));
arguments.add(js.string(namer.getName(element)));
arguments.add(js.string(namer.getLazyInitializerName(element)));
arguments.add(code);
- jsAst.Expression getter = buildLazyInitializedGetter(element);
+ js.Expression getter = buildLazyInitializedGetter(element);
if (getter != null) {
arguments.add(getter);
}
- jsAst.Expression init = js[lazyInitializerName](arguments);
- buffer.add(jsAst.prettyPrint(init, compiler));
+ js.Expression init = js.call(js.use(lazyInitializerName), arguments);
+ buffer.add(js.prettyPrint(init, compiler));
buffer.add("$N");
}
}
}
- jsAst.Expression buildLazyInitializedGetter(VariableElement element) {
+ js.Expression buildLazyInitializedGetter(VariableElement element) {
// Nothing to do, the 'lazy' function will create the getter.
return null;
}
@@ -2125,9 +1861,13 @@
addedMakeConstantList = true;
emitMakeConstantList(buffer);
}
- jsAst.Expression init = js[isolateProperties][name].assign(
- constantInitializerExpression(constant));
- buffer.add(jsAst.prettyPrint(init, compiler));
+ js.Expression init =
+ new js.Assignment(
+ new js.PropertyAccess.field(
+ new js.VariableUse(isolateProperties),
+ name),
+ constantInitializerExpression(constant));
+ buffer.add(js.prettyPrint(init, compiler));
buffer.add('$N');
}
}
@@ -2195,17 +1935,17 @@
return result;
}
- jsAst.Expression generateMethod(String jsName, Selector selector) {
+ js.Expression generateMethod(String jsName, Selector selector) {
// Values match JSInvocationMirror in js-helper library.
int type = selector.invocationMirrorKind;
String methodName = selector.invocationMirrorMemberName;
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
+ List<js.Parameter> parameters = <js.Parameter>[];
CodeBuffer args = new CodeBuffer();
for (int i = 0; i < selector.argumentCount; i++) {
- parameters.add(new jsAst.Parameter('\$$i'));
+ parameters.add(new js.Parameter('\$$i'));
}
- List<jsAst.Expression> argNames =
+ List<js.Expression> argNames =
selector.getOrderedNamedArguments().map((SourceString name) =>
js.string(name.slowToString())).toList();
@@ -2214,15 +1954,26 @@
String createInvocationMirror = namer.getName(
compiler.createInvocationMirrorElement);
- jsAst.Expression expression = js['this'][noSuchMethodName](
- js[namer.CURRENT_ISOLATE][createInvocationMirror]([
- js.string(methodName),
- js.string(internalName),
- type,
- new jsAst.ArrayInitializer.from(
- parameters.map((param) => js[param.name]).toList()),
- new jsAst.ArrayInitializer.from(argNames)]));
- return js.fun(parameters, js.return_(expression));
+ js.Expression expression =
+ new js.This()
+ .dot(noSuchMethodName)
+ .callWith(
+ <js.Expression>[
+ new js.VariableUse(namer.CURRENT_ISOLATE)
+ .dot(createInvocationMirror)
+ .callWith(
+ <js.Expression>[
+ js.string(methodName),
+ js.string(internalName),
+ new js.LiteralNumber('$type'),
+ new js.ArrayInitializer.from(
+ parameters.map((param) => js.use(param.name))
+ .toList()),
+ new js.ArrayInitializer.from(argNames)])]);
+ js.Expression function =
+ new js.Fun(parameters,
+ new js.Block(<js.Statement>[new js.Return(expression)]));
+ return function;
}
void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) {
@@ -2314,7 +2065,7 @@
if (holders.every(hasMatchingMember)) continue;
String jsName = namer.invocationMirrorInternalName(selector);
if (!addedJsNames.contains(jsName)) {
- jsAst.Expression method = generateMethod(jsName, selector);
+ js.Expression method = generateMethod(jsName, selector);
defineStub(jsName, method);
addedJsNames.add(jsName);
}
@@ -2393,34 +2144,36 @@
String objectName,
String key,
Collection<ClassElement> classes) {
- jsAst.Statement buildReturnInterceptor(ClassElement cls) {
- return js.return_(js[namer.isolateAccess(cls)]['prototype']);
+ js.Statement buildReturnInterceptor(ClassElement cls) {
+ return js.return_(js.fieldAccess(js.use(namer.isolateAccess(cls)),
+ 'prototype'));
}
- jsAst.VariableUse receiver = js['receiver'];
+ js.VariableUse receiver = js.use('receiver');
JavaScriptBackend backend = compiler.backend;
/**
* Build a JavaScrit AST node for doing a type check on
* [cls]. [cls] must be an interceptor class.
*/
- jsAst.Statement buildInterceptorCheck(ClassElement cls) {
- jsAst.Expression condition;
+ js.Statement buildInterceptorCheck(ClassElement cls) {
+ js.Expression condition;
assert(backend.isInterceptorClass(cls));
if (cls == backend.jsBoolClass) {
- condition = receiver.typeof.equals(js.string('boolean'));
+ condition = js.equals(js.typeOf(receiver), js.string('boolean'));
} else if (cls == backend.jsIntClass ||
cls == backend.jsDoubleClass ||
cls == backend.jsNumberClass) {
throw 'internal error';
} else if (cls == backend.jsArrayClass) {
- condition = receiver['constructor'].equals('Array');
+ condition = js.equals(js.fieldAccess(receiver, 'constructor'),
+ js.use('Array'));
} else if (cls == backend.jsStringClass) {
- condition = receiver.typeof.equals(js.string('string'));
+ condition = js.equals(js.typeOf(receiver), js.string('string'));
} else if (cls == backend.jsNullClass) {
- condition = receiver.equals(new jsAst.LiteralNull());
+ condition = js.equals(receiver, new js.LiteralNull());
} else if (cls == backend.jsFunctionClass) {
- condition = receiver.typeof.equals(js.string('function'));
+ condition = js.equals(js.typeOf(receiver), js.string('function'));
} else {
throw 'internal error';
}
@@ -2452,28 +2205,31 @@
}
if (hasInt) hasNumber = true;
- jsAst.Block block = new jsAst.Block.empty();
+ js.Block block = new js.Block.empty();
if (hasNumber) {
- jsAst.Statement whenNumber;
+ js.Statement whenNumber;
/// Note: there are two number classes in play: Dart's [num],
/// and JavaScript's Number (typeof receiver == 'number'). This
/// is the fallback used when we have determined that receiver
/// is a JavaScript Number.
- jsAst.Return returnNumberClass = buildReturnInterceptor(
+ js.Return returnNumberClass = buildReturnInterceptor(
hasDouble ? backend.jsDoubleClass : backend.jsNumberClass);
if (hasInt) {
- jsAst.Expression isInt = js['Math']['floor'](receiver).equals(receiver);
- whenNumber = js.block([
- js.if_(isInt, buildReturnInterceptor(backend.jsIntClass)),
- returnNumberClass]);
+ js.Expression isInt =
+ js.equals(js.call(js.fieldAccess(js.use('Math'), 'floor'),
+ [receiver]),
+ receiver);
+ (whenNumber = js.emptyBlock()).statements
+ ..add(js.if_(isInt, buildReturnInterceptor(backend.jsIntClass)))
+ ..add(returnNumberClass);
} else {
whenNumber = returnNumberClass;
}
block.statements.add(
- js.if_(receiver.typeof.equals(js.string('number')),
+ js.if_(js.equals(js.typeOf(receiver), js.string('number')),
whenNumber));
}
@@ -2486,7 +2242,7 @@
// Returning "undefined" here will provoke a JavaScript
// TypeError which is later identified as a null-error by
// [unwrapException] in js_helper.dart.
- block.statements.add(js.if_(receiver.equals(new jsAst.LiteralNull()),
+ block.statements.add(js.if_(js.equals(receiver, new js.LiteralNull()),
js.return_(js.undefined())));
}
if (hasFunction) {
@@ -2500,11 +2256,12 @@
if (hasArray) {
block.statements.add(buildInterceptorCheck(backend.jsArrayClass));
}
- block.statements.add(js.return_(js[objectName]['prototype']));
+ block.statements.add(js.return_(js.fieldAccess(js.use(objectName),
+ 'prototype')));
- buffer.add(jsAst.prettyPrint(
- js[isolateProperties][key].assign(js.fun(['receiver'], block)),
- compiler));
+ js.PropertyAccess name = js.fieldAccess(js.use(isolateProperties), key);
+ buffer.add(js.prettyPrint(js.assign(name, js.fun(['receiver'], block)),
+ compiler));
buffer.add(N);
}
@@ -2564,49 +2321,40 @@
String getInterceptorName =
namer.getInterceptorName(backend.getInterceptorMethod, classes);
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- parameters.add(new jsAst.Parameter('receiver'));
- arguments.add(js['receiver']);
+ List<js.Parameter> parameters = <js.Parameter>[];
+ List<js.Expression> arguments = <js.Expression>[];
+ parameters.add(new js.Parameter('receiver'));
+ arguments.add(js.use('receiver'));
if (selector.isSetter()) {
- parameters.add(new jsAst.Parameter('value'));
- arguments.add(js['value']);
+ parameters.add(new js.Parameter('value'));
+ arguments.add(js.use('value'));
} else {
for (int i = 0; i < selector.argumentCount; i++) {
String argName = 'a$i';
- parameters.add(new jsAst.Parameter(argName));
- arguments.add(js[argName]);
+ parameters.add(new js.Parameter(argName));
+ arguments.add(js.use(argName));
}
}
String invocationName = backend.namer.invocationName(selector);
- jsAst.Fun function = js.fun(parameters, js.return_(
- js[isolateProperties][getInterceptorName]('receiver')[invocationName](
- arguments)));
+ js.Fun function =
+ new js.Fun(parameters,
+ js.block1(js.return_(
+ js.use(isolateProperties)
+ .dot(getInterceptorName)
+ .callWith([js.use('receiver')])
+ .dot(invocationName)
+ .callWith(arguments))));
- jsAst.PropertyAccess property =
- js[isolateProperties][oneShotInterceptorName];
+ js.PropertyAccess property =
+ js.fieldAccess(js.use(isolateProperties), oneShotInterceptorName);
- buffer.add(jsAst.prettyPrint(property.assign(function), compiler));
+ buffer.add(js.prettyPrint(js.assign(property, function), compiler));
buffer.add(N);
}
}
- void emitInitFunction(CodeBuffer buffer) {
- jsAst.Fun fun = js.fun([], [
- // $isolateProperties = {};
- js[isolateProperties].assign({}),
- ]
- ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary())
- ..addAll(buildLazyInitializerFunctionIfNecessary())
- ..addAll(buildFinishIsolateConstructor())
- );
- jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration(
- new jsAst.VariableDeclaration('init'), fun);
- buffer.add(jsAst.prettyPrint(decl, compiler).getText());
- }
-
String assembleProgram() {
measure(() {
computeNeededClasses();
@@ -2656,7 +2404,12 @@
nativeEmitter.assembleCode(mainBuffer);
emitMain(mainBuffer);
- emitInitFunction(mainBuffer);
+ mainBuffer.add('function init()$_{\n');
+ mainBuffer.add('$isolateProperties$_=$_{}$N');
+ addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
+ addLazyInitializerFunctionIfNecessary(mainBuffer);
+ emitFinishIsolateConstructor(mainBuffer);
+ mainBuffer.add('}\n');
compiler.assembledCode = mainBuffer.getText();
if (generateSourceMap) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 8a2f2b8..0bfb5df 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -10,18 +10,15 @@
import '../../compiler.dart' as api;
import '../elements/elements.dart';
import '../elements/modelx.dart' show FunctionElementX;
-
-// TODO(ahe): There seems to be a bug in the VM, so we have to hide "js".
-import '../dart2jslib.dart' hide Selector, js;
+import '../dart2jslib.dart' hide Selector;
import '../dart_types.dart';
-import '../js/js.dart' as jsAst;
-import '../js/js.dart' show js; // TODO(ahe): VM bug, see above.
+import '../js/js.dart' as js;
import '../native_handler.dart' as native;
import '../source_file.dart';
import '../source_map_builder.dart';
-import '../ssa/ssa.dart' hide js; // TODO(ahe): VM bug, see above.
+import '../ssa/ssa.dart';
import '../tree/tree.dart';
-import '../universe/universe.dart' hide js; // TODO(ahe): VM bug, see above.
+import '../universe/universe.dart';
import '../util/characters.dart';
import '../util/util.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 9c96a80..0343457 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -138,11 +138,11 @@
if (builder.properties.isEmpty) return;
String nativeTag = toNativeTag(classElement);
- jsAst.Expression definition =
- js[defineNativeClassName](
- [js.string(nativeTag), builder.toObjectInitializer()]);
+ js.Expression definition =
+ js.call(js.use(defineNativeClassName),
+ [js.string(nativeTag), builder.toObjectInitializer()]);
- nativeBuffer.add(jsAst.prettyPrint(definition, compiler));
+ nativeBuffer.add(js.prettyPrint(definition, compiler));
nativeBuffer.add('$N$n');
classesWithDynamicDispatch.add(classElement);
@@ -153,10 +153,9 @@
return result == null ? const<ClassElement>[] : result;
}
- void potentiallyConvertDartClosuresToJs(
- List<jsAst.Statement> statements,
- FunctionElement member,
- List<jsAst.Parameter> stubParameters) {
+ void potentiallyConvertDartClosuresToJs(List<js.Statement> statements,
+ FunctionElement member,
+ List<js.Parameter> stubParameters) {
FunctionSignature parameters = member.computeSignature(compiler);
Element converter =
compiler.findHelper(const SourceString('convertDartClosureToJS'));
@@ -167,7 +166,7 @@
String name = parameter.name.slowToString();
// If [name] is not in [stubParameters], then the parameter is an optional
// parameter that was not provided for this stub.
- for (jsAst.Parameter stubParameter in stubParameters) {
+ for (js.Parameter stubParameter in stubParameters) {
if (stubParameter.name == name) {
DartType type = parameter.computeType(compiler).unalias(compiler);
if (type is FunctionType) {
@@ -176,12 +175,11 @@
int arity = type.computeArity();
statements.add(
- new jsAst.ExpressionStatement(
+ new js.ExpressionStatement(
js.assign(
- js[name],
- js[closureConverter](
- [js[name],
- new jsAst.LiteralNumber('$arity')]))));
+ js.use(name),
+ js.use(closureConverter).callWith(
+ [js.use(name), new js.LiteralNumber('$arity')]))));
break;
}
}
@@ -189,11 +187,11 @@
});
}
- List<jsAst.Statement> generateParameterStubStatements(
+ List<js.Statement> generateParameterStubStatements(
Element member,
String invocationName,
- List<jsAst.Parameter> stubParameters,
- List<jsAst.Expression> argumentsBuffer,
+ List<js.Parameter> stubParameters,
+ List<js.Expression> argumentsBuffer,
int indexOfLastOptionalArgumentInParameters) {
// The target JS function may check arguments.length so we need to
// make sure not to pass any unspecified optional arguments to it.
@@ -207,11 +205,11 @@
ClassElement classElement = member.enclosingElement;
String nativeTagInfo = classElement.nativeTagInfo.slowToString();
- List<jsAst.Statement> statements = <jsAst.Statement>[];
+ List<js.Statement> statements = <js.Statement>[];
potentiallyConvertDartClosuresToJs(statements, member, stubParameters);
String target;
- List<jsAst.Expression> arguments;
+ List<js.Expression> arguments;
if (!nativeMethods.contains(member)) {
// When calling a method that has a native body, we call it with our
@@ -226,16 +224,16 @@
0, indexOfLastOptionalArgumentInParameters + 1);
}
statements.add(
- new jsAst.Return(
- new jsAst.VariableUse('this')[target](arguments)));
+ new js.Return(
+ new js.VariableUse('this').dot(target).callWith(arguments)));
if (!overriddenMethods.contains(member)) {
// Call the method directly.
return statements;
} else {
- return <jsAst.Statement>[
+ return <js.Statement>[
generateMethodBodyWithPrototypeCheck(
- invocationName, new jsAst.Block(statements), stubParameters)];
+ invocationName, new js.Block(statements), stubParameters)];
}
}
@@ -244,24 +242,26 @@
// super class. If the method is not available, we make a direct call to
// Object.prototype.$methodName. This method will patch the prototype of
// 'this' to the real method.
- jsAst.Statement generateMethodBodyWithPrototypeCheck(
+ js.Statement generateMethodBodyWithPrototypeCheck(
String methodName,
- jsAst.Statement body,
- List<jsAst.Parameter> parameters) {
+ js.Statement body,
+ List<js.Parameter> parameters) {
return js.if_(
- js['Object']['getPrototypeOf']('this')['hasOwnProperty'](
- js.string(methodName)),
+ js.use('Object').dot('getPrototypeOf')
+ .callWith([js.use('this')])
+ .dot('hasOwnProperty').callWith([js.string(methodName)]),
body,
js.return_(
- js['Object']['prototype'][methodName]['call'](
- <jsAst.Expression>[js['this']]..addAll(
- parameters.map((param) => js[param.name])))));
+ js.use('Object').dot('prototype').dot(methodName).dot('call')
+ .callWith(
+ <js.Expression>[js.use('this')]..addAll(
+ parameters.map((param) => js.use(param.name))))));
}
- jsAst.Block generateMethodBodyWithPrototypeCheckForElement(
+ js.Block generateMethodBodyWithPrototypeCheckForElement(
FunctionElement element,
- jsAst.Block body,
- List<jsAst.Parameter> parameters) {
+ js.Block body,
+ List<js.Parameter> parameters) {
ElementKind kind = element.kind;
if (kind != ElementKind.FUNCTION &&
kind != ElementKind.GETTER &&
@@ -270,7 +270,7 @@
}
String methodName = backend.namer.getName(element);
- return new jsAst.Block(
+ return new js.Block(
[generateMethodBodyWithPrototypeCheck(methodName, body, parameters)]);
}
@@ -322,23 +322,23 @@
// Temporary variables for common substrings.
List<String> varNames = <String>[];
// Values of temporary variables.
- Map<String, jsAst.Expression> varDefns = new Map<String, jsAst.Expression>();
+ Map<String, js.Expression> varDefns = new Map<String, js.Expression>();
// Expression to compute tags string for a class. The expression will
// initially be a string or expression building a string, but may be
// replaced with a variable reference to the common substring.
- Map<ClassElement, jsAst.Expression> tagDefns =
- new Map<ClassElement, jsAst.Expression>();
+ Map<ClassElement, js.Expression> tagDefns =
+ new Map<ClassElement, js.Expression>();
- jsAst.Expression makeExpression(ClassElement classElement) {
+ js.Expression makeExpression(ClassElement classElement) {
// Expression fragments for this set of cls keys.
- List<jsAst.Expression> expressions = <jsAst.Expression>[];
+ List<js.Expression> expressions = <js.Expression>[];
// TODO: Remove if cls is abstract.
List<String> subtags = [toNativeTag(classElement)];
void walk(ClassElement cls) {
for (final ClassElement subclass in getDirectSubclasses(cls)) {
ClassElement tag = subclass;
- jsAst.Expression existing = tagDefns[tag];
+ js.Expression existing = tagDefns[tag];
if (existing == null) {
// [subclass] is still within the subtree between dispatch classes.
subtags.add(toNativeTag(tag));
@@ -346,19 +346,19 @@
} else {
// [subclass] is one of the preorderDispatchClasses, so CSE this
// reference with the previous reference.
- jsAst.VariableUse use = existing.asVariableUse();
+ js.VariableUse use = existing.asVariableUse();
if (use != null && varDefns.containsKey(use.name)) {
// We end up here if the subclasses have a DAG structure. We
// don't have DAGs yet, but if the dispatch is used for mixins
// that will be a possibility.
// Re-use the previously created temporary variable.
- expressions.add(new jsAst.VariableUse(use.name));
+ expressions.add(new js.VariableUse(use.name));
} else {
String varName = 'v${varNames.length}_${tag.name.slowToString()}';
varNames.add(varName);
varDefns[varName] = existing;
- tagDefns[tag] = new jsAst.VariableUse(varName);
- expressions.add(new jsAst.VariableUse(varName));
+ tagDefns[tag] = new js.VariableUse(varName);
+ expressions.add(new js.VariableUse(varName));
}
}
}
@@ -368,12 +368,12 @@
if (!subtags.isEmpty) {
expressions.add(js.string(subtags.join('|')));
}
- jsAst.Expression expression;
+ js.Expression expression;
if (expressions.length == 1) {
expression = expressions[0];
} else {
- jsAst.Expression array = new jsAst.ArrayInitializer.from(expressions);
- expression = array['join']([js.string('|')]);
+ js.Expression array = new js.ArrayInitializer.from(expressions);
+ expression = js.call(array.dot('join'), [js.string('|')]);
}
return expression;
}
@@ -384,47 +384,46 @@
// Write out a thunk that builds the metadata.
if (!tagDefns.isEmpty) {
- List<jsAst.Statement> statements = <jsAst.Statement>[];
+ List<js.Statement> statements = <js.Statement>[];
- List<jsAst.VariableInitialization> initializations =
- <jsAst.VariableInitialization>[];
+ List<js.VariableInitialization> initializations =
+ <js.VariableInitialization>[];
for (final String varName in varNames) {
initializations.add(
- new jsAst.VariableInitialization(
- new jsAst.VariableDeclaration(varName),
+ new js.VariableInitialization(
+ new js.VariableDeclaration(varName),
varDefns[varName]));
}
if (!initializations.isEmpty) {
statements.add(
- new jsAst.ExpressionStatement(
- new jsAst.VariableDeclarationList(initializations)));
+ new js.ExpressionStatement(
+ new js.VariableDeclarationList(initializations)));
}
// [table] is a list of lists, each inner list of the form:
// [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
// E.g.
// [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
- jsAst.Expression table =
- new jsAst.ArrayInitializer.from(
+ js.Expression table =
+ new js.ArrayInitializer.from(
preorderDispatchClasses.map((cls) =>
- new jsAst.ArrayInitializer.from([
+ new js.ArrayInitializer.from([
js.string(toNativeTag(cls)),
tagDefns[cls]])));
// $.dynamicSetMetadata(table);
statements.add(
- new jsAst.ExpressionStatement(
- new jsAst.Call(
- new jsAst.VariableUse(dynamicSetMetadataName),
+ new js.ExpressionStatement(
+ new js.Call(
+ new js.VariableUse(dynamicSetMetadataName),
[table])));
// (function(){statements})();
if (emitter.compiler.enableMinification) nativeBuffer.add(';');
nativeBuffer.add(
- jsAst.prettyPrint(
- new jsAst.ExpressionStatement(
- new jsAst.Call(new jsAst.Fun([], new jsAst.Block(statements)),
- [])),
+ js.prettyPrint(
+ new js.ExpressionStatement(
+ new js.Call(new js.Fun([], new js.Block(statements)), [])),
compiler));
}
}
@@ -461,10 +460,10 @@
targetBuffer.add('$defineNativeClassName = '
'$defineNativeClassFunction$N$n');
- List<jsAst.Property> objectProperties = <jsAst.Property>[];
+ List<js.Property> objectProperties = <js.Property>[];
- void addProperty(String name, jsAst.Expression value) {
- objectProperties.add(new jsAst.Property(js.string(name), value));
+ void addProperty(String name, js.Expression value) {
+ objectProperties.add(new js.Property(js.string(name), value));
}
// Because of native classes, we have to generate some is checks
@@ -479,14 +478,16 @@
if (element.isObject(compiler)) continue;
String name = backend.namer.operatorIs(element);
addProperty(name,
- js.fun([], js.return_(new jsAst.LiteralBool(false))));
+ js.fun([], js.block1(js.return_(new js.LiteralBool(false)))));
}
}
emitIsChecks();
- jsAst.Expression makeCallOnThis(String functionName) {
- return js.fun([], js.return_(js[functionName]('this')));
- }
+ js.Expression makeCallOnThis(String functionName) =>
+ js.fun([],
+ js.block1(
+ js.return_(
+ js.call(js.use(functionName), [js.use('this')]))));
// In order to have the toString method on every native class,
// we must patch the JS Object prototype with a helper method.
@@ -502,8 +503,8 @@
// Same as above, but for operator==.
String equalsName = backend.namer.publicInstanceMethodNameByArity(
const SourceString('=='), 1);
- addProperty(equalsName, js.fun(['a'],
- js.return_(js.strictEquals(new jsAst.This(), js['a']))));
+ addProperty(equalsName, js.fun(['a'], js.block1(
+ js.return_(js.strictEquals(new js.This(), js.use('a'))))));
// If the native emitter has been asked to take care of the
// noSuchMethod handlers, we do that now.
@@ -514,25 +515,28 @@
// If we have any properties to add to Object.prototype, we run
// through them and add them using defineProperty.
if (!objectProperties.isEmpty) {
- jsAst.Expression init =
- js.fun(['table'],
- new jsAst.ForIn(
- new jsAst.VariableDeclarationList(
- [new jsAst.VariableInitialization(
- new jsAst.VariableDeclaration('key'),
- null)]),
- js['table'],
- new jsAst.ExpressionStatement(
- js[defPropName](
- [js['Object']['prototype'],
- js['key'],
- new jsAst.PropertyAccess(js['table'],
- js['key'])]))))(
- new jsAst.ObjectInitializer(objectProperties));
+ js.Expression init =
+ js.call(
+ js.fun(['table'],
+ js.block1(
+ new js.ForIn(
+ new js.VariableDeclarationList(
+ [new js.VariableInitialization(
+ new js.VariableDeclaration('key'),
+ null)]),
+ js.use('table'),
+ new js.ExpressionStatement(
+ js.call(
+ js.use(defPropName),
+ [js.use('Object').dot('prototype'),
+ js.use('key'),
+ new js.PropertyAccess(js.use('table'),
+ js.use('key'))]))))),
+ [new js.ObjectInitializer(objectProperties)]);
if (emitter.compiler.enableMinification) targetBuffer.add(';');
- targetBuffer.add(jsAst.prettyPrint(
- new jsAst.ExpressionStatement(init), compiler));
+ targetBuffer.add(js.prettyPrint(
+ new js.ExpressionStatement(init), compiler));
targetBuffer.add('\n');
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
index 91a6782..e33ae3f 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
@@ -230,7 +230,7 @@
bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f);
- Iterable<E> get reversed => IterableMixinWorkaround.reversedList(this);
+ List<E> get reversed => IterableMixinWorkaround.reversedList(this);
void sort([int compare(E a, E b)]) {
checkMutable(this, 'sort');
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index 18c1d7b..81dd6da 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.dart
@@ -318,7 +318,7 @@
}
static Iterable mapList(List list, f(var element)) {
- return new MappedListIterable(list, f);
+ return new MappedListIterable(list, f, 0, null);
}
static List mappedByList(List list, f(var element)) {
@@ -333,7 +333,7 @@
static Iterable takeList(List list, int n) {
// The generic type is currently lost. It will be fixed with mixins.
// This is currently a List as well as an Iterable.
- return new SubListIterable(list, 0, n);
+ return new ListView(list, 0, n);
}
static Iterable takeWhile(Iterable iterable, bool test(var value)) {
@@ -344,7 +344,7 @@
static Iterable skipList(List list, int n) {
// The generic type is currently lost. It will be fixed with mixins.
// This is currently a List as well as an Iterable.
- return new SubListIterable(list, n, null);
+ return new ListView(list, n, null);
}
static Iterable skipWhile(Iterable iterable, bool test(var value)) {
@@ -352,8 +352,8 @@
return new SkipWhileIterable(iterable, test);
}
- static Iterable reversedList(List l) {
- return new ReversedListIterable(l);
+ static List reversedList(List l) {
+ return new ReversedListView(l, 0, null);
}
static void sortList(List l, int compare(a, b)) {
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index ecb5535..10ba3e0 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -77,9 +77,13 @@
void addAll(Iterable<E> iterable);
/**
- * Returns an [Iterable] of the elements of this [List] in reverse order.
+ * Returns a reversed fixed-length view of this [List].
+ *
+ * The reversed list has elements in the opposite order of this list.
+ * It is backed by this list, but will stop working if this list
+ * becomes shorter than its current length.
*/
- Iterable<E> get reversed;
+ List<E> get reversed;
/**
* Sorts the list according to the order specified by the [compare] function.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 86dfb92..8688fea 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -7266,7 +7266,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<DomMimeType> get reversed {
+ List<DomMimeType> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -7523,7 +7523,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<DomPlugin> get reversed {
+ List<DomPlugin> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -7887,7 +7887,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<String> get reversed {
+ List<String> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8165,7 +8165,7 @@
}
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8399,7 +8399,7 @@
throw new UnsupportedError('');
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -10729,7 +10729,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<File> get reversed {
+ List<File> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -11289,7 +11289,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<num> get reversed {
+ List<num> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -11508,7 +11508,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<num> get reversed {
+ List<num> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -12036,7 +12036,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -12246,7 +12246,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -14268,7 +14268,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -14487,7 +14487,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -14706,7 +14706,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -17198,7 +17198,7 @@
return this[index];
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -17607,7 +17607,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -19927,7 +19927,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SourceBuffer> get reversed {
+ List<SourceBuffer> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -20210,7 +20210,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechGrammar> get reversed {
+ List<SpeechGrammar> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -20781,7 +20781,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Map> get reversed {
+ List<Map> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -21867,7 +21867,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<TextTrackCue> get reversed {
+ List<TextTrackCue> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -22075,7 +22075,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<TextTrack> get reversed {
+ List<TextTrack> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -22490,7 +22490,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Touch> get reversed {
+ List<Touch> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -22939,7 +22939,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -23158,7 +23158,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -23377,7 +23377,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -23593,7 +23593,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -27312,7 +27312,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<ClientRect> get reversed {
+ List<ClientRect> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -27512,7 +27512,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<CssRule> get reversed {
+ List<CssRule> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -27712,7 +27712,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<CssValue> get reversed {
+ List<CssValue> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -27912,7 +27912,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Entry> get reversed {
+ List<Entry> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -28112,7 +28112,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<EntrySync> get reversed {
+ List<EntrySync> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -28312,7 +28312,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Gamepad> get reversed {
+ List<Gamepad> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -28575,7 +28575,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<MediaStream> get reversed {
+ List<MediaStream> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -28775,7 +28775,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -28999,7 +28999,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechInputResult> get reversed {
+ List<SpeechInputResult> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -29199,7 +29199,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechRecognitionResult> get reversed {
+ List<SpeechRecognitionResult> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -29399,7 +29399,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<StyleSheet> get reversed {
+ List<StyleSheet> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index db5b57a..ff46655 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -7967,7 +7967,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<DomMimeType> get reversed {
+ List<DomMimeType> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8238,7 +8238,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<DomPlugin> get reversed {
+ List<DomPlugin> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8627,7 +8627,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<String> get reversed {
+ List<String> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8926,7 +8926,7 @@
}
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -9160,7 +9160,7 @@
throw new UnsupportedError('');
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -11465,7 +11465,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<File> get reversed {
+ List<File> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -12079,7 +12079,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<num> get reversed {
+ List<num> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -12317,7 +12317,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<num> get reversed {
+ List<num> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -12915,7 +12915,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -13127,7 +13127,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -15488,7 +15488,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -15726,7 +15726,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -15964,7 +15964,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -18735,7 +18735,7 @@
return this[index];
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -19141,7 +19141,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -21768,7 +21768,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SourceBuffer> get reversed {
+ List<SourceBuffer> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -22089,7 +22089,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechGrammar> get reversed {
+ List<SpeechGrammar> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -22747,7 +22747,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Map> get reversed {
+ List<Map> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -24069,7 +24069,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<TextTrackCue> get reversed {
+ List<TextTrackCue> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -24281,7 +24281,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<TextTrack> get reversed {
+ List<TextTrack> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -24700,7 +24700,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Touch> get reversed {
+ List<Touch> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -25194,7 +25194,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -25432,7 +25432,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -25670,7 +25670,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -25906,7 +25906,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<int> get reversed {
+ List<int> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -29584,7 +29584,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<ClientRect> get reversed {
+ List<ClientRect> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -29788,7 +29788,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<CssRule> get reversed {
+ List<CssRule> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -29992,7 +29992,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<CssValue> get reversed {
+ List<CssValue> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -30339,7 +30339,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Entry> get reversed {
+ List<Entry> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -30543,7 +30543,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<EntrySync> get reversed {
+ List<EntrySync> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -30747,7 +30747,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Gamepad> get reversed {
+ List<Gamepad> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -31042,7 +31042,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<MediaStream> get reversed {
+ List<MediaStream> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -31246,7 +31246,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -31474,7 +31474,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechInputResult> get reversed {
+ List<SpeechInputResult> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -31678,7 +31678,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<SpeechRecognitionResult> get reversed {
+ List<SpeechRecognitionResult> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -31882,7 +31882,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<StyleSheet> get reversed {
+ List<StyleSheet> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index 9820f1a..330b0df 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -69,7 +69,7 @@
return element is Element && _childNodes.contains(element);
}
- Iterable<Element> get reversed => _filtered.reversed;
+ List<Element> get reversed => _filtered.reversed;
void sort([int compare(Element a, Element b)]) {
throw new UnsupportedError('TODO(jacobr): should we impl?');
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index df439d6..09a63ec 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -3149,7 +3149,7 @@
// clear() defined by IDL.
- Iterable<Length> get reversed {
+ List<Length> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -3776,7 +3776,7 @@
// clear() defined by IDL.
- Iterable<Number> get reversed {
+ List<Number> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -4679,7 +4679,7 @@
// clear() defined by IDL.
- Iterable<PathSeg> get reversed {
+ List<PathSeg> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -5566,7 +5566,7 @@
// clear() defined by IDL.
- Iterable<String> get reversed {
+ List<String> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -6732,7 +6732,7 @@
// clear() defined by IDL.
- Iterable<Transform> get reversed {
+ List<Transform> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -7254,7 +7254,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<ElementInstance> get reversed {
+ List<ElementInstance> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 98cb362..debc991 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3413,7 +3413,7 @@
// clear() defined by IDL.
- Iterable<Length> get reversed {
+ List<Length> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -4117,7 +4117,7 @@
// clear() defined by IDL.
- Iterable<Number> get reversed {
+ List<Number> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -5297,7 +5297,7 @@
// clear() defined by IDL.
- Iterable<PathSeg> get reversed {
+ List<PathSeg> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -6282,7 +6282,7 @@
// clear() defined by IDL.
- Iterable<String> get reversed {
+ List<String> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -7537,7 +7537,7 @@
// clear() defined by IDL.
- Iterable<Transform> get reversed {
+ List<Transform> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -8113,7 +8113,7 @@
throw new UnsupportedError("Cannot clear immutable List.");
}
- Iterable<ElementInstance> get reversed {
+ List<ElementInstance> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/tests/corelib/iterable_skip_test.dart b/tests/corelib/iterable_skip_test.dart
index 2889c9c..fff6db7 100644
--- a/tests/corelib/iterable_skip_test.dart
+++ b/tests/corelib/iterable_skip_test.dart
@@ -13,7 +13,7 @@
Set set2 = new Set();
Iterable<int> skip0 = list1.skip(0);
- Expect.isTrue(skip0 is! List);
+ Expect.isTrue(skip0 is List);
Iterator<int> it = skip0.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -26,8 +26,8 @@
Expect.isNull(it.current);
Iterable<int> skip1 = list1.skip(1);
- Expect.isTrue(skip1 is! List);
- Expect.isTrue(skip1.skip(2).skip(1) is! List);
+ Expect.isTrue(skip1 is List);
+ Expect.isTrue(skip1.skip(2).skip(1) is List);
it = skip1.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -38,8 +38,8 @@
Expect.isNull(it.current);
Iterable<int> skip2 = list1.skip(2);
- Expect.isTrue(skip2 is! List);
- Expect.isTrue(skip2.skip(2).skip(1) is! List);
+ Expect.isTrue(skip2 is List);
+ Expect.isTrue(skip2.skip(2).skip(1) is List);
it = skip2.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -48,16 +48,16 @@
Expect.isNull(it.current);
Iterable<int> skip3 = list1.skip(3);
- Expect.isTrue(skip3 is! List);
- Expect.isTrue(skip3.skip(2).skip(1) is! List);
+ Expect.isTrue(skip3 is List);
+ Expect.isTrue(skip3.skip(2).skip(1) is List);
it = skip3.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
Iterable<int> skip4 = list1.skip(4);
- Expect.isTrue(skip4 is! List);
- Expect.isTrue(skip4.skip(2).skip(1) is! List);
+ Expect.isTrue(skip4 is List);
+ Expect.isTrue(skip4.skip(2).skip(1) is List);
it = skip4.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
@@ -102,8 +102,8 @@
Expect.isNull(it.current);
skip0 = list2.skip(0);
- Expect.isTrue(skip0 is! List);
- Expect.isTrue(skip0.skip(2).skip(1) is! List);
+ Expect.isTrue(skip0 is List);
+ Expect.isTrue(skip0.skip(2).skip(1) is List);
it = skip0.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -114,8 +114,8 @@
Expect.isNull(it.current);
skip1 = list2.skip(1);
- Expect.isTrue(skip1 is! List);
- Expect.isTrue(skip1.skip(2).skip(1) is! List);
+ Expect.isTrue(skip1 is List);
+ Expect.isTrue(skip1.skip(2).skip(1) is List);
it = skip1.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -124,32 +124,32 @@
Expect.isNull(it.current);
skip2 = list2.skip(2);
- Expect.isTrue(skip2 is! List);
- Expect.isTrue(skip2.skip(2).skip(1) is! List);
+ Expect.isTrue(skip2 is List);
+ Expect.isTrue(skip2.skip(2).skip(1) is List);
it = skip2.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
skip3 = list2.skip(3);
- Expect.isTrue(skip3 is! List);
- Expect.isTrue(skip3.skip(2).skip(1) is! List);
+ Expect.isTrue(skip3 is List);
+ Expect.isTrue(skip3.skip(2).skip(1) is List);
it = skip3.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
Iterable<String> skip02 = list3.skip(0);
- Expect.isTrue(skip02 is! List);
- Expect.isTrue(skip02.skip(2).skip(1) is! List);
+ Expect.isTrue(skip02 is List);
+ Expect.isTrue(skip02.skip(2).skip(1) is List);
Iterator<String> it2 = skip02.iterator;
Expect.isNull(it2.current);
Expect.isFalse(it2.moveNext());
Expect.isNull(it2.current);
Iterable<String> skip12 = list3.skip(1);
- Expect.isTrue(skip12 is! List);
- Expect.isTrue(skip12.skip(2).skip(1) is! List);
+ Expect.isTrue(skip12 is List);
+ Expect.isTrue(skip12.skip(2).skip(1) is List);
it2 = skip12.iterator;
Expect.isNull(it2.current);
Expect.isFalse(it2.moveNext());
diff --git a/tests/corelib/iterable_take_test.dart b/tests/corelib/iterable_take_test.dart
index 3910769..c775c52 100644
--- a/tests/corelib/iterable_take_test.dart
+++ b/tests/corelib/iterable_take_test.dart
@@ -13,12 +13,16 @@
Set set2 = new Set();
Iterable<int> take0 = list1.take(0);
+ Expect.isTrue(take0 is List);
+ Expect.isTrue(take0.take(2).take(1) is List);
Iterator<int> it = take0.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
Iterable<int> take1 = list1.take(1);
+ Expect.isTrue(take1 is List);
+ Expect.isTrue(take1.take(2).take(1) is List);
it = take1.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -28,6 +32,8 @@
Iterable<int> take2 = list1.take(2);
it = take2.iterator;
+ Expect.isTrue(take2 is List);
+ Expect.isTrue(take2.take(2).take(1) is List);
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
Expect.equals(1, it.current);
@@ -37,6 +43,8 @@
Expect.isNull(it.current);
Iterable<int> take3 = list1.take(3);
+ Expect.isTrue(take3 is List);
+ Expect.isTrue(take3.take(2).take(1) is List);
it = take3.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -49,6 +57,8 @@
Expect.isNull(it.current);
Iterable<int> take4 = list1.take(4);
+ Expect.isTrue(take4 is List);
+ Expect.isTrue(take4.take(2).take(1) is List);
it = take4.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -105,12 +115,16 @@
Expect.isNull(it.current);
take0 = list2.take(0);
+ Expect.isTrue(take0 is List);
+ Expect.isTrue(take0.take(2).take(1) is List);
it = take0.iterator;
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
take1 = list2.take(1);
+ Expect.isTrue(take1 is List);
+ Expect.isTrue(take1.take(2).take(1) is List);
it = take1.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -119,6 +133,8 @@
Expect.isNull(it.current);
take2 = list2.take(2);
+ Expect.isTrue(take2 is List);
+ Expect.isTrue(take2.take(2).take(1) is List);
it = take2.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -129,6 +145,8 @@
Expect.isNull(it.current);
take3 = list2.take(3);
+ Expect.isTrue(take3 is List);
+ Expect.isTrue(take3.take(2).take(1) is List);
it = take3.iterator;
Expect.isNull(it.current);
Expect.isTrue(it.moveNext());
@@ -139,12 +157,16 @@
Expect.isNull(it.current);
Iterable<String> take02 = list3.take(0);
+ Expect.isTrue(take02 is List);
+ Expect.isTrue(take02.take(2).take(1) is List);
Iterator<String> it2 = take02.iterator;
Expect.isNull(it2.current);
Expect.isFalse(it2.moveNext());
Expect.isNull(it2.current);
Iterable<String> take12 = list3.take(1);
+ Expect.isTrue(take12 is List);
+ Expect.isTrue(take12.take(2).take(1) is List);
it2 = take12.iterator;
Expect.isNull(it2.current);
Expect.isFalse(it2.moveNext());
diff --git a/tests/corelib/list_reversed_test.dart b/tests/corelib/list_reversed_test.dart
index dda5b56..03b99ce 100644
--- a/tests/corelib/list_reversed_test.dart
+++ b/tests/corelib/list_reversed_test.dart
@@ -7,11 +7,6 @@
testOperations();
}
-class ThrowMarker {
- const ThrowMarker();
- String toString() => "<<THROWS>>";
-}
-
void testOperations() {
// Comparison lists.
List l = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
@@ -19,116 +14,27 @@
// A base list that starts out like l.
List base = l.toList();
// A lazy reverse of base.
- Iterable reversed = base.reversed;
+ List reversed = base.reversed;
- Expect.listEquals(r, reversed.toList());
- Expect.listEquals(l, reversed.toList().reversed.toList());
+ Expect.listEquals(r, reversed);
+ Expect.listEquals(l, reversed.reversed);
for (int i = 0; i < r.length; i++) {
- Expect.equals(r[i], reversed.elementAt(i));
+ Expect.equals(r[i], reversed[i]);
}
Expect.equals(4, base.indexOf(5));
- Expect.equals(5, reversed.toList().indexOf(5));
+ Expect.equals(5, reversed.indexOf(5));
- // Reversed followed by combinations of skip and take.
+ // Combinations of start and end relative to start/end of list.
List subr = [8, 7, 6, 5, 4, 3];
- Expect.listEquals(subr, reversed.skip(2).take(6).toList());
- Expect.listEquals(subr, reversed.take(8).skip(2).toList());
- Expect.listEquals(subr,
- reversed.toList().reversed.skip(2).take(6).toList().reversed.toList());
- Expect.listEquals(subr,
- reversed.toList().reversed.take(8).skip(2).toList().reversed.toList());
- Expect.listEquals(subr,
- reversed.take(8).toList().reversed.take(6).toList().reversed.toList());
- Expect.listEquals(subr,
- reversed.toList().reversed.take(8).toList().reversed.take(6).toList());
- Expect.listEquals(subr,
- reversed.toList().reversed.skip(2).toList().reversed.skip(2).toList());
- Expect.listEquals(subr,
- reversed.skip(2).toList().reversed.skip(2).toList().reversed.toList());
-
-
- void testList(List list) {
- var throws = const ThrowMarker();
- void testEquals(v1, v2, path) {
- if (v1 is Iterable) {
- Iterator i1 = v1.iterator;
- Iterator i2 = v2.iterator;
- int index = 0;
- while (i1.moveNext()) {
- Expect.isTrue(i2.moveNext(),
- "Too few actual values. Expected[$index] == ${i1.current}");
- testEquals(i1.current, i2.current, "$path[$index]");
- index++;
- }
- Expect.isFalse(i2.moveNext(),
- "Too many actual values. Actual[$index] == ${i2.current}");
- } else {
- Expect.equals(v1, v2, path);
- }
- }
-
- void testOp(operation(Iterable reversedList), name) {
- List reversedList = new List(list.length);
- for (int i = 0; i < list.length; i++) {
- reversedList[i] = list[list.length - 1 - i];
- }
- Iterable reversed = list.reversed;
- var expect;
- try {
- expect = operation(reversedList);
- } catch (e) {
- expect = throws;
- }
- var actual;
- try {
- actual = operation(reversed);
- } catch (e) {
- actual = throws;
- }
- testEquals(expect, actual, "$name: $list");
- }
- testOp((i) => i.first, "first");
- testOp((i) => i.last, "last");
- testOp((i) => i.single, "single");
- testOp((i) => i.firstMatching((n) => n < 5), "firstMatching<5");
- testOp((i) => i.firstMatching((n) => n < 10), "firstMatching<10");
- testOp((i) => i.lastMatching((n) => n < 5), "lastMatching<5");
- testOp((i) => i.lastMatching((n) => n < 10), "lastMatching<10");
- testOp((i) => i.singleMatching((n) => n < 5), "singelMatching<5");
- testOp((i) => i.singleMatching((n) => n < 10), "singelMatching<10");
- testOp((i) => i.contains(5), "contains(5)");
- testOp((i) => i.contains(10), "contains(10)");
- testOp((i) => i.any((n) => n < 5), "any<5");
- testOp((i) => i.any((n) => n < 10), "any<10");
- testOp((i) => i.every((n) => n < 5), "every<5");
- testOp((i) => i.every((n) => n < 10), "every<10");
- testOp((i) => i.max(), "max");
- testOp((i) => i.min(), "min");
- testOp((i) => i.reduce(0, (a, b) => a + b), "reduce-sum");
- testOp((i) => i.join("-"), "join-");
- testOp((i) => i.join(""), "join");
- testOp((i) => i.join(), "join-null");
- testOp((i) => i.map((n) => n * 2), "map*2");
- testOp((i) => i.where((n) => n < 5), "where<5");
- testOp((i) => i.where((n) => n < 10), "where<10");
- testOp((i) => i.expand((n) => []), "expand[]");
- testOp((i) => i.expand((n) => [n]), "expand[n]");
- testOp((i) => i.expand((n) => [n, n]), "expand[n, n]");
- }
-
- // Combinations of lists with 0, 1 and more elements.
- testList([]);
- testList([0]);
- testList([10]);
- testList([0, 1]);
- testList([0, 10]);
- testList([10, 11]);
- testList([0, 5, 10]);
- testList([10, 5, 0]);
- testList([0, 1, 2, 3]);
- testList([3, 4, 5, 6]);
- testList([10, 11, 12, 13]);
+ Expect.listEquals(subr, reversed.skip(2).take(6));
+ Expect.listEquals(subr, reversed.take(8).skip(2));
+ Expect.listEquals(subr, reversed.reversed.skip(2).take(6).reversed);
+ Expect.listEquals(subr, reversed.reversed.take(8).skip(2).reversed);
+ Expect.listEquals(subr, reversed.take(8).reversed.take(6).reversed);
+ Expect.listEquals(subr, reversed.reversed.take(8).reversed.take(6));
+ Expect.listEquals(subr, reversed.reversed.skip(2).reversed.skip(2));
+ Expect.listEquals(subr, reversed.skip(2).reversed.skip(2).reversed);
// Reverse const list.
- Expect.listEquals(r, l.reversed.toList());
+ Expect.listEquals(r, l.reversed);
}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index cbaa158..9652300 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -45,7 +45,6 @@
[ $runtime == vm && $system == windows ]
io/file_system_links_test: Skip # No links on Windows.
-io/socket_stream_close_test: Fail, Pass # Issue 8556.
[ $compiler == none && $runtime == drt ]
io/*: Skip # Don't run tests using dart:io in the browser
diff --git a/tools/VERSION b/tools/VERSION
index 453bc99..9ad9fa1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
-MINOR 1
-BUILD 2
-PATCH 0
+MINOR 3
+BUILD 7
+PATCH 1
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 5e5f0fc..791b1ab 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -149,7 +149,7 @@
}
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
@@ -383,7 +383,7 @@
throw new UnsupportedError('');
}
- Iterable<Element> get reversed {
+ List<Element> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 4f8e0e5..ceeb922 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -200,7 +200,7 @@
return this[index];
}
- Iterable<Node> get reversed {
+ List<Node> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
diff --git a/tools/dom/templates/immutable_list_mixin.darttemplate b/tools/dom/templates/immutable_list_mixin.darttemplate
index 3ec2b79..2c8bf68 100644
--- a/tools/dom/templates/immutable_list_mixin.darttemplate
+++ b/tools/dom/templates/immutable_list_mixin.darttemplate
@@ -107,7 +107,7 @@
// clear() defined by IDL.
$endif
- Iterable<$E> get reversed {
+ List<$E> get reversed {
return IterableMixinWorkaround.reversedList(this);
}