Version 0.7.5.0
svn merge -r 27585:27697 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@27701 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/bin/formatter.dart b/pkg/analyzer_experimental/bin/formatter.dart
index 52b8fd7..504646c 100755
--- a/pkg/analyzer_experimental/bin/formatter.dart
+++ b/pkg/analyzer_experimental/bin/formatter.dart
@@ -116,7 +116,7 @@
/// Format the given [src] as a compilation unit.
String _formatCU(src, {options: const FormatterOptions()}) =>
- new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src);
+ new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src).source;
/// Log the given [msg].
_log(String msg) {
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
index 180e9de..04f0e2b 100644
--- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -78,11 +78,37 @@
/// Format the specified portion (from [offset] with [length]) of the given
/// [source] string, optionally providing an [indentationLevel].
- String format(CodeKind kind, String source, {int offset, int end,
- int indentationLevel: 0});
+ FormattedSource format(CodeKind kind, String source, {int offset, int end,
+ int indentationLevel: 0, Selection selection: null});
}
+/// Source selection state information.
+class Selection {
+
+ /// The offset of the source selection.
+ final int offset;
+
+ /// The length of the selection.
+ final int length;
+
+ Selection(this.offset, this.length);
+}
+
+/// Formatted source.
+class FormattedSource {
+
+ /// Selection state or null if unspecified.
+ final Selection selection;
+
+ /// Formatted source string.
+ final String source;
+
+ /// Create a formatted [source] result, with optional [selection] information.
+ FormattedSource(this.source, [this.selection = null]);
+}
+
+
class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener {
final FormatterOptions options;
@@ -93,8 +119,8 @@
CodeFormatterImpl(this.options);
- String format(CodeKind kind, String source, {int offset, int end,
- int indentationLevel: 0}) {
+ FormattedSource format(CodeKind kind, String source, {int offset, int end,
+ int indentationLevel: 0, Selection selection: null}) {
var startToken = tokenize(source);
checkForErrors();
@@ -109,7 +135,7 @@
checkTokenStreams(startToken, tokenize(formattedSource));
- return formattedSource;
+ return new FormattedSource(formattedSource);
}
checkTokenStreams(Token t1, Token t2) =>
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart
index 37147f7..5503234 100644
--- a/pkg/analyzer_experimental/test/services/formatter_test.dart
+++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -767,7 +767,8 @@
test('initialIndent', () {
var formatter = new CodeFormatter(
new FormatterOptions(initialIndentationLevel: 2));
- var formattedSource = formatter.format(CodeKind.STATEMENT, 'var x;');
+ var formattedSource =
+ formatter.format(CodeKind.STATEMENT, 'var x;').source;
expect(formattedSource, startsWith(' '));
});
@@ -955,10 +956,10 @@
}
String formatCU(src, {options: const FormatterOptions()}) =>
- new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src);
+ new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src).source;
String formatStatement(src, {options: const FormatterOptions()}) =>
- new CodeFormatter(options).format(CodeKind.STATEMENT, src);
+ new CodeFormatter(options).format(CodeKind.STATEMENT, src).source;
Token tokenize(String str) => new StringScanner(null, str, null).tokenize();
diff --git a/pkg/crypto/lib/crypto.dart b/pkg/crypto/lib/crypto.dart
index ee11c25..5125912 100644
--- a/pkg/crypto/lib/crypto.dart
+++ b/pkg/crypto/lib/crypto.dart
@@ -35,7 +35,7 @@
/**
* Add a list of bytes to the hash computation.
*/
- add(List<int> data);
+ void add(List<int> data);
/**
* Finish the hash computation and extract the message digest as
diff --git a/pkg/crypto/lib/src/hash_utils.dart b/pkg/crypto/lib/src/hash_utils.dart
index 713dbb9..84df9d0 100644
--- a/pkg/crypto/lib/src/hash_utils.dart
+++ b/pkg/crypto/lib/src/hash_utils.dart
@@ -22,16 +22,17 @@
// Base class encapsulating common behavior for cryptographic hash
// functions.
abstract class _HashBase implements Hash {
- _HashBase(int this._chunkSizeInWords,
- int this._digestSizeInWords,
+ _HashBase(int chunkSizeInWords,
+ int digestSizeInWords,
bool this._bigEndianWords)
- : _pendingData = [] {
- _currentChunk = new List(_chunkSizeInWords);
- _h = new List(_digestSizeInWords);
- }
+ : _pendingData = [],
+ _currentChunk = new List(chunkSizeInWords),
+ _h = new List(digestSizeInWords),
+ _chunkSizeInWords = chunkSizeInWords,
+ _digestSizeInWords = digestSizeInWords;
// Update the hasher with more data.
- add(List<int> data) {
+ void add(List<int> data) {
if (_digestCalled) {
throw new StateError(
'Hash update method called after digest was retrieved');
@@ -58,18 +59,15 @@
return _chunkSizeInWords * _BYTES_PER_WORD;
}
- // Create a fresh instance of this Hash.
- newInstance();
-
// One round of the hash computation.
- _updateHash(List<int> m);
+ void _updateHash(List<int> m);
// Helper methods.
- _add32(x, y) => (x + y) & _MASK_32;
- _roundUp(val, n) => (val + n - 1) & -n;
+ int _add32(x, y) => (x + y) & _MASK_32;
+ int _roundUp(val, n) => (val + n - 1) & -n;
// Compute the final result as a list of bytes from the hash words.
- _resultAsBytes() {
+ List<int> _resultAsBytes() {
var result = [];
for (var i = 0; i < _h.length; i++) {
result.addAll(_wordToBytes(_h[i]));
@@ -78,7 +76,7 @@
}
// Converts a list of bytes to a chunk of 32-bit words.
- _bytesToChunk(List<int> data, int dataIndex) {
+ void _bytesToChunk(List<int> data, int dataIndex) {
assert((data.length - dataIndex) >= (_chunkSizeInWords * _BYTES_PER_WORD));
for (var wordIndex = 0; wordIndex < _chunkSizeInWords; wordIndex++) {
@@ -96,7 +94,7 @@
}
// Convert a 32-bit word to four bytes.
- _wordToBytes(int word) {
+ List<int> _wordToBytes(int word) {
List<int> bytes = new List(_BYTES_PER_WORD);
bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
@@ -107,7 +105,7 @@
// Iterate through data updating the hash computation for each
// chunk.
- _iterate() {
+ void _iterate() {
var len = _pendingData.length;
var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
if (len >= chunkSizeInBytes) {
@@ -122,7 +120,7 @@
// Finalize the data. Add a 1 bit to the end of the message. Expand with
// 0 bits and add the length of the message.
- _finalizeData() {
+ void _finalizeData() {
_pendingData.add(0x80);
var contentsLength = _lengthInBytes + 9;
var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
@@ -148,7 +146,7 @@
final bool _bigEndianWords;
int _lengthInBytes = 0;
List<int> _pendingData;
- List<int> _currentChunk;
- List<int> _h;
+ final List<int> _currentChunk;
+ final List<int> _h;
bool _digestCalled = false;
}
diff --git a/pkg/crypto/lib/src/hmac.dart b/pkg/crypto/lib/src/hmac.dart
index 59c1771..ba6cc11 100644
--- a/pkg/crypto/lib/src/hmac.dart
+++ b/pkg/crypto/lib/src/hmac.dart
@@ -22,7 +22,7 @@
/**
* Add a list of bytes to the message.
*/
- add(List<int> data) {
+ void add(List<int> data) {
if (_isClosed) throw new StateError("HMAC is closed");
_message.addAll(data);
}
@@ -110,5 +110,5 @@
// HMAC internal state.
Hash _hash;
List<int> _key;
- List<int> _message;
+ final List<int> _message;
}
diff --git a/pkg/crypto/lib/src/sha256.dart b/pkg/crypto/lib/src/sha256.dart
index f1c20e3..b429b8f 100644
--- a/pkg/crypto/lib/src/sha256.dart
+++ b/pkg/crypto/lib/src/sha256.dart
@@ -103,5 +103,5 @@
_h[7] = _add32(h, _h[7]);
}
- List<int> _w;
+ final List<int> _w;
}
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index f5a0810..64ca2b6 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -14,12 +14,7 @@
// integers, storing the 22 low, 22 middle, and 20 high bits of the
// 64-bit value. _l (low) and _m (middle) are in the range
// [0, 2^22 - 1] and _h (high) is in the range [0, 2^20 - 1].
- int _l, _m, _h;
-
- // Note: instances of [Int64] are immutable outside of this library,
- // therefore we may return a reference to an existing instance.
- // We take care to perform mutation only on internally-generated
- // instances before they are exposed to external code.
+ final int _l, _m, _h;
// Note: several functions require _BITS == 22 -- do not change this value.
static const int _BITS = 22;
@@ -30,67 +25,38 @@
static const int _SIGN_BIT = 19; // _BITS2 - 1
static const int _SIGN_BIT_MASK = 524288; // 1 << _SIGN_BIT
- // Cached constants
- static Int64 _MAX_VALUE;
- static Int64 _MIN_VALUE;
- static Int64 _ZERO;
- static Int64 _ONE;
- static Int64 _TWO;
-
- // The remainder of the last divide operation.
- static Int64 _remainder;
-
/**
* The maximum positive value attainable by an [Int64], namely
* 9,223,372,036,854,775,807.
*/
- static Int64 get MAX_VALUE {
- if (_MAX_VALUE == null) {
- _MAX_VALUE = new Int64._bits(_MASK, _MASK, _MASK2 >> 1);
- }
- return _MAX_VALUE;
- }
+ static const Int64 MAX_VALUE = const Int64._bits(_MASK, _MASK, _MASK2 >> 1);
/**
* The minimum positive value attainable by an [Int64], namely
* -9,223,372,036,854,775,808.
*/
- static Int64 get MIN_VALUE {
- if (_MIN_VALUE == null) {
- _MIN_VALUE = new Int64._bits(0, 0, _SIGN_BIT_MASK);
- }
- return _MIN_VALUE;
- }
+ static const Int64 MIN_VALUE = const Int64._bits(0, 0, _SIGN_BIT_MASK);
/**
* An [Int64] constant equal to 0.
*/
- static Int64 get ZERO {
- if (_ZERO == null) {
- _ZERO = new Int64();
- }
- return _ZERO;
- }
+ static const Int64 ZERO = const Int64._bits(0, 0, 0);
/**
* An [Int64] constant equal to 1.
*/
- static Int64 get ONE {
- if (_ONE == null) {
- _ONE = new Int64._bits(1, 0, 0);
- }
- return _ONE;
- }
+ static const Int64 ONE = const Int64._bits(1, 0, 0);
/**
* An [Int64] constant equal to 2.
*/
- static Int64 get TWO {
- if (_TWO == null) {
- _TWO = new Int64._bits(2, 0, 0);
- }
- return _TWO;
- }
+ static const Int64 TWO = const Int64._bits(2, 0, 0);
+
+ /**
+ * Constructs an [Int64] with a given bitwise representation. No validation
+ * is performed.
+ */
+ const Int64._bits(int this._l, int this._m, int this._h);
/**
* Parses a [String] in a given [radix] between 2 and 36 and returns an
@@ -122,26 +88,18 @@
// multiply and add within 30 bit temporary values.
d0 = d0 * radix + digit;
int carry = d0 >> _BITS;
- d0 &= _MASK;
+ d0 = _MASK & d0;
d1 = d1 * radix + carry;
carry = d1 >> _BITS;
- d1 &= _MASK;
+ d1 = _MASK & d1;;
d2 = d2 * radix + carry;
- d2 &= _MASK2;
+ d2 = _MASK2 & d2;
}
- if (negative) {
- d0 = 0 - d0;
- int borrow = (d0 >> _BITS) & 1;
- d0 &= _MASK;
- d1 = 0 - d1 - borrow;
- borrow = (d1 >> _BITS) & 1;
- d1 &= _MASK;
- d2 = 0 - d2 - borrow;
- d2 &= _MASK2;
- }
+ if (negative) return _negate(d0, d1, d2);
+
return new Int64._bits(d0, d1, d2);
}
@@ -167,30 +125,32 @@
/**
* Constructs an [Int64] with a given [int] value.
*/
- Int64.fromInt(int value) {
+ factory Int64.fromInt(int value) {
+ int v0 = 0, v1 = 0, v2 = 0;
bool negative = false;
if (value < 0) {
negative = true;
value = -value - 1;
}
if (_haveBigInts) {
- _l = value & _MASK;
- _m = (value >> _BITS) & _MASK;
- _h = (value >> _BITS01) & _MASK2;
+ v0 = _MASK & value;
+ v1 = _MASK & (value >> _BITS);
+ v2 = _MASK2 & (value >> _BITS01);
} else {
// Avoid using bitwise operations that coerce their input to 32 bits.
- _h = value ~/ 17592186044416; // 2^44
- value -= _h * 17592186044416;
- _m = value ~/ 4194304; // 2^22
- value -= _m * 4194304;
- _l = value;
+ v2 = value ~/ 17592186044416; // 2^44
+ value -= v2 * 17592186044416;
+ v1 = value ~/ 4194304; // 2^22
+ value -= v1 * 4194304;
+ v0 = value;
}
if (negative) {
- _l = ~_l & _MASK;
- _m = ~_m & _MASK;
- _h = ~_h & _MASK2;
+ v0 = _MASK & ~v0;
+ v1 = _MASK & ~v1;
+ v2 = _MASK2 & ~v2;
}
+ return new Int64._bits(v0, v1, v2);
}
factory Int64.fromBytes(List<int> bytes) {
@@ -248,7 +208,7 @@
// Returns the [Int64] representation of the specified value. Throws
// [ArgumentError] for non-integer arguments.
- Int64 _promote(val) {
+ static Int64 _promote(val) {
if (val is Int64) {
return val;
} else if (val is int) {
@@ -262,31 +222,17 @@
Int64 operator +(other) {
Int64 o = _promote(other);
int sum0 = _l + o._l;
- int sum1 = _m + o._m + _shiftRight(sum0, _BITS);
- int sum2 = _h + o._h + _shiftRight(sum1, _BITS);
-
- Int64 result = new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK2);
- return result;
+ int sum1 = _m + o._m + (sum0 >> _BITS);
+ int sum2 = _h + o._h + (sum1 >> _BITS);
+ return Int64._masked(sum0, sum1, sum2);
}
Int64 operator -(other) {
Int64 o = _promote(other);
- int sum0 = _l - o._l;
- int sum1 = _m - o._m + _shiftRight(sum0, _BITS);
- int sum2 = _h - o._h + _shiftRight(sum1, _BITS);
-
- Int64 result = new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK2);
- return result;
+ return _sub(_l, _m, _h, o._l, o._m, o._h);
}
- Int64 operator -() {
- // Like 0 - this.
- int sum0 = -_l;
- int sum1 = -_m + _shiftRight(sum0, _BITS);
- int sum2 = -_h + _shiftRight(sum1, _BITS);
-
- return new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK2);
- }
+ Int64 operator -() => _negate(_l, _m, _h);
Int64 operator *(other) {
Int64 o = _promote(other);
@@ -372,29 +318,11 @@
return new Int64._bits(c0, c1, c2);
}
- Int64 operator %(other) {
- if (other.isZero) {
- throw new IntegerDivisionByZeroException();
- }
- if (this.isZero) {
- return ZERO;
- }
- Int64 o = _promote(other).abs();
- _divMod(this, o, true);
- return _remainder < 0 ? (_remainder + o) : _remainder;
- }
+ Int64 operator %(other) => _divide(this, other, _RETURN_MOD);
- Int64 operator ~/(other) => _divMod(this, _promote(other), false);
+ Int64 operator ~/(other) => _divide(this, other, _RETURN_DIV);
- // Int64 remainder(other) => this - (this ~/ other) * other;
- Int64 remainder(other) {
- if (other.isZero) {
- throw new IntegerDivisionByZeroException();
- }
- Int64 o = _promote(other).abs();
- _divMod(this, o, true);
- return _remainder;
- }
+ Int64 remainder(other) => _divide(this, other, _RETURN_REM);
Int64 operator &(other) {
Int64 o = _promote(other);
@@ -421,8 +349,7 @@
}
Int64 operator ~() {
- var result = new Int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK2);
- return result;
+ return Int64._masked(~_l, ~_m, ~_h);
}
Int64 operator <<(int n) {
@@ -446,7 +373,7 @@
res2 = _l << (n - _BITS01);
}
- return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK2);
+ return Int64._masked(res0, res1, res2);
}
Int64 operator >>(int n) {
@@ -460,8 +387,10 @@
// Sign extend h(a).
int a2 = _h;
bool negative = (a2 & _SIGN_BIT_MASK) != 0;
- if (negative) {
- a2 += 0x3 << _BITS2; // add extra one bits on the left
+ if (negative && _MASK > _MASK2) {
+ // Add extra one bits on the left so the sign gets shifted into the wider
+ // lower words.
+ a2 += (_MASK - _MASK2);
}
if (n < _BITS) {
@@ -487,7 +416,7 @@
}
}
- return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK2);
+ return Int64._masked(res0, res1, res2);
}
Int64 shiftRightUnsigned(int n) {
@@ -497,7 +426,7 @@
n &= 63;
int res0, res1, res2;
- int a2 = _h & _MASK2; // Ensure a2 is positive.
+ int a2 = _MASK2 & _h; // Ensure a2 is positive.
if (n < _BITS) {
res2 = a2 >> n;
res1 = (_m >> n) | (a2 << (_BITS - n));
@@ -512,7 +441,7 @@
res0 = a2 >> (n - _BITS01);
}
- return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK2);
+ return Int64._masked(res0, res1, res2);
}
/**
@@ -524,6 +453,10 @@
if (other is Int64) {
o = other;
} else if (other is int) {
+ if (_h == 0 && _m == 0) return _l == other;
+ // Since we know one of [_h] or [_m] is non-zero, if [other] fits in the
+ // low word then it can't be numerically equal.
+ if ((_MASK & other) == other) return false;
o = new Int64.fromInt(other);
} else if (other is Int32) {
o = other.toInt64();
@@ -578,7 +511,7 @@
bool get isEven => (_l & 0x1) == 0;
bool get isMaxValue => (_h == _MASK2 >> 1) && _m == _MASK && _l == _MASK;
bool get isMinValue => _h == _SIGN_BIT_MASK && _m == 0 && _l == 0;
- bool get isNegative => (_h >> (_BITS2 - 1)) != 0;
+ bool get isNegative => (_h & _SIGN_BIT_MASK) != 0;
bool get isOdd => (_l & 0x1) == 1;
bool get isZero => _h == 0 && _m == 0 && _l == 0;
@@ -586,13 +519,15 @@
* Returns a hash code based on all the bits of this [Int64].
*/
int get hashCode {
+ // TODO(sra): Should we ensure that hashCode values match corresponding int?
+ // i.e. should `new Int64.fromInt(x).hashCode == x.hashCode`?
int bottom = ((_m & 0x3ff) << _BITS) | _l;
int top = (_h << 12) | ((_m >> 10) & 0xfff);
return bottom ^ top;
}
Int64 abs() {
- return this < 0 ? -this : this;
+ return this.isNegative ? -this : this;
}
/**
@@ -689,10 +624,8 @@
// TODO(rice) - Make this faster by avoiding arithmetic.
String toHexString() {
- Int64 x = new Int64._copy(this);
- if (isZero) {
- return "0";
- }
+ if (isZero) return "0";
+ Int64 x = this;
String hexStr = "";
Int64 digit_f = new Int64.fromInt(0xf);
while (!x.isZero) {
@@ -854,19 +787,20 @@
return "Int64[_l=$_l, _m=$_m, _h=$_h]";
}
- /**
- * Constructs an [Int64] with a given bitwise representation. No validation
- * is performed.
- */
- Int64._bits(int this._l, int this._m, int this._h);
- /**
- * Constructs an [Int64] with the same value as an existing [Int64].
- */
- Int64._copy(Int64 other)
- : _l = other._l,
- _m = other._m,
- _h = other._h;
+ static Int64 _masked(int a0, int a1, int a2) =>
+ new Int64._bits(_MASK & a0, _MASK & a1, _MASK2 & a2);
+
+ static Int64 _sub(int a0, int a1, int a2, int b0, int b1, int b2) {
+ int diff0 = a0 - b0;
+ int diff1 = a1 - b1 - ((diff0 >> _BITS) & 1);
+ int diff2 = a2 - b2 - ((diff1 >> _BITS) & 1);
+ return _masked(diff0, diff1, diff2);
+ }
+
+ static Int64 _negate(int b0, int b1, int b2) {
+ return _sub(0, 0, 0, b0, b1, b2);
+ }
// Determine whether the platform supports ints greater than 2^53
// without loss of precision.
@@ -888,40 +822,6 @@
String _hexDigit(int digit) => "0123456789ABCDEF"[digit];
- // Implementation of '~/' and '%'.
-
- // Note: mutates [this].
- void _negate() {
- int neg0 = (~_l + 1) & _MASK;
- int neg1 = (~_m + (neg0 == 0 ? 1 : 0)) & _MASK;
- int neg2 = (~_h + ((neg0 == 0 && neg1 == 0) ? 1 : 0)) & _MASK2;
-
- _l = neg0;
- _m = neg1;
- _h = neg2;
- }
-
- // Note: mutates [this].
- void _setBit(int bit) {
- if (bit < _BITS) {
- _l |= 0x1 << bit;
- } else if (bit < _BITS01) {
- _m |= 0x1 << (bit - _BITS);
- } else {
- _h |= 0x1 << (bit - _BITS01);
- }
- }
-
- // Note: mutates [this].
- void _toShru1() {
- int a2 = _h;
- int a1 = _m;
- int a0 = _l;
-
- _h = a2 >> 1;
- _m = (a1 >> 1) | ((a2 & 0x1) << (_BITS - 1));
- _l = (a0 >> 1) | ((a1 & 0x1) << (_BITS - 1));
- }
// Work around dart2js bugs with negative arguments to '>>' operator.
static int _shiftRight(int x, int n) {
@@ -936,267 +836,157 @@
}
}
- /**
- * Attempt to subtract b from a if a >= b:
- *
- * if (a >= b) {
- * a -= b;
- * return true;
- * } else {
- * return false;
- * }
- */
- // Note: mutates [a].
- static bool _trialSubtract(Int64 a, Int64 b) {
- // Early exit.
- int sum2 = a._h - b._h;
- if (sum2 < 0) {
- return false;
- }
- int sum0 = a._l - b._l;
- int sum1 = a._m - b._m + _shiftRight(sum0, _BITS);
- sum2 += _shiftRight(sum1, _BITS);
+ // Implementation of '~/', '%' and 'remainder'.
- if (sum2 < 0) {
- return false;
- }
-
- a._l = sum0 & _MASK;
- a._m = sum1 & _MASK;
- a._h = sum2 & _MASK2;
-
- return true;
- }
-
- // Note: mutates [a] via _trialSubtract.
- static Int64 _divModHelper(Int64 a, Int64 b,
- bool negative, bool aIsNegative, bool aIsMinValue,
- bool computeRemainder) {
- // Align the leading one bits of a and b by shifting b left.
- int shift = b.numberOfLeadingZeros() - a.numberOfLeadingZeros();
- Int64 bshift = b << shift;
-
- // Quotient must be a new instance since we mutate it.
- Int64 quotient = new Int64();
- while (shift >= 0) {
- bool gte = _trialSubtract(a, bshift);
- if (gte) {
- quotient._setBit(shift);
- if (a.isZero) {
- break;
- }
- }
-
- bshift._toShru1();
- shift--;
- }
-
- if (negative) {
- quotient._negate();
- }
-
- if (computeRemainder) {
- if (aIsNegative) {
- _remainder = -a;
- if (aIsMinValue) {
- _remainder = _remainder - ONE;
- }
- } else {
- _remainder = a;
- }
- }
-
- return quotient;
- }
-
- Int64 _divModByMinValue(bool computeRemainder) {
- // MIN_VALUE / MIN_VALUE == 1, remainder = 0
- // (x != MIN_VALUE) / MIN_VALUE == 0, remainder == x
- if (isMinValue) {
- if (computeRemainder) {
- _remainder = ZERO;
- }
- return ONE;
- }
- if (computeRemainder) {
- _remainder = this;
- }
- return ZERO;
- }
-
- /**
- * this &= ((1L << bits) - 1)
- */
- // Note: mutates [this].
- Int64 _maskRight(int bits) {
- int b0, b1, b2;
- if (bits <= _BITS) {
- b0 = _l & ((1 << bits) - 1);
- b1 = b2 = 0;
- } else if (bits <= _BITS01) {
- b0 = _l;
- b1 = _m & ((1 << (bits - _BITS)) - 1);
- b2 = 0;
- } else {
- b0 = _l;
- b1 = _m;
- b2 = _h & ((1 << (bits - _BITS01)) - 1);
- }
-
- _l = b0;
- _m = b1;
- _h = b2;
- }
-
- static Int64 _divModByShift(Int64 a, int bpower, bool negative, bool aIsCopy,
- bool aIsNegative, bool computeRemainder) {
- Int64 c = a >> bpower;
- if (negative) {
- c._negate();
- }
-
- if (computeRemainder) {
- if (!aIsCopy) {
- a = new Int64._copy(a);
- }
- a._maskRight(bpower);
- if (aIsNegative) {
- a._negate();
- }
- _remainder = a;
- }
- return c;
- }
-
- /**
- * Return the exact log base 2 of this, or -1 if this is not a power of two.
- */
- int _powerOfTwo() {
- // Power of two or 0.
- int l = _l;
- if ((l & (l - 1)) != 0) {
- return -1;
- }
- int m = _m;
- if ((m & (m - 1)) != 0) {
- return -1;
- }
- int h = _h;
- if ((h & (h - 1)) != 0) {
- return -1;
- }
- if (h == 0 && m == 0 && l == 0) {
- return -1;
- }
- if (h == 0 && m == 0 && l != 0) {
- return Int32._numberOfTrailingZeros(l);
- }
- if (h == 0 && m != 0 && l == 0) {
- return Int32._numberOfTrailingZeros(m) + _BITS;
- }
- if (h != 0 && m == 0 && l == 0) {
- return Int32._numberOfTrailingZeros(h) + _BITS01;
- }
-
- return -1;
- }
-
- static Int64 _divMod(Int64 a, Int64 b, bool computeRemainder) {
+ static Int64 _divide(Int64 a, other, int what) {
+ Int64 b = _promote(other);
if (b.isZero) {
throw new IntegerDivisionByZeroException();
}
- if (a.isZero) {
- if (computeRemainder) {
- _remainder = ZERO;
+ if (a.isZero) return ZERO;
+
+ bool aNeg = a.isNegative;
+ bool bNeg = b.isNegative;
+ a = a.abs();
+ b = b.abs();
+
+ int a0 = a._l;
+ int a1 = a._m;
+ int a2 = a._h;
+
+ int b0 = b._l;
+ int b1 = b._m;
+ int b2 = b._h;
+ return _divideHelper(a0, a1, a2, aNeg, b0, b1, b2, bNeg, what);
+ }
+
+ static const _RETURN_DIV = 1;
+ static const _RETURN_REM = 2;
+ static const _RETURN_MOD = 3;
+
+ static _divideHelper(
+ // up to 64 bits unsigned in a2/a1/a0 and b2/b1/b0
+ int a0, int a1, int a2, bool aNeg, // input A.
+ int b0, int b1, int b2, bool bNeg, // input B.
+ int what) {
+ int q0 = 0, q1 = 0, q2 = 0; // result Q.
+ int r0 = 0, r1 = 0, r2 = 0; // result R.
+
+ if (b2 == 0 && b1 == 0 && b0 < (1 << (30 - _BITS))) {
+ // Small divisor can be handled by single-digit division within Smi range.
+ //
+ // Handling small divisors here helps the estimate version below by
+ // handling cases where the estimate is off by more than a small amount.
+
+ q2 = a2 ~/ b0;
+ int carry = a2 - q2 * b0;
+ int d1 = a1 + (carry << _BITS);
+ q1 = d1 ~/ b0;
+ carry = d1 - q1 * b0;
+ int d0 = a0 + (carry << _BITS);
+ q0 = d0 ~/ b0;
+ r0 = d0 - q0 * b0;
+ } else {
+ // Approximate Q = A ~/ B and R = A - Q * B using doubles.
+
+ // The floating point approximation is very close to the correct value
+ // when floor(A/B) fits in fewer that 53 bits.
+
+ // We use double arithmetic for intermediate values. Double arithmetic on
+ // non-negative values is exact under the following conditions:
+ //
+ // - The values are integer values that fit in 53 bits.
+ // - Dividing by powers of two (adjusts exponent only).
+ // - Floor (zeroes bits with fractional weight).
+
+ const double K2 = 17592186044416.0; // 2^44
+ const double K1 = 4194304.0; // 2^22
+
+ // Approximate double values for [a] and [b].
+ double ad = a0 + K1 * a1 + K2 * a2;
+ double bd = b0 + K1 * b1 + K2 * b2;
+ // Approximate quotient.
+ double qd = (ad / bd).floorToDouble();
+
+ // Extract components of [qd] using double arithmetic.
+ double q2d = (qd / K2).floorToDouble();
+ qd = qd - K2 * q2d;
+ double q1d = (qd / K1).floorToDouble();
+ double q0d = qd - K1 * q1d;
+ q2 = q2d.toInt();
+ q1 = q1d.toInt();
+ q0 = q0d.toInt();
+
+ assert(q0 + K1 * q1 + K2 * q2 == (ad / bd).floorToDouble());
+ assert(q2 == 0 || b2 == 0); // Q and B can't both be big since Q*B <= A.
+
+ // P = Q * B, using doubles to hold intermediates.
+ // We don't need all partial sums since Q*B <= A.
+ double p0d = q0d * b0;
+ double p0carry = (p0d / K1).floorToDouble();
+ p0d = p0d - p0carry * K1;
+ double p1d = q1d * b0 + q0d * b1 + p0carry;
+ double p1carry = (p1d / K1).floorToDouble();
+ p1d = p1d - p1carry * K1;
+ double p2d = q2d * b0 + q1d * b1 + q0d * b2 + p1carry;
+ assert(p2d <= _MASK2); // No partial sum overflow.
+
+ // R = A - P
+ int diff0 = a0 - p0d.toInt();
+ int diff1 = a1 - p1d.toInt() - ((diff0 >> _BITS) & 1);
+ int diff2 = a2 - p2d.toInt() - ((diff1 >> _BITS) & 1);
+ r0 = _MASK & diff0;
+ r1 = _MASK & diff1;
+ r2 = _MASK2 & diff2;
+
+ // while (R < 0 || R >= B)
+ // adjust R towards [0, B)
+ while (
+ r2 >= _SIGN_BIT_MASK ||
+ r2 > b2 ||
+ (r2 == b2 && (r1 > b1 || (r1 == b1 && r0 >= b0)))) {
+ // Direction multiplier for adjustment.
+ int m = (r2 & _SIGN_BIT_MASK) == 0 ? 1 : -1;
+ // R = R - B or R = R + B
+ int d0 = r0 - m * b0;
+ int d1 = r1 - m * (b1 + ((d0 >> _BITS) & 1));
+ int d2 = r2 - m * (b2 + ((d1 >> _BITS) & 1));
+ r0 = _MASK & d0;
+ r1 = _MASK & d1;
+ r2 = _MASK2 & d2;
+
+ // Q = Q + 1 or Q = Q - 1
+ d0 = q0 + m;
+ d1 = q1 + m * ((d0 >> _BITS) & 1);
+ d2 = q2 + m * ((d1 >> _BITS) & 1);
+ q0 = _MASK & d0;
+ q1 = _MASK & d1;
+ q2 = _MASK2 & d2;
}
- return ZERO;
}
- // MIN_VALUE / MIN_VALUE = 1, anything other a / MIN_VALUE is 0.
- if (b.isMinValue) {
- return a._divModByMinValue(computeRemainder);
- }
- // Normalize b to abs(b), keeping track of the parity in 'negative'.
- // We can do this because we have already ensured that b != MIN_VALUE.
- bool negative = false;
- if (b.isNegative) {
- b = -b;
- negative = !negative;
- }
- // If b == 2^n, bpower will be n, otherwise it will be -1.
- int bpower = b._powerOfTwo();
- // True if the original value of a is negative.
- bool aIsNegative = false;
- // True if the original value of a is Int64.MIN_VALUE.
- bool aIsMinValue = false;
+ // 0 <= R < B
+ assert(Int64.ZERO <= new Int64._bits(r0, r1, r2));
+ assert(r2 < b2 || // Handles case where B = -(MIN_VALUE)
+ new Int64._bits(r0, r1, r2) < new Int64._bits(b0, b1, b2));
- /*
- * Normalize a to a positive value, keeping track of the sign change in
- * 'negative' (which tracks the sign of both a and b and is used to
- * determine the sign of the quotient) and 'aIsNegative' (which is used to
- * determine the sign of the remainder).
- *
- * For all values of a except MIN_VALUE, we can just negate a and modify
- * negative and aIsNegative appropriately. When a == MIN_VALUE, negation is
- * not possible without overflowing 64 bits, so instead of computing
- * abs(MIN_VALUE) / abs(b) we compute (abs(MIN_VALUE) - 1) / abs(b). The
- * only circumstance under which these quotients differ is when b is a power
- * of two, which will divide abs(MIN_VALUE) == 2^64 exactly. In this case,
- * we can get the proper result by shifting MIN_VALUE in unsigned fashion.
- *
- * We make a single copy of a before the first operation that needs to
- * modify its value.
- */
- bool aIsCopy = false;
- if (a.isMinValue) {
- aIsMinValue = true;
- aIsNegative = true;
- // If b is not a power of two, treat -a as MAX_VALUE (instead of the
- // actual value (MAX_VALUE + 1)).
- if (bpower == -1) {
- a = new Int64._copy(MAX_VALUE);
- aIsCopy = true;
- negative = !negative;
+ assert(what == _RETURN_DIV || what == _RETURN_MOD || what == _RETURN_REM);
+ if (what == _RETURN_DIV) {
+ if (aNeg != bNeg) return _negate(q0, q1, q2);
+ return new Int64._bits(q0, q1, q2);
+ }
+
+ if (!aNeg) return new Int64._bits(r0, r1, r2);
+
+ if (what == _RETURN_MOD) {
+ if (r0 == 0 && r1 == 0 && r2 == 0) {
+ return ZERO;
} else {
- // Signed shift of MIN_VALUE produces the right answer.
- Int64 c = a >> bpower;
- if (negative) {
- c._negate();
- }
- if (computeRemainder) {
- _remainder = ZERO;
- }
- return c;
+ return _sub(b0, b1, b2, r0, r1, r2);
}
- } else if (a.isNegative) {
- aIsNegative = true;
- a = -a;
- aIsCopy = true;
- negative = !negative;
+ } else {
+ return _negate(r0, r1, r2);
}
-
- // Now both a and b are non-negative.
- // If b is a power of two, just shift.
- if (bpower != -1) {
- return _divModByShift(a, bpower, negative, aIsCopy, aIsNegative,
- computeRemainder);
- }
-
- // If a < b, the quotient is 0 and the remainder is a.
- if (a < b) {
- if (computeRemainder) {
- if (aIsNegative) {
- _remainder = -a;
- } else {
- _remainder = aIsCopy ? a : new Int64._copy(a);
- }
- }
- return ZERO;
- }
-
- // Generate the quotient using bit-at-a-time long division.
- return _divModHelper(aIsCopy ? a : new Int64._copy(a), b, negative,
- aIsNegative, aIsMinValue, computeRemainder);
}
}
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index d781984..84323ee 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -45,8 +45,8 @@
new Int64.fromInt(-3333));
expect(new Int64.fromInt(-1111) * new Int64.fromInt(-3),
new Int64.fromInt(3333));
- expect(new Int64.fromInt(100) * new Int64.fromInt(0),
- new Int64.fromInt(0));
+ expect(new Int64.fromInt(100) * Int64.ZERO,
+ Int64.ZERO);
expect(new Int64.fromInts(0x12345678, 0x12345678) *
new Int64.fromInts(0x1234, 0x12345678),
@@ -68,7 +68,7 @@
expect((new Int64.fromInt(123456789) * new Int64.fromInt(987654321)),
new Int64.fromInts(0x1b13114, 0xfbff5385));
- expect(Int64.MIN_VALUE * new Int64.fromInt(2), new Int64.fromInt(0));
+ expect(Int64.MIN_VALUE * new Int64.fromInt(2), Int64.ZERO);
expect(Int64.MIN_VALUE * new Int64.fromInt(1), Int64.MIN_VALUE);
expect(Int64.MIN_VALUE * new Int64.fromInt(-1), Int64.MIN_VALUE);
});
@@ -133,7 +133,7 @@
expect(new Int64.fromInt(-1000) ~/ new Int64.fromInt(-3),
new Int64.fromInt(333));
expect(new Int64.fromInt(3) ~/ new Int64.fromInt(1000),
- new Int64.fromInt(0));
+ Int64.ZERO);
expect(new Int64.fromInts( 0x12345678, 0x12345678) ~/
new Int64.fromInts(0x0, 0x123),
new Int64.fromInts(0x1003d0, 0xe84f5ae8));
@@ -152,7 +152,7 @@
new Int32.fromInt(432461));
expect(new Int64.fromInt(829893893) ~/ 1919,
new Int32.fromInt(432461));
- expect(() => new Int64.fromInt(1) ~/ new Int64.fromInt(0),
+ expect(() => new Int64.fromInt(1) ~/ Int64.ZERO,
throwsA(new isInstanceOf<IntegerDivisionByZeroException>()));
expect(Int64.MIN_VALUE ~/ new Int64.fromInt(2),
new Int64.fromInts(0xc0000000, 0x00000000));
@@ -164,11 +164,11 @@
test("%", () {
// Define % as Euclidean mod, with positive result for all arguments
- expect(Int64.ZERO % new Int64.fromInt(1000), new Int64.fromInt(0));
- expect(Int64.MIN_VALUE % Int64.MIN_VALUE, new Int64.fromInt(0));
+ expect(Int64.ZERO % new Int64.fromInt(1000), Int64.ZERO);
+ expect(Int64.MIN_VALUE % Int64.MIN_VALUE, Int64.ZERO);
expect(new Int64.fromInt(1000) % Int64.MIN_VALUE,
new Int64.fromInt(1000));
- expect(Int64.MIN_VALUE % new Int64.fromInt(8192), new Int64.fromInt(0));
+ expect(Int64.MIN_VALUE % new Int64.fromInt(8192), Int64.ZERO);
expect(Int64.MIN_VALUE % new Int64.fromInt(8193),
new Int64.fromInt(6145));
expect(new Int64.fromInt(-1000) % new Int64.fromInt(8192),
@@ -223,7 +223,7 @@
expect(new Int64.fromInt(10) < new Int32.fromInt(10), false);
expect(new Int64.fromInt(10) < new Int32.fromInt(9), false);
expect(new Int64.fromInt(-10) < new Int64.fromInt(-11), false);
- expect(Int64.MIN_VALUE < new Int64.fromInt(0), true);
+ expect(Int64.MIN_VALUE < Int64.ZERO, true);
expect(largeNeg < largePos, true);
expect(largePos < largePosPlusOne, true);
expect(largePos < largePos, false);
@@ -303,7 +303,7 @@
expect(largePos > largePosPlusOne, false);
expect(largePos > largePos, false);
expect(largePosPlusOne > largePos, true);
- expect(new Int64.fromInt(0) > Int64.MIN_VALUE, true);
+ expect(Int64.ZERO > Int64.MIN_VALUE, true);
expect(Int64.MIN_VALUE > Int64.MAX_VALUE, false);
expect(Int64.MAX_VALUE > Int64.MIN_VALUE, true);
expect(() => new Int64.fromInt(17) > null, throwsArgumentError);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index f5a12e1..57a28b4 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -65,9 +65,6 @@
polymer/test/events_test: Fail # Issue 12865, 13197
polymer/test/event_path_test: Fail # Issue 12865, 13197
-[ $runtime == safari || $runtime == ie9 ]
-polymer_expressions/test/syntax_test: Fail # Issue 13361
-
[ $runtime == ff ]
polymer/test/event_path_test: Fail # Issue 12865, 13197
@@ -126,6 +123,10 @@
crypto/test/sha1_test: Slow, Pass
polymer/example/component: Fail # Issue 13198
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+docgen/test/single_library_test: Fail # TODO(kasperl): Please triage.
+intl/test/date_time_format_http_request_test: Fail # TODO(kasperl): Please triage.
+
[ $browser ]
analyzer_experimental/test/error_test: Fail, OK # Uses dart:io.
analyzer_experimental/test/generated/element_test: Fail, OK # Uses dart:io.
@@ -230,6 +231,3 @@
# Issue http://dartbug.com/12930
[ $runtime == vm ]
intl/test/message_extraction/message_extraction_test: Pass, Fail # Issue 12930
-
-[ $compiler == none && $runtime == drt && $arch == ia32 ]
-custom_element/test/custom_element_test: Fail, Pass # http://dartbug.com/12964
diff --git a/pkg/polymer_expressions/example/example.dart b/pkg/polymer_expressions/example/example.dart
index f3ad658..5266311 100644
--- a/pkg/polymer_expressions/example/example.dart
+++ b/pkg/polymer_expressions/example/example.dart
@@ -4,13 +4,18 @@
import 'dart:html';
-import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:logging/logging.dart';
import 'package:mdv/mdv.dart' as mdv;
+import 'package:polymer_expressions/polymer_expressions.dart';
import 'person.dart';
main() {
mdv.initialize();
+ new Logger('polymer_expressions').onRecord.listen((LogRecord r) {
+ print("${r.loggerName} ${r.level} ${r.message}");
+ });
+
var john = new Person('John', 'Messerly', ['A', 'B', 'C']);
var justin = new Person('Justin', 'Fagnani', ['D', 'E', 'F']);
var globals = {
diff --git a/pkg/polymer_expressions/lib/eval.dart b/pkg/polymer_expressions/lib/eval.dart
index b76b3b8..c191bd9 100644
--- a/pkg/polymer_expressions/lib/eval.dart
+++ b/pkg/polymer_expressions/lib/eval.dart
@@ -47,16 +47,33 @@
/**
* Evaluation [expr] in the context of [scope].
*/
-Object eval(Expression expr, Scope scope) => observe(expr, scope)._value;
+Object eval(Expression expr, Scope scope) {
+ var observer = observe(expr, scope);
+ new Updater(scope).visit(observer);
+ return observer._value;
+}
-
+/**
+ * Returns an [ExpressionObserver] that evaluates [expr] in the context of
+ * scope] and listens for any changes on [Observable] values that are
+ * returned from sub-expressions. When a value changes the expression is
+ * reevaluated and the new result is sent to the [onUpdate] stream of the
+ * [ExpressionObsserver].
+ */
ExpressionObserver observe(Expression expr, Scope scope) {
var observer = new ObserverBuilder(scope).visit(expr);
- new Updater(scope).visit(observer);
return observer;
}
/**
+ * Causes [expr] to be reevaluated a returns it's value.
+ */
+Object update(ExpressionObserver expr, Scope scope) {
+ new Updater(scope).visit(expr);
+ return expr.currentValue;
+}
+
+/**
* Assign [value] to the variable or field referenced by [expr] in the context
* of [scope].
*
@@ -166,7 +183,7 @@
if (parent != null) {
return _convert(parent[name]);
} else {
- throw new EvalException("variable not found: $name in $hashCode");
+ throw new EvalException("variable '$name' not found");
}
}
@@ -205,8 +222,6 @@
}
return false;
}
-
- String toString() => 'Scope($hashCode $parent)';
}
Object _convert(v) {
diff --git a/pkg/polymer_expressions/lib/polymer_expressions.dart b/pkg/polymer_expressions/lib/polymer_expressions.dart
index d74daca..e7148ad 100644
--- a/pkg/polymer_expressions/lib/polymer_expressions.dart
+++ b/pkg/polymer_expressions/lib/polymer_expressions.dart
@@ -16,7 +16,7 @@
* [Polymer.dart](http://www.dartlang.org/polymer-dart/)
* homepage for example code, project status, and
* information about how to get started using Polymer.dart in your apps.
- *
+ *
* ## Other resources
*
* The
@@ -31,11 +31,14 @@
import 'dart:html';
import 'package:observe/observe.dart';
+import 'package:logging/logging.dart';
import 'eval.dart';
import 'expression.dart';
import 'parser.dart';
+final Logger _logger = new Logger('polymer_expressions');
+
// TODO(justin): Investigate XSS protection
Object _classAttributeConverter(v) =>
(v is Map) ? v.keys.where((k) => v[k] == true).join(' ') :
@@ -86,12 +89,18 @@
final _converter;
var _value;
-
_Binding(Expression expr, Scope scope, [this._converter])
: _expr = observe(expr, scope),
_scope = scope {
- _expr.onUpdate.listen(_setValue);
- _setValue(_expr.currentValue);
+ _expr.onUpdate.listen(_setValue).onError((e) {
+ _logger.warning("Error evaluating expression '$_expr': ${e.message}");
+ });
+ try {
+ update(_expr, _scope);
+ _setValue(_expr.currentValue);
+ } on EvalException catch (e) {
+ _logger.warning("Error evaluating expression '$_expr': ${e.message}");
+ }
}
_setValue(v) {
diff --git a/pkg/polymer_expressions/test/eval_test.dart b/pkg/polymer_expressions/test/eval_test.dart
index 96fcd2d..0ed7456 100644
--- a/pkg/polymer_expressions/test/eval_test.dart
+++ b/pkg/polymer_expressions/test/eval_test.dart
@@ -371,8 +371,9 @@
mutate(),
dynamic afterMatcher}) {
- var observer = observe(new Parser(s).parse(),
- new Scope(model: model, variables: variables));
+ var scope = new Scope(model: model, variables: variables);
+ var observer = observe(new Parser(s).parse(), scope);
+ update(observer, scope);
expect(observer.currentValue, beforeMatcher);
var passed = false;
var future = observer.onUpdate.first.then((value) {
diff --git a/pkg/polymer_expressions/test/syntax_test.dart b/pkg/polymer_expressions/test/syntax_test.dart
index 82c3e60..dfc6689 100644
--- a/pkg/polymer_expressions/test/syntax_test.dart
+++ b/pkg/polymer_expressions/test/syntax_test.dart
@@ -5,11 +5,12 @@
import 'dart:async';
import 'dart:html';
-import 'package:polymer_expressions/polymer_expressions.dart';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_enhanced_config.dart';
-import 'package:observe/observe.dart';
import 'package:mdv/mdv.dart' as mdv;
+import 'package:logging/logging.dart';
+import 'package:observe/observe.dart';
+import 'package:polymer_expressions/polymer_expressions.dart';
+import 'package:unittest/html_enhanced_config.dart';
+import 'package:unittest/unittest.dart';
main() {
mdv.initialize();
@@ -23,7 +24,7 @@
});
tearDown(() {
- testDiv.remove();
+ testDiv.firstChild.remove();
testDiv = null;
});
@@ -54,14 +55,30 @@
<template repeat="{{ item in items }}">
{{ item }}
</template>
- </template>'''));
- query('#test')
- ..bindingDelegate = new PolymerExpressions(globals: {'items': null})
- ..model = null;
+ </template>'''));
+ query('#test').bindingDelegate =
+ new PolymerExpressions(globals: {'items': null});
// the template should be the only node
expect(testDiv.nodes.length, 1);
expect(testDiv.nodes[0].id, 'test');
});
+
+ test('should silently handle bad variable names', () {
+ var logger = new Logger('polymer_expressions');
+ var logFuture = logger.onRecord.toList();
+ testDiv.nodes.add(new Element.html('''
+ <template id="test" bind>{{ foo }}</template>'''));
+ query('#test').bindingDelegate = new PolymerExpressions();
+ return new Future(() {
+ logger.clearListeners();
+ return logFuture.then((records) {
+ expect(records.length, 1);
+ expect(records.first.message,
+ contains('Error evaluating expression'));
+ expect(records.first.message, contains('foo'));
+ });
+ });
+ });
});
}
diff --git a/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart b/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart
index c71b7e8..7e6d3fc 100644
--- a/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart
+++ b/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart
@@ -225,52 +225,52 @@
});
test("$name - skip", () {
- expect(wrapped.skip(0), equals(original.skip(0)));
- expect(wrapped.skip(1), equals(original.skip(1)));
- expect(wrapped.skip(5), equals(original.skip(5)));
+ expect(wrapped.skip(0), orderedEquals(original.skip(0)));
+ expect(wrapped.skip(1), orderedEquals(original.skip(1)));
+ expect(wrapped.skip(5), orderedEquals(original.skip(5)));
});
test("$name - skipWhile", () {
expect(wrapped.skipWhile((x) => true),
- equals(original.skipWhile((x) => true)));
+ orderedEquals(original.skipWhile((x) => true)));
expect(wrapped.skipWhile((x) => false),
- equals(original.skipWhile((x) => false)));
+ orderedEquals(original.skipWhile((x) => false)));
expect(wrapped.skipWhile((x) => x != 42),
- equals(original.skipWhile((x) => x != 42)));
+ orderedEquals(original.skipWhile((x) => x != 42)));
});
test("$name - take", () {
- expect(wrapped.take(0), equals(original.take(0)));
- expect(wrapped.take(1), equals(original.take(1)));
- expect(wrapped.take(5), equals(original.take(5)));
+ expect(wrapped.take(0), orderedEquals(original.take(0)));
+ expect(wrapped.take(1), orderedEquals(original.take(1)));
+ expect(wrapped.take(5), orderedEquals(original.take(5)));
});
test("$name - takeWhile", () {
expect(wrapped.takeWhile((x) => true),
- equals(original.takeWhile((x) => true)));
+ orderedEquals(original.takeWhile((x) => true)));
expect(wrapped.takeWhile((x) => false),
- equals(original.takeWhile((x) => false)));
+ orderedEquals(original.takeWhile((x) => false)));
expect(wrapped.takeWhile((x) => x != 42),
- equals(original.takeWhile((x) => x != 42)));
+ orderedEquals(original.takeWhile((x) => x != 42)));
});
test("$name - toList", () {
- expect(wrapped.toList(), equals(original.toList()));
+ expect(wrapped.toList(), orderedEquals(original.toList()));
expect(wrapped.toList(growable: false),
- equals(original.toList(growable: false)));
+ orderedEquals(original.toList(growable: false)));
});
test("$name - toSet", () {
- expect(wrapped.toSet(), equals(original.toSet()));
+ expect(wrapped.toSet(), unorderedEquals(original.toSet()));
});
test("$name - where", () {
expect(wrapped.where((x) => true),
- equals(original.where((x) => true)));
+ orderedEquals(original.where((x) => true)));
expect(wrapped.where((x) => false),
- equals(original.where((x) => false)));
+ orderedEquals(original.where((x) => false)));
expect(wrapped.where((x) => x != 42),
- equals(original.where((x) => x != 42)));
+ orderedEquals(original.where((x) => x != 42)));
});
}
@@ -372,7 +372,7 @@
List sortCopy = new List.from(original);
sortCopy.sort();
wrapped.sort();
- expect(original, equals(sortCopy));
+ expect(original, orderedEquals(sortCopy));
original.setAll(0, copy);
});
@@ -475,20 +475,20 @@
test("$name - intersection", () {
expect(wrapped.intersection(new Set()), isEmpty);
- expect(wrapped.intersection(copy), equals(original));
+ expect(wrapped.intersection(copy), unorderedEquals(original));
expect(wrapped.intersection(new Set.from([42])),
new Set.from(original.contains(42) ? [42] : []));
});
test("$name - union", () {
- expect(wrapped.union(new Set()), equals(original));
- expect(wrapped.union(copy), equals(original));
+ expect(wrapped.union(new Set()), unorderedEquals(original));
+ expect(wrapped.union(copy), unorderedEquals(original));
expect(wrapped.union(new Set.from([42])),
equals(original.union(new Set.from([42]))));
});
test("$name - difference", () {
- expect(wrapped.difference(new Set()), equals(original));
+ expect(wrapped.difference(new Set()), unorderedEquals(original));
expect(wrapped.difference(copy), isEmpty);
expect(wrapped.difference(new Set.from([42])),
equals(original.difference(new Set.from([42]))));
@@ -496,13 +496,13 @@
}
void testNoChangeSet(Set original, Set wrapped, String name) {
- Set copy = new Set.from(original);
+ List originalElements = original.toList();
testThrows(name, thunk) {
test(name, () {
expect(thunk, throwsUnsupportedError);
// No modifications happened.
- expect(original, equals(copy));
+ expect(original.toList(), equals(originalElements));
});
}
@@ -584,11 +584,11 @@
});
test("$name keys", () {
- expect(wrapped.keys, equals(original.keys));
+ expect(wrapped.keys, orderedEquals(original.keys));
});
test("$name values", () {
- expect(wrapped.values, equals(original.values));
+ expect(wrapped.values, orderedEquals(original.values));
});
}
diff --git a/runtime/bin/builtin_impl_sources.gypi b/runtime/bin/builtin_impl_sources.gypi
index 9d9d8ac..d62c091 100644
--- a/runtime/bin/builtin_impl_sources.gypi
+++ b/runtime/bin/builtin_impl_sources.gypi
@@ -61,5 +61,6 @@
'utils_linux.cc',
'utils_macos.cc',
'utils_win.cc',
+ 'utils_win.h',
],
}
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 89698c0..e6f705b 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -54,7 +54,7 @@
V(File_DeleteLink, 1) \
V(File_Rename, 2) \
V(File_RenameLink, 2) \
- V(File_FullPath, 1) \
+ V(File_ResolveSymbolicLinks, 1) \
V(File_OpenStdio, 1) \
V(File_GetStdioHandleType, 1) \
V(File_GetType, 2) \
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 35ea5fc..0ae6aad 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -508,7 +508,7 @@
}
-void FUNCTION_NAME(File_FullPath)(Dart_NativeArguments args) {
+void FUNCTION_NAME(File_ResolveSymbolicLinks)(Dart_NativeArguments args) {
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
char* path = File::GetCanonicalPath(str);
@@ -711,7 +711,7 @@
}
-static CObject* FileFullPathRequest(const CObjectArray& request) {
+static CObject* FileResolveSymbolicLinksRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
char* result = File::GetCanonicalPath(filename.CString());
@@ -1191,8 +1191,8 @@
case File::kRenameRequest:
response = FileRenameRequest(request);
break;
- case File::kFullPathRequest:
- response = FileFullPathRequest(request);
+ case File::kResolveSymbolicLinksRequest:
+ response = FileResolveSymbolicLinksRequest(request);
break;
case File::kCloseRequest:
response = FileCloseRequest(request);
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 3908154..a6eccce 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -67,7 +67,7 @@
kDeleteRequest = 2,
kRenameRequest = 3,
kOpenRequest = 4,
- kFullPathRequest = 5,
+ kResolveSymbolicLinksRequest = 5,
kCloseRequest = 6,
kPositionRequest = 7,
kSetPositionRequest = 8,
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 7732c2c..ea121f2 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -22,7 +22,6 @@
/* patch */ static _lastModified(String path) native "File_LastModified";
/* patch */ static _open(String path, int mode) native "File_Open";
/* patch */ static int _openStdio(int fd) native "File_OpenStdio";
- /* patch */ static _fullPath(String path) native "File_FullPath";
}
patch class _RandomAccessFile {
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 2c2b324..e6b3fdc 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -12,4 +12,6 @@
native "File_GetType";
/* patch */ static _identical(String path1, String path2)
native "File_AreIdentical";
+ /* patch */ static _resolveSymbolicLinks(String path)
+ native "File_ResolveSymbolicLinks";
}
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 08417ea..e7cedb4 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -471,20 +471,50 @@
char* File::GetCanonicalPath(const char* pathname) {
struct _stat st;
const wchar_t* system_name = StringUtils::Utf8ToWide(pathname);
- int stat_status = _wstat(system_name, &st);
- if (stat_status != 0) {
- SetLastError(ERROR_FILE_NOT_FOUND);
+ HANDLE file_handle = CreateFileW(
+ system_name,
+ 0,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (file_handle == INVALID_HANDLE_VALUE) {
free(const_cast<wchar_t*>(system_name));
return NULL;
}
- int required_size = GetFullPathNameW(system_name, 0, NULL, NULL);
+ wchar_t dummy_buffer[1];
+ int required_size = GetFinalPathNameByHandle(file_handle,
+ dummy_buffer,
+ 0,
+ VOLUME_NAME_DOS);
+ if (required_size == 0) {
+ free(const_cast<wchar_t*>(system_name));
+ DWORD error = GetLastError();
+ CloseHandle(file_handle);
+ SetLastError(error);
+ return NULL;
+ }
wchar_t* path =
static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t)));
- int written = GetFullPathNameW(system_name, required_size, path, NULL);
+ int result_size = GetFinalPathNameByHandle(file_handle,
+ path,
+ required_size,
+ VOLUME_NAME_DOS);
+ ASSERT(result_size <= required_size - 1);
+ // Remove leading \\?\ if possible, unless input used it.
+ char* result;
+ if (result_size < MAX_PATH - 1 + 4 &&
+ result_size > 4 &&
+ wcsncmp(path, L"\\\\?\\", 4) == 0 &&
+ wcsncmp(system_name, L"\\\\?\\", 4) != 0) {
+ result = StringUtils::WideToUtf8(path + 4);
+ } else {
+ result = StringUtils::WideToUtf8(path);
+ }
free(const_cast<wchar_t*>(system_name));
- ASSERT(written <= (required_size - 1));
- char* result = StringUtils::WideToUtf8(path);
free(path);
+ CloseHandle(file_handle);
return result;
}
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index d3efd4c..c83afab 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -13,6 +13,7 @@
#include "bin/log.h"
#include "bin/thread.h"
#include "bin/utils.h"
+#include "bin/utils_win.h"
namespace dart {
@@ -305,21 +306,7 @@
int error_code = GetLastError();
static const int kMaxMessageLength = 256;
wchar_t message[kMaxMessageLength];
- DWORD message_size =
- FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error_code,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- message,
- kMaxMessageLength,
- NULL);
- if (message_size == 0) {
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- Log::PrintErr("FormatMessage failed %d\n", GetLastError());
- }
- _snwprintf(message, kMaxMessageLength, L"OS Error %d", error_code);
- }
- message[kMaxMessageLength - 1] = '\0';
+ FormatMessageIntoBuffer(error_code, message, kMaxMessageLength);
*os_error_message = StringUtils::WideToUtf8(message);
return error_code;
}
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index b926dd7..dab7355 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -9,15 +9,14 @@
#include <time.h> // NOLINT
#include "bin/utils.h"
+#include "bin/utils_win.h"
#include "bin/log.h"
namespace dart {
namespace bin {
-static void FormatMessageIntoBuffer(DWORD code,
- wchar_t* buffer,
- int buffer_length) {
+void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length) {
DWORD message_size =
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
@@ -28,11 +27,14 @@
NULL);
if (message_size == 0) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- Log::PrintErr("FormatMessage failed %d\n", GetLastError());
+ Log::PrintErr("FormatMessage failed for error code %d (error %d)\n",
+ code,
+ GetLastError());
}
_snwprintf(buffer, buffer_length, L"OS Error %d", code);
}
- buffer[buffer_length - 1] = '\0';
+ // Ensure string termination.
+ buffer[buffer_length - 1] = 0;
}
diff --git a/runtime/bin/utils_win.h b/runtime/bin/utils_win.h
new file mode 100644
index 0000000..a044760
--- /dev/null
+++ b/runtime/bin/utils_win.h
@@ -0,0 +1,18 @@
+// 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.
+
+#ifndef BIN_UTILS_WIN_H_
+#define BIN_UTILS_WIN_H_
+
+#include "platform/globals.h"
+
+namespace dart {
+namespace bin {
+
+void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length);
+
+} // namespace bin
+} // namespace dart
+
+#endif // BIN_UTILS_WIN_H_
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 3716cca..61cf8d6 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -430,7 +430,7 @@
class _HashMapKeyIterable<K> extends _HashMapIterable<K> {
_HashMapKeyIterable(HashMap map) : super(map);
Iterator<K> get iterator => new _HashMapKeyIterator<K>(_map);
- bool contains(K key) => _map.containsKey(key);
+ bool contains(Object key) => _map.containsKey(key);
void forEach(void action(K key)) {
_map.forEach((K key, _) {
action(key);
@@ -441,7 +441,7 @@
class _HashMapValueIterable<V> extends _HashMapIterable<V> {
_HashMapValueIterable(HashMap map) : super(map);
Iterator<V> get iterator => new _HashMapValueIterator<V>(_map);
- bool contains(V value) => _map.containsValue(value);
+ bool contains(Object value) => _map.containsValue(value);
void forEach(void action(V value)) {
_map.forEach((_, V value) {
action(value);
@@ -504,86 +504,291 @@
}
patch class HashSet<E> {
- static const int _INITIAL_CAPACITY = 8;
- final _HashTable<E> _table;
-
- /* patch */ HashSet() : _table = new _HashTable(_INITIAL_CAPACITY) {
- _table._container = this;
- }
-
- factory HashSet.from(Iterable<E> iterable) {
- return new HashSet<E>()..addAll(iterable);
- }
-
- // Iterable.
- /* patch */ Iterator<E> get iterator => new _HashTableKeyIterator<E>(_table);
-
- /* patch */ int get length => _table._elementCount;
-
- /* patch */ bool get isEmpty => _table._elementCount == 0;
-
- /* patch */ bool get isNotEmpty => !isEmpty;
-
- /* patch */ bool contains(Object object) => _table._get(object) >= 0;
-
- // Collection.
- /* patch */ void add(E element) {
- _table._put(element);
- _table._checkCapacity();
- }
-
- /* patch */ void addAll(Iterable<E> objects) {
- for (E object in objects) {
- _table._put(object);
- _table._checkCapacity();
- }
- }
-
- /* patch */ bool remove(Object object) {
- int offset = _table._remove(object);
- _table._checkCapacity();
- return offset >= 0;
- }
-
- /* patch */ void removeAll(Iterable<Object> objectsToRemove) {
- for (Object object in objectsToRemove) {
- _table._remove(object);
- _table._checkCapacity();
- }
- }
-
- void _filterWhere(bool test(E element), bool removeMatching) {
- int entrySize = _table._entrySize;
- int length = _table._table.length;
- for (int offset = 0; offset < length; offset += entrySize) {
- Object entry = _table._table[offset];
- if (!_table._isFree(entry)) {
- E key = identical(entry, _NULL) ? null : entry;
- int modificationCount = _table._modificationCount;
- bool shouldRemove = (removeMatching == test(key));
- _table._checkModification(modificationCount);
- if (shouldRemove) {
- _table._deleteEntry(offset);
+ /* patch */ factory HashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
+ if (isValidKey == null) {
+ if (hashCode == null) {
+ if (equals == null) {
+ return new _HashSet<E>();
}
+ if (identical(identical, equals)) {
+ return new _IdentityHashSet<E>();
+ }
+ _hashCode = _defaultHashCode;
+ } else if (equals == null) {
+ _equals = _defaultEquals;
}
+ isValidKey = new _TypeTest<E>().test;
+ } else {
+ if (hashCode == null) hashCode = _defaultHashCode;
+ if (equals == null) equals = _defaultEquals;
}
- _table._checkCapacity();
- }
-
- /* patch */ void removeWhere(bool test(E element)) {
- _filterWhere(test, true);
- }
-
- /* patch */ void retainWhere(bool test(E element)) {
- _filterWhere(test, false);
- }
-
- /* patch */ void clear() {
- _table._clear();
+ return new _CustomHashSet<E>(equals, hashCode, isValidKey);
}
}
+class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> {
+ static const int _INITIAL_CAPACITY = 8;
+
+ List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY);
+ int _elementCount = 0;
+ int _modificationCount = 0;
+
+ bool _equals(e1, e2) => e1 == e2;
+ int _hashCode(e) => e.hashCode;
+
+ // Iterable.
+
+ Iterator<E> get iterator => new _HashSetIterator<E>(this);
+
+ int get length => _elementCount;
+
+ bool get isEmpty => _elementCount == 0;
+
+ bool get isNotEmpty => _elementCount != 0;
+
+ bool contains(Object object) {
+ int index = _hashCode(object) & (_buckets.length - 1);
+ HashSetEntry entry = _buckets[index];
+ while (entry != null) {
+ if (_equals(entry.key, object)) return true;
+ entry = entry.next;
+ }
+ return false;
+ }
+
+ // Set.
+
+ void add(E element) {
+ int hashCode = _hashCode(element);
+ int index = hashCode & (_buckets.length - 1);
+ HashSetEntry entry = _buckets[index];
+ while (entry != null) {
+ if (_equals(entry.key, element)) return;
+ entry = entry.next;
+ }
+ _addEntry(element, hashCode, index);
+ }
+
+ void addAll(Iterable<E> objects) {
+ int ctr = 0;
+ for (E object in objects) {
+ ctr++;
+ add(object);
+ }
+ }
+
+ bool _remove(Object object, int hashCode) {
+ int index = hashCode & (_buckets.length - 1);
+ _HashSetEntry entry = _buckets[index];
+ _HashSetEntry previous = null;
+ while (entry != null) {
+ if (_equals(entry.key, object)) {
+ _HashSetEntry next = entry.remove();
+ if (previous == null) {
+ _buckets[index] = next;
+ } else {
+ previous.next = next;
+ }
+ _elementCount--;
+ _modificationCount =
+ (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ return true;
+ }
+ previous = entry;
+ entry = entry.next;
+ }
+ return false;
+ }
+
+ bool remove(Object object) => _remove(object, _hashCode(object));
+
+ void removeAll(Iterable<Object> objectsToRemove) {
+ for (Object object in objectsToRemove) {
+ _remove(object, _hashCode(object));
+ }
+ }
+
+ void retainAll(Iterable<Object> objectsToRetain) {
+ super._retainAll(objectsToRetain, (o) => o is E);
+ }
+
+ void _filterWhere(bool test(E element), bool removeMatching) {
+ int length = _buckets.length;
+ for (int index = 0; index < length; index++) {
+ HashSetEntry entry = _buckets[index];
+ HashSetEntry previous = null;
+ while (entry != null) {
+ int modificationCount = _modificationCount;
+ bool testResult = test(entry.key);
+ if (modificationCount != _modificationCount) {
+ throw new ConcurrentModificationError(this);
+ }
+ if (testResult == removeMatching) {
+ HashSetEntry next = entry.remove();
+ if (previous == null) {
+ _buckets[index] = next;
+ } else {
+ previous.next = next;
+ }
+ _elementCount--;
+ _modificationCount =
+ (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ entry = next;
+ } else {
+ previous = entry;
+ entry = entry.next;
+ }
+ }
+ }
+ }
+
+ void removeWhere(bool test(E element)) {
+ _filterWhere(test, true);
+ }
+
+ void retainWhere(bool test(E element)) {
+ _filterWhere(test, false);
+ }
+
+ void clear() {
+ _elementCount = 0;
+ _buckets = new List(_INITIAL_CAPACITY);
+ _modificationCount++;
+ }
+
+ void _addEntry(E key, int hashCode, int index) {
+ _buckets[index] = new _HashSetEntry(key, hashCode, _buckets[index]);
+ int newElements = _elementCount + 1;
+ _elementCount = newElements;
+ int length = _buckets.length;
+ // If we end up with more than 75% non-empty entries, we
+ // resize the backing store.
+ if ((newElements << 2) > ((length << 1) + length)) _resize();
+ _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ }
+
+ void _resize() {
+ int oldLength = _buckets.length;
+ int newLength = oldLength << 1;
+ List oldBuckets = _buckets;
+ List newBuckets = new List(newLength);
+ for (int i = 0; i < oldLength; i++) {
+ _HashSetEntry entry = oldBuckets[i];
+ while (entry != null) {
+ _HashSetEntry next = entry.next;
+ int newIndex = entry.hashCode & (newLength - 1);
+ entry.next = newBuckets[newIndex];
+ newBuckets[newIndex] = entry;
+ entry = next;
+ }
+ }
+ _buckets = newBuckets;
+ }
+
+ HashSet<E> _newSet() => new _HashSet<E>();
+}
+
+class _IdentityHashSet<E> extends _HashSet<E> {
+ bool _equals(e1, e2) => identical(e1, e2);
+ HashSet<E> _newSet() => new _IdentityHashSet<E>();
+}
+
+class _CustomHashSet<E> extends _HashSet<E> {
+ final _Equality<E> _equality;
+ final _Hasher<E> _hasher;
+ final _Predicate _validKey;
+ _CustomHashSet(this._equality, this._hasher, this._validKey);
+
+ bool remove(Object element) {
+ if (!_validKey(element)) return false;
+ return super.remove(element);
+ }
+
+ bool contains(Object element) {
+ if (!_validKey(element)) return false;
+ return super.contains(element);
+ }
+
+ bool containsAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (!_validKey(element) || !this.contains(element)) return false;
+ }
+ return true;
+ }
+
+ void removeAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (_validKey(element)) {
+ super._remove(element, _hasher(element));
+ }
+ }
+ }
+
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, _validKey);
+ }
+
+ bool _equals(e1, e2) => _equality(e1, e2);
+ int _hashCode(e) => _hasher(e);
+
+ HashSet<E> _newSet() => new _CustomHashSet<E>(_equality, _hasher, _validKey);
+}
+
+class _HashSetEntry {
+ final key;
+ final int hashCode;
+ _HashSetEntry next;
+ _HashSetEntry(this.key, this.hashCode, this.next);
+
+ _HashSetEntry remove() {
+ _HashSetEntry result = next;
+ next = null;
+ return result;
+ }
+}
+
+class _HashSetIterator<E> implements Iterator<E> {
+ final _HashSet _set;
+ final int _modificationCount;
+ int _index = 0;
+ _HashSetEntry _next = null;
+ E _current = null;
+
+ _HashSetIterator(_HashSet hashSet)
+ : _set = hashSet, _modificationCount = hashSet._modificationCount;
+
+ bool moveNext() {
+ if (_modificationCount != _set._modificationCount) {
+ throw new ConcurrentModificationError(_set);
+ }
+ if (_next != null) {
+ _current = _next.key;
+ _next = _next.next;
+ return true;
+ }
+ List<_HashSetEntry> buckets = _set._buckets;
+ while (_index < buckets.length) {
+ _next = buckets[_index];
+ _index = _index + 1;
+ if (_next != null) {
+ _current = _next.key;
+ _next = _next.next;
+ return true;
+ }
+ }
+ _current = null;
+ return false;
+ }
+
+ E get current => _current;
+}
+
class _LinkedHashMapEntry extends _HashMapEntry {
+ /// Double-linked list of entries of a linked hash map.
+ /// The _LinkedHashMap itself is the head of the list, so the type is "var".
+ /// Both are initialized to `this` when initialized.
var _nextEntry;
var _previousEntry;
_LinkedHashMapEntry(key, value, int hashCode, _LinkedHashMapEntry next,
@@ -598,7 +803,7 @@
LinkedHashMap<K, dynamic> _map;
_LinkedHashMapKeyIterable(this._map);
Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map);
- bool contains(K key) => _map.containsKey(key);
+ bool contains(Object key) => _map.containsKey(key);
bool get isEmpty => _map.isEmpty;
bool get isNotEmpty => _map.isNotEmpty;
int get length => _map.length;
@@ -608,7 +813,7 @@
LinkedHashMap<dynamic, V> _map;
_LinkedHashMapValueIterable(this._map);
Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map);
- bool contains(V value) => _map.containsValue(value);
+ bool contains(Object value) => _map.containsValue(value);
bool get isEmpty => _map.isEmpty;
bool get isNotEmpty => _map.isNotEmpty;
int get length => _map.length;
@@ -659,6 +864,11 @@
* A hash-based map that iterates keys and values in key insertion order.
*/
patch class LinkedHashMap<K, V> {
+ /// Holds a double-linked list of entries in insertion order.
+ /// The fields have the same name as the ones in [_LinkedHashMapEntry],
+ /// and this map is itself used as the head entry of the list.
+ /// Set to `this` when initialized, representing the empty list (containing
+ /// only the head entry itself).
var _nextEntry;
var _previousEntry;
@@ -738,6 +948,7 @@
buckets[index] = entry;
int newElements = _elementCount + 1;
_elementCount = newElements;
+
// If we end up with more than 75% non-empty entries, we
// resize the backing store.
if ((newElements << 2) > ((length << 1) + length)) _resize();
@@ -788,703 +999,213 @@
}
-patch class LinkedHashSet<E> extends _HashSetBase<E> {
- static const int _INITIAL_CAPACITY = 8;
- _LinkedHashTable<E> _table;
+patch class LinkedHashSet<E> {
+ /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
+ if (isValidKey == null) {
+ if (hashCode == null) {
+ if (equals == null) {
+ return new _LinkedHashSet<E>();
+ }
+ if (identical(identical, equals)) {
+ return new _LinkedIdentityHashSet<E>();
+ }
+ _hashCode = _defaultHashCode;
+ } else if (equals == null) {
+ _equals = _defaultEquals;
+ }
+ isValidKey = new _TypeTest<E>().test;
+ } else {
+ if (hashCode == null) hashCode = _defaultHashCode;
+ if (equals == null) equals = _defaultEquals;
+ }
+ return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey);
+ }
+}
- /* patch */ LinkedHashSet() {
- _table = new _LinkedHashTable(_INITIAL_CAPACITY);
- _table._container = this;
+class _LinkedHashSetEntry extends _HashSetEntry {
+ /// Links this element into a double-linked list of elements of a hash set.
+ /// The hash set object itself is used as the head entry of the list, so
+ /// the field is typed as "var".
+ /// Both links are initialized to `this` when the object is created.
+ var _nextEntry;
+ var _previousEntry;
+ _LinkedHashSetEntry(var key, int hashCode, _LinkedHashSetEntry next,
+ this._previousEntry, this._nextEntry)
+ : super(key, hashCode, next) {
+ _previousEntry._nextEntry = _nextEntry._previousEntry = this;
+ }
+
+ _LinkedHashSetEntry remove() {
+ _previousEntry._nextEntry = _nextEntry;
+ _nextEntry._previousEntry = _previousEntry;
+ _nextEntry = _previousEntry = this;
+ return super.remove();
+ }
+}
+
+class _LinkedHashSet<E> extends _HashSet<E>
+ implements LinkedHashSet<E> {
+ /// Holds a double linked list of the element entries of the set in
+ /// insertion order.
+ /// The fields have the same names as the ones in [_LinkedHashSetEntry],
+ /// allowing this object to be used as the head entry of the list.
+ /// The fields are initialized to `this` when created, representing the
+ /// empty list that only contains the head entry.
+ var _nextEntry;
+ var _previousEntry;
+
+ _LinkedHashSet() {
+ _nextEntry = _previousEntry = this;
}
// Iterable.
- /* patch */ Iterator<E> get iterator {
- return new _LinkedHashTableKeyIterator<E>(_table);
- }
- /* patch */ int get length => _table._elementCount;
-
- /* patch */ bool get isEmpty => _table._elementCount == 0;
-
- /* patch */ bool get isNotEmpty => !isEmpty;
-
- /* patch */ bool contains(Object object) => _table._get(object) >= 0;
-
- /* patch */ void forEach(void action(E element)) {
- int offset = _table._next(_LinkedHashTable._HEAD_OFFSET);
- int modificationCount = _table._modificationCount;
- while (offset != _LinkedHashTable._HEAD_OFFSET) {
- E key = _table._key(offset);
- action(key);
- _table._checkModification(modificationCount);
- offset = _table._next(offset);
- }
- }
-
- /* patch */ E get first {
- int firstOffset = _table._next(_LinkedHashTable._HEAD_OFFSET);
- if (firstOffset == _LinkedHashTable._HEAD_OFFSET) {
- throw new StateError("No elements");
- }
- return _table._key(firstOffset);
- }
-
- /* patch */ E get last {
- int lastOffset = _table._prev(_LinkedHashTable._HEAD_OFFSET);
- if (lastOffset == _LinkedHashTable._HEAD_OFFSET) {
- throw new StateError("No elements");
- }
- return _table._key(lastOffset);
- }
-
- // Collection.
- void _filterWhere(bool test(E element), bool removeMatching) {
- int entrySize = _table._entrySize;
- int length = _table._table.length;
- int offset = _table._next(_LinkedHashTable._HEAD_OFFSET);
- while (offset != _LinkedHashTable._HEAD_OFFSET) {
- E key = _table._key(offset);
- int nextOffset = _table._next(offset);
- int modificationCount = _table._modificationCount;
- bool shouldRemove = (removeMatching == test(key));
- _table._checkModification(modificationCount);
- if (shouldRemove) {
- _table._deleteEntry(offset);
- }
- offset = nextOffset;
- }
- _table._checkCapacity();
- }
-
- /* patch */ void add(E element) {
- _table._put(element);
- _table._checkCapacity();
- }
-
- /* patch */ void addAll(Iterable<E> objects) {
- for (E object in objects) {
- _table._put(object);
- _table._checkCapacity();
- }
- }
-
- /* patch */ bool remove(Object object) {
- int offset = _table._remove(object);
- if (offset >= 0) {
- _table._checkCapacity();
- return true;
- }
- return false;
- }
-
- /* patch */ void removeAll(Iterable objectsToRemove) {
- for (Object object in objectsToRemove) {
- if (_table._remove(object) >= 0) {
- _table._checkCapacity();
- }
- }
- }
-
- /* patch */ void removeWhere(bool test(E element)) {
- _filterWhere(test, true);
- }
-
- /* patch */ void retainWhere(bool test(E element)) {
- _filterWhere(test, false);
- }
-
- /* patch */ void clear() {
- _table._clear();
- }
-}
-
-class _DeadEntry {
- const _DeadEntry();
-}
-
-class _NullKey {
- const _NullKey();
- int get hashCode => null.hashCode;
-}
-
-const _TOMBSTONE = const _DeadEntry();
-const _NULL = const _NullKey();
-
-class _HashTable<K> {
- /**
- * Table of entries with [_entrySize] slots per entry.
- *
- * Capacity in entries must be factor of two.
- */
- List _table;
- /** Current capacity. Always equal to [:_table.length ~/ _entrySize:]. */
- int _capacity;
- /** Count of occupied entries, including deleted ones. */
- int _entryCount = 0;
- /** Count of deleted entries. */
- int _deletedCount = 0;
- /** Counter incremented when table is modified. */
- int _modificationCount = 0;
- /** If set, used as the source object for [ConcurrentModificationError]s. */
- Object _container;
-
- _HashTable(int initialCapacity) : _capacity = initialCapacity {
- _table = _createTable(initialCapacity);
- }
-
- /** Reads key from table. Converts _NULL marker to null. */
- Object _key(offset) {
- assert(!_isFree(_table[offset]));
- Object key = _table[offset];
- if (!identical(key, _NULL)) return key;
- return null;
- }
-
- /** Writes key to table. Converts null to _NULL marker. */
- void _setKey(int offset, Object key) {
- if (key == null) key = _NULL;
- _table[offset] = key;
- }
-
- int get _elementCount => _entryCount - _deletedCount;
-
- /** Size of each entry. */
- int get _entrySize => 1;
-
- void _checkModification(int expectedModificationCount) {
- if (_modificationCount != expectedModificationCount) {
- throw new ConcurrentModificationError(_container);
- }
- }
-
- void _recordModification() {
- // Value cycles after 2^30 modifications. If you keep hold of an
- // iterator for that long, you might miss a modification detection,
- // and iteration can go sour. Don't do that.
- _modificationCount = (_modificationCount + 1) & (0x3FFFFFFF);
- }
-
- /**
- * Create an empty table.
- */
- List _createTable(int capacity) {
- List table = new List(capacity * _entrySize);
- return table;
- }
-
- /** First table probe. */
- int _firstProbe(int hashCode, int capacity) {
- return hashCode & (capacity - 1);
- }
-
- /** Following table probes. */
- int _nextProbe(int previousIndex, int probeCount, int capacity) {
- // When capacity is a power of 2, this probing algorithm (the triangular
- // number sequence modulo capacity) is guaranteed to hit all indices exactly
- // once before repeating.
- return (previousIndex + probeCount) & (capacity - 1);
- }
-
- /** Whether an object is a free-marker (either tombstone or free). */
- bool _isFree(Object marker) =>
- marker == null || identical(marker, _TOMBSTONE);
-
- /**
- * Look up the offset for an object in the table.
- *
- * Finds the offset of the object in the table, if it is there,
- * or the first free offset for its hashCode.
- */
- int _probeForAdd(int hashCode, Object object) {
- int entrySize = _entrySize;
- int index = _firstProbe(hashCode, _capacity);
- int firstTombstone = -1;
- int probeCount = 0;
- while (true) {
- int offset = index * entrySize;
- Object entry = _table[offset];
- if (identical(entry, _TOMBSTONE)) {
- if (firstTombstone < 0) firstTombstone = offset;
- } else if (entry == null) {
- if (firstTombstone < 0) return offset;
- return firstTombstone;
- } else if (identical(_NULL, entry) ? _equals(null, object)
- : _equals(entry, object)) {
- return offset;
- }
- // The _nextProbe is designed so that it hits
- // every index eventually.
- index = _nextProbe(index, ++probeCount, _capacity);
- }
- }
-
- /**
- * Look up the offset for an object in the table.
- *
- * If the object is in the table, its offset is returned.
- *
- * If the object is not in the table, Otherwise a negative value is returned.
- */
- int _probeForLookup(int hashCode, Object object) {
- int entrySize = _entrySize;
- int index = _firstProbe(hashCode, _capacity);
- int probeCount = 0;
- while (true) {
- int offset = index * entrySize;
- Object entry = _table[offset];
- if (entry == null) {
- return -1;
- } else if (!identical(_TOMBSTONE, entry)) {
- if (identical(_NULL, entry) ? _equals(null, object)
- : _equals(entry, object)) {
- return offset;
- }
- }
- // The _nextProbe is designed so that it hits
- // every index eventually.
- index = _nextProbe(index, ++probeCount, _capacity);
- }
- }
-
- // Override the following two to change equality/hashCode computations
-
- /**
- * Compare two object for equality.
- *
- * The first object is the one already in the table,
- * and the second is the one being searched for.
- */
- bool _equals(Object element, Object other) {
- return element == other;
- }
-
- /**
- * Compute hash-code for an object.
- */
- int _hashCodeOf(Object object) => object.hashCode;
-
- /**
- * Ensure that the table isn't too full for its own good.
- *
- * Call this after adding an element.
- */
- int _checkCapacity() {
- // Compute everything in multiples of entrySize to avoid division.
- int freeCount = _capacity - _entryCount;
- if (freeCount * 4 < _capacity ||
- freeCount < _deletedCount) {
- // Less than 25% free or more deleted entries than free entries.
- _grow(_entryCount - _deletedCount);
- }
- }
-
- void _grow(int contentCount) {
- int capacity = _capacity;
- // Don't grow to less than twice the needed capacity.
- int minCapacity = contentCount * 2;
- while (capacity < minCapacity) {
- capacity *= 2;
- }
- // Reset to another table and add all existing elements.
- List oldTable = _table;
- _table = _createTable(capacity);
- _capacity = capacity;
- _entryCount = 0;
- _deletedCount = 0;
- _addAllEntries(oldTable);
- _recordModification();
- }
-
- /**
- * Copies all non-free entries from the old table to the new empty table.
- */
- void _addAllEntries(List oldTable) {
- for (int i = 0; i < oldTable.length; i += _entrySize) {
- Object object = oldTable[i];
- if (!_isFree(object)) {
- int toOffset = _put(object);
- _copyEntry(oldTable, i, toOffset);
- }
- }
- }
-
- /**
- * Copies everything but the key element from one entry to another.
- *
- * Called while growing the base array.
- *
- * Override this if any non-key fields need copying.
- */
- void _copyEntry(List fromTable, int fromOffset, int toOffset) {}
-
- // The following three methods are for simple get/set/remove operations.
- // They only affect the key of an entry. The remaining fields must be
- // filled by the caller.
-
- /**
- * Returns the offset of a key in [_table], or negative if it's not there.
- */
- int _get(Object key) {
- return _probeForLookup(_hashCodeOf(key), key);
- }
-
- /**
- * Puts the key into the table and returns its offset into [_table].
- *
- * If [_entrySize] is greater than 1, the caller should fill the
- * remaining fields.
- *
- * Remember to call [_checkCapacity] after using this method.
- */
- int _put(K key) {
- int offset = _probeForAdd(_hashCodeOf(key), key);
- Object oldEntry = _table[offset];
- if (oldEntry == null) {
- _entryCount++;
- } else if (identical(oldEntry, _TOMBSTONE)) {
- _deletedCount--;
- } else {
- return offset;
- }
- _setKey(offset, key);
- _recordModification();
- return offset;
- }
-
- /**
- * Removes a key from the table and returns its offset into [_table].
- *
- * Returns null if the key was not in the table.
- * If [_entrySize] is greater than 1, the caller should clean up the
- * remaining fields.
- */
- int _remove(Object key) {
- int offset = _probeForLookup(_hashCodeOf(key), key);
- if (offset >= 0) {
- _deleteEntry(offset);
- }
- return offset;
- }
-
- /** Clears the table completely, leaving it empty. */
- void _clear() {
- if (_elementCount == 0) return;
- for (int i = 0; i < _table.length; i++) {
- _table[i] = null;
- }
- _entryCount = _deletedCount = 0;
- _recordModification();
- }
-
- /** Clears an entry in the table. */
- void _deleteEntry(int offset) {
- assert(!_isFree(_table[offset]));
- _setKey(offset, _TOMBSTONE);
- _deletedCount++;
- _recordModification();
- }
-}
-
-/**
- * Generic iterable based on a [_HashTable].
- */
-abstract class _HashTableIterable<E> extends IterableBase<E> {
- final _HashTable _hashTable;
- _HashTableIterable(this._hashTable);
-
- Iterator<E> get iterator;
-
- /**
- * Return the iterated value for a given entry.
- */
- E _valueAt(int offset, Object key);
-
- int get length => _hashTable._elementCount;
-
- bool get isEmpty => _hashTable._elementCount == 0;
+ Iterator<E> get iterator => new _LinkedHashSetIterator<E>(this);
void forEach(void action(E element)) {
- int entrySize = _hashTable._entrySize;
- List table = _hashTable._table;
- int modificationCount = _hashTable._modificationCount;
- for (int offset = 0; offset < table.length; offset += entrySize) {
- Object entry = table[offset];
- if (!_hashTable._isFree(entry)) {
- E value = _valueAt(offset, entry);
- action(value);
+ var cursor = _nextEntry;
+ int modificationCount = _modificationCount;
+ while (!identical(cursor, this)) {
+ _LinkedHashSetEntry entry = cursor;
+ action(entry.key);
+ if (_modificationCount != modificationCount) {
+ throw new ConcurrentModificationError(this);
}
- _hashTable._checkModification(modificationCount);
+ cursor = entry._nextEntry;
}
}
-}
-abstract class _HashTableIterator<E> implements Iterator<E> {
- final _HashTable _hashTable;
- final int _modificationCount;
- /** Location right after last found element. */
- int _offset = 0;
- E _current = null;
+ E get first {
+ if (identical(_nextEntry, this)) {
+ throw new StateError("No elements");
+ }
+ _LinkedHashSetEntry entry = _nextEntry;
+ return entry.key;
+ }
- _HashTableIterator(_HashTable hashTable)
- : _hashTable = hashTable,
- _modificationCount = hashTable._modificationCount;
+ E get last {
+ if (identical(_previousEntry, this)) {
+ throw new StateError("No elements");
+ }
+ _LinkedHashSetEntry entry = _previousEntry;
+ return entry.key;
+ }
- bool moveNext() {
- _hashTable._checkModification(_modificationCount);
+ // Set.
- List table = _hashTable._table;
- int entrySize = _hashTable._entrySize;
-
- while (_offset < table.length) {
- int currentOffset = _offset;
- Object entry = table[currentOffset];
- _offset = currentOffset + entrySize;
- if (!_hashTable._isFree(entry)) {
- _current = _valueAt(currentOffset, entry);
- return true;
+ void _filterWhere(bool test(E element), bool removeMatching) {
+ var cursor = _nextEntry;
+ while (!identical(cursor, this)) {
+ _LinkedHashSetEntry entry = cursor;
+ int modificationCount = _modificationCount;
+ bool testResult = test(entry.key);
+ if (modificationCount != _modificationCount) {
+ throw new ConcurrentModificationError(this);
+ }
+ cursor = entry._nextEntry;
+ if (testResult == removeMatching) {
+ _remove(entry.key, entry.hashCode);
}
}
- _current = null;
- return false;
}
- E get current => _current;
+ void _addEntry(E key, int hashCode, int index) {
+ _buckets[index] =
+ new _LinkedHashSetEntry(key, hashCode, _buckets[index],
+ _previousEntry, this);
+ int newElements = _elementCount + 1;
+ _elementCount = newElements;
+ int length = _buckets.length;
+ // If we end up with more than 75% non-empty entries, we
+ // resize the backing store.
+ if ((newElements << 2) > ((length << 1) + length)) _resize();
+ _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ }
- E _valueAt(int offset, Object key);
+ void clear() {
+ _nextEntry = _previousEntry = this;
+ super.clear();
+ }
+
+ HashSet<E> _newSet() => new _LinkedHashSet<E>();
}
-class _HashTableKeyIterable<K> extends _HashTableIterable<K> {
- _HashTableKeyIterable(_HashTable<K> hashTable) : super(hashTable);
-
- Iterator<K> get iterator => new _HashTableKeyIterator<K>(_hashTable);
-
- K _valueAt(int offset, Object key) {
- if (identical(key, _NULL)) return null;
- return key;
- }
-
- bool contains(Object value) => _hashTable._get(value) >= 0;
+class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> {
+ bool _equals(e1, e2) => identical(e1, e2);
+ HashSet<E> _newSet() => new _LinkedIdentityHashSet<E>();
}
-class _HashTableKeyIterator<K> extends _HashTableIterator<K> {
- _HashTableKeyIterator(_HashTable hashTable) : super(hashTable);
+class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> {
+ final _Equality<E> _equality;
+ final _Hasher<E> _hasher;
+ final _Predicate _validKey;
- K _valueAt(int offset, Object key) {
- if (identical(key, _NULL)) return null;
- return key;
- }
-}
+ _LinkedCustomHashSet(this._equality, this._hasher, bool validKey(object))
+ : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
-class _HashTableValueIterable<V> extends _HashTableIterable<V> {
- final int _entryIndex;
+ bool _equals(e1, e2) => _equality(e1, e2);
- _HashTableValueIterable(_HashTable hashTable, this._entryIndex)
- : super(hashTable);
+ int _hashCode(e) => _hasher(e);
- Iterator<V> get iterator {
- return new _HashTableValueIterator<V>(_hashTable, _entryIndex);
+ bool contains(Object o) {
+ if (!_validKey(o)) return false;
+ return super.contains(o);
}
- V _valueAt(int offset, Object key) => _hashTable._table[offset + _entryIndex];
-}
-
-class _HashTableValueIterator<V> extends _HashTableIterator<V> {
- final int _entryIndex;
-
- _HashTableValueIterator(_HashTable hashTable, this._entryIndex)
- : super(hashTable);
-
- V _valueAt(int offset, Object key) => _hashTable._table[offset + _entryIndex];
-}
-
-class _HashMapTable<K, V> extends _HashTable<K> {
- static const int _INITIAL_CAPACITY = 8;
- static const int _VALUE_INDEX = 1;
-
- _HashMapTable() : super(_INITIAL_CAPACITY);
-
- int get _entrySize => 2;
-
- V _value(int offset) => _table[offset + _VALUE_INDEX];
- void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
-
- _copyEntry(List fromTable, int fromOffset, int toOffset) {
- _table[toOffset + _VALUE_INDEX] = fromTable[fromOffset + _VALUE_INDEX];
- }
-}
-
-/** Unique marker object for the head of a linked list of entries. */
-class _LinkedHashTableHeadMarker {
- const _LinkedHashTableHeadMarker();
-}
-
-const _LinkedHashTableHeadMarker _HEAD_MARKER =
- const _LinkedHashTableHeadMarker();
-
-class _LinkedHashTable<K> extends _HashTable<K> {
- static const _NEXT_INDEX = 1;
- static const _PREV_INDEX = 2;
- static const _HEAD_OFFSET = 0;
-
- _LinkedHashTable(int initialCapacity) : super(initialCapacity);
-
- int get _entrySize => 3;
-
- List _createTable(int capacity) {
- List result = new List(capacity * _entrySize);
- result[_HEAD_OFFSET] = _HEAD_MARKER;
- result[_HEAD_OFFSET + _NEXT_INDEX] = _HEAD_OFFSET;
- result[_HEAD_OFFSET + _PREV_INDEX] = _HEAD_OFFSET;
- return result;
+ bool remove(Object o) {
+ if (!_validKey(o)) return false;
+ return super.remove(o);
}
- int _next(int offset) => _table[offset + _NEXT_INDEX];
- void _setNext(int offset, int to) { _table[offset + _NEXT_INDEX] = to; }
-
- int _prev(int offset) => _table[offset + _PREV_INDEX];
- void _setPrev(int offset, int to) { _table[offset + _PREV_INDEX] = to; }
-
- void _linkLast(int offset) {
- // Add entry at offset at end of double-linked list.
- int last = _prev(_HEAD_OFFSET);
- _setNext(offset, _HEAD_OFFSET);
- _setPrev(offset, last);
- _setNext(last, offset);
- _setPrev(_HEAD_OFFSET, offset);
- }
-
- void _unlink(int offset) {
- assert(offset != _HEAD_OFFSET);
- int next = _next(offset);
- int prev = _prev(offset);
- _setNext(offset, null);
- _setPrev(offset, null);
- _setNext(prev, next);
- _setPrev(next, prev);
- }
-
- /**
- * Copies all non-free entries from the old table to the new empty table.
- */
- void _addAllEntries(List oldTable) {
- int offset = oldTable[_HEAD_OFFSET + _NEXT_INDEX];
- while (offset != _HEAD_OFFSET) {
- Object object = oldTable[offset];
- int nextOffset = oldTable[offset + _NEXT_INDEX];
- int toOffset = _put(object);
- _copyEntry(oldTable, offset, toOffset);
- offset = nextOffset;
+ bool containsAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (!_validKey(element) || !this.contains(element)) return false;
}
- }
-
- void _clear() {
- if (_elementCount == 0) return;
- _setNext(_HEAD_OFFSET, _HEAD_OFFSET);
- _setPrev(_HEAD_OFFSET, _HEAD_OFFSET);
- for (int i = _entrySize; i < _table.length; i++) {
- _table[i] = null;
- }
- _entryCount = _deletedCount = 0;
- _recordModification();
- }
-
- int _put(K key) {
- int offset = _probeForAdd(_hashCodeOf(key), key);
- Object oldEntry = _table[offset];
- if (identical(oldEntry, _TOMBSTONE)) {
- _deletedCount--;
- } else if (oldEntry == null) {
- _entryCount++;
- } else {
- return offset;
- }
- _recordModification();
- _setKey(offset, key);
- _linkLast(offset);
- return offset;
- }
-
- void _deleteEntry(int offset) {
- _unlink(offset);
- _setKey(offset, _TOMBSTONE);
- _deletedCount++;
- _recordModification();
- }
-}
-
-class _LinkedHashTableKeyIterable<K> extends IterableBase<K> {
- final _LinkedHashTable<K> _table;
- _LinkedHashTableKeyIterable(this._table);
- Iterator<K> get iterator => new _LinkedHashTableKeyIterator<K>(_table);
-
- bool contains(Object value) => _table._get(value) >= 0;
-
- int get length => _table._elementCount;
-}
-
-class _LinkedHashTableKeyIterator<K> extends _LinkedHashTableIterator<K> {
- _LinkedHashTableKeyIterator(_LinkedHashTable<K> hashTable): super(hashTable);
-
- K _getCurrent(int offset) => _hashTable._key(offset);
-}
-
-class _LinkedHashTableValueIterable<V> extends IterableBase<V> {
- final _LinkedHashTable _hashTable;
- final int _valueIndex;
- _LinkedHashTableValueIterable(this._hashTable, this._valueIndex);
- Iterator<V> get iterator =>
- new _LinkedHashTableValueIterator<V>(_hashTable, _valueIndex);
- int get length => _hashTable._elementCount;
-}
-
-class _LinkedHashTableValueIterator<V> extends _LinkedHashTableIterator<V> {
- final int _valueIndex;
-
- _LinkedHashTableValueIterator(_LinkedHashTable hashTable, this._valueIndex)
- : super(hashTable);
-
- V _getCurrent(int offset) => _hashTable._table[offset + _valueIndex];
-}
-
-abstract class _LinkedHashTableIterator<T> implements Iterator<T> {
- final _LinkedHashTable _hashTable;
- final int _modificationCount;
- int _offset;
- T _current;
-
- _LinkedHashTableIterator(_LinkedHashTable table)
- : _hashTable = table,
- _modificationCount = table._modificationCount,
- _offset = table._next(_LinkedHashTable._HEAD_OFFSET);
-
- bool moveNext() {
- _hashTable._checkModification(_modificationCount);
- if (_offset == _LinkedHashTable._HEAD_OFFSET) {
- _current = null;
- return false;
- }
- _current = _getCurrent(_offset);
- _offset = _hashTable._next(_offset);
return true;
}
- T _getCurrent(int offset);
+ void removeAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (_validKey(element)) {
+ super._remove(element, _hasher(element));
+ }
+ }
+ }
- T get current => _current;
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, _validKey);
+ }
+
+ HashSet<E> _newSet() =>
+ new _LinkedCustomHashSet<E>(_equality, _hasher, _validKey);
}
-class _LinkedHashMapTable<K, V> extends _LinkedHashTable<K> {
- static const int _INITIAL_CAPACITY = 8;
- static const int _VALUE_INDEX = 3;
+class _LinkedHashSetIterator<E> implements Iterator<E> {
+ final _LinkedHashSet _set;
+ final int _modificationCount;
+ var _next;
+ E _current;
- int get _entrySize => 4;
+ _LinkedHashSetIterator(_LinkedHashSet hashSet)
+ : _set = hashSet,
+ _modificationCount = hashSet._modificationCount,
+ _next = hashSet._nextEntry;
- _LinkedHashMapTable() : super(_INITIAL_CAPACITY);
-
- V _value(int offset) => _table[offset + _VALUE_INDEX];
- void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
-
- _copyEntry(List oldTable, int fromOffset, int toOffset) {
- _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX];
+ bool moveNext() {
+ if (_modificationCount != _set._modificationCount) {
+ throw new ConcurrentModificationError(_set);
+ }
+ if (identical(_set, _next)) {
+ _current = null;
+ return false;
+ }
+ _LinkedHashSetEntry entry = _next;
+ _current = entry.key;
+ _next = entry._nextEntry;
+ return true;
}
+
+ E get current => _current;
}
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 0487b58..0708da3 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -192,7 +192,7 @@
InstanceMirror getField(Symbol memberName) {
return reflect(this._invokeGetter(_reflectee,
- _n(memberName)));
+ _n(memberName)));
}
InstanceMirror setField(Symbol memberName, Object value) {
@@ -216,7 +216,7 @@
try {
var result = this._invokeGetter(_reflectee,
_n(memberName));
- return new Future.value(reflect(result));
+ return new Future.value(reflect(result));
} catch(e) {
return new Future.error(e);
}
@@ -229,7 +229,7 @@
unwrappedValue = value;
} else if(value is InstanceMirror) {
unwrappedValue = value._reflectee;
- } else {
+ } else {
throw "setter argument ($value) must be"
"a simple value or InstanceMirror";
}
@@ -237,7 +237,7 @@
this._invokeSetter(_reflectee,
_n(memberName),
unwrappedValue);
- return new Future.value(reflect(unwrappedValue));
+ return new Future.value(reflect(unwrappedValue));
} catch(e) {
return new Future.error(e);
}
@@ -285,7 +285,7 @@
// system to access a private field in a different library. For
// some reason, that works. On the other hand, calling a
// private method does not work.
-
+
_LocalInstanceMirrorImpl mirror =
reflect(invocation);
_invokeOnClosure = reflectClass(invocation.runtimeType)
@@ -375,7 +375,7 @@
// replaced with
// return this.invoke(#call, positionalArguments, namedArguments);
// and the native ClosureMirror_apply can be removed.
-
+
int numPositionalArguments = positionalArguments.length + 1; // Receiver.
int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
int numArguments = numPositionalArguments + numNamedArguments;
@@ -515,11 +515,11 @@
klass = klass.superclass;
}
return _s(
- _n(klass.qualifiedName)
+ _n(klass.qualifiedName)
+ ' with '
+ mixins.reversed.map((m)=>_n(m.qualifiedName)).join(', '));
}
-
+
var _mixin;
ClassMirror get mixin {
if (_mixin == null) {
@@ -594,34 +594,33 @@
var stringName = _n(simpleName);
constructorsList.forEach((c) => c._patchConstructorName(stringName));
_constructors = _makeMemberMap(constructorsList);
- }
- return _constructors;
+ }
+ return _constructors;
}
- Map<Symbol, TypeVariableMirror> _typeVariables = null;
- Map<Symbol, TypeVariableMirror> get typeVariables {
+ List<TypeVariableMirror> _typeVariables = null;
+ List<TypeVariableMirror> get typeVariables {
if (_typeVariables == null) {
List params = _ClassMirror_type_variables(_reflectee);
- _typeVariables = new LinkedHashMap<Symbol, TypeVariableMirror>();
+ _typeVariables = new List<TypeVariableMirror>();
var mirror;
for (var i = 0; i < params.length; i += 2) {
mirror = new _LocalTypeVariableMirrorImpl(
params[i + 1], params[i], this);
- _typeVariables[mirror.simpleName] = mirror;
+ _typeVariables.add(mirror);
}
}
return _typeVariables;
}
- Map<Symbol, TypeMirror> _typeArguments = null;
- Map<Symbol, TypeMirror> get typeArguments {
+ List<TypeMirror> _typeArguments = null;
+ List<TypeMirror> get typeArguments {
if(_typeArguments == null) {
if(_isGenericDeclaration) {
- _typeArguments = new LinkedHashMap<Symbol, TypeMirror>();
+ _typeArguments = new List<TypeMirror>();
} else {
_typeArguments =
- new LinkedHashMap<Symbol, TypeMirror>.fromIterables(
- typeVariables.keys, _computeTypeArguments(_reflectedType));
+ new List<TypeMirror>.from(_computeTypeArguments(_reflectedType));
}
}
return _typeArguments;
@@ -705,7 +704,7 @@
_computeMembers(reflectee)
native "ClassMirror_members";
-
+
_computeConstructors(reflectee)
native "ClassMirror_constructors";
@@ -807,7 +806,7 @@
bool operator ==(other) {
return this.runtimeType == other.runtimeType &&
- this._reflectee == other._reflectee;
+ this._reflectee == other._reflectee;
}
int get hashCode => simpleName.hashCode;
@@ -988,7 +987,7 @@
bool operator ==(other) {
return this.runtimeType == other.runtimeType &&
- this._reflectee == other._reflectee;
+ this._reflectee == other._reflectee;
}
int get hashCode => simpleName.hashCode;
@@ -1294,7 +1293,7 @@
// Creates a new local mirror for some Object.
static InstanceMirror reflect(Object reflectee) {
- return reflectee is Function
+ return reflectee is Function
? new _LocalClosureMirrorImpl(reflectee)
: new _LocalInstanceMirrorImpl(reflectee);
}
diff --git a/runtime/vm/bigint_operations.cc b/runtime/vm/bigint_operations.cc
index b7c7a69..a59a6fd 100644
--- a/runtime/vm/bigint_operations.cc
+++ b/runtime/vm/bigint_operations.cc
@@ -2,6 +2,7 @@
#include "vm/bigint_operations.h"
+#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/double_internals.h"
@@ -106,7 +107,9 @@
return result.raw();
}
- intptr_t str_length = strlen(str);
+ // No overflow check needed since overflowing str_length implies that we take
+ // the branch to FromDecimalCString() which contains a check itself.
+ const intptr_t str_length = strlen(str);
if ((str_length > 2) &&
(str[0] == '0') &&
((str[1] == 'x') || (str[1] == 'X'))) {
@@ -121,7 +124,11 @@
intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) {
ASSERT(kDigitBitSize % 4 == 0);
- intptr_t hex_length = strlen(hex_string);
+ const intptr_t hex_length = strlen(hex_string);
+ if (hex_length < 0) {
+ FATAL("Fatal error in BigintOperations::ComputeChunkLength: "
+ "string too long");
+ }
// Round up.
intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1;
return bigint_length;
@@ -158,7 +165,11 @@
const Chunk kTenMultiplier = 100000000;
ASSERT(kDigitBitSize >= 27);
- intptr_t str_length = strlen(str);
+ const intptr_t str_length = strlen(str);
+ if (str_length < 0) {
+ FATAL("Fatal error in BigintOperations::FromDecimalCString: "
+ "string too long");
+ }
intptr_t str_pos = 0;
// Read first digit separately. This avoids a multiplication and addition.
@@ -247,11 +258,21 @@
ASSERT(kDigitBitSize % 4 == 0);
- intptr_t chunk_length = length;
+ // Conservative maximum chunk length.
+ const intptr_t kMaxChunkLen =
+ (kIntptrMax - 2 /* 0x */
+ - 1 /* trailing '\0' */
+ - 1 /* leading '-' */) / kHexCharsPerDigit;
+ const intptr_t chunk_length = length;
+ // Conservative check assuming leading bigint-digit also takes up
+ // kHexCharsPerDigit.
+ if (chunk_length > kMaxChunkLen) {
+ FATAL("Fatal error in BigintOperations::ToHexCString: string too long");
+ }
Chunk* chunk_data = reinterpret_cast<Chunk*>(data);
if (length == 0) {
const char* zero = "0x0";
- const int kLength = strlen(zero);
+ const intptr_t kLength = strlen(zero);
char* result = reinterpret_cast<char*>(allocator(kLength + 1));
ASSERT(result != NULL);
memmove(result, zero, kLength);
@@ -330,7 +351,7 @@
const intptr_t kMaxAllowedDigitLength =
(kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor;
- intptr_t length = bigint.Length();
+ const intptr_t length = bigint.Length();
Isolate* isolate = Isolate::Current();
if (length >= kMaxAllowedDigitLength) {
// Use the preallocated out of memory exception to avoid calling
@@ -365,25 +386,18 @@
ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor);
ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue);
ASSERT(Smi::IsValid(kChunkDivisor));
- const Bigint& divisor = Bigint::Handle(NewFromInt64(kChunkDivisor));
+ const Chunk divisor = static_cast<Chunk>(kChunkDivisor);
// Rest contains the remaining bigint that needs to be printed.
- Bigint& rest = Bigint::Handle(bigint.raw());
- Bigint& quotient = Bigint::Handle();
- Bigint& remainder = Bigint::Handle();
+ const Bigint& rest = Bigint::Handle(Copy(bigint));
while (!rest.IsZero()) {
- HANDLESCOPE(isolate);
- DivideRemainder(rest, divisor, "ient, &remainder);
- ASSERT(remainder.Length() <= 1);
- intptr_t part = (remainder.Length() == 1)
- ? static_cast<intptr_t>(remainder.GetChunkAt(0))
- : 0;
+ Chunk remainder = InplaceUnsignedDivideRemainderDigit(rest, divisor);
+ intptr_t part = static_cast<intptr_t>(remainder);
for (int i = 0; i < kChunkDigits; i++) {
result[result_pos++] = '0' + (part % 10);
part /= 10;
}
ASSERT(part == 0);
- rest = quotient.raw();
}
// Move the resulting position back until we don't have any zeroes anymore.
// This is done so that we can remove all leading zeroes.
@@ -1341,7 +1355,10 @@
// given string has it's lsd at the last position.
// The hex_i index, pointing into the string, starts therefore at the end,
// whereas the bigint-index (i) starts at 0.
- intptr_t hex_length = strlen(hex_string);
+ const intptr_t hex_length = strlen(hex_string);
+ if (hex_length < 0) {
+ FATAL("Fatal error in BigintOperations::FromHexCString: string too long");
+ }
intptr_t hex_i = hex_length - 1;
for (intptr_t i = 0; i < bigint_length; i++) {
Chunk digit = 0;
@@ -1572,6 +1589,22 @@
return;
}
+ intptr_t b_length = b.Length();
+
+ if (b_length == 1) {
+ const Bigint& dividend_quotient = Bigint::Handle(Copy(a));
+ Chunk remainder_digit =
+ BigintOperations::InplaceUnsignedDivideRemainderDigit(
+ dividend_quotient, b.GetChunkAt(0));
+ dividend_quotient.SetSign(a.IsNegative() != b.IsNegative());
+ *quotient = dividend_quotient.raw();
+ *remainder = Bigint::Allocate(1);
+ remainder->SetChunkAt(0, remainder_digit);
+ remainder->SetSign(a.IsNegative());
+ Clamp(*remainder);
+ return;
+ }
+
// High level description:
// The algorithm is basically the algorithm that is taught in school:
// Let a the dividend and b the divisor. We are looking for
@@ -1590,7 +1623,6 @@
//
// Instead of working in base 10 we work in base kDigitBitSize.
- intptr_t b_length = b.Length();
int normalization_shift =
kDigitBitSize - CountBits(b.GetChunkAt(b_length - 1));
Bigint& dividend = Bigint::Handle(ShiftLeft(a, normalization_shift));
@@ -1724,6 +1756,24 @@
}
+BigintOperations::Chunk BigintOperations::InplaceUnsignedDivideRemainderDigit(
+ const Bigint& dividend_quotient, Chunk divisor_digit) {
+ Chunk remainder = 0;
+ for (intptr_t i = dividend_quotient.Length() - 1; i >= 0; i--) {
+ DoubleChunk dividend_digit =
+ (static_cast<DoubleChunk>(remainder) << kDigitBitSize) +
+ dividend_quotient.GetChunkAt(i);
+ Chunk quotient_digit = static_cast<Chunk>(dividend_digit / divisor_digit);
+ remainder = static_cast<Chunk>(
+ dividend_digit -
+ static_cast<DoubleChunk>(quotient_digit) * divisor_digit);
+ dividend_quotient.SetChunkAt(i, quotient_digit);
+ }
+ Clamp(dividend_quotient);
+ return remainder;
+}
+
+
void BigintOperations::Clamp(const Bigint& bigint) {
intptr_t length = bigint.Length();
while (length > 0 && (bigint.GetChunkAt(length - 1) == 0)) {
diff --git a/runtime/vm/bigint_operations.h b/runtime/vm/bigint_operations.h
index b38bc41..54c2416 100644
--- a/runtime/vm/bigint_operations.h
+++ b/runtime/vm/bigint_operations.h
@@ -140,6 +140,8 @@
}
static void DivideRemainder(const Bigint& a, const Bigint& b,
Bigint* quotient, Bigint* remainder);
+ static Chunk InplaceUnsignedDivideRemainderDigit(
+ const Bigint& dividend_quotient, Chunk divisor_digit);
// Removes leading zero-chunks by adjusting the bigint's length.
static void Clamp(const Bigint& bigint);
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 2cf1ac1..e85053a 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -95,4 +95,20 @@
}
}
+
+void ClassTable::PrintToJSONStream(JSONStream* stream) {
+ Class& cls = Class::Handle();
+ JSONObject jsobj(stream);
+ jsobj.AddProperty("type", "ClassList");
+ {
+ JSONArray members(&jsobj, "members");
+ for (intptr_t i = 1; i < top_; i++) {
+ if (HasValidClassAt(i)) {
+ cls = At(i);
+ members.AddValue(cls);
+ }
+ }
+ }
+}
+
} // namespace dart
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 8fe8159..6ea4dfa 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -13,6 +13,7 @@
class Class;
class ObjectPointerVisitor;
class RawClass;
+class JSONStream;
class ClassTable {
public:
@@ -41,6 +42,8 @@
void Print();
+ void PrintToJSONStream(JSONStream* stream);
+
static intptr_t table_offset() {
return OFFSET_OF(ClassTable, table_);
}
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 1f2d1c2..2527c3b 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -270,7 +270,9 @@
LongJump bailout_jump;
isolate->set_long_jump_base(&bailout_jump);
if (setjmp(*bailout_jump.Set()) == 0) {
+ FlowGraphBuilder* builder = NULL;
FlowGraph* flow_graph = NULL;
+ GrowableArray<const Field*> guarded_fields;
// TimerScope needs an isolate to be properly terminated in case of a
// LongJump.
{
@@ -290,11 +292,12 @@
}
// Build the flow graph.
- FlowGraphBuilder builder(parsed_function,
- ic_data_array,
- NULL, // NULL = not inlining.
- osr_id);
- flow_graph = builder.BuildGraph();
+ builder = new FlowGraphBuilder(parsed_function,
+ ic_data_array,
+ NULL, // NULL = not inlining.
+ &guarded_fields,
+ osr_id);
+ flow_graph = builder->BuildGraph();
}
if (FLAG_print_flow_graph ||
@@ -326,13 +329,12 @@
// Collect all instance fields that are loaded in the graph and
// have non-generic type feedback attached to them that can
// potentially affect optimizations.
- GrowableArray<const Field*> guarded_fields(10);
if (optimized) {
TimerScope timer(FLAG_compiler_stats,
&CompilerStats::graphoptimizer_timer,
isolate);
- FlowGraphOptimizer optimizer(flow_graph, &guarded_fields);
+ FlowGraphOptimizer optimizer(flow_graph);
optimizer.ApplyICData();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -358,7 +360,7 @@
optimizer.ApplyClassIds();
DEBUG_ASSERT(flow_graph->VerifyUseLists());
- FlowGraphInliner inliner(flow_graph, &guarded_fields);
+ FlowGraphInliner inliner(flow_graph);
inliner.Inline();
// Use lists are maintained and validated by the inliner.
DEBUG_ASSERT(flow_graph->VerifyUseLists());
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index c3bc011..a88df07 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -230,6 +230,11 @@
// Different objects.
EXPECT_VALID(Dart_ObjectEquals(five, seven, &equal));
EXPECT(!equal);
+
+ // Case where identity is not equality.
+ Dart_Handle nan = Dart_NewDouble(NAN);
+ EXPECT_VALID(Dart_ObjectEquals(nan, nan, &equal));
+ EXPECT(!equal);
}
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 54fbb01..adca206 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1018,7 +1018,7 @@
}
-RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo() {
+RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
// TODO(vegorov): enable compression of deoptimization info containing object
// materialization instructions.
const bool disable_compression =
@@ -1054,14 +1054,17 @@
node = new TrieNode(instr, current_info_number_);
node->AddChild(child);
}
- suffix->AddChild(node);
if (suffix_length > 1) {
+ suffix->AddChild(node);
DeoptInstr* instr =
new DeoptSuffixInstr(suffix->info_number(), suffix_length);
deopt_info.SetAt(length - 1, instr->kind(), instr->from_index());
+ } else {
+ trie_root_->AddChild(node);
}
+ ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table));
instructions_.Clear();
materializations_.Clear();
frame_start_ = -1;
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index a7c8ab9..564b744 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -202,7 +202,7 @@
// Returns the index of the next stack slot. Used for verification.
intptr_t EmitMaterializationArguments(intptr_t to_index);
- RawDeoptInfo* CreateDeoptInfo();
+ RawDeoptInfo* CreateDeoptInfo(const Array& deopt_table);
// Mark the actual start of the frame description after all materialization
// instructions were emitted. Used for verification purposes.
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index 9272794..69e5ed0 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -240,6 +240,7 @@
case 0xA5: return "shld";
case 0xAD: return "shrd";
case 0xAB: return "bts";
+ case 0xBD: return "bsr";
case 0xB1: return "cmpxchg";
case 0x50: return "movmskps";
case 0x51: return "sqrtps";
@@ -1301,7 +1302,7 @@
} else if ((f0byte & 0xF0) == 0x80) {
data += JumpConditional(data, branch_hint);
} else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
- f0byte == 0xB7 || f0byte == 0xAF) {
+ f0byte == 0xB7 || f0byte == 0xAF || f0byte == 0xBD) {
data += 2;
data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
} else if (f0byte == 0x57) {
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index e7f4293..e0a71b0 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -24,6 +24,7 @@
: parent_(),
current_ssa_temp_index_(0),
max_block_id_(max_block_id),
+ builder_(builder),
parsed_function_(*builder.parsed_function()),
num_copied_params_(builder.num_copied_params()),
num_non_copied_params_(builder.num_non_copied_params()),
@@ -97,6 +98,20 @@
}
+Instruction* FlowGraph::AppendTo(Instruction* prev,
+ Instruction* instr,
+ Environment* env,
+ Definition::UseKind use_kind) {
+ if (use_kind == Definition::kValue) {
+ ASSERT(instr->IsDefinition());
+ instr->AsDefinition()->set_ssa_temp_index(alloc_ssa_temp_index());
+ }
+ ASSERT(instr->env() == NULL);
+ if (env != NULL) env->DeepCopyTo(instr);
+ return prev->AppendInstruction(instr);
+}
+
+
void FlowGraph::DiscoverBlocks() {
// Initialize state.
preorder_.Clear();
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 34112c6..7b4be08be 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -48,6 +48,10 @@
GraphEntryInstr* graph_entry,
intptr_t max_block_id);
+ const FlowGraphBuilder& builder() const {
+ return builder_;
+ }
+
// Function properties.
const ParsedFunction& parsed_function() const {
return parsed_function_;
@@ -124,6 +128,10 @@
Instruction* instr,
Environment* env,
Definition::UseKind use_kind);
+ Instruction* AppendTo(Instruction* prev,
+ Instruction* instr,
+ Environment* env,
+ Definition::UseKind use_kind);
// Operations on the flow graph.
void ComputeSSA(intptr_t next_virtual_register_number,
@@ -242,6 +250,7 @@
intptr_t max_block_id_;
// Flow graph fields.
+ const FlowGraphBuilder& builder_;
const ParsedFunction& parsed_function_;
const intptr_t num_copied_params_;
const intptr_t num_non_copied_params_;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 78efd46..42a4ffa 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -45,6 +45,7 @@
FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function,
const Array& ic_data_array,
InlineExitCollector* exit_collector,
+ GrowableArray<const Field*>* guarded_fields,
intptr_t osr_id)
: parsed_function_(parsed_function),
ic_data_array_(ic_data_array),
@@ -55,6 +56,7 @@
: 0),
num_stack_locals_(parsed_function->num_stack_locals()),
exit_collector_(exit_collector),
+ guarded_fields_(guarded_fields),
last_used_block_id_(0), // 0 is used for the graph entry.
context_level_(0),
try_index_(CatchClauseNode::kInvalidTryIndex),
@@ -70,6 +72,20 @@
}
+void FlowGraphBuilder::AddToGuardedFields(const Field& field) const {
+ if ((field.guarded_cid() == kDynamicCid) ||
+ (field.guarded_cid() == kIllegalCid)) {
+ return;
+ }
+ for (intptr_t j = 0; j < guarded_fields_->length(); j++) {
+ if ((*guarded_fields_)[j]->raw() == field.raw()) {
+ return;
+ }
+ }
+ guarded_fields_->Add(&field);
+}
+
+
void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
@@ -3039,6 +3055,17 @@
node->field().Offset(),
AbstractType::ZoneHandle(node->field().type()));
load->set_field(&node->field());
+ if (owner()->exit_collector() != NULL) {
+ // While inlining into an optimized function, the field has
+ // to be added to the list of guarded fields of the caller.
+ if (node->field().guarded_cid() != kIllegalCid) {
+ if (!node->field().is_nullable() ||
+ (node->field().guarded_cid() == kNullCid)) {
+ load->set_result_cid(node->field().guarded_cid());
+ }
+ owner()->AddToGuardedFields(node->field());
+ }
+ }
ReturnDefinition(load);
}
@@ -3768,7 +3795,7 @@
TargetEntryInstr* normal_entry =
new TargetEntryInstr(AllocateBlockId(),
CatchClauseNode::kInvalidTryIndex);
- graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_);
+ graph_entry_ = new GraphEntryInstr(parsed_function(), normal_entry, osr_id_);
EffectGraphVisitor for_effect(this, 0);
// This check may be deleted if the generated code is leaf.
// Native functions don't need a stack check at entry.
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index e3d01c3..2b9f455 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -20,21 +20,21 @@
// (factory-name-symbol, result-cid, fingerprint).
// TODO(srdjan): Store the values in the snapshot instead.
#define RECOGNIZED_LIST_FACTORY_LIST(V) \
- V(ObjectArrayFactory, kArrayCid, 1930677134) \
- V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 1012992871) \
- V(GrowableObjectArrayFactory, kGrowableObjectArrayCid, 1707369421) \
- V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 1340298556) \
- V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1775618642) \
- V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 264668024) \
- V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 1095249987) \
- V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 1275304272) \
- V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 523449884) \
- V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 458531362) \
- V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 1753070829) \
- V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 1561660391) \
- V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 245916452) \
- V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 368082071) \
- V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 1674296969) \
+ V(ObjectArrayFactory, kArrayCid, 1558200848) \
+ V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 619965861) \
+ V(GrowableObjectArrayFactory, kGrowableObjectArrayCid, 1180134731) \
+ V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 810750844) \
+ V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1246070930) \
+ V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 1882603960) \
+ V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 565702275) \
+ V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 745756560) \
+ V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 2141385820) \
+ V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 2076467298) \
+ V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 1223523117) \
+ V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 1032112679) \
+ V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 1863852388) \
+ V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 1986018007) \
+ V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 1144749257) \
// A class to collect the exits from an inlined function during graph
@@ -98,13 +98,14 @@
// Build a flow graph from a parsed function's AST.
-class FlowGraphBuilder: public ValueObject {
+class FlowGraphBuilder: public ZoneAllocated {
public:
// The inlining context is NULL if not inlining. The osr_id is the deopt
// id of the OSR entry or Isolate::kNoDeoptId if not compiling for OSR.
FlowGraphBuilder(ParsedFunction* parsed_function,
const Array& ic_data_array,
InlineExitCollector* exit_collector,
+ GrowableArray<const Field*>* guarded_fields,
intptr_t osr_id);
FlowGraph* BuildGraph();
@@ -147,6 +148,12 @@
bool IsInlining() const { return (exit_collector_ != NULL); }
InlineExitCollector* exit_collector() const { return exit_collector_; }
+ GrowableArray<const Field*>* guarded_fields() const {
+ return guarded_fields_;
+ }
+
+ void AddToGuardedFields(const Field& field) const;
+
intptr_t args_pushed() const { return args_pushed_; }
void add_args_pushed(intptr_t n) { args_pushed_ += n; }
@@ -169,6 +176,7 @@
const intptr_t num_non_copied_params_;
const intptr_t num_stack_locals_; // Does not include any parameters.
InlineExitCollector* const exit_collector_;
+ GrowableArray<const Field*>* guarded_fields_;
intptr_t last_used_block_id_;
intptr_t context_level_;
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index fbe3484..42df32d 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -468,7 +468,7 @@
Smi& reason = Smi::Handle();
for (intptr_t i = 0; i < deopt_infos_.length(); i++) {
offset = Smi::New(deopt_infos_[i]->pc_offset());
- info = deopt_infos_[i]->CreateDeoptInfo(this, &builder);
+ info = deopt_infos_[i]->CreateDeoptInfo(this, &builder, array);
reason = Smi::New(deopt_infos_[i]->reason());
DeoptTable::SetEntry(array, i, offset, info, reason);
}
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 3d174c2..f53ad0f 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -120,7 +120,8 @@
}
RawDeoptInfo* CreateDeoptInfo(FlowGraphCompiler* compiler,
- DeoptInfoBuilder* builder);
+ DeoptInfoBuilder* builder,
+ const Array& deopt_table);
// No code needs to be generated.
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 0854649..7353b27 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -44,7 +44,8 @@
RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
- DeoptInfoBuilder* builder) {
+ DeoptInfoBuilder* builder,
+ const Array& deopt_table) {
if (deopt_env_ == NULL) return DeoptInfo::null();
intptr_t stack_height = compiler->StackSize();
@@ -133,7 +134,8 @@
builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
}
- const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+ const DeoptInfo& deopt_info =
+ DeoptInfo::Handle(builder->CreateDeoptInfo(deopt_table));
return deopt_info.raw();
}
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 151ca9f..2ea07d5 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -48,7 +48,8 @@
RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
- DeoptInfoBuilder* builder) {
+ DeoptInfoBuilder* builder,
+ const Array& deopt_table) {
if (deopt_env_ == NULL) return DeoptInfo::null();
intptr_t stack_height = compiler->StackSize();
@@ -132,7 +133,8 @@
builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
}
- const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+ const DeoptInfo& deopt_info =
+ DeoptInfo::Handle(builder->CreateDeoptInfo(deopt_table));
return deopt_info.raw();
}
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 8e51051..03b0a9a 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -44,7 +44,8 @@
RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
- DeoptInfoBuilder* builder) {
+ DeoptInfoBuilder* builder,
+ const Array& deopt_table) {
if (deopt_env_ == NULL) return DeoptInfo::null();
intptr_t stack_height = compiler->StackSize();
@@ -133,7 +134,8 @@
builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
}
- const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+ const DeoptInfo& deopt_info =
+ DeoptInfo::Handle(builder->CreateDeoptInfo(deopt_table));
return deopt_info.raw();
}
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index e08d1ab..d3c4095 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -45,7 +45,8 @@
RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
- DeoptInfoBuilder* builder) {
+ DeoptInfoBuilder* builder,
+ const Array& deopt_table) {
if (deopt_env_ == NULL) return DeoptInfo::null();
intptr_t stack_height = compiler->StackSize();
@@ -129,7 +130,8 @@
builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
}
- const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
+ const DeoptInfo& deopt_info =
+ DeoptInfo::Handle(builder->CreateDeoptInfo(deopt_table));
return deopt_info.raw();
}
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 692c0f8..f58a97b 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -364,6 +364,7 @@
bool CheckNonInlinedDuplicate(const Function& target);
bool TryInlining(const Function& target);
+ bool TryInlineRecognizedMethod(const Function& target);
TargetEntryInstr* BuildDecisionGraph();
@@ -381,8 +382,7 @@
class CallSiteInliner : public ValueObject {
public:
- CallSiteInliner(FlowGraph* flow_graph,
- GrowableArray<const Field*>* guarded_fields)
+ explicit CallSiteInliner(FlowGraph* flow_graph)
: caller_graph_(flow_graph),
inlined_(false),
initial_size_(flow_graph->InstructionCount()),
@@ -390,8 +390,7 @@
inlining_depth_(1),
collected_call_sites_(NULL),
inlining_call_sites_(NULL),
- function_cache_(),
- guarded_fields_(guarded_fields) { }
+ function_cache_() { }
FlowGraph* caller_graph() const { return caller_graph_; }
@@ -543,17 +542,19 @@
// Build the callee graph.
InlineExitCollector* exit_collector =
new InlineExitCollector(caller_graph_, call);
- FlowGraphBuilder builder(parsed_function,
- ic_data_array,
- exit_collector,
- Isolate::kNoDeoptId);
- builder.SetInitialBlockId(caller_graph_->max_block_id());
+ GrowableArray<const Field*> inlined_guarded_fields;
+ FlowGraphBuilder* builder = new FlowGraphBuilder(parsed_function,
+ ic_data_array,
+ exit_collector,
+ &inlined_guarded_fields,
+ Isolate::kNoDeoptId);
+ builder->SetInitialBlockId(caller_graph_->max_block_id());
FlowGraph* callee_graph;
{
TimerScope timer(FLAG_compiler_stats,
&CompilerStats::graphinliner_build_timer,
isolate);
- callee_graph = builder.BuildGraph();
+ callee_graph = builder->BuildGraph();
}
// The parameter stubs are a copy of the actual arguments providing
@@ -606,7 +607,7 @@
&CompilerStats::graphinliner_opt_timer,
isolate);
// TODO(zerny): Do more optimization passes on the callee graph.
- FlowGraphOptimizer optimizer(callee_graph, guarded_fields_);
+ FlowGraphOptimizer optimizer(callee_graph);
optimizer.ApplyICData();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
}
@@ -667,6 +668,13 @@
call_data->callee_graph = callee_graph;
call_data->parameter_stubs = param_stubs;
call_data->exit_collector = exit_collector;
+
+ // When inlined, we add the guarded fields of the callee to the caller's
+ // list of guarded fields.
+ for (intptr_t i = 0; i < inlined_guarded_fields.length(); ++i) {
+ caller_graph_->builder().AddToGuardedFields(*inlined_guarded_fields[i]);
+ }
+
TRACE_INLINING(OS::Print(" Success\n"));
return true;
} else {
@@ -681,6 +689,8 @@
}
private:
+ friend class PolymorphicInliner;
+
void InlineCall(InlinedCallData* call_data) {
TimerScope timer(FLAG_compiler_stats,
&CompilerStats::graphinliner_subst_timer,
@@ -995,7 +1005,6 @@
CallSites* collected_call_sites_;
CallSites* inlining_call_sites_;
GrowableArray<ParsedFunction*> function_cache_;
- GrowableArray<const Field*>* guarded_fields_;
DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
};
@@ -1083,8 +1092,13 @@
bool PolymorphicInliner::TryInlining(const Function& target) {
if (!target.is_optimizable()) {
+ if (TryInlineRecognizedMethod(target)) {
+ owner_->inlined_ = true;
+ return true;
+ }
return false;
}
+
GrowableArray<Value*> arguments(call_->ArgumentCount());
for (int i = 0; i < call_->ArgumentCount(); ++i) {
arguments.Add(call_->PushArgumentAt(i)->value());
@@ -1144,6 +1158,41 @@
}
+bool PolymorphicInliner::TryInlineRecognizedMethod(const Function& target) {
+ FlowGraphOptimizer optimizer(owner_->caller_graph());
+ TargetEntryInstr* entry;
+ Definition* last;
+ if (optimizer.TryInlineRecognizedMethod(target,
+ call_,
+ call_->ic_data(),
+ &entry, &last)) {
+ // Create a graph fragment.
+ InlineExitCollector* exit_collector =
+ new InlineExitCollector(owner_->caller_graph(), call_);
+
+ ReturnInstr* result =
+ new ReturnInstr(call_->instance_call()->token_pos(),
+ new Value(last));
+ owner_->caller_graph()->AppendTo(
+ last,
+ result,
+ call_->env(), // Return can become deoptimization target.
+ Definition::kEffect);
+ entry->set_last_instruction(result);
+ exit_collector->AddExit(result);
+ GraphEntryInstr* graph_entry =
+ new GraphEntryInstr(NULL, // No parsed function.
+ entry,
+ Isolate::kNoDeoptId); // No OSR id.
+ // Update polymorphic inliner state.
+ inlined_entries_.Add(graph_entry);
+ exit_collector_->Union(exit_collector);
+ return true;
+ }
+ return false;
+}
+
+
// Build a DAG to dispatch to the inlined function bodies. Load the class
// id of the receiver and make explicit comparisons for each inlined body,
// in frequency order. If all variants are inlined, the entry to the last
@@ -1431,7 +1480,7 @@
printer.PrintBlocks();
}
- CallSiteInliner inliner(flow_graph_, guarded_fields_);
+ CallSiteInliner inliner(flow_graph_);
inliner.InlineCalls();
if (inliner.inlined()) {
diff --git a/runtime/vm/flow_graph_inliner.h b/runtime/vm/flow_graph_inliner.h
index 57318e3..dfee0d5 100644
--- a/runtime/vm/flow_graph_inliner.h
+++ b/runtime/vm/flow_graph_inliner.h
@@ -15,9 +15,7 @@
class FlowGraphInliner : ValueObject {
public:
- FlowGraphInliner(FlowGraph* flow_graph,
- GrowableArray<const Field*>* guarded_fields)
- : flow_graph_(flow_graph), guarded_fields_(guarded_fields) {}
+ explicit FlowGraphInliner(FlowGraph* flow_graph) : flow_graph_(flow_graph) { }
// The flow graph is destructively updated upon inlining.
void Inline();
@@ -26,7 +24,6 @@
private:
FlowGraph* flow_graph_;
- GrowableArray<const Field*>* guarded_fields_;
DISALLOW_COPY_AND_ASSIGN(FlowGraphInliner);
};
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 53f4450..44aad69 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -160,6 +160,7 @@
Object::empty_array(), // Dummy argument descriptor.
ic_data.deopt_id(),
ic_data.num_args_tested()));
+ new_ic_data.set_deopt_reason(ic_data.deopt_reason());
const Function& function =
Function::Handle(ic_data.GetTargetForReceiverClassId(cid));
@@ -789,7 +790,6 @@
call->env(),
Definition::kEffect);
-
if (class_id == kGrowableObjectArrayCid) {
// Insert data elements load.
LoadFieldInstr* elements =
@@ -996,11 +996,187 @@
}
+static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
+ switch (kind) {
+ case MethodRecognizer::kImmutableArrayGetIndexed:
+ return kImmutableArrayCid;
+
+ case MethodRecognizer::kObjectArrayGetIndexed:
+ return kArrayCid;
+
+ case MethodRecognizer::kGrowableArrayGetIndexed:
+ return kGrowableObjectArrayCid;
+
+ case MethodRecognizer::kFloat32ArrayGetIndexed:
+ return kTypedDataFloat32ArrayCid;
+
+ case MethodRecognizer::kFloat64ArrayGetIndexed:
+ return kTypedDataFloat64ArrayCid;
+
+ case MethodRecognizer::kInt8ArrayGetIndexed:
+ return kTypedDataInt8ArrayCid;
+
+ case MethodRecognizer::kUint8ArrayGetIndexed:
+ return kTypedDataUint8ArrayCid;
+
+ case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+ return kTypedDataUint8ClampedArrayCid;
+
+ case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+ return kExternalTypedDataUint8ArrayCid;
+
+ case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+ return kExternalTypedDataUint8ClampedArrayCid;
+
+ case MethodRecognizer::kInt16ArrayGetIndexed:
+ return kTypedDataInt16ArrayCid;
+
+ case MethodRecognizer::kUint16ArrayGetIndexed:
+ return kTypedDataUint16ArrayCid;
+
+ case MethodRecognizer::kInt32ArrayGetIndexed:
+ return kTypedDataInt32ArrayCid;
+
+ case MethodRecognizer::kUint32ArrayGetIndexed:
+ return kTypedDataUint32ArrayCid;
+
+ case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+ return kTypedDataFloat32x4ArrayCid;
+
+ default:
+ break;
+ }
+ return kIllegalCid;
+}
+
+
+bool FlowGraphOptimizer::TryInlineRecognizedMethod(const Function& target,
+ Instruction* call,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
+ switch (kind) {
+ case MethodRecognizer::kImmutableArrayGetIndexed:
+ case MethodRecognizer::kObjectArrayGetIndexed:
+ case MethodRecognizer::kGrowableArrayGetIndexed:
+ case MethodRecognizer::kFloat32ArrayGetIndexed:
+ case MethodRecognizer::kFloat64ArrayGetIndexed:
+ case MethodRecognizer::kInt8ArrayGetIndexed:
+ case MethodRecognizer::kUint8ArrayGetIndexed:
+ case MethodRecognizer::kUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ArrayGetIndexed:
+ case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
+ case MethodRecognizer::kInt16ArrayGetIndexed:
+ case MethodRecognizer::kUint16ArrayGetIndexed:
+ case MethodRecognizer::kInt32ArrayGetIndexed:
+ case MethodRecognizer::kUint32ArrayGetIndexed:
+ case MethodRecognizer::kFloat32x4ArrayGetIndexed:
+ return TryInlineGetIndexed(kind, call, ic_data, entry, last);
+ default:
+ return false;
+ }
+}
+
+
+bool FlowGraphOptimizer::TryInlineGetIndexed(MethodRecognizer::Kind kind,
+ Instruction* call,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last) {
+ intptr_t array_cid = MethodKindToCid(kind);
+ ASSERT(array_cid != kIllegalCid);
+
+ // Insert index smi checks and attach a copy of the
+ // original environment because the operation can still deoptimize.
+ Definition* array = call->ArgumentAt(0);
+ Definition* index = call->ArgumentAt(1);
+ *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
+ call->GetBlock()->try_index());
+ (*entry)->InheritDeoptTarget(call);
+
+ Instruction* cursor = *entry;
+ cursor = flow_graph()->AppendTo(cursor,
+ new CheckSmiInstr(new Value(index),
+ call->deopt_id()),
+ call->env(),
+ Definition::kEffect);
+
+ // Insert array length load and bounds check.
+ const bool is_immutable =
+ CheckArrayBoundInstr::IsFixedLengthArrayType(array_cid);
+ LoadFieldInstr* length =
+ new LoadFieldInstr(new Value(array),
+ CheckArrayBoundInstr::LengthOffsetFor(array_cid),
+ Type::ZoneHandle(Type::SmiType()),
+ is_immutable);
+ length->set_result_cid(kSmiCid);
+ length->set_recognized_kind(
+ LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
+ cursor = flow_graph()->AppendTo(cursor,
+ length,
+ NULL,
+ Definition::kValue);
+
+ cursor = flow_graph()->AppendTo(cursor,
+ new CheckArrayBoundInstr(
+ new Value(length),
+ new Value(index),
+ call->deopt_id()),
+ call->env(),
+ Definition::kEffect);
+
+ if (array_cid == kGrowableObjectArrayCid) {
+ // Insert data elements load.
+ LoadFieldInstr* elements =
+ new LoadFieldInstr(new Value(array),
+ GrowableObjectArray::data_offset(),
+ Type::ZoneHandle(Type::DynamicType()));
+ elements->set_result_cid(kArrayCid);
+ cursor = flow_graph()->AppendTo(cursor,
+ elements,
+ NULL,
+ Definition::kValue);
+ // Load from the data from backing store which is a fixed-length array.
+ array = elements;
+ array_cid = kArrayCid;
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ LoadUntaggedInstr* elements =
+ new LoadUntaggedInstr(new Value(array),
+ ExternalTypedData::data_offset());
+ cursor = flow_graph()->AppendTo(cursor,
+ elements,
+ NULL,
+ Definition::kValue);
+ array = elements;
+ }
+
+ intptr_t deopt_id = Isolate::kNoDeoptId;
+ if ((array_cid == kTypedDataInt32ArrayCid) ||
+ (array_cid == kTypedDataUint32ArrayCid)) {
+ // Set deopt_id if we can optimistically assume that the result is Smi.
+ // Assume mixed Mint/Smi if this instruction caused deoptimization once.
+ deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
+ call->deopt_id() : Isolate::kNoDeoptId;
+ }
+
+ // Array load and return.
+ intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
+ *last = new LoadIndexedInstr(new Value(array),
+ new Value(index),
+ index_scale,
+ array_cid,
+ deopt_id);
+ flow_graph()->AppendTo(cursor,
+ *last,
+ deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
+ Definition::kValue);
+ return true;
+}
+
bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
const intptr_t class_id = ReceiverClassId(call);
- // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt.
- intptr_t deopt_id = Isolate::kNoDeoptId;
switch (class_id) {
case kArrayCid:
case kImmutableArrayCid:
@@ -1021,31 +1197,43 @@
}
break;
case kTypedDataInt32ArrayCid:
- case kTypedDataUint32ArrayCid: {
+ case kTypedDataUint32ArrayCid:
if (!CanUnboxInt32()) return false;
-
- // Set deopt_id if we can optimistically assume that the result is Smi.
- // Assume mixed Mint/Smi if this instruction caused deoptimization once.
- ASSERT(call->HasICData());
- const ICData& ic_data = *call->ic_data();
- deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
- call->deopt_id() : Isolate::kNoDeoptId;
- }
break;
default:
return false;
}
- Definition* array = call->ArgumentAt(0);
- Definition* index = call->ArgumentAt(1);
- intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
- intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
- Definition* array_op =
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- index_scale,
- array_cid,
- deopt_id);
- ReplaceCall(call, array_op);
+
+ const Function& target =
+ Function::Handle(call->ic_data()->GetTargetAt(0));
+ TargetEntryInstr* entry;
+ Definition* last;
+ ASSERT(class_id == MethodKindToCid(MethodRecognizer::RecognizeKind(target)));
+ bool success = TryInlineRecognizedMethod(target,
+ call,
+ *call->ic_data(),
+ &entry, &last);
+ ASSERT(success);
+ // Insert receiver class check.
+ AddReceiverCheck(call);
+ // Remove the original push arguments.
+ for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+ PushArgumentInstr* push = call->PushArgumentAt(i);
+ push->ReplaceUsesWith(push->value()->definition());
+ push->RemoveFromGraph();
+ }
+ // Replace all uses of this definition with the result.
+ call->ReplaceUsesWith(last);
+ // Finally insert the sequence other definition in place of this one in the
+ // graph.
+ call->previous()->LinkTo(entry->next());
+ entry->UnuseAllInputs(); // Entry block is not in the graph.
+ last->LinkTo(call);
+ // Remove through the iterator.
+ ASSERT(current_iterator()->Current() == call);
+ current_iterator()->RemoveCurrentFromGraph();
+ call->set_previous(NULL);
+ call->set_next(NULL);
return true;
}
@@ -1382,20 +1570,6 @@
}
-void FlowGraphOptimizer::AddToGuardedFields(const Field& field) {
- if ((field.guarded_cid() == kDynamicCid) ||
- (field.guarded_cid() == kIllegalCid)) {
- return;
- }
- for (intptr_t j = 0; j < guarded_fields_->length(); j++) {
- if ((*guarded_fields_)[j]->raw() == field.raw()) {
- return;
- }
- }
- guarded_fields_->Add(&field);
-}
-
-
void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
ASSERT(call->HasICData());
const ICData& ic_data = *call->ic_data();
@@ -1422,7 +1596,7 @@
if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) {
load->set_result_cid(field.guarded_cid());
}
- AddToGuardedFields(field);
+ flow_graph_->builder().AddToGuardedFields(field);
}
// Discard the environment from the original instruction because the load
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 4243eba..8c9f6fe 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -16,11 +16,9 @@
class FlowGraphOptimizer : public FlowGraphVisitor {
public:
- FlowGraphOptimizer(FlowGraph* flow_graph,
- GrowableArray<const Field*>* guarded_fields)
+ explicit FlowGraphOptimizer(FlowGraph* flow_graph)
: FlowGraphVisitor(flow_graph->reverse_postorder()),
- flow_graph_(flow_graph),
- guarded_fields_(guarded_fields) { }
+ flow_graph_(flow_graph) { }
virtual ~FlowGraphOptimizer() {}
FlowGraph* flow_graph() const { return flow_graph_; }
@@ -46,6 +44,12 @@
void AnalyzeTryCatch();
+ bool TryInlineRecognizedMethod(const Function& target,
+ Instruction* call,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last);
+
// Remove environments from the instructions which do not deoptimize.
void EliminateEnvironments();
@@ -77,6 +81,11 @@
const ICData& value_check,
intptr_t class_id);
bool TryReplaceWithLoadIndexed(InstanceCallInstr* call);
+ bool TryInlineGetIndexed(MethodRecognizer::Kind kind,
+ Instruction* call,
+ const ICData& ic_data,
+ TargetEntryInstr** entry,
+ Definition** last);
bool TryReplaceWithBinaryOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryReplaceWithUnaryOp(InstanceCallInstr* call, Token::Kind op_kind);
@@ -185,10 +194,7 @@
Definition* left_instr,
Definition* right_instr);
- void AddToGuardedFields(const Field& field);
-
FlowGraph* flow_graph_;
- GrowableArray<const Field*>* guarded_fields_;
DISALLOW_COPY_AND_ASSIGN(FlowGraphOptimizer);
};
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 355949f..147ea56 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -265,7 +265,7 @@
}
-GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
+GraphEntryInstr::GraphEntryInstr(const ParsedFunction* parsed_function,
TargetEntryInstr* normal_entry,
intptr_t osr_id)
: BlockEntryInstr(0, CatchClauseNode::kInvalidTryIndex),
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 33cde45..84e9f9d 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -39,11 +39,11 @@
// See intrinsifier for fingerprint computation.
#define RECOGNIZED_LIST(V) \
V(::, identical, ObjectIdentical, 496869842) \
- V(Object, Object., ObjectConstructor, 1058525712) \
- V(Object, get:_cid, ObjectCid, 1498661928) \
- V(_ObjectArray, get:length, ObjectArrayLength, 259323113) \
- V(_ImmutableArray, get:length, ImmutableArrayLength, 1341942416) \
- V(_TypedList, get:length, TypedDataLength, 26556746) \
+ V(Object, Object., ObjectConstructor, 1058585294) \
+ V(Object, get:_cid, ObjectCid, 1498721510) \
+ V(_ObjectArray, get:length, ObjectArrayLength, 259382695) \
+ V(_ImmutableArray, get:length, ImmutableArrayLength, 1342001998) \
+ V(_TypedList, get:length, TypedDataLength, 26616328) \
V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 272598802) \
V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 831354841) \
V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 1832126257) \
@@ -53,25 +53,25 @@
V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 185163470) \
V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 1356392173) \
V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 1239681356) \
- V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 742201367) \
- V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 1163140155) \
- V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 1106354531) \
- V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 545390027) \
- V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 1963924310) \
- V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 724748139) \
- V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 756330666) \
- V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 1495546688) \
- V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 560495357) \
- V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160357614) \
- V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 1509781988) \
- V(_GrowableObjectArray, _setData, GrowableArraySetData, 236295352) \
- V(_GrowableObjectArray, _setLength, GrowableArraySetLength, 1922121178) \
- V(_StringBase, get:length, StringBaseLength, 1483460481) \
- V(_StringBase, get:isEmpty, StringBaseIsEmpty, 1588094430) \
+ V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 1443265945) \
+ V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 1864204733) \
+ V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 1807419109) \
+ V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 1246454605) \
+ V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 517505240) \
+ V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 1425812717) \
+ V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 1457395244) \
+ V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 49127618) \
+ V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 1261559935) \
+ V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160417196) \
+ V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 1509841570) \
+ V(_GrowableObjectArray, _setData, GrowableArraySetData, 1574432374) \
+ V(_GrowableObjectArray, _setLength, GrowableArraySetLength, 1112774552) \
+ V(_StringBase, get:length, StringBaseLength, 1483520063) \
+ V(_StringBase, get:isEmpty, StringBaseIsEmpty, 879849436) \
V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 1958436584) \
- V(_StringBase, [], StringBaseCharAt, 1799392702) \
- V(_OneByteString, _setAt, OneByteStringSetAt, 1754827784) \
- V(_IntegerImplementation, toDouble, IntegerToDouble, 2141284842) \
+ V(_StringBase, [], StringBaseCharAt, 990046076) \
+ V(_OneByteString, _setAt, OneByteStringSetAt, 308408714) \
+ V(_IntegerImplementation, toDouble, IntegerToDouble, 2011998508) \
V(_IntegerImplementation, _leftShiftWithMask32, IntegerLeftShiftWithMask32, \
2095943661) \
V(_Double, toInt, DoubleToInteger, 1328149975) \
@@ -83,18 +83,18 @@
V(::, sqrt, MathSqrt, 465520247) \
V(::, sin, MathSin, 730107143) \
V(::, cos, MathCos, 1282146521) \
- V(::, min, MathMin, 1584022354) \
- V(::, max, MathMax, 328632232) \
- V(::, _doublePow, MathDoublePow, 2002448359) \
- V(Float32x4, Float32x4., Float32x4Constructor, 1876089990) \
- V(Float32x4, Float32x4.zero, Float32x4Zero, 1903586222) \
- V(Float32x4, Float32x4.splat, Float32x4Splat, 38462589) \
+ V(::, min, MathMin, 1602283410) \
+ V(::, max, MathMax, 997766696) \
+ V(::, _doublePow, MathDoublePow, 1728171041) \
+ V(Float32x4, Float32x4., Float32x4Constructor, 786169160) \
+ V(Float32x4, Float32x4.zero, Float32x4Zero, 1589383280) \
+ V(Float32x4, Float32x4.splat, Float32x4Splat, 62513275) \
V(_Float32x4, shuffle, Float32x4Shuffle, 1178727105) \
- V(_Float32x4, get:x, Float32x4ShuffleX, 1351658256) \
- V(_Float32x4, get:y, Float32x4ShuffleY, 217326828) \
- V(_Float32x4, get:z, Float32x4ShuffleZ, 2144864139) \
- V(_Float32x4, get:w, Float32x4ShuffleW, 1447639537) \
- V(_Float32x4, get:signMask, Float32x4GetSignMask, 1198789765) \
+ V(_Float32x4, get:x, Float32x4ShuffleX, 1351717838) \
+ V(_Float32x4, get:y, Float32x4ShuffleY, 217386410) \
+ V(_Float32x4, get:z, Float32x4ShuffleZ, 2144923721) \
+ V(_Float32x4, get:w, Float32x4ShuffleW, 1447699119) \
+ V(_Float32x4, get:signMask, Float32x4GetSignMask, 1198849347) \
V(_Float32x4, _cmpequal, Float32x4Equal, 2141256163) \
V(_Float32x4, _cmpgt, Float32x4GreaterThan, 696292270) \
V(_Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, 1199333164) \
@@ -120,30 +120,46 @@
V(_Float32x4, interleaveZW, Float32x4InterleaveZW, 928280031) \
V(_Float32x4, interleaveXYPairs, Float32x4InterleaveXYPairs, 1046078993) \
V(_Float32x4, interleaveZWPairs, Float32x4InterleaveZWPairs, 1001751955) \
- V(Uint32x4, Uint32x4.bool, Uint32x4BoolConstructor, 733327933) \
- V(_Uint32x4, get:flagX, Uint32x4GetFlagX, 1674637210) \
- V(_Uint32x4, get:flagY, Uint32x4GetFlagY, 2013140570) \
- V(_Uint32x4, get:flagZ, Uint32x4GetFlagZ, 944674353) \
- V(_Uint32x4, get:flagW, Uint32x4GetFlagW, 22686587) \
- V(_Uint32x4, get:signMask, Uint32x4GetSignMask, 1858084501) \
- V(_Uint32x4, select, Uint32x4Select, 881590808) \
+ V(Uint32x4, Uint32x4.bool, Uint32x4BoolConstructor, 517444095) \
+ V(_Uint32x4, get:flagX, Uint32x4GetFlagX, 1674696792) \
+ V(_Uint32x4, get:flagY, Uint32x4GetFlagY, 2013200152) \
+ V(_Uint32x4, get:flagZ, Uint32x4GetFlagZ, 944733935) \
+ V(_Uint32x4, get:flagW, Uint32x4GetFlagW, 22746169) \
+ V(_Uint32x4, get:signMask, Uint32x4GetSignMask, 1858144083) \
+ V(_Uint32x4, select, Uint32x4Select, 72244182) \
V(_Uint32x4, withFlagX, Uint32x4WithFlagX, 1475542073) \
V(_Uint32x4, withFlagY, Uint32x4WithFlagY, 830610988) \
V(_Uint32x4, withFlagZ, Uint32x4WithFlagZ, 1714792414) \
V(_Uint32x4, withFlagW, Uint32x4WithFlagW, 1516924162) \
V(_Uint32x4, _toFloat32x4, Uint32x4ToUint32x4, 2054503505) \
+ V(_ObjectArray, [], ObjectArrayGetIndexed, 544020319) \
+ V(_ImmutableArray, [], ImmutableArrayGetIndexed, 1345387065) \
+ V(_GrowableObjectArray, [], GrowableArrayGetIndexed, 951312767) \
+ V(_Float32Array, [], Float32ArrayGetIndexed, 1225286513) \
+ V(_Float64Array, [], Float64ArrayGetIndexed, 871118335) \
+ V(_Int8Array, [], Int8ArrayGetIndexed, 199925538) \
+ V(_Uint8Array, [], Uint8ArrayGetIndexed, 502448555) \
+ V(_Uint8ClampedArray, [], Uint8ClampedArrayGetIndexed, 1292893603) \
+ V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 1831383216) \
+ V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
+ 1831906095) \
+ V(_Int16Array, [], Int16ArrayGetIndexed, 1191799443) \
+ V(_Uint16Array, [], Uint16ArrayGetIndexed, 814177144) \
+ V(_Int32Array, [], Int32ArrayGetIndexed, 787321640) \
+ V(_Uint32Array, [], Uint32ArrayGetIndexed, 1421922726) \
+ V(_Float32x4Array, [], Float32x4ArrayGetIndexed, 1901126825) \
// A list of core function that should always be inlined.
#define INLINE_WHITE_LIST(V) \
- V(_ObjectArray, get:length, ObjectArrayLength, 259323113) \
- V(_ImmutableArray, get:length, ImmutableArrayLength, 1341942416) \
- V(_TypedList, get:length, TypedDataLength, 26556746) \
- V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160357614) \
- V(_StringBase, get:length, StringBaseLength, 1483460481) \
- V(ListIterator, moveNext, ListIteratorMoveNext, 657540761) \
- V(_GrowableObjectArray, get:iterator, GrowableArrayIterator, 281980741) \
- V(_GrowableObjectArray, forEach, GrowableArrayForEach, 334448248)
+ V(_ObjectArray, get:length, ObjectArrayLength, 259382695) \
+ V(_ImmutableArray, get:length, ImmutableArrayLength, 1342001998) \
+ V(_TypedList, get:length, TypedDataLength, 26616328) \
+ V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160417196) \
+ V(_StringBase, get:length, StringBaseLength, 1483520063) \
+ V(ListIterator, moveNext, ListIteratorMoveNext, 90930587) \
+ V(_GrowableObjectArray, get:iterator, GrowableArrayIterator, 2129691657) \
+ V(_GrowableObjectArray, forEach, GrowableArrayForEach, 1669274418)
// Class that recognizes the name and owner of a function and returns the
@@ -1326,7 +1342,7 @@
class GraphEntryInstr : public BlockEntryInstr {
public:
- GraphEntryInstr(const ParsedFunction& parsed_function,
+ GraphEntryInstr(const ParsedFunction* parsed_function,
TargetEntryInstr* normal_entry,
intptr_t osr_id);
@@ -1371,7 +1387,7 @@
TargetEntryInstr* normal_entry() const { return normal_entry_; }
const ParsedFunction& parsed_function() const {
- return parsed_function_;
+ return *parsed_function_;
}
const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const {
@@ -1384,7 +1400,7 @@
virtual void ClearPredecessors() {}
virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); }
- const ParsedFunction& parsed_function_;
+ const ParsedFunction* parsed_function_;
TargetEntryInstr* normal_entry_;
GrowableArray<CatchBlockEntryInstr*> catch_entries_;
GrowableArray<Definition*> initial_definitions_;
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 9b54c7f..de6d92e 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -16,83 +16,83 @@
// When adding a new function for intrinsification add a 0 as fingerprint,
// build and run to get the correct fingerprint from the mismatch error.
#define CORE_LIB_INTRINSIC_LIST(V) \
- V(_Smi, ~, Smi_bitNegate, 635678453) \
- V(_Smi, get:bitLength, Smi_bitLength, 383357874) \
- V(_Double, >, Double_greaterThan, 1021232334) \
- V(_Double, >=, Double_greaterEqualThan, 324955595) \
- V(_Double, <, Double_lessThan, 978151157) \
- V(_Double, <=, Double_lessEqualThan, 1169397675) \
- V(_Double, ==, Double_equal, 223604237) \
- V(_Double, +, Double_add, 295873577) \
- V(_Double, -, Double_sub, 1180117486) \
- V(_Double, *, Double_mul, 1999983053) \
- V(_Double, /, Double_div, 1904009451) \
- V(_Double, get:isNaN, Double_getIsNaN, 916506740) \
- V(_Double, get:isNegative, Double_getIsNegative, 1711332287) \
- V(_Double, _mulFromInteger, Double_mulFromInteger, 930284178) \
- V(_Double, .fromInteger, Double_fromInteger, 475441744) \
- V(_ObjectArray, ., ObjectArray_Allocate, 1930677134) \
- V(_ObjectArray, get:length, Array_getLength, 259323113) \
- V(_ObjectArray, [], Array_getIndexed, 1353366945) \
- V(_ObjectArray, []=, Array_setIndexed, 1492559642) \
- V(_GrowableObjectArray, .withData, GrowableArray_Allocate, 1012992871) \
- V(_GrowableObjectArray, get:length, GrowableArray_getLength, 1160357614) \
- V(_GrowableObjectArray, get:_capacity, GrowableArray_getCapacity, 1509781988)\
- V(_GrowableObjectArray, [], GrowableArray_getIndexed, 1760659393) \
- V(_GrowableObjectArray, []=, GrowableArray_setIndexed, 407626503) \
- V(_GrowableObjectArray, _setLength, GrowableArray_setLength, 1922121178) \
- V(_GrowableObjectArray, _setData, GrowableArray_setData, 236295352) \
- V(_GrowableObjectArray, add, GrowableArray_add, 1442410650) \
- V(_ImmutableArray, [], ImmutableArray_getIndexed, 7250043) \
- V(_ImmutableArray, get:length, ImmutableArray_getLength, 1341942416) \
- V(Object, ==, Object_equal, 677817295) \
- V(_StringBase, get:hashCode, String_getHashCode, 654483446) \
- V(_StringBase, get:isEmpty, String_getIsEmpty, 1588094430) \
- V(_StringBase, get:length, String_getLength, 1483460481) \
+ V(_Smi, ~, Smi_bitNegate, 692936755) \
+ V(_Smi, get:bitLength, Smi_bitLength, 383417456) \
+ V(_Double, >, Double_greaterThan, 1187341070) \
+ V(_Double, >=, Double_greaterEqualThan, 1770896399) \
+ V(_Double, <, Double_lessThan, 1238163699) \
+ V(_Double, <=, Double_lessEqualThan, 467854831) \
+ V(_Double, ==, Double_equal, 1917937673) \
+ V(_Double, +, Double_add, 461982313) \
+ V(_Double, -, Double_sub, 1346226222) \
+ V(_Double, *, Double_mul, 18608141) \
+ V(_Double, /, Double_div, 2070118187) \
+ V(_Double, get:isNaN, Double_getIsNaN, 916566322) \
+ V(_Double, get:isNegative, Double_getIsNegative, 1711391869) \
+ V(_Double, _mulFromInteger, Double_mulFromInteger, 1238321808) \
+ V(_Double, .fromInteger, Double_fromInteger, 82414734) \
+ V(_ObjectArray, ., ObjectArray_Allocate, 1558200848) \
+ V(_ObjectArray, get:length, Array_getLength, 259382695) \
+ V(_ObjectArray, [], Array_getIndexed, 544020319) \
+ V(_ObjectArray, []=, Array_setIndexed, 304306010) \
+ V(_GrowableObjectArray, .withData, GrowableArray_Allocate, 619965861) \
+ V(_GrowableObjectArray, get:length, GrowableArray_getLength, 1160417196) \
+ V(_GrowableObjectArray, get:_capacity, GrowableArray_getCapacity, 1509841570)\
+ V(_GrowableObjectArray, [], GrowableArray_getIndexed, 951312767) \
+ V(_GrowableObjectArray, []=, GrowableArray_setIndexed, 1366856519) \
+ V(_GrowableObjectArray, _setLength, GrowableArray_setLength, 1112774552) \
+ V(_GrowableObjectArray, _setData, GrowableArray_setData, 1574432374) \
+ V(_GrowableObjectArray, add, GrowableArray_add, 635801182) \
+ V(_ImmutableArray, [], ImmutableArray_getIndexed, 1345387065) \
+ V(_ImmutableArray, get:length, ImmutableArray_getLength, 1342001998) \
+ V(Object, ==, Object_equal, 936042315) \
+ V(_StringBase, get:hashCode, String_getHashCode, 654543028) \
+ V(_StringBase, get:isEmpty, String_getIsEmpty, 879849436) \
+ V(_StringBase, get:length, String_getLength, 1483520063) \
V(_StringBase, codeUnitAt, String_codeUnitAt, 1958436584) \
- V(_OneByteString, get:hashCode, OneByteString_getHashCode, 1236404434) \
+ V(_OneByteString, get:hashCode, OneByteString_getHashCode, 1236464016) \
V(_OneByteString, _substringUncheckedNative, \
OneByteString_substringUnchecked, 25652388) \
- V(_OneByteString, _setAt, OneByteString_setAt, 1754827784) \
- V(_OneByteString, _allocate, OneByteString_allocate, 1064009711) \
+ V(_OneByteString, _setAt, OneByteString_setAt, 308408714) \
+ V(_OneByteString, _allocate, OneByteString_allocate, 1744068081) \
#define CORE_INTEGER_LIB_INTRINSIC_LIST(V) \
V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger, \
740884607) \
- V(_IntegerImplementation, +, Integer_add, 714540399) \
+ V(_IntegerImplementation, +, Integer_add, 772815665) \
V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, \
584777821) \
- V(_IntegerImplementation, -, Integer_sub, 1880284412) \
+ V(_IntegerImplementation, -, Integer_sub, 1938559678) \
V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger, \
1757603756) \
- V(_IntegerImplementation, *, Integer_mul, 1935440252) \
- V(_IntegerImplementation, remainder, Integer_remainder, 2140653009) \
+ V(_IntegerImplementation, *, Integer_mul, 1993715518) \
+ V(_IntegerImplementation, remainder, Integer_remainder, 1331308305) \
V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger, \
1398988805) \
- V(_IntegerImplementation, ~/, Integer_truncDivide, 250357385) \
- V(_IntegerImplementation, unary-, Integer_negate, 732448114) \
+ V(_IntegerImplementation, ~/, Integer_truncDivide, 41718791) \
+ V(_IntegerImplementation, unary-, Integer_negate, 341268208) \
V(_IntegerImplementation, _bitAndFromInteger, \
Integer_bitAndFromInteger, 512285096) \
- V(_IntegerImplementation, &, Integer_bitAnd, 1677634910) \
+ V(_IntegerImplementation, &, Integer_bitAnd, 1735910176) \
V(_IntegerImplementation, _bitOrFromInteger, \
Integer_bitOrFromInteger, 333543947) \
- V(_IntegerImplementation, |, Integer_bitOr, 1062616305) \
+ V(_IntegerImplementation, |, Integer_bitOr, 1120891571) \
V(_IntegerImplementation, _bitXorFromInteger, \
Integer_bitXorFromInteger, 1746295953) \
- V(_IntegerImplementation, ^, Integer_bitXor, 2111001841) \
+ V(_IntegerImplementation, ^, Integer_bitXor, 21793459) \
V(_IntegerImplementation, \
_greaterThanFromInteger, \
Integer_greaterThanFromInt, 1883218996) \
- V(_IntegerImplementation, >, Integer_greaterThan, 195542579) \
- V(_IntegerImplementation, ==, Integer_equal, 288044426) \
+ V(_IntegerImplementation, >, Integer_greaterThan, 253817845) \
+ V(_IntegerImplementation, ==, Integer_equal, 1899239372) \
V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger, \
111745915) \
- V(_IntegerImplementation, <, Integer_lessThan, 1133694259) \
- V(_IntegerImplementation, <=, Integer_lessEqualThan, 1724243945) \
- V(_IntegerImplementation, >=, Integer_greaterEqualThan, 879801865) \
- V(_IntegerImplementation, <<, Integer_shl, 1508088336) \
- V(_IntegerImplementation, >>, Integer_sar, 1786839625) \
+ V(_IntegerImplementation, <, Integer_lessThan, 1393706801) \
+ V(_IntegerImplementation, <=, Integer_lessEqualThan, 1022701101) \
+ V(_IntegerImplementation, >=, Integer_greaterEqualThan, 178259021) \
+ V(_IntegerImplementation, <<, Integer_shl, 1566363602) \
+ V(_IntegerImplementation, >>, Integer_sar, 1845114891) \
V(_Double, toInt, Double_toInt, 1328149975)
@@ -100,35 +100,35 @@
V(::, sqrt, Math_sqrt, 465520247) \
V(::, sin, Math_sin, 730107143) \
V(::, cos, Math_cos, 1282146521) \
- V(_Random, _nextState, Random_nextState, 1088413969) \
+ V(_Random, _nextState, Random_nextState, 1145672271) \
#define TYPED_DATA_LIB_INTRINSIC_LIST(V) \
- V(_TypedList, get:length, TypedData_getLength, 26556746) \
- V(_Int8Array, _new, TypedData_Int8Array_new, 1145746295) \
- V(_Uint8Array, _new, TypedData_Uint8Array_new, 1097983968) \
- V(_Uint8ClampedArray, _new, TypedData_Uint8ClampedArray_new, 2036179275) \
- V(_Int16Array, _new, TypedData_Int16Array_new, 1550281862) \
- V(_Uint16Array, _new, TypedData_Uint16Array_new, 381457023) \
- V(_Int32Array, _new, TypedData_Int32Array_new, 1331503368) \
- V(_Uint32Array, _new, TypedData_Uint32Array_new, 2068855037) \
- V(_Int64Array, _new, TypedData_Int64Array_new, 2608399) \
- V(_Uint64Array, _new, TypedData_Uint64Array_new, 1855520143) \
- V(_Float32Array, _new, TypedData_Float32Array_new, 1251124964) \
- V(_Float64Array, _new, TypedData_Float64Array_new, 1439361428) \
- V(_Float32x4Array, _new, TypedData_Float32x4Array_new, 1902726893) \
- V(_Int8Array, ., TypedData_Int8Array_factory, 1340298556) \
- V(_Uint8Array, ., TypedData_Uint8Array_factory, 1775618642) \
- V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 264668024) \
- V(_Int16Array, ., TypedData_Int16Array_factory, 1095249987) \
- V(_Uint16Array, ., TypedData_Uint16Array_factory, 1275304272) \
- V(_Int32Array, ., TypedData_Int32Array_factory, 523449884) \
- V(_Uint32Array, ., TypedData_Uint32Array_factory, 458531362) \
- V(_Int64Array, ., TypedData_Int64Array_factory, 1753070829) \
- V(_Uint64Array, ., TypedData_Uint64Array_factory, 1561660391) \
- V(_Float32Array, ., TypedData_Float32Array_factory, 368082071) \
- V(_Float64Array, ., TypedData_Float64Array_factory, 245916452) \
- V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 1674296969) \
+ V(_TypedList, get:length, TypedData_getLength, 26616328) \
+ V(_Int8Array, _new, TypedData_Int8Array_new, 1825804665) \
+ V(_Uint8Array, _new, TypedData_Uint8Array_new, 1778042338) \
+ V(_Uint8ClampedArray, _new, TypedData_Uint8ClampedArray_new, 568753997) \
+ V(_Int16Array, _new, TypedData_Int16Array_new, 82856584) \
+ V(_Uint16Array, _new, TypedData_Uint16Array_new, 1061515393) \
+ V(_Int32Array, _new, TypedData_Int32Array_new, 2011561738) \
+ V(_Uint32Array, _new, TypedData_Uint32Array_new, 601429759) \
+ V(_Int64Array, _new, TypedData_Int64Array_new, 682666769) \
+ V(_Uint64Array, _new, TypedData_Uint64Array_new, 388094865) \
+ V(_Float32Array, _new, TypedData_Float32Array_new, 1931183334) \
+ V(_Float64Array, _new, TypedData_Float64Array_new, 2119419798) \
+ V(_Float32x4Array, _new, TypedData_Float32x4Array_new, 435301615) \
+ V(_Int8Array, ., TypedData_Int8Array_factory, 810750844) \
+ V(_Uint8Array, ., TypedData_Uint8Array_factory, 1246070930) \
+ V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 1882603960) \
+ V(_Int16Array, ., TypedData_Int16Array_factory, 565702275) \
+ V(_Uint16Array, ., TypedData_Uint16Array_factory, 745756560) \
+ V(_Int32Array, ., TypedData_Int32Array_factory, 2141385820) \
+ V(_Uint32Array, ., TypedData_Uint32Array_factory, 2076467298) \
+ V(_Int64Array, ., TypedData_Int64Array_factory, 1223523117) \
+ V(_Uint64Array, ., TypedData_Uint64Array_factory, 1032112679) \
+ V(_Float32Array, ., TypedData_Float32Array_factory, 1986018007) \
+ V(_Float64Array, ., TypedData_Float64Array_factory, 1863852388) \
+ V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 1144749257) \
// TODO(srdjan): Implement _FixedSizeArrayIterator, get:current and
// _FixedSizeArrayIterator, moveNext.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index cdfa888..83180be 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -915,11 +915,12 @@
// can be Smi, Mint, Bigint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
Label fall_through, true_label, check_for_mint;
+ const intptr_t kReceiverOffset = 2;
+ const intptr_t kArgumentOffset = 1;
+
// For integer receiver '===' check first.
- // Entering a dart frame so we can use the PP for loading True and False.
- __ EnterDartFrame(0);
- __ movq(RAX, Address(RSP, + 4 * kWordSize));
- __ movq(RCX, Address(RSP, + 5 * kWordSize));
+ __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
+ __ movq(RCX, Address(RSP, + kReceiverOffset * kWordSize));
__ cmpq(RAX, RCX);
__ j(EQUAL, &true_label, Assembler::kNearJump);
__ orq(RAX, RCX);
@@ -927,28 +928,25 @@
__ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
// Both arguments are smi, '===' is good enough.
__ LoadObject(RAX, Bool::False(), PP);
- __ LeaveFrameWithPP();
__ ret();
__ Bind(&true_label);
__ LoadObject(RAX, Bool::True(), PP);
- __ LeaveFrameWithPP();
__ ret();
// At least one of the arguments was not Smi.
Label receiver_not_smi;
__ Bind(&check_for_mint);
- __ movq(RAX, Address(RSP, + 5 * kWordSize)); // Receiver.
+ __ movq(RAX, Address(RSP, + kReceiverOffset * kWordSize));
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &receiver_not_smi);
// Left (receiver) is Smi, return false if right is not Double.
// Note that an instance of Mint or Bigint never contains a value that can be
// represented by Smi.
- __ movq(RAX, Address(RSP, + 4 * kWordSize));
+ __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
__ CompareClassId(RAX, kDoubleCid);
__ j(EQUAL, &fall_through);
__ LoadObject(RAX, Bool::False(), PP);
- __ LeaveFrameWithPP();
__ ret();
__ Bind(&receiver_not_smi);
@@ -956,17 +954,15 @@
__ CompareClassId(RAX, kMintCid);
__ j(NOT_EQUAL, &fall_through);
// Receiver is Mint, return false if right is Smi.
- __ movq(RAX, Address(RSP, + 4 * kWordSize)); // Right argument.
+ __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through);
// Smi == Mint -> false.
__ LoadObject(RAX, Bool::False(), PP);
- __ LeaveFrameWithPP();
__ ret();
// TODO(srdjan): Implement Mint == Mint comparison.
__ Bind(&fall_through);
- __ LeaveFrameWithPP();
}
@@ -1351,24 +1347,19 @@
__ ret();
}
-
// Identity comparison.
void Intrinsifier::Object_equal(Assembler* assembler) {
Label is_true;
- // This intrinsic is used from the API even when we have not entered any
- // Dart frame, yet, so the PP would otherwise be null in this case unless
- // we enter a Dart frame here.
- __ EnterDartFrame(0);
- __ movq(RAX, Address(RSP, + 4 * kWordSize));
- __ cmpq(RAX, Address(RSP, + 5 * kWordSize));
+ const intptr_t kReceiverOffset = 2;
+ const intptr_t kArgumentOffset = 1;
+
+ __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize));
+ __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize));
__ j(EQUAL, &is_true, Assembler::kNearJump);
- __ movq(RAX, Immediate(reinterpret_cast<int64_t>(Bool::False().raw())));
__ LoadObject(RAX, Bool::False(), PP);
- __ LeaveFrameWithPP();
__ ret();
__ Bind(&is_true);
__ LoadObject(RAX, Bool::True(), PP);
- __ LeaveFrameWithPP();
__ ret();
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c3d31e7..85f0f08 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2926,15 +2926,48 @@
void Class::PrintToJSONStream(JSONStream* stream, bool ref) const {
- const char* class_name = String::Handle(UserVisibleName()).ToCString();
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
JSONObject jsobj(stream);
+ if ((raw() == Class::null()) || (id() == kFreeListElement)) {
+ jsobj.AddProperty("type", "Null");
+ return;
+ }
+ const char* internal_class_name = String::Handle(Name()).ToCString();
+ const char* user_visible_class_name =
+ String::Handle(UserVisibleName()).ToCString();
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
- jsobj.AddProperty("name", class_name);
+ jsobj.AddProperty("id", id());
+ jsobj.AddProperty("name", internal_class_name);
+ jsobj.AddProperty("user_name", user_visible_class_name);
if (!ref) {
+ jsobj.AddProperty("implemented", is_implemented());
+ jsobj.AddProperty("abstract", is_abstract());
+ jsobj.AddProperty("patch", is_patch());
+ jsobj.AddProperty("finalized", is_finalized());
+ jsobj.AddProperty("const", is_const());
+ jsobj.AddProperty("super", Class::Handle(SuperClass()));
jsobj.AddProperty("library", Object::Handle(library()));
+ {
+ JSONArray fields_array(&jsobj, "fields");
+ const Array& field_array = Array::Handle(fields());
+ Field& field = Field::Handle();
+ if (!field_array.IsNull()) {
+ for (intptr_t i = 0; i < field_array.Length(); ++i) {
+ field ^= field_array.At(i);
+ fields_array.AddValue(field);
+ }
+ }
+ }
+ {
+ JSONArray functions_array(&jsobj, "functions");
+ const Array& function_array = Array::Handle(functions());
+ Function& function = Function::Handle();
+ if (!function_array.IsNull()) {
+ for (intptr_t i = 0; i < function_array.Length(); i++) {
+ function ^= function_array.At(i);
+ functions_array.AddValue(function);
+ }
+ }
+ }
}
}
@@ -5090,6 +5123,7 @@
void Function::PrintToJSONStream(JSONStream* stream, bool ref) const {
+ const char* internal_function_name = String::Handle(name()).ToCString();
const char* function_name =
String::Handle(QualifiedUserVisibleName()).ToCString();
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
@@ -5097,7 +5131,8 @@
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
- jsobj.AddProperty("name", function_name);
+ jsobj.AddProperty("name", internal_function_name);
+ jsobj.AddProperty("user_name", function_name);
if (ref) return;
jsobj.AddProperty("is_static", is_static());
jsobj.AddProperty("is_const", is_const());
@@ -5412,6 +5447,44 @@
void Field::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ const char* internal_field_name = String::Handle(name()).ToCString();
+ const char* field_name = String::Handle(UserVisibleName()).ToCString();
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddProperty("id", id);
+ jsobj.AddProperty("name", internal_field_name);
+ jsobj.AddProperty("user_name", field_name);
+ if (ref) {
+ return;
+ }
+ Class& cls = Class::Handle(owner());
+ jsobj.AddProperty("type", "Field");
+ jsobj.AddProperty("id", id);
+ jsobj.AddProperty("name", internal_field_name);
+ jsobj.AddProperty("user_name", field_name);
+ jsobj.AddProperty("class", cls);
+ jsobj.AddProperty("static", is_static());
+ jsobj.AddProperty("final", is_final());
+ jsobj.AddProperty("const", is_const());
+ jsobj.AddProperty("guard_nullable", is_nullable());
+ if (guarded_cid() == kIllegalCid) {
+ jsobj.AddProperty("guard_class", "unknown");
+ } else if (guarded_cid() == kDynamicCid) {
+ jsobj.AddProperty("guard_class", "dynamic");
+ } else {
+ ClassTable* table = Isolate::Current()->class_table();
+ ASSERT(table->IsValidIndex(guarded_cid()));
+ cls ^= table->At(guarded_cid());
+ jsobj.AddProperty("guard_class", cls);
+ }
+ if (guarded_list_length() == kUnknownFixedLength) {
+ jsobj.AddProperty("guard_length", "unknown");
+ } else if (guarded_list_length() == kNoFixedLength) {
+ jsobj.AddProperty("guard_length", "variable");
+ } else {
+ jsobj.AddProperty("guard_length", guarded_list_length());
+ }
}
@@ -6052,7 +6125,9 @@
}
-TokenStream::Iterator::Iterator(const TokenStream& tokens, intptr_t token_pos)
+TokenStream::Iterator::Iterator(const TokenStream& tokens,
+ intptr_t token_pos,
+ Iterator::StreamType stream_type)
: tokens_(TokenStream::Handle(tokens.raw())),
data_(ExternalTypedData::Handle(tokens.GetStream())),
stream_(reinterpret_cast<uint8_t*>(data_.DataAddr(0)), data_.Length()),
@@ -6060,7 +6135,8 @@
obj_(Object::Handle()),
cur_token_pos_(token_pos),
cur_token_kind_(Token::kILLEGAL),
- cur_token_obj_index_(-1) {
+ cur_token_obj_index_(-1),
+ stream_type_(stream_type) {
SetCurrentPosition(token_pos);
}
@@ -6092,7 +6168,10 @@
intptr_t count = 0;
while (count < num_tokens && value != Token::kEOS) {
value = ReadToken();
- count += 1;
+ if ((stream_type_ == kAllTokens) ||
+ (static_cast<Token::Kind>(value) != Token::kNEWLINE)) {
+ count += 1;
+ }
}
if (value < Token::kNumTokens) {
kind = static_cast<Token::Kind>(value);
@@ -6124,8 +6203,12 @@
void TokenStream::Iterator::Advance() {
- cur_token_pos_ = stream_.Position();
- intptr_t value = ReadToken();
+ intptr_t value;
+ do {
+ cur_token_pos_ = stream_.Position();
+ value = ReadToken();
+ } while ((stream_type_ == kNoNewlines) &&
+ (static_cast<Token::Kind>(value) == Token::kNEWLINE));
if (value < Token::kNumTokens) {
cur_token_kind_ = static_cast<Token::Kind>(value);
cur_token_obj_index_ = -1;
@@ -7839,6 +7922,7 @@
all_libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
all_libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
RECOGNIZED_LIST(CHECK_FINGERPRINTS);
+ INLINE_WHITE_LIST(CHECK_FINGERPRINTS);
all_libs.Clear();
all_libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
@@ -8567,6 +8651,20 @@
}
+// Returns a bool so it can be asserted.
+bool DeoptInfo::VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
+ const Array& deopt_table) const {
+ intptr_t length = TranslationLength();
+ GrowableArray<DeoptInstr*> unpacked(length);
+ ToInstructions(deopt_table, &unpacked);
+ ASSERT(unpacked.length() == original.length());
+ for (intptr_t i = 0; i < unpacked.length(); ++i) {
+ ASSERT(unpacked[i]->Equals(*original[i]));
+ }
+ return true;
+}
+
+
void DeoptInfo::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
}
@@ -9573,6 +9671,7 @@
Array::Handle(arguments_descriptor()),
deopt_id(),
kNumArgsTested));
+ result.set_deopt_reason(deopt_reason());
const intptr_t len = NumberOfChecks();
for (intptr_t i = 0; i < len; i++) {
const intptr_t class_id = GetClassIdAt(i, arg_nr);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 56ce807..d5c8cad 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2175,7 +2175,14 @@
// in a TokenStream object.
class Iterator : ValueObject {
public:
- Iterator(const TokenStream& tokens, intptr_t token_pos);
+ enum StreamType {
+ kNoNewlines,
+ kAllTokens
+ };
+
+ Iterator(const TokenStream& tokens,
+ intptr_t token_pos,
+ Iterator::StreamType stream_type = kNoNewlines);
void SetStream(const TokenStream& tokens, intptr_t token_pos);
bool IsValid() const;
@@ -2212,6 +2219,7 @@
intptr_t cur_token_pos_;
Token::Kind cur_token_kind_;
intptr_t cur_token_obj_index_;
+ Iterator::StreamType stream_type_;
};
private:
@@ -2940,6 +2948,12 @@
void ToInstructions(const Array& table,
GrowableArray<DeoptInstr*>* instructions) const;
+
+ // Returns true iff decompression yields the same instructions as the
+ // original.
+ bool VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
+ const Array& deopt_table) const;
+
private:
intptr_t* EntryAddr(intptr_t index, intptr_t entry_offset) const {
ASSERT((index >=0) && (index < Length()));
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 82a5d8d..dcb3bbe 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2080,8 +2080,8 @@
EXPECT_EQ(0, first_idx); // Token 'main' is first token.
EXPECT_EQ(3, last_idx); // Token { is last token.
script.TokenRangeAtLine(5, &first_idx, &last_idx);
- EXPECT_EQ(7, first_idx); // Token } is first and only token.
- EXPECT_EQ(7, last_idx);
+ EXPECT_EQ(9, first_idx); // Token } is first and only token.
+ EXPECT_EQ(9, last_idx);
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 81407aa..aeb31c6 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1351,12 +1351,16 @@
void Parser::SkipBlock() {
ASSERT(CurrentToken() == Token::kLBRACE);
GrowableArray<Token::Kind> token_stack(8);
+ // Adding the first kLBRACE here, because it will be consumed in the loop
+ // right away.
+ token_stack.Add(CurrentToken());
const intptr_t block_start_pos = TokenPos();
bool is_match = true;
bool unexpected_token_found = false;
Token::Kind token;
intptr_t token_pos;
do {
+ ConsumeToken();
token = CurrentToken();
token_pos = TokenPos();
switch (token) {
@@ -1381,7 +1385,6 @@
// nothing.
break;
}
- ConsumeToken();
} while (!token_stack.is_empty() && is_match && !unexpected_token_found);
if (!is_match) {
ErrorMsg(token_pos, "unbalanced '%s'", Token::Str(token));
@@ -1420,9 +1423,6 @@
this_seen = true;
parameter.is_field_initializer = true;
}
- if (params->implicitly_final) {
- parameter.is_final = true;
- }
if ((parameter.type == NULL) && (CurrentToken() == Token::kVOID)) {
ConsumeToken();
// This must later be changed to a closure type if we recognize
@@ -1582,6 +1582,9 @@
if (parameter.type->IsVoidType()) {
ErrorMsg("parameter '%s' may not be 'void'", parameter.name->ToCString());
}
+ if (params->implicitly_final) {
+ parameter.is_final = true;
+ }
params->parameters->Add(parameter);
}
@@ -1897,7 +1900,7 @@
negate_result = true;
}
- ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kBIT_OR));
+ ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kEQ));
AstNode* other_operand = ParseBinaryExpr(Token::Precedence(op) + 1);
ArgumentListNode* op_arguments = new ArgumentListNode(operator_pos);
@@ -2349,18 +2352,6 @@
TRACE_PARSER("ParseInitializers");
bool super_init_seen = false;
if (CurrentToken() == Token::kCOLON) {
- if ((LookaheadToken(1) == Token::kTHIS) &&
- ((LookaheadToken(2) == Token::kLPAREN) ||
- ((LookaheadToken(2) == Token::kPERIOD) &&
- (LookaheadToken(4) == Token::kLPAREN)))) {
- // Either we see this(...) or this.xxx(...) which is a
- // redirected constructor. We don't need to check whether
- // const fields are initialized. The other constructor will
- // guarantee that.
- ConsumeToken(); // Colon.
- ParseConstructorRedirection(cls, receiver);
- return;
- }
do {
ConsumeToken(); // Colon or comma.
AstNode* init_statement;
@@ -2388,6 +2379,7 @@
void Parser::ParseConstructorRedirection(const Class& cls,
LocalVariable* receiver) {
TRACE_PARSER("ParseConstructorRedirection");
+ ExpectToken(Token::kCOLON);
ASSERT(CurrentToken() == Token::kTHIS);
const intptr_t call_pos = TokenPos();
ConsumeToken();
@@ -2568,24 +2560,36 @@
// Now populate function scope with the formal parameters.
AddFormalParamsToScope(¶ms, current_block_->scope);
- // Initialize instance fields that have an explicit initializer expression.
- // The formal parameter names must not be visible to the instance
- // field initializer expressions, yet the parameters must be added to
- // the scope so the expressions use the correct offsets for 'this' when
- // storing values. We make the formal parameters temporarily invisible
- // while parsing the instance field initializer expressions.
- params.SetInvisible(true);
- GrowableArray<Field*> initialized_fields;
- LocalVariable* receiver = current_block_->scope->VariableAt(0);
- OpenBlock();
- ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
- // Make the parameters (which are in the outer scope) visible again.
- params.SetInvisible(false);
+ const bool is_redirecting_constructor =
+ (CurrentToken() == Token::kCOLON) &&
+ ((LookaheadToken(1) == Token::kTHIS) &&
+ ((LookaheadToken(2) == Token::kLPAREN) ||
+ ((LookaheadToken(2) == Token::kPERIOD) &&
+ (LookaheadToken(4) == Token::kLPAREN))));
- // Turn formal field parameters into field initializers or report error
- // if the function is not a constructor.
+ GrowableArray<Field*> initialized_fields;
+ LocalVariable* receiver = (*params.parameters)[0].var;
+ OpenBlock();
+
+ // If this is not a redirecting constructor, initialize
+ // instance fields that have an explicit initializer expression.
+ if (!is_redirecting_constructor) {
+ // The formal parameter names must not be visible to the instance
+ // field initializer expressions, yet the parameters must be added to
+ // the scope so the expressions use the correct offsets for 'this' when
+ // storing values. We make the formal parameters temporarily invisible
+ // while parsing the instance field initializer expressions.
+ params.SetInvisible(true);
+ ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
+ // Make the parameters (which are in the outer scope) visible again.
+ params.SetInvisible(false);
+ }
+
+ // Turn formal field parameters into field initializers.
if (params.has_field_initializer) {
- for (int i = 0; i < params.parameters->length(); i++) {
+ // First two parameters are implicit receiver and phase.
+ ASSERT(params.parameters->length() >= 2);
+ for (int i = 2; i < params.parameters->length(); i++) {
ParamDesc& param = (*params.parameters)[i];
if (param.is_field_initializer) {
const String& field_name = *param.name;
@@ -2595,6 +2599,11 @@
"unresolved reference to instance field '%s'",
field_name.ToCString());
}
+ if (is_redirecting_constructor) {
+ ErrorMsg(param.name_pos,
+ "redirecting constructors may not have "
+ "initializing formal parameters");
+ }
CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
AstNode* instance = new LoadLocalNode(param.name_pos, receiver);
// Initializing formals cannot be used in the explicit initializer
@@ -2612,8 +2621,11 @@
}
}
- // Now parse the explicit initializer list or constructor redirection.
- ParseInitializers(cls, receiver, &initialized_fields);
+ if (is_redirecting_constructor) {
+ ParseConstructorRedirection(cls, receiver);
+ } else {
+ ParseInitializers(cls, receiver, &initialized_fields);
+ }
SequenceNode* init_statements = CloseBlock();
if (init_statements->length() > 0) {
@@ -2660,6 +2672,11 @@
// saves the evaluated actual arguments in temporary variables.
// The temporary variables are necessary so that the argument
// expressions are not evaluated twice.
+ // Note: we should never get here in the case of a redirecting
+ // constructor. In that case, the call to the target constructor
+ // is the "super call" and is implicitly at the end of the
+ // initializer list.
+ ASSERT(!is_redirecting_constructor);
ArgumentListNode* ctor_args = super_call->arguments();
// The super initializer call has at least 2 arguments: the
// implicit receiver, and the hidden construction phase.
@@ -2719,6 +2736,9 @@
}
if (CurrentToken() == Token::kLBRACE) {
+ // We checked in the top-level parse phase that a redirecting
+ // constructor does not have a body.
+ ASSERT(!is_redirecting_constructor);
ConsumeToken();
ParseStatementSequence();
ExpectToken(Token::kRBRACE);
@@ -2888,6 +2908,7 @@
} else {
UnexpectedToken();
}
+
ASSERT(func.end_token_pos() == func.token_pos() ||
func.end_token_pos() == end_token_pos);
func.set_end_token_pos(end_token_pos);
@@ -3171,12 +3192,14 @@
}
if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
+ method_end_pos = TokenPos();
+ ExpectToken(Token::kRBRACE);
} else {
ConsumeToken();
SkipExpr();
+ method_end_pos = TokenPos();
ExpectSemicolon();
}
- method_end_pos = TokenPos() - 1;
} else if (IsLiteral("native")) {
if (method->has_abstract) {
ErrorMsg(method->name_pos,
@@ -3806,6 +3829,7 @@
ErrorMsg("{ expected");
}
SkipBlock();
+ ExpectToken(Token::kRBRACE);
}
@@ -4564,7 +4588,8 @@
ExpectSemicolon();
} else if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
- function_end_pos = TokenPos() - 1;
+ function_end_pos = TokenPos();
+ ExpectToken(Token::kRBRACE);
} else if (CurrentToken() == Token::kARROW) {
ConsumeToken();
SkipExpr();
@@ -4692,7 +4717,8 @@
ExpectSemicolon();
} else if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
- accessor_end_pos = TokenPos() - 1;
+ accessor_end_pos = TokenPos();
+ ExpectToken(Token::kRBRACE);
} else if (CurrentToken() == Token::kARROW) {
ConsumeToken();
SkipExpr();
@@ -7345,7 +7371,7 @@
AstNode* Parser::ParseBinaryExpr(int min_preced) {
TRACE_PARSER("ParseBinaryExpr");
- ASSERT(min_preced >= 4);
+ ASSERT(min_preced >= Token::Precedence(Token::kOR));
AstNode* left_operand = ParseUnaryExpr();
if (left_operand->IsPrimaryNode() &&
(left_operand->AsPrimaryNode()->IsSuper())) {
@@ -9561,6 +9587,50 @@
}
+AstNode* Parser::ParseSymbolLiteral() {
+ ASSERT(CurrentToken() == Token::kHASH);
+ ConsumeToken();
+ intptr_t symbol_pos = TokenPos();
+ String& symbol = String::Handle();
+ if (IsIdentifier()) {
+ symbol = CurrentLiteral()->raw();
+ ConsumeToken();
+ while (CurrentToken() == Token::kPERIOD) {
+ symbol = String::Concat(symbol, Symbols::Dot());
+ ConsumeToken();
+ symbol = String::Concat(symbol,
+ *ExpectIdentifier("identifier expected"));
+ }
+ } else if (Token::CanBeOverloaded(CurrentToken())) {
+ symbol = String::New(Token::Str(CurrentToken()));
+ ConsumeToken();
+ } else {
+ ErrorMsg("illegal symbol literal");
+ }
+ // Lookup class Symbol from collection_dev library and call the
+ // constructor to create a symbol instance.
+ const Library& lib = Library::Handle(Library::CollectionDevLibrary());
+ const Class& symbol_class = Class::Handle(lib.LookupClass(Symbols::Symbol()));
+ ASSERT(!symbol_class.IsNull());
+ ArgumentListNode* constr_args = new ArgumentListNode(symbol_pos);
+ constr_args->Add(new LiteralNode(
+ symbol_pos, String::ZoneHandle(Symbols::New(symbol))));
+ const Function& constr = Function::ZoneHandle(
+ symbol_class.LookupConstructor(Symbols::SymbolCtor()));
+ ASSERT(!constr.IsNull());
+ const Object& result = Object::Handle(
+ EvaluateConstConstructorCall(symbol_class,
+ TypeArguments::Handle(),
+ constr,
+ constr_args));
+ if (result.IsUnhandledException()) {
+ return GenerateRethrow(symbol_pos, result);
+ }
+ const Instance& instance = Instance::Cast(result);
+ return new LiteralNode(symbol_pos, Instance::ZoneHandle(instance.raw()));
+}
+
+
static const String& BuildConstructorName(const String& type_class_name,
const String* named_constructor) {
// By convention, the static function implementing a named constructor 'C'
@@ -10051,6 +10121,8 @@
CurrentToken() == Token::kINDEX ||
CurrentToken() == Token::kLBRACE) {
primary = ParseCompoundLiteral();
+ } else if (CurrentToken() == Token::kHASH) {
+ primary = ParseSymbolLiteral();
} else if (CurrentToken() == Token::kSUPER) {
if (current_function().is_static()) {
ErrorMsg("cannot access superclass from static method");
@@ -10137,6 +10209,7 @@
}
if (CurrentToken() == Token::kLBRACE) {
SkipBlock();
+ ExpectToken(Token::kRBRACE);
} else if (CurrentToken() == Token::kARROW) {
ConsumeToken();
SkipExpr();
@@ -10233,6 +10306,22 @@
}
+void Parser::SkipSymbolLiteral() {
+ ConsumeToken(); // Hash sign.
+ if (IsIdentifier()) {
+ ConsumeToken();
+ while (CurrentToken() == Token::kPERIOD) {
+ ConsumeToken();
+ ExpectIdentifier("identifier expected");
+ }
+ } else if (Token::CanBeOverloaded(CurrentToken())) {
+ ConsumeToken();
+ } else {
+ UnexpectedToken();
+ }
+}
+
+
void Parser::SkipNewOperator() {
ConsumeToken(); // Skip new or const keyword.
if (IsIdentifier()) {
@@ -10310,6 +10399,9 @@
case Token::kINDEX:
SkipCompoundLiteral();
break;
+ case Token::kHASH:
+ SkipSymbolLiteral();
+ break;
default:
if (IsIdentifier()) {
ConsumeToken(); // Handle pseudo-keyword identifiers.
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index b286b69..20fc8ca 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -296,6 +296,7 @@
void SkipSelectors();
void SkipPrimary();
void SkipCompoundLiteral();
+ void SkipSymbolLiteral();
void SkipNewOperator();
void SkipActualParameters();
void SkipMapLiteral();
@@ -555,6 +556,7 @@
AstNode* ParseStringLiteral();
String* ParseImportStringLiteral();
AstNode* ParseCompoundLiteral();
+ AstNode* ParseSymbolLiteral();
AstNode* ParseListLiteral(intptr_t type_pos,
bool is_const,
const AbstractTypeArguments& type_arguments);
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index ec87bd7..ecbe709 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -42,10 +42,18 @@
void Scanner::Reset() {
+ // Non-chaning newline properties.
+ newline_token_.kind = Token::kNEWLINE;
+ newline_token_.literal = NULL;
+ newline_token_.length = 1;
+ // We don't preserve the column information.
+ newline_token_.position.column = 0;
+
lookahead_pos_ = -1;
token_start_ = 0;
c0_ = '\0';
newline_seen_ = false;
+ prev_token_line_ = 1;
while (saved_context_ != NULL) {
ScanContext* ctx = saved_context_;
saved_context_ = ctx->next;
@@ -400,17 +408,11 @@
void Scanner::ScanScriptTag() {
ReadChar();
- if (c0_ == '!') {
- Recognize(Token::kSCRIPTTAG);
- // The script tag extends to the end of the line. Just treat this
- // similar to a line comment.
- SkipLine();
- return;
- } else {
- ErrorMsg("unexpected character: '#'");
- SkipLine();
- return;
- }
+ ASSERT(c0_ == '!');
+ Recognize(Token::kSCRIPTTAG);
+ // The script tag extends to the end of the line. Just treat this
+ // similar to a line comment.
+ SkipLine();
}
@@ -837,7 +839,11 @@
break;
case '#':
- ScanScriptTag();
+ if (LookaheadChar(1) == '!') {
+ ScanScriptTag();
+ } else {
+ Recognize(Token::kHASH);
+ }
break;
default:
@@ -865,7 +871,16 @@
Reset();
do {
Scan();
+
+ for (intptr_t diff = current_token_.position.line - prev_token_line_;
+ diff > 0;
+ diff--) {
+ newline_token_.position.line = current_token_.position.line - diff;
+ token_stream->Add(newline_token_);
+ }
+
token_stream->Add(current_token_);
+ prev_token_line_ = current_token_.position.line;
} while (current_token_.kind != Token::kEOS);
}
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 316ac98..5d59dee 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -203,6 +203,7 @@
static void PrintTokens(const GrowableTokenStream& ts);
TokenDescriptor current_token_; // Current token.
+ TokenDescriptor newline_token_; // Newline token.
const String& source_; // The source text being tokenized.
intptr_t source_length_; // The length of the source text.
intptr_t lookahead_pos_; // Position of lookahead character
@@ -210,6 +211,7 @@
intptr_t token_start_; // Begin of current token in src_.
int32_t c0_; // Lookahead character.
bool newline_seen_; // Newline before current token.
+ intptr_t prev_token_line_; // Line number of the previous token.
// The following fields keep track whether we are scanning a string literal
// and its interpolated expressions.
diff --git a/runtime/vm/scanner_test.cc b/runtime/vm/scanner_test.cc
index d4a653a..bf56873 100644
--- a/runtime/vm/scanner_test.cc
+++ b/runtime/vm/scanner_test.cc
@@ -122,13 +122,14 @@
Scan("Foo( /*block \n"
"comment*/ 0xff) // line comment;");
- CheckNumTokens(tokens, 5);
+ CheckNumTokens(tokens, 6);
CheckIdent(tokens, 0, "Foo");
CheckLineNumber(tokens, 0, 1);
CheckKind(tokens, 1, Token::kLPAREN);
- CheckInteger(tokens, 2, "0xff");
- CheckKind(tokens, 3, Token::kRPAREN);
- CheckLineNumber(tokens, 3, 2);
+ CheckKind(tokens, 2, Token::kNEWLINE);
+ CheckInteger(tokens, 3, "0xff");
+ CheckKind(tokens, 4, Token::kRPAREN);
+ CheckLineNumber(tokens, 4, 2);
}
@@ -270,14 +271,16 @@
// |2''';
const Scanner::GrowableTokenStream& tokens = Scan("mls = '''\n1' x\n2''';");
- EXPECT_EQ(5, tokens.length());
+ EXPECT_EQ(7, tokens.length());
CheckIdent(tokens, 0, "mls");
CheckKind(tokens, 1, Token::kASSIGN);
CheckKind(tokens, 2, Token::kSTRING);
- CheckKind(tokens, 3, Token::kSEMICOLON);
- CheckKind(tokens, 4, Token::kEOS);
+ CheckKind(tokens, 3, Token::kNEWLINE);
+ CheckKind(tokens, 4, Token::kNEWLINE);
+ CheckKind(tokens, 5, Token::kSEMICOLON);
+ CheckKind(tokens, 6, Token::kEOS);
CheckLineNumber(tokens, 0, 1);
- CheckLineNumber(tokens, 4, 3); // Semicolon is on line 3.
+ CheckLineNumber(tokens, 5, 3); // Semicolon is on line 3.
const char* litchars = (tokens)[2].literal->ToCString();
EXPECT_EQ(6, (tokens)[2].literal->Length());
@@ -429,6 +432,39 @@
}
+void NewlinesTest() {
+ const char* source =
+ "var es = /* a\n"
+ " b\n"
+ " */ \"\"\"\n"
+ "c\n"
+ "d\n"
+ "\"\"\";";
+
+ const Scanner::GrowableTokenStream& tokens = Scan(source);
+
+ EXPECT_EQ(11, tokens.length());
+ CheckKind(tokens, 0, Token::kVAR);
+ CheckIdent(tokens, 1, "es");
+ CheckKind(tokens, 2, Token::kASSIGN);
+ CheckKind(tokens, 3, Token::kNEWLINE);
+ CheckKind(tokens, 4, Token::kNEWLINE);
+ CheckKind(tokens, 5, Token::kSTRING);
+ CheckKind(tokens, 6, Token::kNEWLINE);
+ CheckKind(tokens, 7, Token::kNEWLINE);
+ CheckKind(tokens, 8, Token::kNEWLINE);
+ CheckKind(tokens, 9, Token::kSEMICOLON);
+ CheckKind(tokens, 10, Token::kEOS);
+
+ EXPECT_EQ(4, (tokens)[5].literal->Length());
+ const char* litchars = (tokens)[5].literal->ToCString();
+ EXPECT_EQ('c', litchars[0]); // First newline is dropped.
+ EXPECT_EQ('\n', litchars[1]);
+ EXPECT_EQ('d', litchars[2]);
+ EXPECT_EQ('\n', litchars[3]);
+}
+
+
TEST_CASE(Scanner_Test) {
ScanLargeText();
@@ -444,6 +480,7 @@
NumberLiteral();
InvalidText();
FindLineTest();
+ NewlinesTest();
}
} // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index d7cea49..2b3e633 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -149,6 +149,14 @@
}
+static void PrintGenericError(JSONStream* js) {
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "error");
+ jsobj.AddProperty("text", "Invalid request.");
+ PrintArgumentsAndOptions(jsobj, js);
+}
+
+
static void HandleName(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "IsolateName");
@@ -197,6 +205,7 @@
PrintArgumentsAndOptions(jsobj, js);
}
+
// Print an error message if there is no ID argument.
#define REQUIRE_COLLECTION_ID(collection) \
if (js->num_arguments() == 1) { \
@@ -204,46 +213,44 @@
return; \
}
-// Print a Dart object to the stream if found in ring. Otherwise print null.
-#define PRINT_RING_OBJ(type) \
- ASSERT(js->num_arguments() >= 2); \
- ObjectIdRing* ring = isolate->object_id_ring(); \
- ASSERT(ring != NULL); \
- intptr_t id = atoi(js->GetArgument(1)); \
- Object& obj = Object::Handle(ring->GetObjectForId(id)); \
- if (!obj.Is##type()) { \
- /* Object is not type, replace with null. */ \
- obj = Object::null(); \
- } \
- obj.PrintToJSONStream(js, false)
-
-static void HandleLibraries(Isolate* isolate, JSONStream* js) {
+static void HandleClasses(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
- const Library& lib =
- Library::Handle(isolate->object_store()->root_library());
- lib.PrintToJSONStream(js, true);
+ ClassTable* table = isolate->class_table();
+ table->PrintToJSONStream(js);
+ return;
+ }
+ ASSERT(js->num_arguments() >= 2);
+ intptr_t id = atoi(js->GetArgument(1));
+ ClassTable* table = isolate->class_table();
+ if (!table->IsValidIndex(id)) {
+ Object::null_object().PrintToJSONStream(js, false);
} else {
- PRINT_RING_OBJ(Library);
+ Class& cls = Class::Handle(table->At(id));
+ cls.PrintToJSONStream(js, false);
}
}
-static void HandleFunctions(Isolate* isolate, JSONStream* js) {
- REQUIRE_COLLECTION_ID("functions");
- PRINT_RING_OBJ(Function);
+static void HandleLibrary(Isolate* isolate, JSONStream* js) {
+ if (js->num_arguments() == 1) {
+ const Library& lib =
+ Library::Handle(isolate->object_store()->root_library());
+ lib.PrintToJSONStream(js, false);
+ return;
+ }
+ PrintGenericError(js);
}
-static void HandleClasses(Isolate* isolate, JSONStream* js) {
- REQUIRE_COLLECTION_ID("classes");
- PRINT_RING_OBJ(Class);
-}
-
-
-static void HandleCodes(Isolate* isolate, JSONStream* js) {
- REQUIRE_COLLECTION_ID("codes");
- PRINT_RING_OBJ(Code);
+static void HandleObjects(Isolate* isolate, JSONStream* js) {
+ REQUIRE_COLLECTION_ID("objects");
+ ASSERT(js->num_arguments() >= 2);
+ ObjectIdRing* ring = isolate->object_id_ring();
+ ASSERT(ring != NULL);
+ intptr_t id = atoi(js->GetArgument(1));
+ Object& obj = Object::Handle(ring->GetObjectForId(id));
+ obj.PrintToJSONStream(js, false);
}
@@ -251,10 +258,9 @@
{ "name", HandleName },
{ "stacktrace", HandleStackTrace },
{ "objecthistogram", HandleObjectHistogram},
- { "libraries", HandleLibraries },
- { "functions", HandleFunctions },
+ { "library", HandleLibrary },
{ "classes", HandleClasses },
- { "codes", HandleCodes },
+ { "objects", HandleObjects },
{ "_echo", HandleEcho },
};
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index a9d3777..7d47618 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -765,12 +765,20 @@
// RCX : new context containing the current isolate pointer.
void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
// Save frame pointer coming in.
- __ EnterStubFrame();
+ __ EnterStubFrameWithPP();
+ // At this point, the stack looks like:
+ // | saved RC15/PP | <-- RSP / TOS
+ // | "saved PC area" = 0 |
+ // | saved RBP | <-- RBP
+ // | saved PC (return to DartEntry::InvokeFunction) |
+
+ // The old frame pointer, the return address, the old R15 (for PP).
+ const intptr_t kInitialOffset = 3;
// Save arguments descriptor array and new context.
- const intptr_t kArgumentsDescOffset = -2 * kWordSize;
+ const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize;
__ pushq(RSI);
- const intptr_t kNewContextOffset = -3 * kWordSize;
+ const intptr_t kNewContextOffset = -(kInitialOffset + 1) * kWordSize;
__ pushq(RCX);
// Save C++ ABI callee-saved registers.
@@ -778,7 +786,11 @@
__ pushq(R12);
__ pushq(R13);
__ pushq(R14);
- __ pushq(R15);
+ // R15 is already saved above by EnterStubFrameWithPP.
+
+ // If any additional (or fewer) values are pushed, the offsets in
+ // kExitLinkSlotFromEntryFp and kSavedContextSlotFromEntryFp will need to be
+ // changed.
// The new Context structure contains a pointer to the current Isolate
// structure. Cache the Context pointer in the CTX register so that it is
@@ -866,14 +878,14 @@
__ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), RDX);
// Restore C++ ABI callee-saved registers.
- __ popq(R15);
+ // R15 will be restored below by LeaveFrameWithPP.
__ popq(R14);
__ popq(R13);
__ popq(R12);
__ popq(RBX);
// Restore the frame pointer.
- __ LeaveFrame();
+ __ LeaveFrameWithPP();
__ ret();
}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 4f4a670..987eb45 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -41,6 +41,8 @@
V(AbstractClassInstantiationError, "AbstractClassInstantiationError") \
V(NoSuchMethodError, "NoSuchMethodError") \
V(ThrowNew, "_throwNew") \
+ V(Symbol, "Symbol") \
+ V(SymbolCtor, "Symbol.") \
V(List, "List") \
V(ListLiteralFactory, "List._fromLiteral") \
V(ListFactory, "List.") \
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index a52c97a..00c90bf 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -14,11 +14,11 @@
// 13 multiplicative * / ~/ %
// 12 additive + -
// 11 shift << >>
-// 10 relational >= > <= < is as
-// 9 equality == != === !==
-// 8 bitwise and &
-// 7 bitwise xor ^
-// 6 bitwise or |
+// 10 bitwise and &
+// 9 bitwise xor ^
+// 8 bitwise or |
+// 7 relational >= > <= < is as
+// 6 equality == != === !==
// 5 logical and &&
// 4 logical or ||
// 3 conditional ?
@@ -67,9 +67,9 @@
TOK(kCOMMA, ",", 1, kNoAttribute) \
TOK(kOR, "||", 4, kNoAttribute) \
TOK(kAND, "&&", 5, kNoAttribute) \
- TOK(kBIT_OR, "|", 6, kNoAttribute) \
- TOK(kBIT_XOR, "^", 7, kNoAttribute) \
- TOK(kBIT_AND, "&", 8, kNoAttribute) \
+ TOK(kBIT_OR, "|", 8, kNoAttribute) \
+ TOK(kBIT_XOR, "^", 9, kNoAttribute) \
+ TOK(kBIT_AND, "&", 10, kNoAttribute) \
TOK(kBIT_NOT, "~", 0, kNoAttribute) \
\
/* Shift operators. */ \
@@ -92,18 +92,18 @@
/* Equality operators. */ \
/* Please update IsEqualityOperator() if you make */ \
/* any changes to this block. */ \
- TOK(kEQ, "==", 9, kNoAttribute) \
- TOK(kNE, "!=", 9, kNoAttribute) \
- TOK(kEQ_STRICT, "===", 9, kNoAttribute) \
- TOK(kNE_STRICT, "!==", 9, kNoAttribute) \
+ TOK(kEQ, "==", 6, kNoAttribute) \
+ TOK(kNE, "!=", 6, kNoAttribute) \
+ TOK(kEQ_STRICT, "===", 6, kNoAttribute) \
+ TOK(kNE_STRICT, "!==", 6, kNoAttribute) \
\
/* Relational operators. */ \
/* Please update IsRelationalOperator() if you make */ \
/* any changes to this block. */ \
- TOK(kLT, "<", 10, kNoAttribute) \
- TOK(kGT, ">", 10, kNoAttribute) \
- TOK(kLTE, "<=", 10, kNoAttribute) \
- TOK(kGTE, ">=", 10, kNoAttribute) \
+ TOK(kLT, "<", 7, kNoAttribute) \
+ TOK(kGT, ">", 7, kNoAttribute) \
+ TOK(kLTE, "<=", 7, kNoAttribute) \
+ TOK(kGTE, ">=", 7, kNoAttribute) \
\
/* Internal token for !(expr is Type) negative type test operator */ \
TOK(kISNOT, "", 10, kNoAttribute) \
@@ -122,7 +122,9 @@
TOK(kINTERPOL_END, "}", 0, kNoAttribute) \
\
TOK(kAT, "@", 0, kNoAttribute) \
+ TOK(kHASH, "#", 0, kNoAttribute) \
\
+ TOK(kNEWLINE, "\n", 0, kNoAttribute) \
TOK(kWHITESP, "", 0, kNoAttribute) \
TOK(kERROR, "", 0, kNoAttribute) \
TOK(kILLEGAL, "", 0, kNoAttribute) \
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 04a316e..084df7e 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -33,7 +33,7 @@
# Stdout is a terminal.
if test 8 -le `tput colors`; then
# Stdout has at least 8 colors, so enable colors.
- EXTRA_OPTIONS[${#EXTRA_OPTIONS[@]}]='--enable-diagnostic-colors'
+ EXTRA_OPTIONS+=('--enable-diagnostic-colors')
fi
fi
@@ -41,7 +41,7 @@
declare -a EXTRA_VM_OPTIONS
if test -f "$SNAPSHOT"; then
- EXTRA_OPTIONS[${#EXTRA_OPTIONS[@]}]="--library-root=$SDK_DIR"
+ EXTRA_OPTIONS+=("--library-root=$SDK_DIR")
fi
# Tell the VM to grow the heap more aggressively. This should only
@@ -52,10 +52,16 @@
case $0 in
*_developer)
- EXTRA_VM_OPTIONS[${#EXTRA_VM_OPTIONS[@]}]='--checked'
+ EXTRA_VM_OPTIONS+=('--checked')
;;
esac
+# We allow extra vm options to be passed in through an environment variable.
+if [[ $DART_VM_OPTIONS ]]; then
+ read -a OPTIONS <<< "$DART_VM_OPTIONS"
+ EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
+fi
+
if test -f "$SNAPSHOT"; then
exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "${EXTRA_OPTIONS[@]}" "$@"
else
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index ae7612c..e324121 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -35,6 +35,11 @@
rem See comments regarding options below in dart2js shell script.
set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --heap_growth_rate=512
+rem We allow extra vm options to be passed in through an environment variable.
+if not _%DART_VM_OPTIONS%_ == __ (
+ set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
+)
+
if exist "%SNAPSHOT%" (
"%DART%" %EXTRA_VM_OPTIONS% "%SNAPSHOT%" %EXTRA_OPTIONS% %*
) else (
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index 5832103..6986414 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -164,7 +164,7 @@
// TODO(johnniwinther): Add [:report(..., {Element element}):] to
// report methods in Compiler.
- void reportReadError(String exception) {
+ void reportReadError(exception) {
withCurrentElement(element, () {
reportError(node,
leg.MessageKind.READ_SCRIPT_ERROR,
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 432292e..a91f9ab 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -247,10 +247,6 @@
final Set<Element> usedVariablesInTry;
- // A map from the parameter element to the variable element that
- // holds the sentinel check.
- final Map<Element, Element> parametersWithSentinel;
-
ClosureClassMap(this.closureElement,
this.closureClassElement,
this.callElement,
@@ -258,18 +254,25 @@
: this.freeVariableMapping = new Map<Element, Element>(),
this.capturedFieldMapping = new Map<Element, Element>(),
this.capturingScopes = new Map<Node, ClosureScope>(),
- this.usedVariablesInTry = new Set<Element>(),
- this.parametersWithSentinel = new Map<Element, Element>();
+ this.usedVariablesInTry = new Set<Element>();
bool isClosure() => closureElement != null;
bool isVariableCaptured(Element element) {
- return freeVariableMapping.containsKey(element);
+ return freeVariableMapping.containsKey(element)
+ || capturingScopesBox(element);
+ }
+
+ bool capturingScopesBox(Element element) {
+ return capturingScopes.values.any((scope) {
+ return scope.boxedLoopVariables.contains(element);
+ });
}
bool isVariableBoxed(Element element) {
Element copy = freeVariableMapping[element];
- return copy != null && !copy.isMember();
+ if (copy != null && !copy.isMember()) return true;
+ return capturingScopesBox(element);
}
void forEachCapturedVariable(void f(Element local, Element field)) {
@@ -277,6 +280,9 @@
if (variable is BoxElement) return;
f(variable, copy);
});
+ capturingScopes.values.forEach((scope) {
+ scope.capturedVariableMapping.forEach(f);
+ });
}
void forEachBoxedVariable(void f(Element local, Element field)) {
@@ -284,6 +290,9 @@
if (!isVariableBoxed(variable)) return;
f(variable, copy);
});
+ capturingScopes.values.forEach((scope) {
+ scope.capturedVariableMapping.forEach(f);
+ });
}
void forEachNonBoxedCapturedVariable(void f(Element local, Element field)) {
@@ -536,6 +545,9 @@
} else if (node.isTypeCast) {
DartType type = elements.getType(node.arguments.head);
analyzeType(type);
+ } else if (element == compiler.assertMethod
+ && !compiler.enableUserAssertions) {
+ return;
}
node.visitChildren(this);
}
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index f9339f0..5c2e393 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -205,7 +205,7 @@
node, MessageKind.NOT_ASSIGNABLE.error,
{'fromType': constantType, 'toType': elementType});
} else {
- // If the field can be lazily initialized, we will throw
+ // If the field cannot be lazily initialized, we will throw
// the exception at runtime.
value = null;
}
@@ -386,46 +386,53 @@
if (!node.isConst()) {
return signalNotCompileTimeConstant(node);
}
- List<StringConstant> keys = <StringConstant>[];
- Map<StringConstant, Constant> map = new Map<StringConstant, Constant>();
+ List<Constant> keys = <Constant>[];
+ Map<Constant, Constant> map = new Map<Constant, Constant>();
for (Link<Node> link = node.entries.nodes;
!link.isEmpty;
link = link.tail) {
LiteralMapEntry entry = link.head;
Constant key = evaluateConstant(entry.key);
- if (!key.isString() || entry.key.asStringNode() == null) {
- compiler.reportFatalError(
- entry.key, MessageKind.KEY_NOT_A_STRING_LITERAL);
- }
- StringConstant keyConstant = key;
if (!map.containsKey(key)) keys.add(key);
map[key] = evaluateConstant(entry.value);
}
- List<Constant> values = <Constant>[];
+
+ bool onlyStringKeys = true;
Constant protoValue = null;
- for (StringConstant key in keys) {
- if (key.value == MapConstant.PROTO_PROPERTY) {
- protoValue = map[key];
+ for (var key in keys) {
+ if (key.isString()) {
+ if (key.value == MapConstant.PROTO_PROPERTY) {
+ protoValue = map[key];
+ }
} else {
- values.add(map[key]);
+ onlyStringKeys = false;
+ // Don't handle __proto__ values specially in the general map case.
+ protoValue = null;
+ break;
}
}
+
bool hasProtoKey = (protoValue != null);
+ List<Constant> values = map.values.toList();
InterfaceType sourceType = elements.getType(node);
Link<DartType> arguments =
new Link<DartType>.fromList([compiler.stringClass.rawType]);
DartType keysType = new InterfaceType(compiler.listClass, arguments);
ListConstant keysList = new ListConstant(keysType, keys);
- handler.registerCompileTimeConstant(keysList, elements);
- SourceString className = hasProtoKey
- ? MapConstant.DART_PROTO_CLASS
- : MapConstant.DART_CLASS;
+ if (onlyStringKeys) {
+ handler.registerCompileTimeConstant(keysList, elements);
+ }
+ SourceString className = onlyStringKeys
+ ? (hasProtoKey ? MapConstant.DART_PROTO_CLASS
+ : MapConstant.DART_STRING_CLASS)
+ : MapConstant.DART_GENERAL_CLASS;
ClassElement classElement = compiler.jsHelperLibrary.find(className);
classElement.ensureResolved(compiler);
- Link<DartType> typeArgument = sourceType.typeArguments.tail;
+ Link<DartType> typeArgument = sourceType.typeArguments;
InterfaceType type = new InterfaceType(classElement, typeArgument);
handler.registerInstantiatedType(type, elements);
- Constant constant = new MapConstant(type, keysList, values, protoValue);
+ Constant constant =
+ new MapConstant(type, keysList, values, protoValue, onlyStringKeys);
handler.registerCompileTimeConstant(constant, elements);
return constant;
}
@@ -713,6 +720,9 @@
type = constructor.computeTargetType(compiler, type);
}
+ // The redirection chain of this element may not have been resolved through
+ // a post-process action, so we have to make sure it is done here.
+ compiler.resolver.resolveRedirectionChain(constructor, node);
constructor = constructor.redirectionTarget;
ClassElement classElement = constructor.getEnclosingClass();
// The constructor must be an implementation to ensure that field
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index 4ff011c..bca6524 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -374,19 +374,26 @@
/** The dart class implementing constant map literals. */
static const SourceString DART_CLASS = const SourceString("ConstantMap");
+ static const SourceString DART_STRING_CLASS =
+ const SourceString("ConstantStringMap");
static const SourceString DART_PROTO_CLASS =
const SourceString("ConstantProtoMap");
+ static const SourceString DART_GENERAL_CLASS =
+ const SourceString("GeneralConstantMap");
static const SourceString LENGTH_NAME = const SourceString("length");
static const SourceString JS_OBJECT_NAME = const SourceString("_jsObject");
static const SourceString KEYS_NAME = const SourceString("_keys");
static const SourceString PROTO_VALUE = const SourceString("_protoValue");
+ static const SourceString JS_DATA_NAME = const SourceString("_jsData");
final ListConstant keys;
final List<Constant> values;
final Constant protoValue;
final int hashCode;
+ final bool onlyStringKeys;
- MapConstant(DartType type, this.keys, List<Constant> values, this.protoValue)
+ MapConstant(DartType type, this.keys, List<Constant> values, this.protoValue,
+ this.onlyStringKeys)
: this.values = values,
this.hashCode = computeHash(type, values),
super(type);
@@ -415,7 +422,14 @@
}
List<Constant> getDependencies() {
- List<Constant> result = <Constant>[keys];
+ List<Constant> result = <Constant>[];
+ if (onlyStringKeys) {
+ result.add(keys);
+ } else {
+ // Add the keys individually to avoid generating a unused list constant
+ // for the keys.
+ result.addAll(keys.entries);
+ }
result.addAll(values);
return result;
}
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index eb211bb..a4e367f 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -44,9 +44,9 @@
class SendVisitor extends ResolvedVisitor {
final PlaceholderCollector collector;
- get compiler => collector.compiler;
-
- SendVisitor(this.collector, TreeElements elements) : super(elements);
+ SendVisitor(collector, TreeElements elements)
+ : this.collector = collector,
+ super(elements, collector.compiler);
visitOperatorSend(Send node) {
}
@@ -104,6 +104,10 @@
}
}
+ visitAssert(node) {
+ visitStaticSend(node);
+ }
+
visitStaticSend(Send node) {
final element = elements[node];
collector.backend.registerStaticSend(element, node);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index fda82a7..82f5e73 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1189,28 +1189,32 @@
* exception/call.
*/
bool isCompatibleWith(FunctionSignature signature) {
- if (optionalParametersAreNamed != signature.optionalParametersAreNamed) {
- return false;
- }
if (optionalParametersAreNamed) {
+ if (!signature.optionalParametersAreNamed) {
+ return requiredParameterCount == signature.parameterCount;
+ }
+ // If both signatures have named parameters, then they must have
+ // the same number of required parameters, and the names in
+ // [signature] must all be in [:this:].
if (requiredParameterCount != signature.requiredParameterCount) {
return false;
}
+ Set<String> names = optionalParameters.toList().map(
+ (Element element) => element.name.slowToString()).toSet();
for (Element namedParameter in signature.optionalParameters) {
- if (!optionalParameters.contains(namedParameter)) {
+ if (!names.contains(namedParameter.name.slowToString())) {
return false;
}
}
} else {
+ if (signature.optionalParametersAreNamed) return false;
// There must be at least as many arguments as in the other signature, but
// this signature must not have more required parameters. Having more
// optional parameters is not a problem, they simply are never provided
// by call sites of a call to a method with the other signature.
- if (requiredParameterCount > signature.requiredParameterCount ||
- requiredParameterCount < signature.parameterCount ||
- parameterCount < signature.parameterCount) {
- return false;
- }
+ int otherTotalCount = signature.parameterCount;
+ return requiredParameterCount <= otherTotalCount
+ && parameterCount >= otherTotalCount;
}
return true;
}
@@ -1275,22 +1279,20 @@
bool get isRedirectingFactory => defaultImplementation != this;
- FunctionElement get redirectionTarget {
- if (this == defaultImplementation) return this;
- var target = defaultImplementation;
- Set<Element> seen = new Set<Element>();
- seen.add(target);
- while (!target.isErroneous() && target != target.defaultImplementation) {
- target = target.defaultImplementation;
- if (seen.contains(target)) {
- // TODO(ahe): This is expedient for now, but it should be
- // checked by the resolver. Keeping http://dartbug.com/3970
- // open to track this.
- throw new SpannableAssertionFailure(
- target, 'redirecting factory leads to cycle');
- }
+ /// This field is set by the post process queue when checking for cycles.
+ FunctionElement internalRedirectionTarget;
+
+ set redirectionTarget(FunctionElement constructor) {
+ assert(constructor != null && internalRedirectionTarget == null);
+ internalRedirectionTarget = constructor;
+ }
+
+ get redirectionTarget {
+ if (Elements.isErroneousElement(defaultImplementation)) {
+ return defaultImplementation;
}
- return target;
+ assert(!isRedirectingFactory || internalRedirectionTarget != null);
+ return isRedirectingFactory ? internalRedirectionTarget : this;
}
InterfaceType computeTargetType(Compiler compiler,
@@ -1962,6 +1964,9 @@
}
void addToScope(Element element, DiagnosticListener listener) {
+ if (element.isField() && element.name == name) {
+ listener.reportError(element, MessageKind.MEMBER_USES_CLASS_NAME);
+ }
localScope.add(element, listener);
}
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 2324884a4..d1ee2cc 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -423,7 +423,7 @@
if (selector.isGetter()) {
processInstanceFunctions(methodName, (Element member) {
if (selector.appliesUnnamed(member, compiler)) {
- registerBoundClosure();
+ registerClosurizedMember(member, compiler.globalDependencies);
return true;
}
return false;
@@ -517,18 +517,22 @@
}
void registerClosurizedMember(Element element, TreeElements elements) {
- if (element.computeType(compiler).containsTypeVariables) {
- registerClosurizedGenericMember(element, elements);
- } else {
- registerBoundClosure();
- }
+ assert(element.isInstanceMember());
+ registerIfGeneric(element, elements);
+ registerBoundClosure();
universe.closurizedMembers.add(element);
}
- void registerClosurizedGenericMember(Element element, TreeElements elements) {
- registerBoundClosure();
- compiler.backend.registerGenericClosure(element, this, elements);
- universe.closurizedGenericMembers.add(element);
+
+ void registerIfGeneric(Element element, TreeElements elements) {
+ if (element.computeType(compiler).containsTypeVariables) {
+ compiler.backend.registerGenericClosure(element, this, elements);
+ universe.genericClosures.add(element);
+ }
+ }
+
+ void registerClosure(Element element, TreeElements elements) {
+ registerIfGeneric(element, elements);
}
void forEach(f(WorkItem work)) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 703979d..376fdfc 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -1167,14 +1167,17 @@
}
void registerConstantMap(TreeElements elements) {
- Element e = compiler.findHelper(const SourceString('ConstantMap'));
- if (e != null) {
- enqueueClass(compiler.enqueuer.resolution, e, elements);
+ void enqueue(SourceString name) {
+ Element e = compiler.findHelper(name);
+ if (e != null) {
+ enqueueClass(compiler.enqueuer.resolution, e, elements);
+ }
}
- e = compiler.findHelper(const SourceString('ConstantProtoMap'));
- if (e != null) {
- enqueueClass(compiler.enqueuer.resolution, e, elements);
- }
+
+ enqueue(MapConstant.DART_CLASS);
+ enqueue(MapConstant.DART_PROTO_CLASS);
+ enqueue(MapConstant.DART_STRING_CLASS);
+ enqueue(MapConstant.DART_GENERAL_CLASS);
}
void codegen(CodegenWorkItem work) {
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 9ed0647..16ffce5 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -215,7 +215,6 @@
jsAst.Expression visitMap(MapConstant constant) {
jsAst.Expression jsMap() {
List<jsAst.Property> properties = <jsAst.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;
@@ -223,21 +222,27 @@
// Keys in literal maps must be emitted in place.
jsAst.Literal keyExpression = _visit(key);
jsAst.Expression valueExpression =
- _reference(constant.values[valueIndex++]);
+ _reference(constant.values[i]);
properties.add(new jsAst.Property(keyExpression, valueExpression));
}
- if (valueIndex != constant.values.length) {
- compiler.internalError("Bad value count.");
- }
return new jsAst.ObjectInitializer(properties);
}
- void badFieldCountError() {
- compiler.internalError(
- "Compiler and ConstantMap disagree on number of fields.");
+ jsAst.Expression jsGeneralMap() {
+ List<jsAst.Expression> data = <jsAst.Expression>[];
+ for (int i = 0; i < constant.keys.entries.length; i++) {
+ jsAst.Expression keyExpression =
+ _reference(constant.keys.entries[i]);
+ jsAst.Expression valueExpression =
+ _reference(constant.values[i]);
+ data.add(keyExpression);
+ data.add(valueExpression);
+ }
+ return new jsAst.ArrayInitializer.from(data);
}
ClassElement classElement = constant.type.element;
+ SourceString className = classElement.name;
List<jsAst.Expression> arguments = <jsAst.Expression>[];
@@ -256,16 +261,24 @@
} else if (field.name == MapConstant.PROTO_VALUE) {
assert(constant.protoValue != null);
arguments.add(_reference(constant.protoValue));
+ } else if (field.name == MapConstant.JS_DATA_NAME) {
+ arguments.add(jsGeneralMap());
} else {
- badFieldCountError();
+ compiler.internalError(
+ "Compiler has unexpected field ${field.name} for "
+ "${className}.");
}
emittedArgumentCount++;
},
includeSuperAndInjectedMembers: true);
-
- if ((constant.protoValue == null && emittedArgumentCount != 3) ||
- (constant.protoValue != null && emittedArgumentCount != 4)) {
- badFieldCountError();
+ if ((className == MapConstant.DART_STRING_CLASS &&
+ emittedArgumentCount != 3) ||
+ (className == MapConstant.DART_PROTO_CLASS &&
+ emittedArgumentCount != 4) ||
+ (className == MapConstant.DART_GENERAL_CLASS &&
+ emittedArgumentCount != 1)) {
+ compiler.internalError(
+ "Compiler and ${className} disagree on number of fields.");
}
jsAst.Expression value = new jsAst.New(
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index 5f9041f..6a52399 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -183,8 +183,7 @@
methodsNeedingRti.add(method);
}
}
- compiler.resolverWorld.closurizedGenericMembers.forEach(
- analyzeMethod);
+ compiler.resolverWorld.genericClosures.forEach(analyzeMethod);
compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod);
}
}
@@ -198,7 +197,7 @@
methodsNeedingRti.add(method);
}
}
- compiler.resolverWorld.closurizedGenericMembers.forEach(analyzeMethod);
+ compiler.resolverWorld.genericClosures.forEach(analyzeMethod);
compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod);
}
// Add the classes that need RTI because they use a type variable as
diff --git a/sdk/lib/_internal/compiler/implementation/patch_parser.dart b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
index 42d036f..88da806 100644
--- a/sdk/lib/_internal/compiler/implementation/patch_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/patch_parser.dart
@@ -118,7 +118,6 @@
import "tree/tree.dart" as tree;
import "dart2jslib.dart" as leg; // CompilerTask, Compiler.
-import "../compiler.dart" as api;
import "scanner/scannerlib.dart"; // Scanner, Parsers, Listeners
import "elements/elements.dart";
import "elements/modelx.dart" show LibraryElementX, MetadataAnnotationX;
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 130943c..4135d0c 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -454,7 +454,7 @@
if (Elements.isStaticOrTopLevelField(element)) {
if (tree.asSendSet() != null) {
- // TODO(ngeoffray): We could do better here by using the
+ // TODO(13429): We could do better here by using the
// constant handler to figure out if it's a lazy field or not.
compiler.backend.registerLazyField(visitor.mapping);
} else {
@@ -494,6 +494,33 @@
return result;
}
+ void resolveRedirectionChain(FunctionElement constructor, Node node) {
+ FunctionElementX current = constructor;
+ List<Element> seen = new List<Element>();
+ // Follow the chain of redirections and check for cycles.
+ while (current != current.defaultImplementation) {
+ if (current.internalRedirectionTarget != null) {
+ // We found a constructor that already has been processed.
+ current = current.internalRedirectionTarget;
+ break;
+ }
+ Element target = current.defaultImplementation;
+ if (seen.contains(target)) {
+ error(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
+ break;
+ }
+ seen.add(current);
+ current = target;
+ }
+ // [current] is now the actual target of the redirections. Run through
+ // the constructors again and set their [redirectionTarget], so that we
+ // do not have to run the loop for these constructors again.
+ while (!seen.isEmpty) {
+ FunctionElementX factory = seen.removeLast();
+ factory.redirectionTarget = current;
+ }
+ }
+
/**
* Load and resolve the supertypes of [cls].
*
@@ -2097,7 +2124,7 @@
scope = oldScope;
enclosingElement = previousEnclosingElement;
- world.registerClosurizedMember(function, mapping);
+ world.registerClosure(function, mapping);
world.registerInstantiatedClass(compiler.functionClass, mapping);
}
@@ -2653,7 +2680,8 @@
FunctionType targetType = redirectionTarget.computeType(compiler)
.subst(type.typeArguments, targetClass.typeVariables);
FunctionType constructorType = constructor.computeType(compiler);
- if (!compiler.types.isSubtype(targetType, constructorType)) {
+ bool isSubtype = compiler.types.isSubtype(targetType, constructorType);
+ if (!isSubtype) {
warning(node, MessageKind.NOT_ASSIGNABLE.warning,
{'fromType': targetType, 'toType': constructorType});
}
@@ -2663,22 +2691,16 @@
FunctionSignature constructorSignature =
constructor.computeSignature(compiler);
if (!targetSignature.isCompatibleWith(constructorSignature)) {
+ assert(!isSubtype);
compiler.backend.registerThrowNoSuchMethod(mapping);
}
- // TODO(ahe): Check that this doesn't lead to a cycle. For now,
- // just make sure that the redirection target isn't itself a
- // redirecting factory.
- { // This entire block is temporary code per the above TODO.
- FunctionElement targetImplementation = redirectionTarget.implementation;
- FunctionExpression function = targetImplementation.parseNode(compiler);
- if (function != null
- && function.body != null
- && function.body.asReturn() != null
- && function.body.asReturn().isRedirectingFactoryBody) {
- unimplemented(node.expression, 'redirecting to redirecting factory');
- }
- }
+ // Register a post process to check for cycles in the redirection chain and
+ // set the actual generative constructor at the end of the chain.
+ compiler.enqueuer.resolution.addPostProcessAction(constructor, () {
+ compiler.resolver.resolveRedirectionChain(constructor, node);
+ });
+
world.registerStaticUse(redirectionTarget);
world.registerInstantiatedClass(
redirectionTarget.enclosingElement.declaration, mapping);
@@ -2749,7 +2771,8 @@
if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) {
world.registerFactoryWithTypeArguments(mapping);
}
- if (cls.isAbstract(compiler)) {
+ if (constructor.isGenerativeConstructor() && cls.isAbstract(compiler)) {
+ warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
compiler.backend.registerAbstractClassInstantiation(mapping);
}
@@ -3340,7 +3363,101 @@
element.alias = compiler.computeFunctionType(
element, element.functionSignature);
- // TODO(johnniwinther): Check for cyclic references in the typedef alias.
+ void checkCyclicReference() {
+ var visitor = new TypedefCyclicVisitor(compiler, element);
+ type.accept(visitor, null);
+ }
+ compiler.enqueuer.resolution.addPostProcessAction(element,
+ checkCyclicReference);
+ }
+}
+
+// TODO(johnniwinther): Replace with a traversal on the AST when the type
+// annotations in typedef alias are stored in a [TreeElements] mapping.
+class TypedefCyclicVisitor extends DartTypeVisitor {
+ final Compiler compiler;
+ final TypedefElement element;
+ bool hasCyclicReference = false;
+
+ /// Counter for how many bounds the visitor currently has on the call-stack.
+ /// Used to detect when to report [Messagekind.CYCLIC_TYPEDEF_TYPEVAR].
+ int seenBoundsCount = 0;
+
+ Link<TypedefElement> seenTypedefs = const Link<TypedefElement>();
+
+ int seenTypedefsCount = 0;
+
+ Link<TypeVariableElement> seenTypeVariables =
+ const Link<TypeVariableElement>();
+
+ TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element);
+
+ visitType(DartType type, _) {
+ // Do nothing.
+ }
+
+ visitTypedefType(TypedefType type, _) {
+ TypedefElement typedefElement = type.element;
+ if (seenTypedefs.contains(typedefElement)) {
+ if (!hasCyclicReference && identical(element, typedefElement)) {
+ // Only report an error on the checked typedef to avoid generating
+ // multiple errors for the same cyclicity.
+ hasCyclicReference = true;
+ if (seenBoundsCount > 0) {
+ compiler.reportError(element, MessageKind.CYCLIC_TYPEDEF_TYPEVAR);
+ } else if (seenTypedefsCount == 1) {
+ // Direct cyclicity.
+ compiler.reportError(element,
+ MessageKind.CYCLIC_TYPEDEF,
+ {'typedefName': element.name});
+ } else if (seenTypedefsCount == 2) {
+ // Cyclicity through one other typedef.
+ compiler.reportError(element,
+ MessageKind.CYCLIC_TYPEDEF_ONE,
+ {'typedefName': element.name,
+ 'otherTypedefName': seenTypedefs.head.name});
+ } else {
+ // Cyclicity through more than one other typedef.
+ for (TypedefElement cycle in seenTypedefs) {
+ if (!identical(typedefElement, cycle)) {
+ compiler.reportError(element,
+ MessageKind.CYCLIC_TYPEDEF_ONE,
+ {'typedefName': element.name,
+ 'otherTypedefName': cycle.name});
+ }
+ }
+ }
+ }
+ } else {
+ seenTypedefs = seenTypedefs.prepend(typedefElement);
+ seenTypedefsCount++;
+ type.visitChildren(this, null);
+ typedefElement.alias.accept(this, null);
+ seenTypedefs = seenTypedefs.tail;
+ seenTypedefsCount--;
+ }
+ }
+
+ visitFunctionType(FunctionType type, _) {
+ type.visitChildren(this, null);
+ }
+
+ visitInterfaceType(InterfaceType type, _) {
+ type.visitChildren(this, null);
+ }
+
+ visitTypeVariableType(TypeVariableType type, _) {
+ TypeVariableElement typeVariableElement = type.element;
+ if (seenTypeVariables.contains(typeVariableElement)) {
+ // Avoid running in cycles on cyclic type variable bounds.
+ // Cyclicity is reported elsewhere.
+ return;
+ }
+ seenTypeVariables = seenTypeVariables.prepend(typeVariableElement);
+ seenBoundsCount++;
+ typeVariableElement.bound.accept(this, null);
+ seenBoundsCount--;
+ seenTypeVariables = seenTypeVariables.tail;
}
}
@@ -3816,13 +3933,16 @@
resolver.error(identifier, MessageKind.REFERENCE_IN_INITIALIZATION,
{'variableName': name.toString()});
}
- return visit(node.selector);
+ return name;
}
SourceString visitIdentifier(Identifier node) {
// The variable is initialized to null.
resolver.world.registerInstantiatedClass(compiler.nullClass,
resolver.mapping);
+ if (definitions.modifiers.isConst()) {
+ compiler.reportError(node, MessageKind.CONST_WITHOUT_INITIALIZER);
+ }
return node.source;
}
@@ -3879,6 +3999,9 @@
if (definition is NodeList) {
cancel(node, 'optional parameters are not implemented');
}
+ if (node.modifiers.isConst()) {
+ error(node, MessageKind.FORMAL_DECLARED_CONST);
+ }
if (currentDefinitions != null) {
cancel(node, 'function type parameters not supported');
diff --git a/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart b/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
index 9a85b9a..df68e6e 100644
--- a/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolved_visitor.dart
@@ -5,9 +5,10 @@
part of dart2js;
abstract class ResolvedVisitor<R> extends Visitor<R> {
+ final Compiler compiler;
TreeElements elements;
- ResolvedVisitor(this.elements);
+ ResolvedVisitor(this.elements, this.compiler);
R visitSend(Send node) {
Element element = elements[node];
@@ -26,6 +27,9 @@
return visitStaticSend(node);
} else if (Elements.isClosureSend(node, element)) {
return visitClosureSend(node);
+ } else if (element == compiler.assertMethod) {
+ assert(element != null);
+ return visitAssert(node);
} else {
if (Elements.isUnresolved(element)) {
if (element == null) {
@@ -59,6 +63,7 @@
R visitDynamicSend(Send node);
R visitStaticSend(Send node);
R visitTypeReferenceSend(Send node);
+ R visitAssert(Send node);
void internalError(String reason, {Node node});
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 1e8f36a..dc912fb 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -1622,9 +1622,6 @@
void endLiteralMapEntry(Token colon, Token endToken) {
Expression value = popNode();
Expression key = popNode();
- if (key.asStringNode() == null) {
- recoverableError('expected a string', node: key);
- }
pushNode(new LiteralMapEntry(key, colon, value));
}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 63e7da7..05b1acf 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -1581,6 +1581,12 @@
}
info = token.info;
tokenLevel = info.precedence;
+ if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) {
+ // We don't allow (a == b == c) or (a < b < c).
+ // Continue the outer loop if we have matched one equality or
+ // relational operator.
+ break;
+ }
}
}
return token;
@@ -1623,23 +1629,8 @@
String value = token.stringValue;
// Prefix:
if (identical(value, '+')) {
- // Dart only allows "prefix plus" as an initial part of a
- // decimal literal. We scan it as a separate token and let
- // the parser listener combine it with the digits.
- Token next = token.next;
- if (identical(next.charOffset, token.charOffset + 1)) {
- if (identical(next.kind, INT_TOKEN)) {
- listener.handleLiteralInt(token);
- return next.next;
- }
- if (identical(next.kind, DOUBLE_TOKEN)) {
- listener.handleLiteralDouble(token);
- return next.next;
- }
- }
- listener.recoverableError("Unexpected token '+'", token: token);
- return parsePrecedenceExpression(next, POSTFIX_PRECEDENCE,
- allowCascades);
+ // Dart no longer allows prefix-plus.
+ listener.reportError(token, MessageKind.UNSUPPORTED_PREFIX_PLUS);
} else if ((identical(value, '!')) ||
(identical(value, '-')) ||
(identical(value, '~'))) {
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/token.dart b/sdk/lib/_internal/compiler/implementation/scanner/token.dart
index e74c702..bda4b76 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/token.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/token.dart
@@ -422,37 +422,49 @@
const PrecedenceInfo(const SourceString('&&'), 5, AMPERSAND_AMPERSAND_TOKEN);
const PrecedenceInfo BAR_INFO =
- const PrecedenceInfo(const SourceString('|'), 6, BAR_TOKEN);
+ const PrecedenceInfo(const SourceString('|'), 8, BAR_TOKEN);
const PrecedenceInfo CARET_INFO =
- const PrecedenceInfo(const SourceString('^'), 7, CARET_TOKEN);
+ const PrecedenceInfo(const SourceString('^'), 9, CARET_TOKEN);
const PrecedenceInfo AMPERSAND_INFO =
- const PrecedenceInfo(const SourceString('&'), 8, AMPERSAND_TOKEN);
+ const PrecedenceInfo(const SourceString('&'), 10, AMPERSAND_TOKEN);
// Equality operators.
+const int EQUALITY_PRECEDENCE = 6;
const PrecedenceInfo BANG_EQ_EQ_INFO =
- const PrecedenceInfo(const SourceString('!=='), 9, BANG_EQ_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('!=='),
+ EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
const PrecedenceInfo BANG_EQ_INFO =
- const PrecedenceInfo(const SourceString('!='), 9, BANG_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('!='),
+ EQUALITY_PRECEDENCE, BANG_EQ_TOKEN);
const PrecedenceInfo EQ_EQ_EQ_INFO =
- const PrecedenceInfo(const SourceString('==='), 9, EQ_EQ_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('==='),
+ EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
const PrecedenceInfo EQ_EQ_INFO =
- const PrecedenceInfo(const SourceString('=='), 9, EQ_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('=='),
+ EQUALITY_PRECEDENCE, EQ_EQ_TOKEN);
// Relational operators.
+const int RELATIONAL_PRECEDENCE = 7;
const PrecedenceInfo GT_EQ_INFO =
- const PrecedenceInfo(const SourceString('>='), 10, GT_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('>='),
+ RELATIONAL_PRECEDENCE, GT_EQ_TOKEN);
const PrecedenceInfo GT_INFO =
- const PrecedenceInfo(const SourceString('>'), 10, GT_TOKEN);
+ const PrecedenceInfo(const SourceString('>'),
+ RELATIONAL_PRECEDENCE, GT_TOKEN);
const PrecedenceInfo IS_INFO =
- const PrecedenceInfo(const SourceString('is'), 10, KEYWORD_TOKEN);
+ const PrecedenceInfo(const SourceString('is'),
+ RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
const PrecedenceInfo AS_INFO =
- const PrecedenceInfo(const SourceString('as'), 10, KEYWORD_TOKEN);
+ const PrecedenceInfo(const SourceString('as'),
+ RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
const PrecedenceInfo LT_EQ_INFO =
- const PrecedenceInfo(const SourceString('<='), 10, LT_EQ_TOKEN);
+ const PrecedenceInfo(const SourceString('<='),
+ RELATIONAL_PRECEDENCE, LT_EQ_TOKEN);
const PrecedenceInfo LT_INFO =
- const PrecedenceInfo(const SourceString('<'), 10, LT_TOKEN);
+ const PrecedenceInfo(const SourceString('<'),
+ RELATIONAL_PRECEDENCE, LT_TOKEN);
// Shift operators.
const PrecedenceInfo GT_GT_INFO =
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 4e50630..9f0826b 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -935,7 +935,7 @@
sourceElementStack = <Element>[work.element],
inliningStack = <InliningState>[],
rti = builder.backend.rti,
- super(work.resolutionTree) {
+ super(work.resolutionTree, builder.compiler) {
localsHandler = new LocalsHandler(this);
}
@@ -3601,6 +3601,14 @@
}
}
+ visitAssert(node) {
+ if (!compiler.enableUserAssertions) {
+ stack.add(graph.addConstantNull(compiler));
+ return;
+ }
+ visitStaticSend(node);
+ }
+
visitStaticSend(Send node) {
Selector selector = elements.getSelector(node);
Element element = elements[node];
@@ -3614,11 +3622,6 @@
argumentNodes: node.arguments);
return;
}
- if (identical(element, compiler.assertMethod)
- && !compiler.enableUserAssertions) {
- stack.add(graph.addConstantNull(compiler));
- return;
- }
compiler.ensure(!element.isGenerativeConstructor());
if (element.isFunction()) {
var inputs = <HInstruction>[];
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index 372b4ae..6f3389a5 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -174,6 +174,7 @@
Modifiers asModifiers() => null;
NamedArgument asNamedArgument() => null;
NamedMixinApplication asNamedMixinApplication() => null;
+ NewExpression asNewExpression() => null;
NodeList asNodeList() => null;
Operator asOperator() => null;
ParenthesizedExpression asParenthesizedExpression() => null;
@@ -473,6 +474,8 @@
NewExpression([this.newToken, this.send]);
+ NewExpression asNewExpression() => this;
+
accept(Visitor visitor) => visitor.visitNewExpression(this);
visitChildren(Visitor visitor) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 49d14b1..9dda20d 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -1666,7 +1666,7 @@
ConcreteTypesInferrer inferrer, this.environment)
: this.inferrer = inferrer
, this.backend = inferrer.compiler.backend
- , super(elements) {
+ , super(elements, inferrer.compiler) {
for (Element element in elements.otherDependencies) {
if (element.isClass()) {
inferrer.augmentSeenClasses(inferrer.normalize(element));
@@ -2378,6 +2378,14 @@
return inferrer.unknownConcreteType;
}
+ ConcreteType visitAssert(Send node) {
+ if (!compiler.enableUserAssertions) {
+ return inferrer.nullConcreteType;
+ } else {
+ return visitStaticSend(node);
+ }
+ }
+
ConcreteType visitStaticSend(Send node) {
if (elements.getSelector(node).name == const SourceString('JS')) {
return inferrer.getNativeCallReturnType(node);
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index 9569030..7f9cef0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -554,7 +554,6 @@
final Element analyzedElement;
final TypeSystem<T> types;
final E inferrer;
- final Compiler compiler;
final Map<TargetElement, List<LocalsHandler<T>>> breaksFor =
new Map<TargetElement, List<LocalsHandler<T>>>();
final Map<TargetElement, List<LocalsHandler>> continuesFor =
@@ -584,10 +583,10 @@
this.types,
Compiler compiler,
[LocalsHandler<T> handler])
- : this.compiler = compiler,
- this.analyzedElement = analyzedElement,
+ : this.analyzedElement = analyzedElement,
this.locals = handler,
- super(compiler.enqueuer.resolution.getCachedElements(analyzedElement)) {
+ super(compiler.enqueuer.resolution.getCachedElements(analyzedElement),
+ compiler) {
if (handler != null) return;
Node node = analyzedElement.parseNode(compiler);
FieldInitializationScope<T> fieldScope =
@@ -615,6 +614,13 @@
T visitFunctionExpression(FunctionExpression node);
+ T visitAssert(Send node) {
+ if (!compiler.enableUserAssertions) {
+ return types.nullType;
+ }
+ return visitStaticSend(node);
+ }
+
T visitNode(Node node) {
node.visitChildren(this);
}
@@ -975,7 +981,7 @@
T visitThrow(Throw node) {
node.visitChildren(this);
locals.seenReturnOrThrow = true;
- return types.dynamicType;
+ return types.nonNullEmpty();
}
T visitCatchBlock(CatchBlock node) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 4ff9f72..acacbe2 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -1665,12 +1665,9 @@
ClosureClassMap closureData =
compiler.closureToClassMapper.computeClosureToClassMapping(
analyzedElement, node, elements);
- ClosureScope scopeData = closureData.capturingScopes[node];
- if (scopeData != null) {
- scopeData.capturedVariableMapping.forEach((variable, field) {
- locals.setCapturedAndBoxed(variable, field);
- });
- }
+ closureData.forEachBoxedVariable((variable, field) {
+ locals.setCapturedAndBoxed(variable, field);
+ });
if (analyzedElement.isField()) {
return visit(node.asSendSet().arguments.head);
}
@@ -1784,8 +1781,10 @@
compiler.closureToClassMapper.getMappingForNestedFunction(node);
nestedClosureData.forEachCapturedVariable((variable, field) {
if (!nestedClosureData.isVariableBoxed(variable)) {
- // The type may be null for instance contexts: the 'this'
- // variable and type parameters.
+ if (variable == nestedClosureData.thisElement) {
+ inferrer.recordType(field, thisType);
+ }
+ // The type is null for type parameters.
if (locals.locals[variable] == null) return;
inferrer.recordType(field, locals.locals[variable]);
}
@@ -2269,10 +2268,15 @@
returnType = inferrer.addReturnTypeFor(analyzedElement, returnType, type);
}
- void synthesizeForwardingCall(Spannable node, FunctionElement element) {
+ T synthesizeForwardingCall(Spannable node, FunctionElement element) {
element = element.implementation;
FunctionElement function = analyzedElement;
FunctionSignature signature = function.computeSignature(compiler);
+ FunctionSignature calleeSignature = element.computeSignature(compiler);
+ if (!calleeSignature.isCompatibleWith(signature)) {
+ return types.nonNullEmpty();
+ }
+
List<T> unnamed = <T>[];
Map<SourceString, T> named = new Map<SourceString, T>();
signature.forEachRequiredParameter((Element element) {
@@ -2295,6 +2299,7 @@
null,
sideEffects,
inLoop);
+ return inferrer.returnTypeOfElement(element);
}
T visitReturn(Return node) {
@@ -2307,8 +2312,8 @@
// the send is just a property access. Therefore we must
// manually create the [ArgumentsTypes] of the call, and
// manually register [analyzedElement] as a caller of [element].
- synthesizeForwardingCall(node.expression, element);
- recordReturnType(inferrer.returnTypeOfElement(element));
+ T mask = synthesizeForwardingCall(node.expression, element);
+ recordReturnType(mask);
}
} else {
Node expression = node.expression;
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/type_graph_inferrer.dart
index 730153d..10d96a0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/type_graph_inferrer.dart
@@ -1022,6 +1022,17 @@
} else {
recordTypeOfNonFinalField(node, element, type, null);
}
+ if (Elements.isStaticOrTopLevelField(element)
+ && node.asSendSet() != null
+ && !element.modifiers.isConst()) {
+ var argument = node.asSendSet().arguments.head;
+ // TODO(13429): We could do better here by using the
+ // constant handler to figure out if it's a lazy field or not.
+ if (argument.asSend() != null
+ || (argument.asNewExpression() != null && !argument.isConst())) {
+ recordType(element, types.nullType);
+ }
+ }
} else {
recordReturnType(element, type);
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index a192b65..6b7afbb 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -7,10 +7,8 @@
import '../dart2jslib.dart' hide Selector, TypedSelector;
import '../tree/tree.dart';
import '../elements/elements.dart';
-import '../native_handler.dart' as native;
import '../util/util.dart';
import '../universe/universe.dart';
-import 'simple_types_inferrer.dart' show SimpleTypesInferrer;
import 'type_graph_inferrer.dart' show TypeGraphInferrer;
import 'concrete_types_inferrer.dart' show ConcreteTypesInferrer;
import '../dart_types.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 5658fe1..4802139 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -54,11 +54,14 @@
final Set<Element> genericCallMethods;
/**
- * Set of methods in instantiated classes that use type variables in their
- * signature and have potentially been closurized.
+ * Set of closures that use type variables in their signature.
*/
- final Set<Element> closurizedGenericMembers;
+ final Set<Element> genericClosures;
+ /**
+ * Set of methods in instantiated classes that are potentially
+ * closurized.
+ */
final Set<Element> closurizedMembers;
bool usingFactoryWithTypeArguments = false;
@@ -73,7 +76,7 @@
fieldSetters = new Set<Element>(),
isChecks = new Set<DartType>(),
genericCallMethods = new Set<Element>(),
- closurizedGenericMembers = new Set<Element>(),
+ genericClosures = new Set<Element>(),
closurizedMembers = new Set<Element>();
bool hasMatchingSelector(Set<Selector> selectors,
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 93a1a04..23ec164 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -169,9 +169,18 @@
'Error: Cannot resolve constructor "#{constructorName}".');
static const MessageKind CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT =
- const MessageKind(
- 'Error: cannot resolve constructor "#{constructorName}" for implicit'
- 'super call.');
+ const MessageKind('Error: cannot resolve constructor "#{constructorName}"'
+ ' for implicit super call.',
+ howToFix: 'Try explicitly invoking a constructor of the super class',
+ examples: const ["""
+class A {
+ A.foo() {}
+}
+class B extends A {
+ B();
+}
+main() => new B();
+"""]);
static const MessageKind INVALID_UNNAMED_CONSTRUCTOR_NAME = const MessageKind(
'Error: Unnamed constructor name must be "#{name}".');
@@ -266,6 +275,9 @@
static const MessageKind CYCLIC_CLASS_HIERARCHY = const MessageKind(
'Error: "#{className}" creates a cycle in the class hierarchy.');
+ static const MessageKind CYCLIC_REDIRECTING_FACTORY = const MessageKind(
+ 'Error: Redirecting factory leads to a cyclic redirection.');
+
static const MessageKind INVALID_RECEIVER_IN_INITIALIZER = const MessageKind(
'Error: Field initializer expected.');
@@ -538,12 +550,52 @@
F f;
}"""]);
+ static const MessageKind FORMAL_DECLARED_CONST = const MessageKind(
+ "Error: A formal parameter can't be declared const.",
+ howToFix: "Try removing 'const'.",
+ examples: const ["""
+foo(const x) {}
+main() => foo(42);
+""", """
+foo({const x}) {}
+main() => foo(42);
+""", """
+foo([const x]) {}
+main() => foo(42);
+"""]);
+
static const MessageKind CANNOT_INSTANTIATE_TYPE_VARIABLE = const MessageKind(
'Error: Cannot instantiate type variable "#{typeVariableName}".');
static const MessageKind CYCLIC_TYPE_VARIABLE = const MessageKind(
'Warning: Type variable "#{typeVariableName}" is a supertype of itself.');
+ static const CYCLIC_TYPEDEF = const MessageKind(
+ "Error: A typedef can't refer to itself.",
+ howToFix: "Try removing all references to '#{typedefName}' "
+ "in the definition of '#{typedefName}'.",
+ examples: const ["""
+typedef F F(); // The return type 'F' is a self-reference.
+main() { F f = null; }"""]);
+
+ static const CYCLIC_TYPEDEF_ONE = const MessageKind(
+ "Error: A typedef can't refer to itself through another typedef.",
+ howToFix: "Try removing all references to "
+ "'#{otherTypedefName}' in the definition of '#{typedefName}'.",
+ examples: const ["""
+typedef G F(); // The return type 'G' is a self-reference through typedef 'G'.
+typedef F G(); // The return type 'F' is a self-reference through typedef 'F'.
+main() { F f = null; }""",
+"""
+typedef G F(); // The return type 'G' creates a self-reference.
+typedef H G(); // The return type 'H' creates a self-reference.
+typedef H(F f); // The argument type 'F' creates a self-reference.
+main() { F f = null; }"""]);
+
+ static const CYCLIC_TYPEDEF_TYPEVAR = const MessageKind(
+ "Internal Error: Recursive type variable bounds are not "
+ "supported on typedefs.");
+
static const MessageKind CLASS_NAME_EXPECTED = const MessageKind(
'Error: Class name expected.');
@@ -757,6 +809,29 @@
main() => foo(1);
"""]);
+ static const MessageKind CONST_WITHOUT_INITIALIZER = const MessageKind(
+ "Error: A constant variable must be initialized.",
+ howToFix: "Try adding an initializer or "
+ "removing the 'const' modifier.",
+ examples: const ["""
+void main() {
+ const c; // This constant variable must be initialized.
+}"""]);
+
+ static const MessageKind MEMBER_USES_CLASS_NAME = const MessageKind(
+ "Error: Member variable can't have the same name as the class it is "
+ "declared in.",
+ howToFix: "Try renaming the variable.",
+ examples: const ["""
+class A { var A; }
+main() {
+ var a = new A();
+ a.A = 1;
+}
+""", """
+class A { static var A; }
+main() => A.A = 1;
+"""]);
static const MessageKind WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT =
const MessageKind(
@@ -840,6 +915,13 @@
'Error: "!==" is not an operator. '
'Did you mean "#{lhs} != #{rhs}" or "!identical(#{lhs}, #{rhs})"?');
+ static const MessageKind UNSUPPORTED_PREFIX_PLUS = const MessageKind(
+ "Error: '+' is not a prefix operator. ",
+ howToFix: "Try removing '+'.",
+ examples: const [
+ "main() => +2; // No longer a valid way to write '2'"
+ ]);
+
static const MessageKind UNSUPPORTED_THROW_WITHOUT_EXP = const MessageKind(
'Error: No expression after "throw". '
'Did you mean "rethrow"?');
@@ -988,6 +1070,11 @@
"static foo; main(){}",
"external foo; main(){}"]);
+ static const MessageKind ABSTRACT_CLASS_INSTANTIATION = const MessageKind(
+ "Warning: Can't instantiate abstract class.",
+ howToFix: DONT_KNOW_HOW_TO_FIX,
+ examples: const ["abstract class A {} main() { new A(); }"]);
+
static const MessageKind BODY_EXPECTED = const MessageKind(
"Error: Expected a function body or '=>'.",
// TODO(ahe): In some scenarios, we can suggest removing the 'static'
diff --git a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
index 4aa4935..be14aa0 100644
--- a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
@@ -17,6 +17,8 @@
import 'markdown_test.dart';
main() {
+ // Some tests take more than the default 20 second unittest timeout.
+ unittestConfiguration.timeout = null;
group('isAbsolute', () {
final doc = new dd.Dartdoc();
diff --git a/sdk/lib/_internal/lib/collection_patch.dart b/sdk/lib/_internal/lib/collection_patch.dart
index 670b4ab..7066b05 100644
--- a/sdk/lib/_internal/lib/collection_patch.dart
+++ b/sdk/lib/_internal/lib/collection_patch.dart
@@ -883,6 +883,30 @@
}
patch class HashSet<E> {
+ patch factory HashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
+ if (isValidKey == null) {
+ if (hashCode == null) {
+ if (equals == null) {
+ return new _HashSet<E>();
+ }
+ if (identical(identical, equals)) {
+ return new _IdentityHashSet<E>();
+ }
+ hashCode = _defaultHashCode;
+ } else if (equals == null) {
+ equals = _defaultEquals;
+ }
+ } else {
+ if (hashCode == null) hashCode = _defaultHashCode;
+ if (equals == null) equals = _defaultEquals;
+ }
+ return new _CustomHashSet<E>(equals, hashCode, isValidKey);
+ }
+}
+
+class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> {
int _length = 0;
// The hash set contents are divided into three parts: one part for
@@ -904,18 +928,20 @@
// guard against concurrent modifications.
List _elements;
- patch HashSet();
+ _HashSet();
+
+ Set<E> _newSet() => new _HashSet<E>();
// Iterable.
- patch Iterator<E> get iterator {
+ Iterator<E> get iterator {
return new HashSetIterator<E>(this, _computeElements());
}
- patch int get length => _length;
- patch bool get isEmpty => _length == 0;
- patch bool get isNotEmpty => !isEmpty;
+ int get length => _length;
+ bool get isEmpty => _length == 0;
+ bool get isNotEmpty => !isEmpty;
- patch bool contains(Object object) {
+ bool contains(Object object) {
if (_isStringElement(object)) {
var strings = _strings;
return (strings == null) ? false : _hasTableEntry(strings, object);
@@ -931,7 +957,7 @@
}
// Collection.
- patch void add(E element) {
+ void add(E element) {
if (_isStringElement(element)) {
var strings = _strings;
if (strings == null) _strings = strings = _newHashTable();
@@ -957,13 +983,13 @@
}
}
- patch void addAll(Iterable<E> objects) {
+ void addAll(Iterable<E> objects) {
for (E each in objects) {
add(each);
}
}
- patch bool remove(Object object) {
+ bool remove(Object object) {
if (_isStringElement(object)) {
return _removeHashTableEntry(_strings, object);
} else if (_isNumericElement(object)) {
@@ -985,21 +1011,25 @@
}
}
- patch void removeAll(Iterable<Object> objectsToRemove) {
+ void removeAll(Iterable<Object> objectsToRemove) {
for (var each in objectsToRemove) {
remove(each);
}
}
- patch void removeWhere(bool test(E element)) {
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, (o) => o is E);
+ }
+
+ void removeWhere(bool test(E element)) {
removeAll(_computeElements().where(test));
}
- patch void retainWhere(bool test(E element)) {
+ void retainWhere(bool test(E element)) {
removeAll(_computeElements().where((E element) => !test(element)));
}
- patch void clear() {
+ void clear() {
if (_length > 0) {
_strings = _nums = _rest = _elements = null;
_length = 0;
@@ -1063,7 +1093,7 @@
_elements = null;
}
- bool _removeHashTableEntry(var table, E element) {
+ bool _removeHashTableEntry(var table, Object element) {
if (table != null && _hasTableEntry(table, element)) {
_deleteTableEntry(table, element);
_length--;
@@ -1086,7 +1116,7 @@
JS('bool', '(# & 0x3ffffff) === #', element, element);
}
- static int _computeHashCode(var element) {
+ int _computeHashCode(var element) {
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
@@ -1111,12 +1141,12 @@
JS('void', 'delete #[#]', table, key);
}
- static List _getBucket(var table, var element) {
+ List _getBucket(var table, var element) {
var hash = _computeHashCode(element);
return JS('var', '#[#]', table, hash);
}
- static int _findBucketIndex(var bucket, var element) {
+ int _findBucketIndex(var bucket, var element) {
if (bucket == null) return -1;
int length = JS('int', '#.length', bucket);
for (int i = 0; i < length; i++) {
@@ -1139,6 +1169,75 @@
}
}
+class _IdentityHashSet<E> extends _HashSet<E> {
+ Set<E> _newSet() => new _IdentityHashSet<E>();
+
+ int _findBucketIndex(var bucket, var element) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i++) {
+ if (identical(JS('var', '#[#]', bucket, i), element)) return i;
+ }
+ return -1;
+ }
+}
+
+class _CustomHashSet<E> extends _HashSet<E> {
+ _Equality<E> _equality;
+ _Hasher<E> _hasher;
+ _Predicate _validKey;
+ _CustomHashSet(this._equality, this._hasher, bool validKey(potentialKey))
+ : _validKey = (validKey != null) ? validKey : ((x) => x is E);
+
+ Set<E> _newSet() => new _CustomHashSet<E>(_equality, _hasher, _validKey);
+
+ int _findBucketIndex(var bucket, var element) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i++) {
+ if (_equality(JS('var', '#[#]', bucket, i), element)) return i;
+ }
+ return -1;
+ }
+
+ int _computeHashCode(var element) {
+ // We force the hash codes to be unsigned 30-bit integers to avoid
+ // issues with problematic elements like '__proto__'. Another
+ // option would be to throw an exception if the hash code isn't a
+ // number.
+ return JS('int', '# & 0x3ffffff', _hasher(element));
+ }
+
+ bool contains(Object object) {
+ if (!_validKey(object)) return false;
+ return super.contains(object);
+ }
+
+ bool remove(Object object) {
+ if (!_validKey(object)) return false;
+ return super.remove(object);
+ }
+
+ bool containsAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (!_validKey(element) || !this.contains(element)) return false;
+ }
+ return true;
+ }
+
+ void removeAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (_validKey(element)) {
+ super.remove(element);
+ }
+ }
+ }
+
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, _validKey);
+ }
+}
+
// TODO(kasperl): Share this code with HashMapKeyIterator<E>?
class HashSetIterator<E> implements Iterator<E> {
final _set;
@@ -1169,7 +1268,31 @@
}
}
-patch class LinkedHashSet<E> extends _HashSetBase<E> {
+patch class LinkedHashSet<E> {
+ patch factory LinkedHashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
+ if (isValidKey == null) {
+ if (hashCode == null) {
+ if (equals == null) {
+ return new _LinkedHashSet<E>();
+ }
+ if (identical(identical, equals)) {
+ return new _LinkedIdentityHashSet<E>();
+ }
+ hashCode = _defaultHashCode;
+ } else if (equals == null) {
+ equals = _defaultEquals;
+ }
+ } else {
+ if (hashCode == null) hashCode = _defaultHashCode;
+ if (equals == null) equals = _defaultEquals;
+ }
+ return new _LinkedCustomHashSet<E>(equals, hashCode, isValidKey);
+ }
+}
+
+class _LinkedHashSet<E> extends _HashSetBase<E> implements LinkedHashSet<E> {
int _length = 0;
// The hash set contents are divided into three parts: one part for
@@ -1195,22 +1318,24 @@
// over.
int _modifications = 0;
- patch LinkedHashSet();
+ _LinkedHashSet();
+
+ Set<E> _newSet() => new _LinkedHashSet<E>();
void _unsupported(String operation) {
throw 'LinkedHashSet: unsupported $operation';
}
// Iterable.
- patch Iterator<E> get iterator {
+ Iterator<E> get iterator {
return new LinkedHashSetIterator(this, _modifications);
}
- patch int get length => _length;
- patch bool get isEmpty => _length == 0;
- patch bool get isNotEmpty => !isEmpty;
+ int get length => _length;
+ bool get isEmpty => _length == 0;
+ bool get isNotEmpty => !isEmpty;
- patch bool contains(Object object) {
+ bool contains(Object object) {
if (_isStringElement(object)) {
var strings = _strings;
if (strings == null) return false;
@@ -1229,7 +1354,7 @@
}
}
- patch void forEach(void action(E element)) {
+ void forEach(void action(E element)) {
LinkedHashSetCell cell = _first;
int modifications = _modifications;
while (cell != null) {
@@ -1241,18 +1366,18 @@
}
}
- patch E get first {
+ E get first {
if (_first == null) throw new StateError("No elements");
return _first._element;
}
- patch E get last {
+ E get last {
if (_last == null) throw new StateError("No elements");
return _last._element;
}
// Collection.
- patch void add(E element) {
+ void add(E element) {
if (_isStringElement(element)) {
var strings = _strings;
if (strings == null) _strings = strings = _newHashTable();
@@ -1278,13 +1403,13 @@
}
}
- patch void addAll(Iterable<E> objects) {
+ void addAll(Iterable<E> objects) {
for (E object in objects) {
add(object);
}
}
- patch bool remove(Object object) {
+ bool remove(Object object) {
if (_isStringElement(object)) {
return _removeHashTableEntry(_strings, object);
} else if (_isNumericElement(object)) {
@@ -1303,17 +1428,21 @@
}
}
- patch void removeAll(Iterable objectsToRemove) {
+ void removeAll(Iterable objectsToRemove) {
for (var each in objectsToRemove) {
remove(each);
}
}
- patch void removeWhere(bool test(E element)) {
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, (o) => o is E);
+ }
+
+ void removeWhere(bool test(E element)) {
_filterWhere(test, true);
}
- patch void retainWhere(bool test(E element)) {
+ void retainWhere(bool test(E element)) {
_filterWhere(test, false);
}
@@ -1332,7 +1461,7 @@
}
}
- patch void clear() {
+ void clear() {
if (_length > 0) {
_strings = _nums = _rest = _first = _last = null;
_length = 0;
@@ -1346,7 +1475,7 @@
_setTableEntry(table, element, _newLinkedCell(element));
}
- bool _removeHashTableEntry(var table, E element) {
+ bool _removeHashTableEntry(var table, Object element) {
if (table == null) return false;
LinkedHashSetCell cell = _getTableEntry(table, element);
if (cell == null) return false;
@@ -1409,7 +1538,7 @@
JS('bool', '(# & 0x3ffffff) === #', element, element);
}
- static int _computeHashCode(var element) {
+ int _computeHashCode(var element) {
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
@@ -1430,12 +1559,12 @@
JS('void', 'delete #[#]', table, key);
}
- static List _getBucket(var table, var element) {
+ List _getBucket(var table, var element) {
var hash = _computeHashCode(element);
return JS('var', '#[#]', table, hash);
}
- static int _findBucketIndex(var bucket, var element) {
+ int _findBucketIndex(var bucket, var element) {
if (bucket == null) return -1;
int length = JS('int', '#.length', bucket);
for (int i = 0; i < length; i++) {
@@ -1459,6 +1588,79 @@
}
}
+class _LinkedIdentityHashSet<E> extends _LinkedHashSet<E> {
+ Set<E> _newSet() => new _LinkedIdentityHashSet<E>();
+
+ int _findBucketIndex(var bucket, var element) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i++) {
+ LinkedHashSetCell cell = JS('var', '#[#]', bucket, i);
+ if (identical(cell._element, element)) return i;
+ }
+ return -1;
+ }
+}
+
+class _LinkedCustomHashSet<E> extends _LinkedHashSet<E> {
+ _Equality<E> _equality;
+ _Hasher<E> _hasher;
+ _Predicate _validKey;
+ _LinkedCustomHashSet(this._equality, this._hasher,
+ bool validKey(potentialKey))
+ : _validKey = (validKey != null) ? validKey : ((x) => x is E);
+
+ Set<E> _newSet() =>
+ new _LinkedCustomHashSet<E>(_equality, _hasher, _validKey);
+
+ int _findBucketIndex(var bucket, var element) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i++) {
+ LinkedHashSetCell cell = JS('var', '#[#]', bucket, i);
+ if (_equality(cell._element, element)) return i;
+ }
+ return -1;
+ }
+
+ int _computeHashCode(var element) {
+ // We force the hash codes to be unsigned 30-bit integers to avoid
+ // issues with problematic elements like '__proto__'. Another
+ // option would be to throw an exception if the hash code isn't a
+ // number.
+ return JS('int', '# & 0x3ffffff', _hasher(element));
+ }
+
+ bool contains(Object object) {
+ if (!_validKey(object)) return false;
+ return super.contains(object);
+ }
+
+ bool remove(Object object) {
+ if (!_validKey(object)) return false;
+ return super.remove(object);
+ }
+
+ bool containsAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (!_validKey(element) || !this.contains(element)) return false;
+ }
+ return true;
+ }
+
+ void removeAll(Iterable<Object> elements) {
+ for (Object element in elements) {
+ if (_validKey(element)) {
+ super.remove(element);
+ }
+ }
+ }
+
+ void retainAll(Iterable<Object> elements) {
+ super._retainAll(elements, _validKey);
+ }
+}
+
class LinkedHashSetCell {
final _element;
diff --git a/sdk/lib/_internal/lib/constant_map.dart b/sdk/lib/_internal/lib/constant_map.dart
index 60300fc..7febd18 100644
--- a/sdk/lib/_internal/lib/constant_map.dart
+++ b/sdk/lib/_internal/lib/constant_map.dart
@@ -4,40 +4,7 @@
part of _js_helper;
-// This class has no constructor. This is on purpose since the instantiation
-// is shortcut by the compiler.
-class ConstantMap<V> implements Map<String, V> {
- final int length;
- // A constant map is backed by a JavaScript object.
- final _jsObject;
- final List<String> _keys;
-
- bool containsValue(V needle) {
- return values.any((V value) => value == needle);
- }
-
- bool containsKey(String key) {
- if (key == '__proto__') return false;
- return jsHasOwnProperty(_jsObject, key);
- }
-
- V operator [](String key) {
- if (!containsKey(key)) return null;
- return jsPropertyAccess(_jsObject, key);
- }
-
- void forEach(void f(String key, V value)) {
- _keys.forEach((String key) => f(key, this[key]));
- }
-
- Iterable<String> get keys {
- return new _ConstantMapKeyIterable(this);
- }
-
- Iterable<V> get values {
- return _keys.map((String key) => this[key]);
- }
-
+abstract class ConstantMap<K, V> implements Map<K, V> {
bool get isEmpty => length == 0;
bool get isNotEmpty => !isEmpty;
@@ -47,32 +14,109 @@
_throwUnmodifiable() {
throw new UnsupportedError("Cannot modify unmodifiable Map");
}
- void operator []=(String key, V val) => _throwUnmodifiable();
- V putIfAbsent(String key, V ifAbsent()) => _throwUnmodifiable();
- V remove(String key) => _throwUnmodifiable();
+ void operator []=(K key, V val) => _throwUnmodifiable();
+ V putIfAbsent(K key, V ifAbsent()) => _throwUnmodifiable();
+ V remove(K key) => _throwUnmodifiable();
void clear() => _throwUnmodifiable();
- void addAll(Map<String, V> other) => _throwUnmodifiable();
+ void addAll(Map<K, V> other) => _throwUnmodifiable();
}
// This class has no constructor. This is on purpose since the instantiation
// is shortcut by the compiler.
-class ConstantProtoMap<V> extends ConstantMap<V> {
+class ConstantStringMap<K, V> extends ConstantMap<K, V> {
+ final int length;
+ // A constant map is backed by a JavaScript object.
+ final _jsObject;
+ final List<K> _keys;
+
+ bool containsValue(V needle) {
+ return values.any((V value) => value == needle);
+ }
+
+ bool containsKey(Object key) {
+ if (key is! String) return false;
+ if (key == '__proto__') return false;
+ return jsHasOwnProperty(_jsObject, key);
+ }
+
+ V operator [](Object key) {
+ if (key is! String) return null;
+ if (!containsKey(key)) return null;
+ return jsPropertyAccess(_jsObject, key);
+ }
+
+ void forEach(void f(K key, V value)) {
+ _keys.forEach((key) => f(key, this[key]));
+ }
+
+ Iterable<K> get keys {
+ return new _ConstantMapKeyIterable<K>(this);
+ }
+
+ Iterable<V> get values {
+ return _keys.map((key) => this[key]);
+ }
+}
+
+// This class has no constructor. This is on purpose since the instantiation
+// is shortcut by the compiler.
+class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
final V _protoValue;
- bool containsKey(String key) {
+ bool containsKey(Object key) {
if (key == '__proto__') return true;
return super.containsKey(key);
}
- V operator [](String key) {
+ V operator [](Object key) {
if (key == '__proto__') return _protoValue;
return super[key];
}
}
-class _ConstantMapKeyIterable extends IterableBase<String> {
- ConstantMap _map;
+class _ConstantMapKeyIterable<K> extends IterableBase<K> {
+ ConstantStringMap<K, dynamic> _map;
_ConstantMapKeyIterable(this._map);
- Iterator<String> get iterator => _map._keys.iterator;
+ Iterator<K> get iterator => _map._keys.iterator;
+}
+
+// This class has no constructor. This is on purpose since the instantiation
+// is shortcut by the compiler.
+class GeneralConstantMap<K, V> extends ConstantMap<K, V> {
+ // [_jsData] holds a key-value pair list.
+ final _jsData;
+
+ // We cannot create the backing map on creation since hashCode interceptors
+ // have not been defined when constants are created.
+ Map<K, V> _getMap() {
+ if (JS('bool', r'!this.$map')) {
+ JS('', r'this.$map = #', makeConstantMap(_jsData));
+ }
+ return JS('Map', r'this.$map');
+ }
+
+ bool containsValue(V needle) {
+ return _getMap().containsValue(needle);
+ }
+
+ bool containsKey(Object key) {
+ return _getMap().containsKey(key);
+ }
+
+ V operator [](Object key) {
+ return _getMap()[key];
+ }
+
+ void forEach(void f(K key, V value)) {
+ _getMap().forEach(f);
+ }
+
+ Iterable<K> get keys {
+ return _getMap().keys;
+ }
+
+ Iterable<V> get values {
+ return _getMap().values;
+ }
}
diff --git a/sdk/lib/_internal/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart
index 1837aaf..b87d045 100644
--- a/sdk/lib/_internal/lib/io_patch.dart
+++ b/sdk/lib/_internal/lib/io_patch.dart
@@ -59,6 +59,9 @@
patch static _identical(String path1, String path2) {
throw new UnsupportedError("FileSystemEntity._identical");
}
+ patch static _resolveSymbolicLinks(String path) {
+ throw new UnsupportedError("FileSystemEntity._resolveSymbolicLinks");
+ }
}
patch class _File {
@@ -98,9 +101,6 @@
patch static int _openStdio(int fd) {
throw new UnsupportedError("File._openStdio");
}
- patch static _fullPath(String path) {
- throw new UnsupportedError("File._fullPath");
- }
}
patch class _RandomAccessFile {
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index f31a0b8..073436e 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -1422,17 +1422,35 @@
}
}
+int _objectHashCode(var object) {
+ if (object == null || JS('bool', "typeof # != 'object'", object)) {
+ return object.hashCode;
+ } else {
+ return Primitives.objectHashCode(object);
+ }
+}
+
/**
* Called by generated code to build a map literal. [keyValuePairs] is
* a list of key, value, key, value, ..., etc.
*/
-makeLiteralMap(List keyValuePairs) {
- Iterator iterator = keyValuePairs.iterator;
- Map result = new LinkedHashMap();
- while (iterator.moveNext()) {
- String key = iterator.current;
- iterator.moveNext();
- var value = iterator.current;
+makeLiteralMap(keyValuePairs) {
+ return fillLiteralMap(keyValuePairs, new LinkedHashMap());
+}
+
+makeConstantMap(keyValuePairs) {
+ return fillLiteralMap(keyValuePairs,
+ new LinkedHashMap(equals: identical, hashCode: _objectHashCode));
+}
+
+fillLiteralMap(keyValuePairs, Map result) {
+ // TODO(johnniwinther): Use JSArray to optimize this code instead of calling
+ // [getLength] and [getIndex].
+ int index = 0;
+ int length = getLength(keyValuePairs);
+ while (index < length) {
+ var key = getIndex(keyValuePairs, index++);
+ var value = getIndex(keyValuePairs, index++);
result[key] = value;
}
return result;
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 948a0d8..cf002e8 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -418,10 +418,7 @@
}
ClassMirror reflectType(Type key) {
- // TODO(ahe): Don't discard type arguments to support
- // [ClassMirror.isOriginalDeclaration] and [ClassMirror.originalDeclaration]
- // correctly.
- return reflectClassByMangledName(getMangledTypeName(key).split('<')[0]);
+ return reflectClassByMangledName(getMangledTypeName(key));
}
ClassMirror reflectClassByMangledName(String mangledName) {
@@ -437,6 +434,15 @@
var mirror = JsCache.fetch(classMirrors, mangledName);
if (mirror != null) return mirror;
disableTreeShaking();
+ int typeArgIndex = mangledName.indexOf("<");
+ if (typeArgIndex != -1) {
+ mirror = new JsTypeBoundClassMirror(
+ reflectClassByMangledName(mangledName.substring(0, typeArgIndex)),
+ // Remove the angle brackets enclosing the type arguments.
+ mangledName.substring(typeArgIndex + 1, mangledName.length - 1));
+ JsCache.update(classMirrors, mangledName, mirror);
+ return mirror;
+ }
var constructorOrInterceptor =
Primitives.getConstructorOrInterceptor(mangledName);
if (constructorOrInterceptor == null) {
@@ -581,11 +587,12 @@
ClassMirror get originalDeclaration => this;
- // TODO(ahe): Implement these.
- Map<Symbol, TypeVariableMirror> get typeVariables {
+ // TODO(ahe): Implement this.
+ List<TypeVariableMirror> get typeVariables {
throw new UnimplementedError();
}
- Map<Symbol, TypeMirror> get typeArguments => throw new UnimplementedError();
+
+ List<TypeMirror> get typeArguments => new List();
}
abstract class JsObjectMirror implements ObjectMirror {
@@ -709,7 +716,7 @@
// identical. Otherwise, use the primitive identity hash to maintain
// correctness even if a user-defined hashCode returns different values for
// successive invocations.
- var h = ((JS('bool', 'typeof # != "object"', reflectee)) ||
+ var h = ((JS('bool', 'typeof # != "object"', reflectee)) ||
(reflectee == null))
? reflectee.hashCode
: Primitives.objectHashCode(reflectee);
@@ -724,6 +731,155 @@
MirrorSystem get mirrors => currentJsMirrorSystem;
}
+/**
+ * ClassMirror for generic classes where the type parameters are bound.
+ *
+ * [typeArguments] will return a list of the type arguments, in constrast
+ * to JsCLassMirror that returns an empty list since it represents original
+ * declarations and classes that are not generic.
+ */
+class JsTypeBoundClassMirror implements ClassMirror {
+ final JsClassMirror _class;
+
+ /**
+ * When instantiated this field will hold a string representing the list of
+ * type arguments for the class, i.e. what is inside the outermost angle
+ * brackets. Then, when get typeArguments is called the first time, the string
+ * is parsed into the actual list of TypeMirrors, and the field is overridden
+ * with this value.
+ */
+ var _typeArgs;
+
+ JsTypeBoundClassMirror(this._class, this._typeArgs);
+
+ List<TypeVariableMirror> get typeVariables => _class.typeVariables;
+
+ List<TypeMirror> get typeArguments {
+ if (_typeArgs is! String) return _typeArgs;
+ List result = new List();
+ if (_typeArgs.indexOf('<') == -1) {
+ for (String s in _typeArgs.split(',')) {
+ result.add(reflectClassByMangledName(s.trim()));
+ }
+ } else {
+ int level = 0;
+ StringBuffer currentTypeArg = new StringBuffer();
+
+ addCurrentTypeArg() {
+ var classMirror = reflectClassByMangledName(currentTypeArg.toString());
+ result.add(classMirror);
+ currentTypeArg.clear();
+ }
+
+ for (int i = 0; i < _typeArgs.length; i++) {
+ var character = _typeArgs[i];
+ if (character == ' ') {
+ continue;
+ } else if (character == '<') {
+ currentTypeArg.write(character);
+ level++;
+ } else if (character == '>') {
+ currentTypeArg.write(character);
+ level--;
+ } else if (character == ',') {
+ if (level > 0) {
+ currentTypeArg.write(character);
+ } else {
+ addCurrentTypeArg();
+ }
+ } else {
+ currentTypeArg.write(character);
+ }
+ }
+ addCurrentTypeArg();
+ }
+ return _typeArgs = new UnmodifiableListView(result);
+ }
+
+ Map<Symbol, MethodMirror> get constructors => _class.constructors;
+
+ Map<Symbol, MethodMirror> get methods => _class.methods;
+
+ Map<Symbol, MethodMirror> get getters => _class.getters;
+
+ Map<Symbol, MethodMirror> get setters => _class.setters;
+
+ Map<Symbol, VariableMirror> get variables => _class.variables;
+
+ Map<Symbol, Mirror> get members => _class.members;
+
+ InstanceMirror setField(Symbol fieldName, Object arg) {
+ return _class.setField(fieldName, arg);
+ }
+
+ InstanceMirror getField(Symbol fieldName) => _class.getField(fieldName);
+
+ InstanceMirror newInstance(Symbol constructorName,
+ List positionalArguments,
+ [Map<Symbol, dynamic> namedArguments]) {
+ return _class.newInstance(constructorName,
+ positionalArguments,
+ namedArguments);
+ }
+
+ Future<InstanceMirror> newInstanceAsync(
+ Symbol constructorName,
+ List positionalArguments,
+ [Map<Symbol, dynamic> namedArguments]) {
+ return _class.newInstanceAsync(constructorName,
+ positionalArguments,
+ namedArguments);
+ }
+
+ JsLibraryMirror get owner => _class.owner;
+
+ List<InstanceMirror> get metadata => _class.metadata;
+
+ ClassMirror get superclass => _class.superclass;
+
+ InstanceMirror invoke(Symbol memberName,
+ List positionalArguments,
+ [Map<Symbol,dynamic> namedArguments]) {
+ return _class.invoke(memberName, positionalArguments, namedArguments);
+ }
+
+ bool get isOriginalDeclaration => false;
+
+ ClassMirror get originalDeclaration => _class;
+
+ List<ClassMirror> get superinterfaces => _class.superinterfaces;
+
+ Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
+ return _class.getFieldAsync(fieldName);
+ }
+
+ bool get hasReflectedType => _class.hasReflectedType;
+
+ Future<InstanceMirror> invokeAsync(Symbol memberName,
+ List positionalArguments,
+ [Map<Symbol, dynamic> namedArguments]) {
+ return _class.invokeAsync(memberName, positionalArguments, namedArguments);
+ }
+
+ bool get isPrivate => _class.isPrivate;
+
+ bool get isTopLevel => _class.isTopLevel;
+
+ SourceLocation get location => _class.location;
+
+ MirrorSystem get mirrors => _class.mirrors;
+
+ Symbol get qualifiedName => _class.qualifiedName;
+
+ Type get reflectedType => _class.reflectedType;
+
+ Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
+ return _class.setFieldAsync(fieldName, value);
+ }
+
+ Symbol get simpleName => _class.simpleName;
+}
+
class JsClassMirror extends JsTypeMirror with JsObjectMirror
implements ClassMirror {
final String _mangledName;
@@ -1088,9 +1244,9 @@
}
// TODO(ahe): Implement these.
- Map<Symbol, TypeVariableMirror> get typeVariables
+ List<TypeVariableMirror> get typeVariables
=> throw new UnimplementedError();
- Map<Symbol, TypeMirror> get typeArguments => throw new UnimplementedError();
+ List<TypeMirror> get typeArguments => new List();
}
class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
@@ -1460,6 +1616,10 @@
JsFunctionTypeMirror get value => referent;
String get _prettyName => 'TypedefMirror';
+
+ // TODO(zarah): This method doesn't belong here, since TypedefMirror shouldn't
+ // be a subtype of ClassMirror.
+ ClassMirror get originalDeclaration => this;
}
class JsFunctionTypeMirror implements FunctionTypeMirror {
diff --git a/sdk/lib/_internal/lib/mirrors_patch.dart b/sdk/lib/_internal/lib/mirrors_patch.dart
index 2fddaef..4700984 100644
--- a/sdk/lib/_internal/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/lib/mirrors_patch.dart
@@ -18,4 +18,6 @@
patch InstanceMirror reflect(Object reflectee) => js.reflect(reflectee);
-patch ClassMirror reflectClass(Type key) => js.reflectType(key);
+patch ClassMirror reflectClass(Type key) {
+ return js.reflectType(key).originalDeclaration;
+}
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index 9dd5a3c..bb850fa 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -18,8 +18,10 @@
test/install/hosted/install_test: Pass, Fail # Issue 12837
test/install/hosted/install_transitive_test: Pass, Fail # Issue 12837
test/install/hosted/repair_cache_test: Pass, Fail # Issue 12837
+test/install/hosted/stay_locked_if_compatible_test: Pass, Fail # Issue 12837
test/install/hosted/stay_locked_if_new_is_satisfied_test: Pass, Fail # Issue 12837
test/install/hosted/stay_locked_test: Pass, Fail # Issue 12837
+test/install/hosted/resolve_constraints_test: Pass, Fail # Issue 12837
test/install/hosted/unlock_if_incompatible_test: Pass, Fail # Issue 12837
test/install/hosted/unlock_if_new_is_unsatisfied_test: Pass, Fail # Issue 12837
test/install/hosted/version_negotiation_test: Pass, Fail # Issue 12837
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 6b6c760..ab4b666 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -138,11 +138,11 @@
* A future whose value is available in the next event-loop iteration.
*
* If [value] is not a [Future], using this constructor is equivalent
- * to [:new Future.sync(() => value):].
+ * to [:new Future<T>.sync(() => value):].
*
* See [Completer] to create a Future and complete it later.
*/
- factory Future.value([T value]) {
+ factory Future.value([value]) {
return new _Future<T>.immediate(value);
}
@@ -365,7 +365,7 @@
*
* If you already have a Future, you probably don't need a Completer.
* Instead, you can usually use [Future.then], which returns a Future:
- *
+ *
* Future doStuff(){
* return someAsyncOperation().then((result) {
* // Do something.
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index ea8f902..a149161 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -143,7 +143,8 @@
: _onValueCallback = null, _errorTestCallback = null,
_onErrorCallback = null, _whenCompleteActionCallback = null;
- _Future.immediate(T value)
+ /// Valid types for value: `T` or `Future<T>`.
+ _Future.immediate(value)
: _onValueCallback = null, _errorTestCallback = null,
_onErrorCallback = null, _whenCompleteActionCallback = null {
_asyncComplete(value);
@@ -321,6 +322,14 @@
// Otherwise the value could complete with an error and report an
// unhandled error, even though we know we are already going to listen to
// it.
+
+ // Assign to typed variables so we get earlier checks in checked mode.
+ if (value is Future) {
+ Future<T> typedFuture = value;
+ } else {
+ T typedValue = value;
+ }
+
if (value is Future &&
(value is! _Future || !(value as _Future)._isComplete)) {
// Case 2 from above. We need to register.
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index 147d1ca..f1241a8 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -16,7 +16,7 @@
}
/** Create a new Set of the same type as this. */
- Set _newSet();
+ HashSet<E> _newSet();
Set<E> intersection(Set<Object> other) {
Set<E> result = _newSet();
@@ -44,16 +44,27 @@
return result;
}
- void retainAll(Iterable objectsToRetain) {
- Set retainSet;
- if (objectsToRetain is Set) {
- retainSet = objectsToRetain;
- } else {
- retainSet = objectsToRetain.toSet();
+ void _retainAll(Iterable objectsToRetain, bool isValidKey(Object o)) {
+ // TODO(lrn): Consider optimizing table based versions by
+ // building a new table of the entries to retain.
+ Set retainSet = _newSet();
+ for (Object o in objectsToRetain) {
+ if (isValidKey(o)) {
+ retainSet.add(o);
+ }
}
retainWhere(retainSet.contains);
}
+ List<E> toList({bool growable: true}) {
+ List<E> result = new List<E>()..length = this.length;
+ int i = 0;
+ for (E element in this) result[i++] = element;
+ return result;
+ }
+
+ Set<E> toSet() => _newSet()..addAll(this);
+
// TODO(zarah) Remove this, and let it be inherited by IterableBase
String toString() => IterableMixinWorkaround.toStringIterable(this, '{', '}');
}
@@ -61,49 +72,50 @@
/**
* A [HashSet] is a hash-table based [Set] implementation.
*
- * The elements of a `HashSet` must have consistent [Object.operator==]
- * and [Object.hashCode] implementations. This means that the `==` operator
+ * The elements of a `HashSet` must have consistent equality
+ * and hashCode implementations. This means that the equals operation
* must define a stable equivalence relation on the elements (reflexive,
- * anti-symmetric, transitive, and consistent over time), and that `hashCode`
- * must be the same for objects that are considered equal by `==`.
+ * anti-symmetric, transitive, and consistent over time), and that the hashCode
+ * must consistent with equality, so that the same for objects that are
+ * considered equal.
*
* The set allows `null` as an element.
*
* Most simple operations on `HashSet` are done in constant time: [add],
* [contains], [remove], and [length].
*/
-class HashSet<E> extends _HashSetBase<E> {
- external HashSet();
+class HashSet<E> implements Set<E> {
+ /**
+ * Create a hash set using the provided [equals] as equality.
+ *
+ * The provided [equals] must define a stable equivalence relation, and
+ * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
+ * methods won't work on all objects, but only to instances of E, the
+ * [isValidKey] predicate can be used to restrict the keys that they are
+ * applied to. Any key for which [isValidKey] returns false is automatically
+ * assumed to not be in the set.
+ *
+ * If [equals], [hashCode] and [isValidKey] are omitted, the set uses
+ * the objects' intrinsic [Object.operator==] and [Object.hashCode].
+ *
+ * If [isValidKey] is omitted, it defaults to testing if the object is an
+ * [E] instance.
+ *
+ * If [equals] is [identical], this creates an identity set. Any hashCode
+ * is compatible with [identical], and it applies to all objects, so
+ * [hashCode] and [isValidKey] can safely be omitted.
+ */
+ external factory HashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) });
+ /**
+ * Create a hash set containing the elements of [iterable].
+ *
+ * Creates a hash set as by `new HashSet<E>()` and adds each element of
+ * `iterable` to this set in the order they are iterated.
+ */
factory HashSet.from(Iterable<E> iterable) {
return new HashSet<E>()..addAll(iterable);
}
-
- // Iterable.
- external Iterator<E> get iterator;
-
- external int get length;
-
- external bool get isEmpty;
-
- external bool get isNotEmpty;
-
- external bool contains(Object object);
-
- // Set.
- external void add(E element);
-
- external void addAll(Iterable<E> objects);
-
- external bool remove(Object object);
-
- external void removeAll(Iterable<Object> objectsToRemove);
-
- external void removeWhere(bool test(E element));
-
- external void retainWhere(bool test(E element));
-
- external void clear();
-
- Set<E> _newSet() => new HashSet<E>();
}
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index 28b7ce2..d9aadf2 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -21,55 +21,13 @@
* Most simple operations on `HashSet` are done in constant time: [add],
* [contains], [remove], and [length].
*/
-class LinkedHashSet<E> extends _HashSetBase<E> {
+class LinkedHashSet<E> implements HashSet<E> {
- external LinkedHashSet();
+ external factory LinkedHashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) });
factory LinkedHashSet.from(Iterable<E> iterable) {
return new LinkedHashSet<E>()..addAll(iterable);
}
-
- // Iterable.
-
- /** Return an iterator that iterates over elements in insertion order. */
- external Iterator<E> get iterator;
-
- external int get length;
-
- external bool get isEmpty;
-
- external bool get isNotEmpty;
-
- external bool contains(Object object);
-
- /** Perform an operation on each element in insertion order. */
- external void forEach(void action(E element));
-
- external E get first;
-
- external E get last;
-
- E get single {
- if (length == 1) return first;
- var message = (length == 0) ? "No Elements" : "Too many elements";
- throw new StateError(message);
- }
-
- // Collection.
- external void add(E element);
-
- external void addAll(Iterable<E> objects);
-
- external bool remove(Object object);
-
- external void removeAll(Iterable objectsToRemove);
-
- external void removeWhere(bool test(E element));
-
- external void retainWhere(bool test(E element));
-
- external void clear();
-
- // Set.
- Set<E> _newSet() => new LinkedHashSet<E>();
}
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 3c27d04..d311785 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -192,7 +192,7 @@
* Removes all objects from this list;
* the length of the list becomes zero.
*
- * Throws an [UnsupportedError], and retains all objects, if this
+ * Throws an [UnsupportedError], and retains all objects, if this
* is a fixed-length list.
*/
void clear();
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 9c9eb23..8e4cf12 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -88,6 +88,10 @@
*/
Directory createTempSync();
+ Future<String> resolveSymbolicLinks();
+
+ String resolveSymbolicLinksSync();
+
/**
* Renames this directory. Returns a [:Future<Directory>:] that completes
* with a [Directory] instance for the renamed directory.
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index ae08c22..2e9df8e 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -156,14 +156,23 @@
/**
* Get the canonical full path corresponding to the file path.
* Returns a [:Future<String>:] that completes with the path.
+ *
+ * *FullPath is deprecated. Use absolutePath or resolveSymbolicLinks
+ * instead. FullPath will be removed the 23rd of September, 2013.*
*/
+ @deprecated
Future<String> fullPath();
/**
* Synchronously get the canonical full path corresponding to the file path.
*
* Throws a [FileException] if the operation fails.
+ *
+ * *FullPathSync is deprecated. Use absolutePathSync or
+ * resolveSymbolicLinksSync instead. FullPathSync will be removed
+ * the 23rd of September, 2013.*
*/
+ @deprecated
String fullPathSync();
/**
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 86acf77..1ec4b11 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -204,7 +204,7 @@
const int _DELETE_REQUEST = 2;
const int _RENAME_REQUEST = 3;
const int _OPEN_REQUEST = 4;
-const int _FULL_PATH_REQUEST = 5;
+const int _RESOLVE_SYMBOLIC_LINKS_REQUEST = 5;
const int _CLOSE_REQUEST = 6;
const int _POSITION_REQUEST = 7;
const int _SET_POSITION_REQUEST = 8;
@@ -446,28 +446,9 @@
return new _RandomAccessFile(id, "");
}
- Future<String> fullPath() {
- _ensureFileService();
- List request = new List(2);
- request[0] = _FULL_PATH_REQUEST;
- request[1] = path;
- return _fileService.call(request).then((response) {
- if (_isErrorResponse(response)) {
- throw _exceptionFromResponse(response,
- "Cannot retrieve full path",
- path);
- }
- return response;
- });
- }
+ Future<String> fullPath() => resolveSymbolicLinks();
- external static _fullPath(String path);
-
- String fullPathSync() {
- var result = _fullPath(path);
- throwIfError(result, "Cannot retrieve full path", path);
- return result;
- }
+ String fullPathSync() => resolveSymbolicLinksSync();
Stream<List<int>> openRead([int start, int end]) {
return new _FileStream(path, start, end);
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index ab2b7d3..10d632b 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -221,6 +221,68 @@
FileSystemEntity renameSync(String newPath);
/**
+ * Resolves the path of a file system object relative to the
+ * current working directory, resolving all symbolic links on
+ * the path and resolving all '..' and '.' path segments.
+ * [resolveSymbolicLinks] returns a [:Future<String>:]
+ *
+ * [resolveSymbolicLinks] uses the operating system's native filesystem api
+ * to resolve the path, using the realpath function on linux and
+ * Mac OS, and the GetFinalPathNameByHandle function on Windows.
+ * If the path does not point to an existing file system object,
+ * [resolveSymbolicLinks] completes the returned Future with an FileException.
+ *
+ * On Windows, symbolic links are resolved to their target before applying
+ * a '..' that follows, and on other platforms, the '..' is applied to the
+ * symbolic link without resolving it. The second behavior can be emulated
+ * on Windows by processing any '..' segments before calling
+ * [resolveSymbolicLinks]. One way of doing this is with the URI class:
+ * [:new Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();],
+ * since [resolve] removes '..' segments.
+ */
+ Future<String> resolveSymbolicLinks() {
+ // Get a new file service port for each request. We could also cache one.
+ var service = _FileUtils._newServicePort();
+ List request = new List(2);
+ request[0] = _RESOLVE_SYMBOLIC_LINKS_REQUEST;
+ request[1] = path;
+ return service.call(request).then((response) {
+ if (_isErrorResponse(response)) {
+ throw _exceptionFromResponse(response,
+ "Cannot resolve symbolic links",
+ path);
+ }
+ return response;
+ });
+ }
+
+ /**
+ * Resolves the path of a file system object relative to the
+ * current working directory, resolving all symbolic links on
+ * the path and resolving all '..' and '.' path segments.
+ *
+ * [resolveSymbolicLinksSync] uses the operating system's native
+ * filesystem api to resolve the path, using the realpath function
+ * on linux and Mac OS, and the GetFinalPathNameByHandle function on Windows.
+ * If the path does not point to an existing file system object,
+ * [resolveSymbolicLinksSync] throws a FileException.
+ *
+ * On Windows, symbolic links are resolved to their target before applying
+ * a '..' that follows, and on other platforms, the '..' is applied to the
+ * symbolic link without resolving it. The second behavior can be emulated
+ * on Windows by processing any '..' segments before calling
+ * [resolveSymbolicLinks]. One way of doing this is with the URI class:
+ * [:new Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();],
+ * since [resolve] removes '..' segments.
+ */
+ String resolveSymbolicLinksSync() {
+ var result = _resolveSymbolicLinks(path);
+ _throwIfError(result, "Cannot resolve symbolic links", path);
+ return result;
+ }
+
+
+ /**
* Calls the operating system's stat() function on the [path] of this
* [FileSystemEntity]. Identical to [:FileStat.stat(this.path):].
*
@@ -316,7 +378,7 @@
void _deleteSync({recursive: false});
/**
- * Synchronously checks whether two paths refer to the same object in the
+ * Checks whether two paths refer to the same object in the
* file system. Returns a [:Future<bool>:] that completes with the result.
*
* Comparing a link to its target returns false, as does comparing two links
@@ -481,6 +543,7 @@
external static _getType(String path, bool followLinks);
external static _identical(String path1, String path2);
+ external static _resolveSymbolicLinks(String path);
static int _getTypeSync(String path, bool followLinks) {
var result = _getType(path, followLinks);
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 474aa51..c889a70 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -65,6 +65,10 @@
*/
Future<Link> update(String target);
+ Future<String> resolveSymbolicLinks();
+
+ String resolveSymbolicLinksSync();
+
/**
* Renames this link. Returns a `Future<Link>` that completes
* with a [Link] instance for the renamed link.
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 313026f..f6fc7fa 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -748,32 +748,30 @@
Map<Symbol, MethodMirror> get constructors;
/**
- * An immutable map from names to mirrors for all type variables for
- * this type.
- * If this type is a generic declaration or an invocation of
- * a generic declaration, the returned map has the names of the formal
- * type parameters of the original declaration as its keys, and
- * each such key maps to a TypeVariableMirror on the corresponding
- * type variable. Otherwise, the returned map is empty.
+ * An immutable list with mirrors for all type variables for this type.
*
- * This map preserves the order of declaration of the type variables.
+ * If this type is a generic declaration or an invocation of a generic
+ * declaration, the returned list contains mirrors on the type variables.
+ * Otherwise, the returned list is empty.
+ *
+ * This list preserves the order of declaration of the type variables.
*/
- Map<Symbol, TypeVariableMirror> get typeVariables;
+ List<TypeVariableMirror> get typeVariables;
/**
- * An immutable map from names to mirrors for all type arguments for
- * this type. The keys of the map are the names of the
- * corresponding type variables.
+ * An immutable list with mirrors for all type arguments for
+ * this type.
*
* If the the reflectee is an invocation of a generic class,
* the type arguments are the bindings of its type parameters.
* If the reflectee is the original declaration of a generic,
- * it has no type arguments and this method returns an empty map.
+ * it has no type arguments and this method returns an empty list.
* If the reflectee is a not generic, then
- * it has no type arguments and this method returns an empty map.
- * This map preserves the order of declaration of the type variables.
+ * it has no type arguments and this method returns an empty list.
+ *
+ * This list preserves the order of declaration of the type variables.
*/
- Map<Symbol, TypeMirror> get typeArguments;
+ List<TypeMirror> get typeArguments;
/**
* Is this the original declaration of this type?
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 8befe3d..845974e 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -40,14 +40,11 @@
LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591
# co19 issue #380, Strings class has been removed
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail, OK
LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK
# co19 issue #400, collection library reorg
-LibTest/core/String/String_class_A01_t01: fail, OK
LibTest/core/String/concat_A01_t01: fail, OK
LibTest/core/String/concat_A02_t01: fail, OK
-LibTest/core/String/hashCode_A01_t01: fail, OK
LibTest/core/Set/isSubsetOf_A01_t01: fail, OK
LibTest/core/Set/isSubsetOf_A01_t02: fail, OK
@@ -64,20 +61,9 @@
Language/05_Variables/05_Variables_A13_t01: fail, OK
Language/07_Classes/07_Classes_A02_t11: fail, OK
-# co19 issue #464, not initialized final instance variable is warning, not error
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
-
# co19 issue #442, undefined name "Expect"
Language/15_Types/4_Interface_Types_A08_t03: fail, OK
-# co19 issue #448, Collection was removed
-LibTest/collection/Queue/Queue.from_A01_t01: fail, OK
-LibTest/collection/Queue/Queue.from_A01_t02: fail, OK
-LibTest/core/Set/intersection_A01_t02: fail, OK
-
-# co19 issue 452, more method in Iterable
-LibTest/core/Set/Set.from_A01_t02: fail, OK
-
# co19 issue #455, undeclared identifier is static warning
Language/12_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail, OK
Language/13_Statements/04_Local_Function_Declaration_A02_t02: fail, OK
@@ -131,120 +117,8 @@
Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail, OK
Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail, OK
-# co19 issue #565: not implemented members in non-abstract class
-LibTest/async/EventTransformStream/asBroadcastStream_A01_t02: fail, OK
-LibTest/async/Stream/asBroadcastStream_A01_t02: fail, OK
-LibTest/async/Stream/asBroadcastStream_A02_t01: fail, OK
-LibTest/async/Stream/isBroadcast_A01_t01: fail, OK
-LibTest/async/Stream/isBroadcast_A01_t02: fail, OK
+Language/07_Classes/1_Instance_Methods_A03_t06: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/4_Abstract_Instance_Members_A07_t08: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure
-# co19 issue #566: Undefined class 'T'
-LibTest/async/EventTransformStream/distinct_A01_t02: fail, OK
-LibTest/async/EventTransformStream/EventTransformStream_A01_t02: fail, OK
-LibTest/async/EventTransformStream/expand_A01_t01: fail, OK
-LibTest/async/Stream/contains_A03_t01: fail, OK
-LibTest/async/Stream/distinct_A01_t01: fail, OK
-LibTest/async/Stream/distinct_A01_t02: fail, OK
-LibTest/async/Stream/expand_A01_t01: fail, OK
-LibTest/core/List/List.filled_A01_t01: fail, OK
-LibTest/core/List/List.generate_A01_t01: fail, OK
-LibTest/core/List/List.generate_A01_t02: fail, OK
-LibTest/core/List/List.generate_A01_t03: fail, OK
-LibTest/core/List/replaceRange_A01_t01: fail, OK
-LibTest/core/List/replaceRange_A01_t02: fail, OK
-LibTest/core/List/skipWhile_A02_t01: fail, OK
-LibTest/core/List/takeWhile_A02_t01: fail, OK
-
-# co19 issue #567: Undefined name 'value'
-LibTest/async/EventTransformStream/drain_A02_t01: fail, OK
-LibTest/async/EventTransformStream/drain_A02_t02: fail, OK
-LibTest/async/Stream/drain_A02_t01: fail, OK
-LibTest/async/Stream/drain_A02_t02: fail, OK
-
-# co19 issue #568: Undefined name 'Expec'
-LibTest/async/EventTransformStream/first_A02_t01: fail, OK
-
-# co19 issue #569: There is no such getter 'message' in 'Object'
-LibTest/async/EventTransformStream/handleError_A03_t01: fail, OK
-LibTest/async/EventTransformStream/listen_A03_t01: fail, OK
-LibTest/async/Stream/handleError_A03_t01: fail, OK
-LibTest/async/Stream/listen_A03_t01: fail, OK
-
-# co19 issue #570: undefined name 'events1'
-LibTest/async/StreamController/hasListener_A01_t01: fail, OK
-LibTest/async/StreamController/hasListener_A01_t02: fail, OK
-LibTest/async/StreamController/isPaused_A01_t01: fail, OK
-LibTest/async/StreamController/isPaused_A01_t03: fail, OK
-
-# co19 issue #571: There is no such getter 'hasListener' in 'EventSink'
-LibTest/async/StreamController/sink_A01_t01: fail, OK
-
-# co19 issue #572: Undefined class 'boolean'; did you mean 'bool'?
-LibTest/async/StreamController/StreamController.broadcast_A04_t01: fail, OK
-LibTest/async/StreamIterator/cancel_A01_t01: fail, OK
-LibTest/core/List/map_A02_t01: fail, OK
-
-# co19 issue #573: There is no such operator '<' in 'Object'
-LibTest/async/StreamEventTransformer/handleData_A01_t01: fail, OK
-LibTest/async/StreamEventTransformer/handleDone_A01_t01: fail, OK
-LibTest/async/StreamEventTransformer/handleError_A01_t01: fail, OK
-
-# co19 issue #574: Abstract classes cannot be created with a 'new' expression
-LibTest/async/Stream/Stream_A01_t01: fail, OK
-
-# co19 issue #575: Error has not constructor parameters
-LibTest/async/Stream/Stream.fromFuture_A02_t01: fail, OK
-LibTest/async/Stream/Stream.fromFuture_A02_t02: fail, OK
-LibTest/async/Stream/Stream.fromIterable_A01_t02: fail, OK
-
-# co19 issue #576: The name 'timer' cannot be referenced in the initializer of a variable with the same name
-LibTest/async/Timer/cancel_A01_t01: fail, OK
-
-# co19 issue #577: The argument type 'int' cannot be assigned to the parameter type 'Duration'
-LibTest/core/DateTime/subtract_A02_t01: fail, OK
-
-# co19 issue #578: Undefined class 'long'
-LibTest/core/Duration/operator_div_A01_t01: fail, OK
-LibTest/core/Duration/operator_eq_A01_t01: fail, OK
-LibTest/core/Duration/operator_gt_A01_t01: fail, OK
-LibTest/core/Duration/operator_lt_A01_t01: fail, OK
-LibTest/core/Duration/operator_lte_A01_t01: fail, OK
-LibTest/core/Duration/operator_minus_A01_t01: fail, OK
-LibTest/core/Duration/operator_mult_A01_t01: fail, OK
-LibTest/core/Duration/operator_plus_A01_t01: fail, OK
-
-# co19 issue #579: The argument type 'bool' cannot be assigned to the parameter type '(String) -> bool'
-LibTest/core/List/every_A03_t01: fail, OK
-LibTest/core/List/forEach_A01_t02: fail, OK
-
-# co19 issue #580: Undefined name 'faled'
-LibTest/core/List/lastWhere_A03_t01: fail, OK
-
-# co19 issue #581: Undefined name 'Expect'
-LibTest/core/List/List_A01_t03: fail, OK
-LibTest/core/List/List.from_A01_t03: fail, OK
-LibTest/core/List/toList_A01_t03: fail, OK
-
-# co19 issue #582: The method 'addAll' is not defined for the class 'StringBuffer'
-LibTest/core/StringBuffer/writeAll_A03_t01: fail, OK
-
-# co19 issue #583: The method 'close' is not defined for the class 'SendPort'
-LibTest/isolate/isolate_api/streamSpawnFunction_A01_t01: fail, OK
-LibTest/isolate/IsolateSink/add_A01_t02: fail, OK
-LibTest/isolate/IsolateSink/operator_equality_A01_t01: fail, OK
-
-# co19 issue #584: Undefined name 'received
-LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: fail, OK
-
-# co19 issue #585: Undefined name 'messagesList'
-LibTest/isolate/IsolateSink/addError_A01_t01: fail, OK
-
-# co19 issue #586: Undefined name 'message'
-LibTest/isolate/IsolateSink/addError_A01_t02: fail, OK
-
-# co19 issue #587: Missing dart:async import and other mistypes
-LibTest/isolate/IsolateStream/any_A02_t01: fail, OK
-LibTest/isolate/IsolateStream/asBroadcastStream_A01_t01: fail, OK
-LibTest/isolate/IsolateStream/contains_A01_t01: fail, OK
-LibTest/isolate/IsolateStream/contains_A02_t01: fail, OK
-LibTest/isolate/IsolateStream/isBroadcast_A01_t02: fail, OK
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index cdcaa67..8a26565 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -33,14 +33,11 @@
LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591
# co19 issue #380, Strings class has been removed
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail, OK
LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK
# co19 issue #400, collection library reorg
-LibTest/core/String/String_class_A01_t01: fail, OK
LibTest/core/String/concat_A01_t01: fail, OK
LibTest/core/String/concat_A02_t01: fail, OK
-LibTest/core/String/hashCode_A01_t01: fail, OK
# co19 issue #424, Uninitialized finals are warnings not errors
Language/05_Variables/05_Variables_A07_t05: fail, OK
@@ -55,19 +52,9 @@
Language/05_Variables/05_Variables_A13_t01: fail, OK
Language/07_Classes/07_Classes_A02_t11: fail, OK
-# co19 issue #464, not initialized final instance variable is warning, not error
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
-
# co19 issue #442, undefined name "Expect"
Language/15_Types/4_Interface_Types_A08_t03: fail, OK
-# co19 issue #448, Collection was removed
-LibTest/collection/Queue/Queue.from_A01_t01: fail, OK
-LibTest/collection/Queue/Queue.from_A01_t02: fail, OK
-
-# co19 issue 452, more method in Iterable
-LibTest/core/Set/Set.from_A01_t02: fail, OK
-
# co19 issue #455, undeclared identifier is static warning
Language/12_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail, OK
Language/13_Statements/04_Local_Function_Declaration_A02_t02: fail, OK
@@ -100,6 +87,10 @@
# co19 issue #543: invocation of a non-function
Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A03_t02: fail, OK
+Language/07_Classes/1_Instance_Methods_A03_t06: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/4_Abstract_Instance_Members_A07_t08: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure
Language/13_Statements/11_Return_A07_t01: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/1_Imports_A03_t47: fail # co19-roll r546: Please triage this failure
@@ -109,78 +100,6 @@
Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r546: Please triage this failure
Language/15_Types/6_Type_dynamic_A03_t01: fail # co19-roll r546: Please triage this failure
Language/15_Types/6_Type_dynamic_A04_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/asBroadcastStream_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/distinct_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/drain_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/drain_A02_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/EventTransformStream_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/expand_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/first_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/handleError_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/EventTransformStream/listen_A03_t01: fail # co19-roll r546: Please triage this failure
LibTest/async/Future/asStream_A01_t02: pass # co19-roll r546: Please triage this failure
LibTest/async/Future/asStream_A02_t01: pass # co19-roll r546: Please triage this failure
LibTest/async/Future/whenComplete_A03_t01: pass # co19-roll r546: Please triage this failure
-LibTest/async/Stream/asBroadcastStream_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/asBroadcastStream_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/contains_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/hasListener_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/hasListener_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/isPaused_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/isPaused_A01_t03: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/sink_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamController/StreamController.broadcast_A04_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/distinct_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/distinct_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/drain_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/drain_A02_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamEventTransformer/handleData_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamEventTransformer/handleDone_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamEventTransformer/handleError_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/expand_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/handleError_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/isBroadcast_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/isBroadcast_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/StreamIterator/cancel_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/listen_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/Stream_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/Stream.fromFuture_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/Stream.fromFuture_A02_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/Stream/Stream.fromIterable_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/async/Timer/cancel_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/DateTime/subtract_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_div_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_eq_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_gt_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_lt_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_lte_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_minus_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_mult_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/Duration/operator_plus_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/every_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/forEach_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/lastWhere_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List_A01_t03: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List.filled_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List.from_A01_t03: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List.generate_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List.generate_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List.generate_A01_t03: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/map_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/replaceRange_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/replaceRange_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/skipWhile_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/takeWhile_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/toList_A01_t03: fail # co19-roll r546: Please triage this failure
-LibTest/core/StringBuffer/writeAll_A03_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/isolate_api/streamSpawnFunction_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: fail # co19-roll r576: Please triage this failure
-LibTest/isolate/IsolateSink/add_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/addError_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/addError_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/operator_equality_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/asBroadcastStream_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/contains_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/contains_A02_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateStream/isBroadcast_A01_t02: fail # co19-roll r546: Please triage this failure
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 5ded114..d2a26cd 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -10,12 +10,10 @@
[ $runtime == vm || $compiler == dart2dart || $compiler == dart2js ]
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure
LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591
-LibTest/core/Uri/encodeComponent_A01_t02: fail # Issue 13251, co19 Issues 588, 589
LibTest/core/Uri/toFilePath_A01_t01: pass, fail, ok # co19 Issue 592
-LibTest/core/Uri/Uri_A03_t01: fail # Issue 13250, co19 Issue 588
-LibTest/core/Uri/Uri.http_A02_t01: fail # Issue 13250, co19 Issue 588
-LibTest/core/Uri/Uri.https_A02_t01: fail # Issue 13250, co19 Issue 588
# Maybe we should wait until isolate library is sealed before triaging these.
LibTest/isolate/isolate_api/spawnFunction_A04_t01: fail, timeout # co19-roll r546: Please triage this failure
LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: fail, timeout # co19-roll r546: Please triage this failure
@@ -36,7 +34,6 @@
LibTest/math/exp_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/math/max_A01_t03: FAIL, OK # co19 issue 467
LibTest/math/min_A01_t03: FAIL, OK # co19 issue 467
-LibTest/math/pow_A01_t01: FAIL, OK # co19 issue 44
LibTest/math/sin_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/math/tan_A01_t01: PASS, FAIL, OK # co19 issue 44
@@ -96,18 +93,17 @@
LibTest/typed_data/Uint8List/removeAll_A01_t01: Fail # co19 issue 548
LibTest/typed_data/Uint8List/retainAll_A01_t01: Fail # co19 issue 548
-Language/12_Expressions/06_Lists_A08_t01: Fail # co19 issue 561
-LibTest/core/String/String_class_A01_t01: Fail # co19 issue 561
LibTest/core/String/concat_A01_t01: Fail # co19 issue 561
LibTest/core/String/concat_A02_t01: Fail # co19 issue 561
-LibTest/core/String/hashCode_A01_t01: Fail # co19 issue 561
-[ $compiler == dart2dart || $compiler == dart2js ]
-Language/14_Libraries_and_Scripts/1_Imports_A03_t49: Fail # co19 Issue 590
+[ $compiler != dartanalyzer ]
+# Dart2js/Dart2dart succeedes due to a bug in their parser (issue 13223).
+Language/12_Expressions/21_Bitwise_Expressions_A01_t01: Fail # co19 Issue 595
### CHECKED MODE FAILURES ###
[ ($runtime == vm || $compiler == dart2js) && $checked]
+Language/07_Classes/6_Constructors/2_Factories_A12_t02: fail # co19-roll r587: Please triage this failure
Language/13_Statements/09_Switch_A05_t01: FAIL, OK # co19 issue 498
Language/14_Libraries_and_Scripts/1_Imports_A03_t26: FAIL, OK # co19 issue 498
Language/14_Libraries_and_Scripts/1_Imports_A03_t46: PASS, FAIL, OK # co19 issue 560
@@ -123,4 +119,3 @@
LibTest/core/TypeError/line_A01_t01: FAIL, OK # co19 issue 510
LibTest/core/TypeError/srcType_A01_t01: FAIL, OK # co19 issue 510
LibTest/core/TypeError/url_A01_t01: FAIL, OK # co19 issue 510
-LibTest/core/Uri/encodeFull_A01_t02: fail # co19 Issue 589
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 369134f..4d70e82 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -24,15 +24,12 @@
Language/05_Variables/05_Variables_A01_t12: Fail # http://dartbug.com/5519
Language/05_Variables/05_Variables_A01_t13: Fail # http://dartbug.com/5519
Language/05_Variables/05_Variables_A01_t14: Fail # http://dartbug.com/5519
-Language/05_Variables/05_Variables_A07_t05: Fail # Inherited from dart2js
-Language/05_Variables/05_Variables_A07_t06: Fail # Inherited from dart2js
Language/05_Variables/05_Variables_A07_t07: Fail # Inherited from dart2js
Language/05_Variables/05_Variables_A07_t08: Fail # Inherited from dart2js
Language/05_Variables/05_Variables_A08_t01: Fail # Inherited from dart2js
Language/05_Variables/05_Variables_A08_t02: Fail # Inherited from dart2js
Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Inherited from VM (circular initialization?).
Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Inherited from dart2js
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t03: Fail # http://dartbug.com/5519
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t04: Fail # http://dartbug.com/5519
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: Fail # http://dartbug.com/5519
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: Fail # http://dartbug.com/5519
@@ -40,12 +37,6 @@
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A02_t02: Fail # http://dartbug.com/5519
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: Fail # inherited from VM
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t04: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t01: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t02: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t03: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t04: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t05: Fail # http://dartbug.com/5519
-Language/06_Functions/2_Formal_Parameters_A03_t06: Fail # http://dartbug.com/5519
Language/06_Functions/4_External_Functions_A01_t01: Fail # inherited from VM
Language/07_Classes/07_Classes_A02_t11: Fail # http://dartbug.com/5519
Language/07_Classes/3_Setters_A04_t01: Fail # inherited from VM
@@ -56,7 +47,6 @@
Language/07_Classes/3_Setters_A04_t06: Fail # inherited from VM
Language/07_Classes/3_Setters_A04_t07: Fail # inherited from VM
Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Fail # http://dartbug.com/5519
-Language/07_Classes/6_Constructors/2_Factories_A07_t01: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # inherited from VM
@@ -64,6 +54,7 @@
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: Fail # inherited from VM
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: Fail # inherited from VM
Language/07_Classes/6_Constructors_A02_t01: Fail # http://dartbug.com/5519
+Language/12_Expressions/07_Maps_A12_t03: Fail # http://dartbug.com/5519
LibTest/core/Match/operator_subscript_A01_t01: Fail # inherited from VM
LibTest/core/Match/operator_subscript_A01_t01: Fail, OK # co19 issue 294
LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # inherited from VM
@@ -88,7 +79,6 @@
LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail, OK # Problems with the test: encoded file name
LibTest/isolate/isolate_api/spawnUri_A01_t05: Fail, OK # Problems with the test: encoded file name
LibTest/math/exp_A01_t01: Fail # Issue co19 - 44
-LibTest/math/pow_A01_t01: Fail # Inherited from VM.
LibTest/math/sin_A01_t01: Fail # Inherited from VM.
LibTest/math/tan_A01_t01: Fail # Issue co19 - 44
@@ -125,8 +115,7 @@
Language/05_Variables/05_Variables_A06_t04: fail # co19-roll r546: Please triage this failure
Language/05_Variables/05_Variables_A06_t05: fail # co19-roll r546: Please triage this failure
Language/05_Variables/05_Variables_A06_t06: fail # co19-roll r546: Please triage this failure
-Language/07_Classes/07_Classes_A11_t01: fail # co19-roll r546: Please triage this failure
-Language/07_Classes/07_Classes_A11_t03: fail # co19-roll r546: Please triage this failure
+Language/07_Classes/1_Instance_Methods/2_Operators_A09_t01: fail # co19-roll r587: Please triage this failure
Language/07_Classes/1_Instance_Methods_A01_t01: Fail # co19-roll r559: Please triage this failure
Language/07_Classes/1_Instance_Methods_A01_t02: Fail # co19-roll r559: Please triage this failure
Language/07_Classes/1_Instance_Methods_A01_t03: Fail # co19-roll r559: Please triage this failure
@@ -138,7 +127,8 @@
Language/07_Classes/4_Abstract_Instance_Members_A03_t03: Fail # co19-roll r559: Please triage this failure
Language/07_Classes/4_Abstract_Instance_Members_A03_t04: Fail # co19-roll r559: Please triage this failure
Language/07_Classes/4_Abstract_Instance_Members_A03_t05: Fail # co19-roll r559: Please triage this failure
-Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t02: fail # co19-roll r546: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A10_t01: crash # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A10_t04: crash # co19-roll r587: Please triage this failure
Language/12_Expressions/01_Constants_A03_t02: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/01_Constants_A03_t03: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/01_Constants_A03_t04: fail # co19-roll r546: Please triage this failure
@@ -191,16 +181,9 @@
Language/12_Expressions/05_Strings_A20_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/06_Lists_A03_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/06_Lists_A03_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A01_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/07_Maps_A02_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/07_Maps_A02_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A08_t02: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/07_Maps_A12_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t04: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t05: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t06: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t07: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t03: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t05: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t06: fail # co19-roll r546: Please triage this failure
@@ -219,15 +202,9 @@
Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/22_Equality_A01_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/22_Equality_A01_t15: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/22_Equality_A01_t16: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/22_Equality_A01_t19: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/22_Equality_A01_t20: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/22_Equality_A05_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/23_Relational_Expressions_A01_t10: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/23_Relational_Expressions_A01_t11: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/23_Relational_Expressions_A01_t12: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/23_Relational_Expressions_A01_t13: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/27_Unary_Expressions_A01_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/30_Identifier_Reference_A02_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/30_Identifier_Reference_A04_t09: fail # co19-roll r546: Please triage this failure
@@ -254,20 +231,13 @@
Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/1_Imports_A03_t29: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/1_Imports_A03_t30: fail # co19-roll r546: Please triage this failure
-Language/14_Libraries_and_Scripts/1_Imports_A03_t49: fail # co19-roll r546: Please triage this failure
+Language/14_Libraries_and_Scripts/1_Imports_A03_t65: pass, fail, ok # co19 issue 560
Language/14_Libraries_and_Scripts/1_Imports_A04_t03: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/4_Scripts_A03_t01: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/4_Scripts_A03_t03: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/5_URIs_A01_t01: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/5_URIs_A01_t11: fail # co19-roll r546: Please triage this failure
Language/14_Libraries_and_Scripts/5_URIs_A01_t21: fail # co19-roll r546: Please triage this failure
-Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail # co19-roll r546: Please triage this failure
-Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r546: Please triage this failure
-Language/14_Libraries_and_Scripts/1_Imports_A03_t65: pass, fail, ok # co19 issue 560
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t01: fail # co19-roll r546: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t02: fail # co19-roll r546: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t03: fail # co19-roll r546: Please triage this failure
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t04: fail # co19-roll r546: Please triage this failure
Language/15_Types/4_Interface_Types_A11_t01: crash # co19-roll r546: Please triage this failure
Language/15_Types/4_Interface_Types_A11_t02: crash # co19-roll r546: Please triage this failure
Language/15_Types/5_Function_Types_A06_t01: fail # co19-roll r546: Please triage this failure
@@ -286,8 +256,12 @@
LibTest/isolate/SendPort/send_A02_t03: timeout # co19-roll r546: Please triage this failure
[ $compiler == dart2dart && $minified ]
-Language/13_Statements/11_Try_A06_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail # co19-roll r559: Please triage this failure
Language/12_Expressions/17_Getter_Invocation_A02_t01: fail # co19-roll r559: Please triage this failure
Language/12_Expressions/18_Assignment_A05_t02: fail # co19-roll r559: Please triage this failure
Language/12_Expressions/18_Assignment_A05_t04: fail # co19-roll r559: Please triage this failure
+Language/13_Statements/11_Try_A06_t01: fail # co19-roll r546: Please triage this failure
+LibTest/json/stringify_A02_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/stringify_A03_t02: fail # co19-roll r587: Please triage this failure
+
+
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 8f61e3a..b8db1bf 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -22,13 +22,11 @@
Language/03_Overview/1_Scoping_A02_t05: Fail # TODO(ahe): Please triage this failure.
Language/03_Overview/1_Scoping_A02_t06: Fail # TODO(ahe): Please triage this failure.
Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: fail # co19-roll r576: Please triage this failure
-Language/07_Classes/6_Constructors/2_Factories_A07_t01: Fail # TODO(ahe): Please triage this failure.
Language/13_Statements/11_Try_A07_t03: fail # co19-roll r576: Please triage this failure
LibTest/core/double/INFINITY_A01_t04: Fail # TODO(ahe): Please triage this failure.
LibTest/core/double/NEGATIVE_INFINITY_A01_t04: Fail # TODO(ahe): Please triage this failure.
LibTest/core/List/List_A03_t01: Fail # TODO(kasperl): Please triage this failure.
LibTest/core/List/sort_A01_t04: Pass, Slow # http://dartbug.com/11846
-LibTest/math/pow_A13_t01: FAIL, OK # co19 issue 507
LibTest/math/pow_A18_t01: FAIL, OK # co19 issue 507
LibTest/typed_data/ByteData/getFloat32_A02_t02: fail # co19-roll r569: Please triage this failure
@@ -80,14 +78,6 @@
LibTest/isolate/ReceivePort/receive_A01_t02: Fail # Issue 6750
-LibTest/typed_data/Float64List/Float64List.view_A01_t01: Fail, OK # Issue 12928
-LibTest/typed_data/Float32List/Float32List.view_A01_t01: Fail, OK # Issue 12928
-LibTest/typed_data/Uint16List/Uint16List.view_A01_t01: Fail, OK # Issue 12928
-LibTest/typed_data/Uint32List/Uint32List.view_A01_t01: Fail, OK # Issue 12928
-LibTest/typed_data/Int32List/Int32List.view_A01_t01: Fail, OK # Issue 12928
-LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t01: Fail, OK # Issue 12928
-
-
[ $compiler == dart2js && $runtime == ie9 ]
LibTest/async/Completer/completeError_A02_t01: Pass, Fail # Issue 8920
LibTest/async/Stream/listen_A04_t01: Pass, Timeout # Issue: 8920
@@ -280,6 +270,40 @@
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Expect.fail('Some exception expected')
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Expect.fail('Some exception expected')
+
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+LibTest/isolate/IsolateSink/add_A01_t02: Pass # TODO(kasperl): Please triage.
+LibTest/isolate/IsolateSink/operator_equality_A01_t01: Pass # TODO(kasperl): Please triage.
+
+Language/12_Expressions/05_Strings_A06_t01: Pass, Slow # TODO(kasperl): Please triage.
+LibTest/core/Set/removeAll_A01_t02: Pass, Slow # TODO(kasperl): Please triage.
+LibTest/typed_data/Float64List/join_A01_t01: Pass, Slow # TODO(kasperl): Please triage.
+LibTest/typed_data/Int8List/sublist_A02_t01: Pass, Slow # TODO(kasperl): Please triage.
+LibTest/typed_data/Int16List/single_A01_t02: Pass, Slow # TODO(kasperl): Please triage.
+LibTest/typed_data/Uint8ClampedList/map_A02_t01: Pass, Slow # TODO(kasperl): Please triage.
+
+LibTest/isolate/isolate_api/spawnUri_A01_t01: Timeout # TODO(kasperl): Please triage.
+LibTest/isolate/isolate_api/spawnUri_A01_t02: Timeout # TODO(kasperl): Please triage.
+LibTest/isolate/isolate_api/spawnUri_A01_t03: Timeout # TODO(kasperl): Please triage.
+LibTest/isolate/isolate_api/spawnUri_A01_t04: Timeout # TODO(kasperl): Please triage.
+LibTest/isolate/isolate_api/spawnUri_A01_t05: Timeout # TODO(kasperl): Please triage.
+
+LibTest/core/int/compareTo_A01_t01: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/operator_left_shift_A01_t01: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/operator_remainder_A01_t03: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/operator_truncating_division_A01_t02: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/remainder_A01_t01: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/remainder_A01_t03: Fail # TODO(kasperl): Please triage.
+LibTest/core/int/toRadixString_A01_t01: Fail # TODO(kasperl): Please triage.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail # TODO(kasperl): Please triage.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # TODO(kasperl): Please triage.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # TODO(kasperl): Please triage.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # TODO(kasperl): Please triage.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # TODO(kasperl): Please triage.
+LibTest/isolate/ReceivePort/toSendPort_A01_t02: Fail # TODO(kasperl): Please triage.
+LibTest/math/log_A01_t01: Fail # TODO(kasperl): Please triage.
+
+
[ $compiler == dart2js && ($runtime == ie10 || $runtime == ff || $runtime == chrome || $runtime == drt || $runtime == safari || $runtime == opera) ]
*: Skip
@@ -294,46 +318,22 @@
Language/05_Variables/05_Variables_A01_t12: Fail # Checks that variable declaration cannot contain both 'const' and 'var'.
Language/05_Variables/05_Variables_A01_t13: Fail # Checks that variable declaration cannot contain both 'const' and 'final'.
Language/05_Variables/05_Variables_A01_t14: Fail # Checks that variable declaration cannot contain 'const', 'final' and 'var' simultaneously.
-Language/05_Variables/05_Variables_A07_t05: Fail # Checks that a compile-time error occurs if a local constant variable is not initialized at declaration.
-Language/05_Variables/05_Variables_A07_t06: Fail # Checks that a compile-time error occurs if a local typed constant variable is not initialized at declaration.
Language/05_Variables/05_Variables_A07_t07: Fail # Checks that a compile-time error occurs if a global constant variable is not initialized at declaration.
Language/05_Variables/05_Variables_A07_t08: Fail # Checks that a compile-time error occurs if a global typed constant variable is not initialized at declaration.
Language/05_Variables/05_Variables_A08_t01: Fail # Checks that a compile-time error occurs if a constant variable is not initialized.
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t03: Fail # Checks that a required parameter can be constant. Reassigning it should produce a compile-time error.
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t04: Fail # Checks that static variable declaration can't be a required formal parameter
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: Fail # Checks that a functionSignature parameter cannot be final.
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: Fail # Checks that a functionSignature parameter cannot be declared as variable.
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: Fail # TODO(ahe): Enforce optional parameter semantics.
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t04: Fail # TODO(ahe): Enforce optional parameter semantics.
-Language/06_Functions/2_Formal_Parameters_A03_t01: Fail # Checks that it is a compile-time error if a required parameter is declared as a constant variable.
-Language/06_Functions/2_Formal_Parameters_A03_t02: Fail # Checks that it is a compile-time error if a required parameter is declared as a constant typed variable.
-Language/06_Functions/2_Formal_Parameters_A03_t03: Fail # TODO(ahe): Enforce optional parameter semantics.
-Language/06_Functions/2_Formal_Parameters_A03_t04: Fail # TODO(ahe): Enforce optional parameter semantics.
-Language/06_Functions/2_Formal_Parameters_A03_t05: Fail # Checks that it is a compile-time error if an optional named parameter is declared as a constant typed variable.
-Language/06_Functions/2_Formal_Parameters_A03_t05: Fail # Checks that it is a compile-time error if an optional positional parameter is declared as a constant variable.
-Language/06_Functions/2_Formal_Parameters_A03_t06: Fail # TODO(ahe): Enforce optional parameter semantics.
Language/07_Classes/07_Classes_A02_t11: Fail # Checks that it is a compile-time error if a static final variable declaration does not include explicit initializer.
-Language/07_Classes/07_Classes_A11_t01: Fail # Checks that a class name cannot be used as a name of a member variable.
-Language/07_Classes/07_Classes_A11_t03: Fail # Checks that a class name cannot be used as a name of a static variable.
Language/12_Expressions/01_Constants_A20_t03: Fail # Checks that an identifier expression that denotes a type parameter can not be assigned to a constant variable.
Language/12_Expressions/05_Strings/1_String_Interpolation_A01_t09: Fail # Checks that it is a compile-time error if a string interpolation construct does not start with IDENTIFIER_NO_DOLLAR or opening brace.
Language/12_Expressions/05_Strings_A02_t46: Fail # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors.
Language/12_Expressions/05_Strings_A02_t48: Fail # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors.
-Language/12_Expressions/22_Equality_A01_t15: Fail # Checks that equality expressions cannot be operands of another equality expression.
-Language/12_Expressions/22_Equality_A01_t16: Fail # Checks that equality expressions cannot be operands of another equality expression.
-Language/12_Expressions/23_Relational_Expressions_A01_t10: Fail # Checks that a relational expression cannot be the operand of another relational expression.
-Language/12_Expressions/23_Relational_Expressions_A01_t11: Fail # Checks that a relational expression cannot be the operand of another relational expression.
-Language/12_Expressions/23_Relational_Expressions_A01_t12: Fail # Checks that a relational expression cannot be the operand of another relational expression.
-Language/12_Expressions/23_Relational_Expressions_A01_t13: Fail # Checks that a relational expression cannot be the operand of another relational expression.
Language/12_Expressions/30_Identifier_Reference_A04_t09: Fail # Checks that it is a compile-time error when a built-in identifier dynamic is used as the declared name of a type variable.
Language/12_Expressions/30_Identifier_Reference_A05_t01: Fail # Checks that it is a compile-time error when a built-in identifier "abstract" is used as a type annotation of a local variable.
Language/12_Expressions/30_Identifier_Reference_A05_t12: Fail # Checks that it is a compile-time error when a built-in identifier "static" is used as a type annotation of a local variable.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t24: Fail # Checks that it is a compile-time error when the URI in a part directive consists of two adjacent string literals instead of one.
-Language/14_Libraries_and_Scripts/5_URIs_A01_t25: Fail # Checks that it is a compile-time error when the URI in a part directive consists of two adjacent multi-line string literals instead of one.
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t01: Fail # Checks that self-referencing typedef is not allowed (return value type annotation has the same name as the type alias).
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t02: Fail # Checks that self-referencing typedef is not allowed (positional formal parameter type annotation has the same name as the type alias).
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail # Checks that self-referencing typedef is not allowed (positional optional parameter type annotation has the same name as the type alias).
-Language/15_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # Checks that self-referencing typedef is not allowed (named optional parameter type annotation has the same name as the type alias).
Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: Fail # Checks that other Unicode whitespaces are not allowed: check NO-BREAK SPACE (U+00A0)
Language/16_Reference/1_Lexical_Rules_A02_t06: Fail # Checks that Unicode whitespaces other than WHITESPACE are not permitted in the source code. Checks symbol U+00a0.
@@ -436,21 +436,12 @@
Language/07_Classes/4_Abstract_Instance_Members_A03_t04: fail # co19-roll r559: Please triage this failure
Language/07_Classes/4_Abstract_Instance_Members_A03_t05: fail # co19-roll r559: Please triage this failure
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A02_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t02: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A06_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A06_t02: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/01_Constants_A03_t01: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/03_Numbers_A01_t06: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/03_Numbers_A01_t09: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/05_Strings_A20_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A01_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A08_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t02: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t04: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t05: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t06: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/07_Maps_A12_t07: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t03: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t05: fail # co19-roll r546: Please triage this failure
Language/12_Expressions/12_Instance_Creation/1_New_A02_t06: fail # co19-roll r546: Please triage this failure
@@ -503,27 +494,20 @@
LibTest/isolate/isolate_api/spawnFunction_A04_t03: fail # co19-roll r546: Please triage this failure
LibTest/isolate/isolate_api/spawnUri_A02_t02: fail # co19-roll r546: Please triage this failure
LibTest/isolate/isolate_api/spawnUri_A02_t03: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/isolate_api/streamSpawnFunction_A01_t01: fail # co19-roll r546: Please triage this failure
LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: fail # co19-roll r546: Please triage this failure
LibTest/isolate/IsolateSink/add_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/add_A01_t02: fail # co19-roll r546: Please triage this failure
LibTest/isolate/IsolateSink/addError_A01_t01: fail # co19-roll r546: Please triage this failure
LibTest/isolate/IsolateSink/addError_A01_t02: fail # co19-roll r546: Please triage this failure
-LibTest/isolate/IsolateSink/operator_equality_A01_t01: fail # co19-roll r546: Please triage this failure
LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
LibTest/isolate/IsolateStream/contains_A02_t01: fail # co19-roll r546: Please triage this failure
LibTest/isolate/SendPort/send_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/typed_data/Float32List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Float32List/Float32List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Float32List/Float32List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/Float32List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/Float32List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/fold_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/join_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/join_A01_t02: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Float32List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
LibTest/typed_data/Float32x4/clamp_A01_t01: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Float32x4List/Float32x4List.view_A02_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32x4List/Float32x4List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32x4List/Float32x4List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
@@ -531,39 +515,24 @@
LibTest/typed_data/Float32x4List/fold_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32x4List/join_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32x4List/join_A01_t02: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Float64List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Float64List/Float64List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Float64List/Float64List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/Float64List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/Float64List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/fold_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/join_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/join_A01_t02: fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Float64List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Int16List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Int16List/Int16List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Int16List/Int16List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int16List/Int16List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int16List/Int16List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Int16List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Int32List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Int32List/Int32List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Int32List/Int32List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int32List/Int32List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int32List/Int32List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Int32List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
LibTest/typed_data/Int8List/Int8List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int8List/Int8List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int8List/Int8List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Uint16List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Uint16List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Uint16List/Uint16List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Uint16List/Uint16List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint16List/Uint16List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint16List/Uint16List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
-LibTest/typed_data/Uint32List/buffer_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Uint32List/offsetInBytes_A01_t01: Fail, Ok # co19 issue: 549
-LibTest/typed_data/Uint32List/Uint32List.view_A01_t02: Fail, Ok # co19 issue: 549
LibTest/typed_data/Uint32List/Uint32List.view_A05_t01: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint32List/Uint32List.view_A05_t02: Fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint32List/Uint32List.view_A05_t03: Fail # co19-roll r559: Please triage this failure
@@ -595,14 +564,18 @@
LibTest/typed_data/Float32x4List/reduce_A01_t01: Fail # co19-roll r559: Please triage this failure
[ $compiler == dart2js && $runtime == jsshell ]
+LibTest/typed_data/Float32List/Float32List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Float32List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float32List/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
+LibTest/typed_data/Float64List/Float64List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Float64List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Float64List/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
LibTest/typed_data/Int16List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
+LibTest/typed_data/Int16List/Int16List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Int16List/toList_A01_t01: pass, fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int16List/toList_A01_t01: timeout # co19-roll r559: Please triage this failure
LibTest/typed_data/Int32List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
+LibTest/typed_data/Int32List/Int32List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Int32List/toList_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Int32List/toList_A01_t01: pass, timeout # co19-roll r559: Please triage this failure
LibTest/typed_data/Int8List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
@@ -610,8 +583,10 @@
LibTest/typed_data/Uint16List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint16List/toList_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint16List/toList_A01_t01: timeout # co19-roll r559: Please triage this failure
+LibTest/typed_data/Uint16List/Uint16List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Uint32List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint32List/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
+LibTest/typed_data/Uint32List/Uint32List.view_A06_t01: fail # co19-roll r587: Please triage this failure
LibTest/typed_data/Uint8ClampedList/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint8ClampedList/toList_A01_t01: fail, timeout # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint8List/hashCode_A01_t01: fail # co19-roll r559: Please triage this failure
@@ -629,6 +604,8 @@
LibTest/async/Stream/Stream.periodic_A02_t01: fail # co19-roll r546: Please triage this failure
LibTest/async/Timer/cancel_A01_t01: fail # co19-roll r546: Please triage this failure
LibTest/async/Timer/Timer_A01_t01: fail # co19-roll r546: Please triage this failure
+LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t02: fail # co19-roll r587: Please triage this failure
+LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: fail # co19-roll r587: Please triage this failure
[ $compiler == dart2js && $minified ]
Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail # co19-roll r559: Please triage this failure
@@ -651,8 +628,31 @@
LibTest/typed_data/Uint8List/runtimeType_A01_t01: fail # co19-roll r559: Please triage this failure
[ $compiler == dart2js || $compiler == dart2dart ]
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t08: fail # co19-roll r569: Please triage this failure
-LibTest/core/NoSuchMethodError/NoSuchMethodError_A01_t01: fail # co19-roll r576: Please triage this failure
-LibTest/core/Uri/Uri_A06_t02: fail # co19-roll r576: Please triage this failure
-LibTest/core/Uri/Uri_A06_t03: fail # co19-roll r576: Please triage this failure
+Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t08: fail # co19-roll r587: Please triage this failure
+Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t09: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/1_Instance_Methods_A03_t06: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/1_Instance_Methods_A07_t01: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A08_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A09_t01: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A09_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A10_t02: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/2_Factories_A10_t03: fail # co19-roll r587: Please triage this failure
+Language/10_Generics/09_Generics_A01_t17: fail # co19-roll r587: Please triage this failure
+LibTest/json/parse_A01_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/parse_A02_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A01_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A02_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A03_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A03_t02: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A03_t03: fail # co19-roll r587: Please triage this failure
+LibTest/json/printOn_A04_t01: fail # co19-roll r587: Please triage this failure
+
+[ $compiler == dart2js ]
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: fail # co19-roll r587: Please triage this failure
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: fail # co19-roll r587: Please triage this failure
+LibTest/json/stringify_A01_t01: fail # co19-roll r587: Please triage this failure
+LibTest/json/stringify_A02_t01: fail # co19-roll r587: Please triage this failure
+LibTest/math/pow_A04_t01: fail # co19-roll r587: Please triage this failure
+LibTest/math/pow_A14_t01: fail # co19-roll r587: Please triage this failure
+LibTest/math/pow_A16_t01: fail # co19-roll r587: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index f160171..33966f7 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -5,40 +5,6 @@
[ $runtime == vm ]
Language/12_Expressions/01_Constants_A16_t04: fail # Issue 392
Language/12_Expressions/01_Constants_A16_t05: fail # Issue 392
-LibTest/typed_data/Float32List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Float32List/Float32List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Float32List/Float32List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Float32List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Float64List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Float64List/Float64List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Float64List/Float64List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Float64List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Int16List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Int16List/Int16List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Int16List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Int32List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Int32List/Int32List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Int32List/Int32List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Int32List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Int64List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Int64List/Int64List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Int64List/Int64List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Int64List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint16List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint16List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint16List/Uint16List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint16List/Uint16List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Uint32List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint32List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint32List/Uint32List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint32List/Uint32List.view_A01_t02: fail # Issue 549
-LibTest/typed_data/Uint64List/buffer_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint64List/offsetInBytes_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint64List/Uint64List.view_A01_t01: fail # Issue 549
-LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: fail # Issue 549
[ $runtime == vm && $system == windows ]
LibTest/core/Stopwatch/elapsed_A01_t01: Pass, Fail # Issue 11382.
@@ -90,10 +56,6 @@
LibTest/math/log_A01_t01: Fail
LibTest/core/double/toInt_A01_t01: Fail
-[ $compiler == none && $runtime == vm && $arch == arm ]
-LibTest/typed_data/Float32List/Float32List.view_A01_t02: Crash # Issue 12868
-LibTest/typed_data/Float64List/Float64List.view_A01_t02: Crash # Issue 12868
-
[ $compiler == none && $runtime == vm && ($arch == simarm || $arch == simmips) ]
LibTest/core/Uri/Uri_A06_t03: Pass, Timeout # co19-roll r576: Please triage this failure
@@ -155,6 +117,9 @@
LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail # VM triage, check spec.
LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail # VM triage, check spec.
+Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail # co19-roll r587: Please triage this failure
+Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail # co19-roll r587: Please triage this failure
+
[ $compiler == none && $runtime == vm && $checked ]
LibTest/typed_data/Float32x4List/elementAt_A01_t01: Fail # Dart issue 12861
@@ -184,7 +149,3 @@
Language/15_Types/4_Interface_Types_A11_t01: pass, timeout # Issue 13349
Language/15_Types/4_Interface_Types_A11_t02: pass, timeout # Issue 13349
-[ $compiler == none && $runtime == vm && $system == windows ]
-LibTest/core/Uri/toFilePath_A02_t01: fail # co19 Issue 594
-LibTest/core/Uri/Uri.file_A01_t01: fail # co19 Issue 594
-
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart
index 608ec55..355d2cf 100644
--- a/tests/compiler/dart2js/dart_backend_test.dart
+++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -63,6 +63,7 @@
const helperLib = r'''
library js_helper;
class JSInvocationMirror {}
+assertHelper(a) {}
''';
const foreignLib = r'''
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index 8ebdf7d..135b025 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -33,8 +33,9 @@
return super.readStringFromUri(resourceUri);
}
String source = memorySourceFiles[resourceUri.path];
- // TODO(ahe): Return new Future.error(...) ?
- if (source == null) return new Future.error('No such file $resourceUri');
+ if (source == null) {
+ return new Future.error(new Exception('No such file $resourceUri'));
+ }
String resourceName = '$resourceUri';
this.sourceFiles[resourceName] = new SourceFile(resourceName, source);
return new Future.value(source);
diff --git a/tests/compiler/dart2js/missing_file_test.dart b/tests/compiler/dart2js/missing_file_test.dart
index 349b61c..06b75dd 100644
--- a/tests/compiler/dart2js/missing_file_test.dart
+++ b/tests/compiler/dart2js/missing_file_test.dart
@@ -69,10 +69,10 @@
void main() {
runCompiler(Uri.parse('memory:main.dart'),
"Error: Can't read 'memory:foo.dart' "
- "(No such file memory:foo.dart).");
+ "(Exception: No such file memory:foo.dart).");
runCompiler(Uri.parse('memory:foo.dart'),
"Error: Can't read 'memory:foo.dart' "
- "(No such file memory:foo.dart).");
+ "(Exception: No such file memory:foo.dart).");
runCompiler(Uri.parse('dart:foo'),
'Error: Library not found "dart:foo".');
}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 0a6bfc2..5fb2d85 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -253,7 +253,7 @@
libraryLoader.importLibrary(interceptorsLibrary, coreLibrary, null);
libraryLoader.importLibrary(isolateHelperLibrary, coreLibrary, null);
- assertMethod = jsHelperLibrary.find(buildSourceString('assert'));
+ assertMethod = jsHelperLibrary.find(buildSourceString('assertHelper'));
identicalFunction = coreLibrary.find(buildSourceString('identical'));
mainApp = mockLibrary(this, "");
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index ef06d96..a8093aa 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -5,6 +5,7 @@
import 'package:expect/expect.dart';
import "package:async_helper/async_helper.dart";
import 'compiler_helper.dart';
+import 'parser_helper.dart' show buildSourceString;
const String TEST = """
returnInt1() {
@@ -82,6 +83,23 @@
return a;
}
+returnIntOrNull() {
+ for (var b in [42]) {
+ var bar = 42;
+ f() => bar;
+ bar = null;
+ return f();
+ }
+ return 42;
+}
+
+class A {
+ foo() {
+ f() => this;
+ return f();
+ }
+}
+
main() {
returnInt1();
returnDyn1();
@@ -91,6 +109,8 @@
returnDyn3();
returnInt4();
returnNum1();
+ returnIntOrNull();
+ new A().foo();
}
""";
@@ -111,10 +131,20 @@
checkReturn('returnInt2', compiler.typesTask.intType);
checkReturn('returnInt3', compiler.typesTask.intType);
checkReturn('returnInt4', compiler.typesTask.intType);
+ checkReturn('returnIntOrNull', compiler.typesTask.intType.nullable());
checkReturn('returnDyn1', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnDyn2', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnDyn3', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnNum1', compiler.typesTask.numType);
+
+ checkReturnInClass(String className, String methodName, type) {
+ var cls = findElement(compiler, className);
+ var element = cls.lookupLocalMember(buildSourceString(methodName));
+ Expect.equals(type,
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
+ }
+ var cls = findElement(compiler, 'A');
+ checkReturnInClass('A', 'foo', new TypeMask.nonNullExact(cls.rawType));
}));
}
diff --git a/tests/compiler/dart2js/unparser_test.dart b/tests/compiler/dart2js/unparser_test.dart
index 38e9bdb..c00d6e2 100644
--- a/tests/compiler/dart2js/unparser_test.dart
+++ b/tests/compiler/dart2js/unparser_test.dart
@@ -29,13 +29,8 @@
}
testSignedConstants() {
- testUnparse('var x=+42;');
- testUnparse('var x=+.42;');
testUnparse('var x=-42;');
testUnparse('var x=-.42;');
- testUnparse('var x=+0;');
- testUnparse('var x=+0.0;');
- testUnparse('var x=+.0;');
testUnparse('var x=-0;');
testUnparse('var x=-0.0;');
testUnparse('var x=-.0;');
@@ -342,7 +337,7 @@
}
testSymbolLiterals() {
- testUnparse("#+;");
+ testUnparse("#+;");
testUnparse("#-;");
testUnparse("#*;");
testUnparse("#/;");
@@ -356,7 +351,7 @@
testUnparse("#&;");
testUnparse("#|;");
testUnparse("#^;");
-
+
testUnparse("#a;");
testUnparse("#a.b;");
testUnparse("#a.b.c;");
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 31e3827..4e065b9 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -22,6 +22,9 @@
class_test: Fail
deferred/*: Skip # http://dartbug.com/12635
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+no_such_method_mirrors_test: Pass, Slow # TODO(kasperl): Please triage.
+
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index e46b59f..e58bc11 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -53,6 +53,9 @@
string_base_vm_test: Fail # BUG(3304): Maybe this doesn't time out?
list_test: Fail # IE doesn't support typed data.
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+list_as_map_test: Pass, Slow # TODO(kasperl): Please triage.
+
[ $compiler == dart2js && ($runtime == firefox || $runtime == safari || $runtime == chrome || $runtime == drt) ]
[ $compiler == dart2dart ]
diff --git a/tests/corelib/hash_set_test.dart b/tests/corelib/hash_set_test.dart
index ee4bd16..175cba5 100644
--- a/tests/corelib/hash_set_test.dart
+++ b/tests/corelib/hash_set_test.dart
@@ -10,6 +10,7 @@
import 'dart:collection';
testSet(Set newSet(), Set newSetFrom(Set from)) {
+
Set gen(int from, int to) =>
new Set.from(new Iterable.generate(to - from, (n) => n + from));
@@ -22,6 +23,7 @@
for (int i = 0; i < 256; i++) {
set.add(i);
}
+
set.addAll(gen(256, 512));
set.addAll(newSetFrom(gen(512, 1000)));
Expect.equals(1000, set.length);
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart
index a700027..7e9d50d 100644
--- a/tests/corelib/map_test.dart
+++ b/tests/corelib/map_test.dart
@@ -456,8 +456,24 @@
void testLength(int length, Map map) {
Expect.equals(length, map.length);
- (length == 0 ? Expect.isTrue : Expect.isFalse)(map.isEmpty);
- (length != 0 ? Expect.isTrue : Expect.isFalse)(map.isNotEmpty);
+ Expect.equals(length, map.keys.length);
+ Expect.equals(length, map.values.length);
+ // Check being-empty.
+ var ifEmpty = (length == 0) ? Expect.isTrue : Expect.isFalse;
+ var ifNotEmpty = (length != 0) ? Expect.isTrue : Expect.isFalse;
+ ifEmpty(map.isEmpty);
+ ifNotEmpty(map.isNotEmpty);
+ ifEmpty(map.keys.isEmpty);
+ ifNotEmpty(map.keys.isNotEmpty);
+ ifEmpty(map.values.isEmpty);
+ ifNotEmpty(map.values.isNotEmpty);
+ // Test key/value iterators match their isEmpty/isNotEmpty.
+ ifNotEmpty(map.keys.iterator.moveNext());
+ ifNotEmpty(map.values.iterator.moveNext());
+ if (length == 0) {
+ for (var k in map.keys) Expect.fail("contains key when iterating: $k");
+ for (var v in map.values) Expect.fail("contains values when iterating: $v");
+ }
}
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index f085835..b0246f0 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -9,7 +9,13 @@
import "dart:collection";
void testMain(Set create()) {
+ testInts(create);
+ testStrings(create);
+}
+
+void testInts(Set create()) {
Set set = create();
+
testLength(0, set);
set.add(1);
testLength(1, set);
@@ -186,9 +192,145 @@
Expect.equals(length, set.length);
(length == 0 ? Expect.isTrue : Expect.isFalse)(set.isEmpty);
(length != 0 ? Expect.isTrue : Expect.isFalse)(set.isNotEmpty);
+ if (length == 0) {
+ for (var e in set) { Expect.fail("contains element when iterated: $e"); }
+ }
+ (length == 0 ? Expect.isFalse : Expect.isTrue)(set.iterator.moveNext());
}
+void testStrings(Set create()) {
+ var set = create();
+ var strings = ["foo", "bar", "baz", "qux", "fisk", "hest", "svin", "pigvar"];
+ set.addAll(strings);
+ testLength(8, set);
+ set.removeAll(strings.where((x) => x.length == 3));
+ testLength(4, set);
+ set.add("bar");
+ set.add("qux");
+ testLength(6, set);
+ set.addAll(strings);
+ testLength(8, set);
+ set.removeWhere((x) => x.length != 3);
+ testLength(4, set);
+ set.retainWhere((x) => x[1] == "a");
+ testLength(2, set);
+ Expect.isTrue(set.containsAll(["baz", "bar"]));
+
+ set = set.union(strings.where((x) => x.length != 3).toSet());
+ testLength(6, set);
+ set = set.intersection(["qux", "baz", "fisk", "egern"].toSet());
+ testLength(2, set);
+ Expect.isTrue(set.containsAll(["baz", "fisk"]));
+}
+
+void testTypeAnnotations(Set<int> set) {
+ set.add(0);
+ set.add(999);
+ set.add(0x800000000);
+ set.add(0x20000000000000);
+ Expect.isFalse(set.contains("not an it"));
+ Expect.isFalse(set.remove("not an it"));
+ Expect.isFalse(set.containsAll(["Not an int", "Also no an int"]));
+
+ testLength(4, set);
+ set.removeAll(["Not an int", 999, "Also no an int"]);
+ testLength(3, set);
+ set.retainAll(["Not an int", 0, "Also no an int"]);
+ testLength(1, set);
+}
+
+void testRetainWhere(Set create([equals, hashCode, validKey])) {
+ // The retainWhere method must not collapse the argument Iterable
+ // in a way that doesn't match the equality of the set.
+ // It must not throw away equal elements that are different in the
+ // equality of the set.
+ // It must not consider objects to be not there if they are equal
+ // in the equality of the set.
+
+ // If set equality is natural equality, using different but equal objects
+ // must work. Can't use an identity set internally (as was done at some point
+ // during development).
+ Set set = create();
+ set.addAll([new EO(0), new EO(1), new EO(2)]);
+ Expect.equals(3, set.length); // All different.
+ set.retainAll([new EO(0), new EO(2)]);
+ Expect.equals(2, set.length);
+ Expect.isTrue(set.contains(new EO(0)));
+ Expect.isTrue(set.contains(new EO(2)));
+
+ // If equality of set is identity, we can't internally use a non-identity
+ // based set because it might throw away equal objects that are not identical.
+ var elems = [new EO(0), new EO(1), new EO(2), new EO(0)];
+ set = create(identical);
+ set.addAll(elems);
+ Expect.equals(4, set.length);
+ set.retainAll([elems[0], elems[2], elems[3]]);
+ Expect.equals(3, set.length);
+ Expect.isTrue(set.contains(elems[0]));
+ Expect.isTrue(set.contains(elems[2]));
+ Expect.isTrue(set.contains(elems[3]));
+
+ // If set equality is less precise than equality, we must not use equality
+ // internally to see if the element is there:
+ set = create(customEq(3), customHash(3), validKey);
+ set.addAll([new EO(0), new EO(1), new EO(2)]);
+ Expect.equals(3, set.length);
+ set.retainAll([new EO(3), new EO(5)]);
+ Expect.equals(2, set.length);
+ Expect.isTrue(set.contains(new EO(6)));
+ Expect.isTrue(set.contains(new EO(8)));
+
+ // It shouldn't matter if the input is a set.
+ set.clear();
+ set.addAll([new EO(0), new EO(1), new EO(2)]);
+ Expect.equals(3, set.length);
+ set.retainAll(new Set.from([new EO(3), new EO(5)]));
+ Expect.equals(2, set.length);
+ Expect.isTrue(set.contains(new EO(6)));
+ Expect.isTrue(set.contains(new EO(8)));
+}
+
+// Objects that are equal based on data.
+class EO {
+ final int id;
+ const EO(this.id);
+ int get hashCode => id;
+ bool operator==(Object other) => other is EO && id == (other as EO).id;
+}
+
+// Equality of Id objects based on id modulo value.
+Function customEq(int mod) => (EO e1, EO e2) => ((e1.id - e2.id) % mod) == 0;
+Function customHash(int mod) => (EO e) => e.id % mod;
+bool validKey(Object o) => o is EO;
+
+
main() {
- testMain(() => new Set());
testMain(() => new HashSet());
+ testMain(() => new LinkedHashSet());
+ testMain(() => new HashSet(equals: identical));
+ testMain(() => new LinkedHashSet(equals: identical));
+ testMain(() => new HashSet(equals: (a, b) => a == b,
+ hashCode: (a) => -a.hashCode,
+ isValidKey: (a) => true));
+ testMain(() => new LinkedHashSet(
+ equals: (a, b) => a == b,
+ hashCode: (a) => -a.hashCode,
+ isValidKey: (a) => true));
+
+ testTypeAnnotations(new HashSet<int>());
+ testTypeAnnotations(new LinkedHashSet<int>());
+ testTypeAnnotations(new HashSet<int>(equals: identical));
+ testTypeAnnotations(new LinkedHashSet<int>(equals: identical));
+ testTypeAnnotations(new HashSet<int>(equals: (int a, int b) => a == b,
+ hashCode: (int a) => a.hashCode,
+ isValidKey: (a) => a is int));
+ testTypeAnnotations(new LinkedHashSet<int>(equals: (int a, int b) => a == b,
+ hashCode: (int a) => a.hashCode,
+ isValidKey: (a) => a is int));
+
+ testRetainWhere(([equals, hashCode, validKey]) =>
+ new HashSet(equals: equals, hashCode: hashCode, isValidKey: validKey));
+ testRetainWhere(([equals, hashCode, validKey]) =>
+ new LinkedHashSet(equals: equals, hashCode: hashCode,
+ isValidKey: validKey));
}
diff --git a/tests/html/html.status b/tests/html/html.status
index ac55ad5..e27c033 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -33,6 +33,31 @@
[ $compiler == none && $runtime == drt && $system == windows ]
worker_test/functional: Pass, Crash # Issue 9929.
+
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+crypto_test/functional: Pass, Slow # TODO(kasperl): Please triage.
+input_element_test/supported_datetime-local: Pass, Slow # TODO(kasperl): Please triage.
+
+fileapi_test/entry: Fail, Pass # TODO(kasperl): Please triage.
+fileapi_test/fileEntry: Fail, Pass # TODO(kasperl): Please triage.
+fileapi_test/getDirectory: Fail, Pass # TODO(kasperl): Please triage.
+fileapi_test/getFile: Fail, Pass # TODO(kasperl): Please triage.
+
+audiobuffersourcenode_test/supported: Fail # TODO(kasperl): Please triage.
+canvasrenderingcontext2d_test/drawImage_video_element: Fail # TODO(kasperl): Please triage.
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # TODO(kasperl): Please triage.
+dromaeo_smoke_test: Fail # TODO(kasperl): Please triage.
+element_types_test/supported_datalist: Fail # TODO(kasperl): Please triage.
+fileapi_test/directoryReader: Fail # TODO(kasperl): Please triage.
+input_element_test/supported_week: Fail # TODO(kasperl): Please triage.
+media_stream_test/supported_media: Fail # TODO(kasperl): Please triage.
+notifications_test/supported: Fail # TODO(kasperl): Please triage.
+rtc_test/supported: Fail # TODO(kasperl): Please triage.
+speechrecognition_test/supported: Fail # TODO(kasperl): Please triage.
+speechrecognition_test/types: Fail # TODO(kasperl): Please triage.
+xhr_test/json: Fail # TODO(kasperl): Please triage.
+
+
[ $compiler == dart2js && $runtime == ie10 ]
async_test: Pass, Fail # timers test fails on ie10.
indexeddb_5_test: Fail # Issue 12893
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index d96a036..a3a9274 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -78,6 +78,12 @@
isolate2_negative_test: Fail # Issue 12628
illegal_msg_test: Pass # Issue 12628
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+isolate_stress_test: Pass, Slow # TODO(kasperl): Please triage.
+mandel_isolate_stream_test: Pass, Slow # TODO(kasperl): Please triage.
+
+mandel_isolate_test: Pass, Timeout # TODO(kasperl): Please triage.
+
[ $compiler == dart2dart ]
*: Skip # Issue 12629
diff --git a/tests/language/bit_operations_test.dart b/tests/language/bit_operations_test.dart
index dc548d1..6c7b106 100644
--- a/tests/language/bit_operations_test.dart
+++ b/tests/language/bit_operations_test.dart
@@ -6,174 +6,190 @@
import "package:expect/expect.dart";
-class BitOperationsTest {
- static testMain() {
- for (int i = 0; i < 4; i++) {
- testOne();
- }
+void main() {
+ for (int i = 0; i < 4; i++) {
+ test();
}
- static testOne() {
- Expect.equals(3, (3 & 7));
- Expect.equals(7, (3 | 7));
- Expect.equals(4, (3 ^ 7));
- Expect.equals(25, (100 >> 2));
- Expect.equals(400, (100 << 2));
- Expect.equals(-25, (-100 >> 2));
- Expect.equals(-101, ~100);
- Expect.equals(0x10000000000000000, 1 << 64);
- Expect.equals(-0x10000000000000000, -1 << 64);
- Expect.equals(0x40000000, 0x04000000 << 4);
- Expect.equals(0x4000000000000000, 0x0400000000000000 << 4);
- Expect.equals(0, ~-1);
- Expect.equals(-1, ~0);
-
- Expect.equals(0, 1 >> 160);
- Expect.equals(-1, -1 >> 160);
-
- Expect.equals(0x100000000000000001,
- 0x100000000000000001 & 0x100000100F00000001);
- Expect.equals(0x1, 0x1 & 0x100000100F00000001);
- Expect.equals(0x1, 0x100000100F00000001 & 0x1);
-
- Expect.equals(0x100000100F00000001,
- 0x100000000000000001 | 0x100000100F00000001);
- Expect.equals(0x100000100F00000011, 0x11 | 0x100000100F00000001);
- Expect.equals(0x100000100F00000011, 0x100000100F00000001 | 0x11);
-
- Expect.equals(0x0F000F00000000000000,
- 0x0F00F00000000000001 ^ 0xFF00000000000000001);
- Expect.equals(0x31, 0xF00F00000000000001 ^ 0xF00F00000000000030);
- Expect.equals(0xF00F00000000000031, 0xF00F00000000000001 ^ 0x30);
- Expect.equals(0xF00F00000000000031, 0x30 ^ 0xF00F00000000000001);
-
- Expect.equals(0xF0000000000000000F, 0xF0000000000000000F7 >> 4);
- Expect.equals(15, 0xF00000000 >> 32);
- Expect.equals(1030792151040, 16492674416655 >> 4);
-
- Expect.equals(0xF0000000000000000F0, 0xF0000000000000000F << 4);
- Expect.equals(0xF00000000, 15 << 32);
-
- TestNegativeValueShifts();
- TestPositiveValueShifts();
- TestNoMaskingOfShiftCount();
- TestNegativeCountShifts();
- for (int i = 0; i < 20; i++) {
- TestCornerCasesRightShifts();
- TestRightShift64Bit();
- TestLeftShift64Bit();
- TestLeftShift64BitWithOverflow1();
- TestLeftShift64BitWithOverflow2();
- TestLeftShift64BitWithOverflow3();
- }
- }
-
- static void TestCornerCasesRightShifts() {
- var v32 = 0xFF000000;
- var v64 = 0xFF00000000000000;
- Expect.equals(0x3, v32 >> 0x1E);
- Expect.equals(0x1, v32 >> 0x1F);
- Expect.equals(0x0, v32 >> 0x20);
- Expect.equals(0x3, v64 >> 0x3E);
- Expect.equals(0x1, v64 >> 0x3F);
- Expect.equals(0x0, v64 >> 0x40);
- }
-
- static void TestRightShift64Bit() {
- var t = 0x1ffffffff;
- Expect.equals(0xffffffff, t >> 1);
- }
-
- static void TestLeftShift64Bit() {
- var t = 0xffffffff;
- Expect.equals(0xffffffff, t << 0);
- Expect.equals(0x1fffffffe, t << 1);
- Expect.equals(0x7fffffff80000000, t << 31);
- Expect.equals(0x10000000000000000, 2*(t+1) << 31);
- Expect.equals(0x20000000000000000, 4*(t+1) << 31);
- Expect.equals(0x8000000000000000, (t+1) << 31);
- }
-
- static void TestLeftShift64BitWithOverflow1() {
- var t = 0xffffffff;
- Expect.equals(0x10000000000000000, 2*(t+1) << 31);
- }
-
- static void TestLeftShift64BitWithOverflow2() {
- var t = 0xffffffff;
- Expect.equals(0x20000000000000000, 4*(t+1) << 31);
- }
-
- static void TestLeftShift64BitWithOverflow3() {
- var t = 0xffffffff;
- Expect.equals(0x8000000000000000, (t+1) << 31);
- }
-
- static void TestNegativeCountShifts() {
- bool throwOnLeft(a, b) {
- try {
- var x = a << b;
- return false;
- } catch (e) {
- return true;
- }
- }
-
- bool throwOnRight(a, b) {
- try {
- var x = a >> b;
- return false;
- } catch (e) {
- return true;
- }
- }
-
- Expect.isTrue(throwOnLeft(12, -3));
- Expect.isTrue(throwOnRight(12, -3));
- for (int i = 0; i < 20; i++) {
- Expect.isFalse(throwOnLeft(12, 3));
- Expect.isFalse(throwOnRight(12, 3));
- }
- }
-
- static void TestNegativeValueShifts() {
- for (int value = 0; value > -100; value--) {
- for (int i = 0; i < 300; i++) {
- int b = (value << i) >> i;
- Expect.equals(value, b);
- }
- }
- }
-
- static void TestPositiveValueShifts() {
- for (int value = 0; value < 100; value++) {
- for (int i = 0; i < 300; i++) {
- int b = (value << i) >> i;
- Expect.equals(value, b);
- }
- }
- }
-
- static void TestNoMaskingOfShiftCount() {
- // Shifts which would behave differently if shift count was masked into a
- // range.
- Expect.equals(0, 0 >> 256);
- Expect.equals(0, 1 >> 256);
- Expect.equals(0, 2 >> 256);
- Expect.equals(0, ShiftRight(0, 256));
- Expect.equals(0, ShiftRight(1, 256));
- Expect.equals(0, ShiftRight(2, 256));
-
- for (int shift = 1; shift <= 256; shift++) {
- Expect.equals(0, ShiftRight(1, shift));
- Expect.equals(-1, ShiftRight(-1, shift));
- Expect.equals(true, ShiftLeft(1, shift) > ShiftLeft(1, shift - 1));
- }
- }
-
- static int ShiftLeft(int a, int b) { return a << b; }
- static int ShiftRight(int a, int b) { return a >> b; }
}
-main() {
- BitOperationsTest.testMain();
+void test() {
+ Expect.equals(3, (3 & 7));
+ Expect.equals(7, (3 | 7));
+ Expect.equals(4, (3 ^ 7));
+ Expect.equals(25, (100 >> 2));
+ Expect.equals(400, (100 << 2));
+ Expect.equals(-25, (-100 >> 2));
+ Expect.equals(-101, ~100);
+ Expect.equals(0x10000000000000000, 1 << 64);
+ Expect.equals(-0x10000000000000000, -1 << 64);
+ Expect.equals(0x40000000, 0x04000000 << 4);
+ Expect.equals(0x4000000000000000, 0x0400000000000000 << 4);
+ Expect.equals(0, ~-1);
+ Expect.equals(-1, ~0);
+
+ Expect.equals(0, 1 >> 160);
+ Expect.equals(-1, -1 >> 160);
+
+ Expect.equals(0x100000000000000001,
+ 0x100000000000000001 & 0x100000100F00000001);
+ Expect.equals(0x1, 0x1 & 0x100000100F00000001);
+ Expect.equals(0x1, 0x100000100F00000001 & 0x1);
+
+ Expect.equals(0x100000100F00000001,
+ 0x100000000000000001 | 0x100000100F00000001);
+ Expect.equals(0x100000100F00000011, 0x11 | 0x100000100F00000001);
+ Expect.equals(0x100000100F00000011, 0x100000100F00000001 | 0x11);
+
+ Expect.equals(0x0F000F00000000000000,
+ 0x0F00F00000000000001 ^ 0xFF00000000000000001);
+ Expect.equals(0x31, 0xF00F00000000000001 ^ 0xF00F00000000000030);
+ Expect.equals(0xF00F00000000000031, 0xF00F00000000000001 ^ 0x30);
+ Expect.equals(0xF00F00000000000031, 0x30 ^ 0xF00F00000000000001);
+
+ Expect.equals(0xF0000000000000000F, 0xF0000000000000000F7 >> 4);
+ Expect.equals(15, 0xF00000000 >> 32);
+ Expect.equals(1030792151040, 16492674416655 >> 4);
+
+ Expect.equals(0xF0000000000000000F0, 0xF0000000000000000F << 4);
+ Expect.equals(0xF00000000, 15 << 32);
+
+ testNegativeValueShifts();
+ testPositiveValueShifts();
+ testNoMaskingOfShiftCount();
+ testNegativeCountShifts();
+ for (int i = 0; i < 20; i++) {
+ testCornerCasesRightShifts();
+ testRightShift64Bit();
+ testLeftShift64Bit();
+ testLeftShift64BitWithOverflow1();
+ testLeftShift64BitWithOverflow2();
+ testLeftShift64BitWithOverflow3();
+ }
+
+ // Test precedence.
+ testPrecedence(4,5,3,1);
+ testPrecedence(3,4,5,9);
+ testPrecedence(0x5c71, 0x6b92, 0x7654, 0x7d28);
+}
+
+void testCornerCasesRightShifts() {
+ var v32 = 0xFF000000;
+ var v64 = 0xFF00000000000000;
+ Expect.equals(0x3, v32 >> 0x1E);
+ Expect.equals(0x1, v32 >> 0x1F);
+ Expect.equals(0x0, v32 >> 0x20);
+ Expect.equals(0x3, v64 >> 0x3E);
+ Expect.equals(0x1, v64 >> 0x3F);
+ Expect.equals(0x0, v64 >> 0x40);
+}
+
+void testRightShift64Bit() {
+ var t = 0x1ffffffff;
+ Expect.equals(0xffffffff, t >> 1);
+}
+
+void testLeftShift64Bit() {
+ var t = 0xffffffff;
+ Expect.equals(0xffffffff, t << 0);
+ Expect.equals(0x1fffffffe, t << 1);
+ Expect.equals(0x7fffffff80000000, t << 31);
+ Expect.equals(0x10000000000000000, 2*(t+1) << 31);
+ Expect.equals(0x20000000000000000, 4*(t+1) << 31);
+ Expect.equals(0x8000000000000000, (t+1) << 31);
+}
+
+void testLeftShift64BitWithOverflow1() {
+ var t = 0xffffffff;
+ Expect.equals(0x10000000000000000, 2*(t+1) << 31);
+}
+
+void testLeftShift64BitWithOverflow2() {
+ var t = 0xffffffff;
+ Expect.equals(0x20000000000000000, 4*(t+1) << 31);
+}
+
+void testLeftShift64BitWithOverflow3() {
+ var t = 0xffffffff;
+ Expect.equals(0x8000000000000000, (t+1) << 31);
+}
+
+void testNegativeCountShifts() {
+ bool throwOnLeft(a, b) {
+ try {
+ var x = a << b;
+ return false;
+ } catch (e) {
+ return true;
+ }
+ }
+
+ bool throwOnRight(a, b) {
+ try {
+ var x = a >> b;
+ return false;
+ } catch (e) {
+ return true;
+ }
+ }
+
+ Expect.isTrue(throwOnLeft(12, -3));
+ Expect.isTrue(throwOnRight(12, -3));
+ for (int i = 0; i < 20; i++) {
+ Expect.isFalse(throwOnLeft(12, 3));
+ Expect.isFalse(throwOnRight(12, 3));
+ }
+}
+
+void testNegativeValueShifts() {
+ for (int value = 0; value > -100; value--) {
+ for (int i = 0; i < 300; i++) {
+ int b = (value << i) >> i;
+ Expect.equals(value, b);
+ }
+ }
+}
+
+void testPositiveValueShifts() {
+ for (int value = 0; value < 100; value++) {
+ for (int i = 0; i < 300; i++) {
+ int b = (value << i) >> i;
+ Expect.equals(value, b);
+ }
+ }
+}
+
+void testNoMaskingOfShiftCount() {
+ // Shifts which would behave differently if shift count was masked into a
+ // range.
+ Expect.equals(0, 0 >> 256);
+ Expect.equals(0, 1 >> 256);
+ Expect.equals(0, 2 >> 256);
+ Expect.equals(0, shiftRight(0, 256));
+ Expect.equals(0, shiftRight(1, 256));
+ Expect.equals(0, shiftRight(2, 256));
+
+ for (int shift = 1; shift <= 256; shift++) {
+ Expect.equals(0, shiftRight(1, shift));
+ Expect.equals(-1, shiftRight(-1, shift));
+ Expect.equals(true, shiftLeft(1, shift) > shiftLeft(1, shift - 1));
+ }
+}
+
+int shiftLeft(int a, int b) { return a << b; }
+int shiftRight(int a, int b) { return a >> b; }
+
+void testPrecedence(int a, int b, int c, int d) {
+ // & binds stronger than ^, which binds stronger than |.
+ int result = a & b ^ c | d & b ^ c;
+ Expect.equals(((a & b) ^ c) | ((d & b) ^ c), result); // &^|
+ Expect.notEquals((a & (b ^ c)) | (d & (b ^ c)), result); // ^&|
+ Expect.notEquals((a & b) ^ (c | (d & b)) ^ c, result); // &|^
+ Expect.notEquals((a & b) ^ ((c | d) & b) ^ c, result); // |&^
+ Expect.notEquals(a & (b ^ (c | d)) & (b ^ c), result); // |^&
+ Expect.notEquals(a & ((b ^ c) | d) & (b ^ c), result); // ^|&
+ // Binds stronger than relational operators.
+ Expect.equals((a & b) < (c & d), a & b < c & d);
+ // Binds weaker than shift operators.
+ Expect.equals((a & (b << c)) ^ d, a & b << c ^ d);
+ Expect.notEquals((a & b) << (c ^ d), a & b << c ^ d);
}
diff --git a/tests/language/cyclic_typedef_test.dart b/tests/language/cyclic_typedef_test.dart
new file mode 100644
index 0000000..61d8d0b
--- /dev/null
+++ b/tests/language/cyclic_typedef_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2013, 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.
+
+// Check that cyclic reference of a typedef is a compile-time error.
+
+// To test various cyclic references the definition of the [:typedef A():] is
+// split over several lines:
+typedef
+
+// Cyclic through return type.
+A /// 01: compile-time error
+
+A // The name of the typedef
+
+( // The left parenthesis of the typedef arguments.
+
+// Cyclic through parameter type.
+A a /// 02: compile-time error
+
+// Cyclic through optional parameter type.
+[A a] /// 03: compile-time error
+
+// Cyclic through named parameter type.
+{A a} /// 04: compile-time error
+
+// Cyclic through generic parameter type.
+List<A> a /// 05: compile-time error
+
+// Cyclic through return type of function typed parameter.
+A f() /// 06: compile-time error
+
+// Cyclic through parameter type of function typed parameter.
+f(A a) /// 07: compile-time error
+
+// Cyclic through another typedef.
+B b /// 08: compile-time error
+
+// Cyclic through another more typedefs.
+C c /// 09: compile-time error
+
+); // The right parenthesis of the typedef arguments.
+
+typedef B(A a);
+typedef C(B b);
+
+void testA(A a) {}
+
+void main() {
+ testA(null);
+}
\ No newline at end of file
diff --git a/tests/language/factory_redirection3_cyclic_test.dart b/tests/language/factory_redirection3_cyclic_test.dart
new file mode 100644
index 0000000..4662911
--- /dev/null
+++ b/tests/language/factory_redirection3_cyclic_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, 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.
+
+// Test that a cycle in redirecting factories leads to a compile-time error.
+
+class A {
+ factory A.foo() = B;
+}
+
+class B implements A {
+ factory B() = C.bar;
+}
+
+class C implements B {
+ factory C.bar() = C.foo;
+ factory C.foo() = C
+ .bar /// 01: compile-time error
+;
+ C();
+}
+
+main() {
+ new A.foo();
+}
diff --git a/tests/language/function_type_parameter_test.dart b/tests/language/function_type_parameter_test.dart
index 7ffe052..94ce81e 100644
--- a/tests/language/function_type_parameter_test.dart
+++ b/tests/language/function_type_parameter_test.dart
@@ -10,6 +10,7 @@
class A {
final f;
A(int this.f());
+ const A.nother(int this.f());
static Function func;
@@ -28,4 +29,5 @@
Expect.equals(null, A.func);
Expect.equals(42, new A(() => 42).f());
+ Expect.equals(42, new A.nother(() => 42).f());
}
diff --git a/tests/language/issue10561_test.dart b/tests/language/issue10561_test.dart
index 7ff80be..24c308c 100644
--- a/tests/language/issue10561_test.dart
+++ b/tests/language/issue10561_test.dart
@@ -9,9 +9,9 @@
import 'dart:collection';
-class Foo extends HashSet {
+class Foo extends Expando {
}
main() {
- Expect.equals(0, new Foo().length);
+ Expect.isNull(new Foo()[new Object()]);
}
diff --git a/tests/language/issue9949_test.dart b/tests/language/issue9949_test.dart
index d5df0ca..46c73d2 100644
--- a/tests/language/issue9949_test.dart
+++ b/tests/language/issue9949_test.dart
@@ -8,11 +8,11 @@
import "package:expect/expect.dart";
import 'dart:collection';
-class Crash extends HashSet<String> {
+class Crash extends Expando<String> {
Crash(): super();
}
void main() {
- Crash map = new Crash();
- Expect.isTrue(map is HashSet);
+ Crash expando = new Crash();
+ Expect.isTrue(expando is Expando);
}
diff --git a/tests/language/language.status b/tests/language/language.status
index 60a165a..67a94c1 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -12,8 +12,7 @@
library_juxtaposition_test: Fail # Issue 6877
switch_int_double_test/01: Fail # Issue 7307
switch_int_double_test/02: Fail # Issue 7307
-symbol_literal_test: Fail # Issue 12171
-evaluation_redirecting_constructor_test: Fail # Issue 13347
+throwing_lazy_variable_test: Fail # Issue 5802
# These bugs refer currently ongoing language discussions.
constructor_initializer_test/none: Fail # Issue 12633
@@ -28,6 +27,9 @@
on_catch_malformed_type_test: Fail # Issue 8601
mixin_mixin_test: Fail # Issue 9683
mixin_mixin2_test: Fail # Issue 9683
+mixin_mixin3_test: Fail # Issue 9683
+mixin_mixin4_test: Fail # Issue 9683
+mixin_mixin5_test: Fail # Issue 9683
mixin_issue10216_2_test: Fail # Issue 9683
mixin_illegal_object_test/01: Crash # Issue 10952
mixin_illegal_object_test/02: Crash # Issue 10952
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 87285e6..c71efb6 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -4,7 +4,6 @@
[ $compiler == dart2js || $compiler == dart2dart ]
block_scope_test: Fail # Issue 13204.
-compile_time_constant_c_test/none: Fail # Issue 11583
null_test/03: Fail # Issue 12445.
black_listed_test/none: Fail # Issue 12446.
malformed_test/none: Fail # Issue 12695
@@ -38,7 +37,6 @@
redirecting_factory_malbounded_test/01: Fail # Issue 12825
[ $compiler == dart2js && $unchecked ]
-factory_redirection_test/14: Fail # Issue 10959
type_checks_in_factory_method_test: Fail # Issue 12746
assertion_test: Fail # Issue 12748
double_to_string_as_exponential2_test: Fail # Issue 12749
@@ -67,10 +65,13 @@
[ $compiler == dart2js && $minified ]
f_bounded_quantification4_test: Fail # Issue 12605.
f_bounded_quantification5_test: Fail # Issue 12605.
+mixin_generic_test: Fail # Issue 12605.
mixin_mixin2_test: Fail # Issue 12605.
+mixin_mixin3_test: Fail # Issue 12605.
+mixin_mixin4_test: Fail # Issue 12605.
+mixin_mixin5_test: Fail # Issue 12605.
[ $compiler == dart2js ]
-function_type_alias6_test/00: Crash # Issue 9792
function_type_alias9_test/00: Crash # Issue 9792
branch_canonicalization_test: Fail # Issue 638.
div_with_power_of_two_test: Fail # Issue 8301.
@@ -113,6 +114,7 @@
infinity_test: Fail # Issue 4984
positive_bit_operations_test: Fail # Issue 12795
mixin_mixin2_test: Fail # Issue 13109.
+mixin_mixin3_test: Fail # Issue 13109.
# Compilation errors.
const_var_test: Fail # Issue 12793
@@ -136,8 +138,6 @@
map_literal4_test: Fail # Issue 12891
built_in_identifier_test/01: Fail # Issue 13022
-const_syntax_test/01: Fail # Issue 12932
-const_syntax_test/02: Fail # Issue 12932
const_syntax_test/03: Fail # Issue 12932
const_syntax_test/04: Fail # Issue 12932
constructor9_test/01: Fail # Issue 12934
@@ -168,6 +168,8 @@
[ $compiler == dart2js && ($runtime == ff || $runtime == jsshell || $runtime == ie9 || $runtime == safari)]
round_test: Fail, OK # Common JavaScript engine Math.round bug.
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
[ $compiler == dart2js && $runtime == ie9 ]
double_to_string_as_exponential3_test: Fail # Issue 12750
@@ -194,9 +196,7 @@
[ $compiler == dart2dart ]
mixin_super_constructor_named_test: Fail # Issue 12631
mixin_super_constructor_positionals_test: Fail # Issue 12631
-function_type_alias6_test/00: Fail # Issue 11986
function_type_alias9_test/00: Crash # Issue 11986
-symbol_literal_test: Fail # Issue 12171
built_in_identifier_prefix_test: Fail # Issue 6972
constructor_initializer_test/none: Fail # Issue 12633
@@ -208,6 +208,9 @@
# Mixins fail on the VM.
mixin_mixin_test: Fail # Issue 9683
mixin_mixin2_test: Fail # Issue 9683
+mixin_mixin3_test: Fail # Issue 9683
+mixin_mixin4_test: Fail # Issue 9683
+mixin_mixin5_test: Fail # Issue 9683
mixin_issue10216_2_test: Fail # Issue 9683
mixin_forwarding_constructor2_test: Fail # Issue 11888
mixin_typedef_constructor_test: Fail # Issue 11888
@@ -249,8 +252,6 @@
compile_time_constant_arguments_test/03: Fail # Issue 5519
compile_time_constant_arguments_test/05: Fail # Issue 5519
compile_time_constant_arguments_test/06: Fail # Issue 5519
-const_syntax_test/01: Fail # Issue 12933
-const_syntax_test/02: Fail # Issue 12933
const_syntax_test/03: Fail # Issue 12933
const_syntax_test/04: Fail # Issue 12933
const_syntax_test/05: Fail # Issue 12933
@@ -258,6 +259,8 @@
const_syntax_test/07: Fail # Issue 12933
const_syntax_test/08: Fail # Issue 12933
const_syntax_test/10: Fail # Issue 12933
+map_literal11_test: Fail # Issue 12933
+compile_time_constant_c_test/02: Fail # Issue 12933
constructor9_test/01: Fail # Issue 12935
constructor_named_arguments_test/01: Fail # Issue 5519
final_syntax_test/01: Fail # Issue 13020
@@ -295,7 +298,6 @@
factory_redirection_test/03: Crash # Issue 12753
factory_redirection_test/07: Fail # Issue 12753
factory_redirection_test/09: Fail # Issue 12753
-factory_redirection_test/14: Fail # Issue 10959
function_type_alias5_test/00: Fail # Issue 12755
function_type_alias5_test/01: Fail # Issue 12755
function_type_alias5_test/02: Fail # Issue 12755
@@ -306,7 +308,8 @@
constructor6_test: Fail
closure_in_initializer_test: Fail
super_first_constructor_test: Fail
-evaluation_redirecting_constructor_test: Fail # Issue 13347
+throwing_lazy_variable_test: Fail # Issue 5802
+
# Minified mode failures.
new_expression_type_args_test/00: Fail # Wrongly reports compile-time error.
diff --git a/tests/language/map_literal10_test.dart b/tests/language/map_literal10_test.dart
new file mode 100644
index 0000000..d1d3886
--- /dev/null
+++ b/tests/language/map_literal10_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, 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.
+
+// Test the use of '__proto__' keys in maps.
+
+library map_literal10_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+ var m1 = const {"__proto__": 0, 1: 1};
+ Expect.isTrue(m1.containsKey("__proto__"));
+ Expect.equals(0, m1["__proto__"]);
+ Expect.isTrue(m1.containsKey(1));
+ Expect.equals(1, m1[1]);
+ Expect.listEquals(["__proto__", 1], m1.keys.toList());
+
+ var m2 = const {1: 0, "__proto__": 1};
+ Expect.isTrue(m2.containsKey(1));
+ Expect.equals(0, m2[1]);
+ Expect.isTrue(m2.containsKey("__proto__"));
+ Expect.equals(1, m2["__proto__"]);
+ Expect.listEquals([1, "__proto__"], m2.keys.toList());
+
+ var m3 = const {"1": 0, "__proto__": 1};
+ Expect.isTrue(m3.containsKey("1"));
+ Expect.equals(0, m3["1"]);
+ Expect.isTrue(m3.containsKey("__proto__"));
+ Expect.equals(1, m3["__proto__"]);
+ Expect.listEquals(["1", "__proto__"], m3.keys.toList());
+
+ var m4 = const {"__proto__": 1, "1": 2};
+ Expect.isTrue(m4.containsKey("1"));
+ Expect.equals(2, m4["1"]);
+ Expect.isTrue(m4.containsKey("__proto__"));
+ Expect.equals(1, m4["__proto__"]);
+ Expect.listEquals(["__proto__", "1"], m4.keys.toList());
+}
diff --git a/tests/language/map_literal11_test.dart b/tests/language/map_literal11_test.dart
new file mode 100644
index 0000000..7461b80
--- /dev/null
+++ b/tests/language/map_literal11_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2013, 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.
+
+// Test the use of reliance on identity for keys in constant maps.
+
+library map_literal11_test;
+
+import "package:expect/expect.dart";
+
+
+class A {
+ static int accessCount = 0;
+
+ final int field;
+
+ const A(this.field);
+ int get hashCode => accessCount++;
+}
+
+void main() {
+ // Non-constant map are not based on identity.
+ var m1 = {const A(0): 0, const A(1): 1, null: 2, "3": 3, 4: 4};
+ Expect.isFalse(m1.containsKey(const A(0)));
+ Expect.isFalse(m1.containsKey(const A(1)));
+ Expect.isTrue(m1.containsKey(null));
+ Expect.isTrue(m1.containsKey("3"));
+ Expect.isTrue(m1.containsKey(4));
+ Expect.isNull(m1[const A(0)]);
+ Expect.isNull(m1[const A(1)]);
+ Expect.equals(2, m1[null]);
+ Expect.equals(3, m1["3"]);
+ Expect.equals(4, m1[4]);
+
+ // Constant map are based on identity.
+ var m2 = const {const A(0): 0, const A(1): 1, null: 2, "3": 3, 4: 4};
+ Expect.isTrue(m2.containsKey(const A(0)));
+ Expect.isTrue(m2.containsKey(const A(1)));
+ Expect.isTrue(m2.containsKey(null));
+ Expect.isTrue(m2.containsKey("3"));
+ Expect.isTrue(m2.containsKey(4));
+ Expect.equals(0, m2[const A(0)]);
+ Expect.equals(1, m2[const A(1)]);
+ Expect.equals(2, m2[null]);
+ Expect.equals(3, m2["3"]);
+ Expect.equals(4, m2[4]);
+}
diff --git a/tests/language/map_literal5_test.dart b/tests/language/map_literal5_test.dart
new file mode 100644
index 0000000..365f218
--- /dev/null
+++ b/tests/language/map_literal5_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, 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.
+
+// Test the use of general expression as keys in map literals.
+
+library map_literal5_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+ test(true);
+ test(false);
+}
+
+void test(bool b) {
+ var m = create(b);
+ Expect.equals(b, m.containsKey(true));
+ Expect.equals(b, m.containsKey(2));
+ Expect.equals(b, m.containsKey(1));
+ Expect.equals(!b, m.containsKey(false));
+ Expect.equals(!b, m.containsKey("bar"));
+ Expect.equals(!b, m.containsKey("foo"));
+ if (b) {
+ Expect.equals(0, m[true]);
+ Expect.equals(3, m[2]);
+ Expect.equals(2, m[1]);
+ } else {
+ Expect.equals(0, m[false]);
+ Expect.equals("baz", m["bar"]);
+ Expect.equals(2, m["foo"]);
+ }
+}
+
+create(bool b) {
+ return {
+ b: 0,
+ m(b): n(b),
+ b ? 1 : "foo": 2,
+ };
+}
+
+m(bool b) => b ? 2 : "bar";
+n(bool b) => b ? 3 : "baz";
\ No newline at end of file
diff --git a/tests/language/map_literal6_test.dart b/tests/language/map_literal6_test.dart
new file mode 100644
index 0000000..24935bf
--- /dev/null
+++ b/tests/language/map_literal6_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, 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.
+
+// Test the use of general expression as keys in const map literals.
+
+library map_literal6_test;
+
+import "package:expect/expect.dart";
+
+class A {
+ const A();
+}
+class B {
+ final a;
+ const B(this.a);
+}
+
+void main() {
+ var m1 = const {
+ const A(): 0,
+ const B(0): 1,
+ const B(1): 2,
+ const B(const A()): 3,
+ const B(0): 4,
+ };
+ Expect.isTrue(m1.containsKey(const A()));
+ Expect.isTrue(m1.containsKey(const B(0)));
+ Expect.isTrue(m1.containsKey(const B(1)));
+ Expect.isTrue(m1.containsKey(const B(const A())));
+ Expect.equals(0, m1[const A()]);
+ Expect.equals(4, m1[const B(0)]);
+ Expect.equals(2, m1[const B(1)]);
+ Expect.equals(3, m1[const B(const A())]);
+}
diff --git a/tests/language/map_literal7_test.dart b/tests/language/map_literal7_test.dart
new file mode 100644
index 0000000..a1d53c4
--- /dev/null
+++ b/tests/language/map_literal7_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, 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.
+
+// Test the use type arguments on constant maps.
+
+library map_literal7_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+ var m1 = const {"0": 0, "1": 1};
+ Expect.isTrue(m1 is Map);
+ Expect.isTrue(m1 is Map<String,int>);
+ Expect.isTrue(m1 is Map<int,dynamic>);
+ Expect.isTrue(m1 is Map<dynamic,String>);
+
+ var m2 = const <String,int>{"0": 0, "1": 1};
+ Expect.isTrue(m2 is Map);
+ Expect.isTrue(m2 is Map<String,int>);
+ Expect.isFalse(m2 is Map<int,dynamic>);
+ Expect.isFalse(m2 is Map<dynamic,String>);
+}
diff --git a/tests/language/map_literal8_test.dart b/tests/language/map_literal8_test.dart
new file mode 100644
index 0000000..ac68d84
--- /dev/null
+++ b/tests/language/map_literal8_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, 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.
+
+// Test the use of type arguments on const map literals using general expression
+// as keys.
+
+library map_literal8_test;
+
+import "package:expect/expect.dart";
+
+class A {
+ const A();
+}
+class B extends A {
+ final a;
+ const B(this.a);
+}
+
+void main() {
+ var m1 = const {
+ const A(): 0,
+ const B(0): 1,
+ const B(1): 2,
+ const B(const A()): 3,
+ const B(0): 4,
+ };
+ Expect.isTrue(m1 is Map);
+ Expect.isTrue(m1 is Map<A,int>);
+ Expect.isTrue(m1 is Map<int, dynamic>);
+ Expect.isTrue(m1 is Map<dynamic, A>);
+
+ var m2 = const <A, int>{
+ const A(): 0,
+ const B(0): 1,
+ const B(1): 2,
+ const B(const A()): 3,
+ const B(0): 4,
+ };
+ Expect.isTrue(m2 is Map);
+ Expect.isTrue(m2 is Map<A, int>);
+ Expect.isFalse(m2 is Map<int, dynamic>);
+ Expect.isFalse(m2 is Map<dynamic, A>);
+}
diff --git a/tests/language/map_literal9_test.dart b/tests/language/map_literal9_test.dart
new file mode 100644
index 0000000..cc12411
--- /dev/null
+++ b/tests/language/map_literal9_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, 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.
+
+// Test the use type arguments on constant maps.
+
+library map_literal9_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+ var m1 = const {"[object Object]": 0, "1": 1};
+ Expect.isFalse(m1.containsKey(new Object()));
+ Expect.isNull(m1[new Object()]);
+ Expect.isFalse(m1.containsKey(1));
+ Expect.isNull(m1[1]);
+
+ var m2 = const {"[object Object]": 0, "1": 1, "__proto__": 2};
+ Expect.isFalse(m2.containsKey(new Object()));
+ Expect.isNull(m2[new Object()]);
+ Expect.isFalse(m2.containsKey(1));
+ Expect.isNull(m2[1]);
+}
diff --git a/tests/language/mixin_generic_test.dart b/tests/language/mixin_generic_test.dart
new file mode 100644
index 0000000..445fbed
--- /dev/null
+++ b/tests/language/mixin_generic_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, 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.
+
+import "package:expect/expect.dart";
+
+class S<T> {
+ s() { return T; }
+}
+
+class M<T> {
+ m() { return T; }
+}
+
+class N<T> {
+ n() { return T; }
+}
+
+class C<U, V> extends S<Map<U, V>> with M<List<U>>, N<Set<V>> { }
+
+main() {
+ var c = new C<int, bool>();
+ Expect.isTrue(c is S<Map<int, bool>>);
+ Expect.equals("Map<int, bool>", c.s().toString());
+ Expect.isTrue(c is M<List<int>>);
+ Expect.equals("List<int>", c.m().toString());
+ Expect.isTrue(c is N<Set<bool>>);
+ Expect.equals("Set<bool>", c.n().toString());
+}
diff --git a/tests/language/mixin_mixin3_test.dart b/tests/language/mixin_mixin3_test.dart
new file mode 100644
index 0000000..844dd30
--- /dev/null
+++ b/tests/language/mixin_mixin3_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2013, 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.
+
+import "package:expect/expect.dart";
+
+class M<T> {
+ t() { return T; }
+}
+
+typedef A<U> = Object with M<List<U>>;
+
+typedef B0 = Object with A<Set<bool>>;
+
+typedef B1 = Object with A<Set<int>>;
+
+class C0 extends B0 { }
+
+class C1 extends B1 { }
+
+typedef A2<K, V> = Object with M<Map<K, V>>;
+
+typedef B2<V> = Object with A2<Set<V>, List<V>>;
+
+typedef B3<K, V> = Object with A2<Set<K>, List<V>>;
+
+class C2<T> extends B2<T> { }
+
+class C3<T> extends B3<T, int> { }
+
+class N {
+ q() { return 42; }
+}
+
+typedef O<U> = Object with N;
+
+typedef P<K, V> = Object with O<V>;
+
+class Q<K, V> extends P<K, V> { }
+
+main() {
+ Expect.equals("List<Set<bool>>", new C0().t().toString());
+ Expect.equals("List<Set<int>>", new C1().t().toString());
+ Expect.equals("Map<Set<bool>, List<bool>>", new C2<bool>().t().toString());
+ Expect.equals("Map<Set<bool>, List<int>>", new C3<bool>().t().toString());
+ Expect.equals(42, new Q<bool, int>().q());
+}
diff --git a/tests/language/mixin_mixin4_test.dart b/tests/language/mixin_mixin4_test.dart
new file mode 100644
index 0000000..61815b4
--- /dev/null
+++ b/tests/language/mixin_mixin4_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, 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.
+
+import "package:expect/expect.dart";
+
+class I<T> { }
+
+class J<T> { }
+
+class S<T> { }
+
+class M<T> {
+ t() { return T; }
+}
+
+typedef A<U, V> = Object with M<Map<U, V>> implements I<V>;
+
+typedef C<T, K> = S<T> with A<T, List<K>> implements J<K>;
+
+main() {
+ var c = new C<int, bool>();
+ Expect.equals("Map<int, List<bool>>", c.t().toString());
+ Expect.isTrue(c is I<List<bool>>);
+ Expect.isTrue(c is J<bool>);
+ Expect.isTrue(c is S<int>);
+ Expect.isTrue(c is A<int, List<bool>>);
+ Expect.isTrue(c is M<Map<int, List<bool>>>);
+}
diff --git a/tests/language/mixin_mixin5_test.dart b/tests/language/mixin_mixin5_test.dart
new file mode 100644
index 0000000..2ee8be7
--- /dev/null
+++ b/tests/language/mixin_mixin5_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, 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.
+
+import "package:expect/expect.dart";
+
+class I<T> { }
+
+class J<T> { }
+
+class K<T> { }
+
+class S<T> { }
+
+class M<T> {
+ m() { return T; }
+}
+
+typedef A<U, V> = Object with M<Map<U, V>> implements I<V>;
+
+typedef B<T> = Object with A<T, Set<T>> implements J<T>;
+
+typedef C<T> = S<List<T>> with B<List<T>> implements K<T>;
+
+main() {
+ var c = new C<int>();
+ Expect.equals("Map<List<int>, Set<List<int>>>", c.m().toString());
+ Expect.isTrue(c is K<int>);
+ Expect.isTrue(c is J<List<int>>);
+ Expect.isTrue(c is I<Set<List<int>>>);
+ Expect.isTrue(c is S<List<int>>);
+ Expect.isTrue(c is A<List<int>, Set<List<int>>>);
+ Expect.isTrue(c is M<Map<List<int>, Set<List<int>>>>);
+}
diff --git a/tests/language/redirecting_factory_incompatible_signature_test.dart b/tests/language/redirecting_factory_incompatible_signature_test.dart
new file mode 100644
index 0000000..18129a0
--- /dev/null
+++ b/tests/language/redirecting_factory_incompatible_signature_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, 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.
+
+// Test that incompatible signatures in a forwarding factory
+// constructor leads to a [NoSuchMethodError].
+
+import "package:expect/expect.dart";
+
+class A {
+ A(a, b);
+ factory A.f() = A;
+}
+
+main() {
+ Expect.throws(() => new A.f(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/throwing_lazy_variable_test.dart b/tests/language/throwing_lazy_variable_test.dart
new file mode 100644
index 0000000..c97d2fb
--- /dev/null
+++ b/tests/language/throwing_lazy_variable_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, 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.
+
+// Test that engines will not infer that [a] is always of type int.
+
+var a = foo();
+
+foo() {
+ () => 42;
+ if (true) throw 'Sorry';
+ return 42;
+}
+
+main() {
+ try {
+ a;
+ } catch (e) {
+ // Ignore.
+ }
+ if (a is num) throw 'Test failed';
+}
diff --git a/tests/language/vm/optimized_guarded_field_test.dart b/tests/language/vm/optimized_guarded_field_test.dart
new file mode 100644
index 0000000..2ef5dcb
--- /dev/null
+++ b/tests/language/vm/optimized_guarded_field_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, 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.
+// Test correct handling of phis with only environment uses that were inserted
+// by store to load forwarding.
+// VMOptions=--optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+class A {
+ var foo;
+}
+
+class B {
+ get foo => null;
+}
+
+test(obj) => obj.foo == null ? "null" : "other";
+
+main() {
+ var a = new A();
+ var b = new B();
+ // Trigger optimization of test with a polymorphic load.
+ // The guarded type of foo is null.
+ test(a);
+ test(b);
+ for (var i = 0; i < 20; ++i) test(a);
+ Expect.equals("null", test(a));
+ Expect.equals("null", test(b));
+
+ // Store a non-null object into foo to trigger deoptimization of test.
+ a.foo = 123;
+ Expect.equals("other", test(a));
+ Expect.equals("null", test(b));
+}
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index 1594832..5fa450c 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -617,6 +617,19 @@
completer.complete(21);
}
+void testSyncFuture_i13368() {
+ asyncStart();
+
+ final future = new Future<int>.sync(() {
+ return new Future<int>.value(42);
+ });
+
+ future.then((int val) {
+ Expect.equals(val, 42);
+ asyncEnd();
+ });
+}
+
main() {
testValue();
testSync();
@@ -658,4 +671,6 @@
testChainedFutureValue();
testChainedFutureValueDelay();
testChainedFutureError();
+
+ testSyncFuture_i13368();
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index d0b9b70..098b947 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -11,10 +11,10 @@
math/low_test: Fail
math/random_test: Fail
mirrors/class_mirror_type_variables_test: Fail # Issue 12087
-mirrors/equality_test: Fail # Issue 12333
+mirrors/equality_test/02: Fail # Issue 12333
mirrors/fake_function_test: Fail # Issue 11612
mirrors/function_type_mirror_test: Fail # Issue 12166
-mirrors/generics_test: Fail # Issue 12333
+mirrors/generics_test/01: Fail # Issue 12333
mirrors/hierarchy_invariants_test: Fail # Issue 11863
mirrors/invoke_test: Fail # Issue 11954
mirrors/invoke_named_test: Fail # Issue 10471, 12863
@@ -29,7 +29,7 @@
mirrors/mixin_test/none: Fail # Issue 12464
mirrors/new_instance_with_type_arguments_test: Fail # Issue 12333
mirrors/null_test : Fail # Issue 12129
-mirrors/parameter_test: Fail # Issue 6490
+mirrors/parameter_test/none: Fail # Issue 6490
mirrors/parameter_metadata_test: Fail # Issue 10905
mirrors/reflected_type_test: Fail # Issue 12607
mirrors/typedef_metadata_test: Fail # Issue 12785
@@ -164,6 +164,8 @@
[ $compiler == dartanalyzer ]
mirrors/library_metadata2_test/01: Fail # http://dartbug.com/12950
mirrors/typedef_test/none: Fail # Issue 13093
+mirrors/generics_test/none: Fail # Issue 13432
[ $compiler == dart2analyzer ]
mirrors/library_metadata2_test/01: Fail # http://dartbug.com/12950
+
diff --git a/tests/lib/mirrors/class_mirror_type_variables_test.dart b/tests/lib/mirrors/class_mirror_type_variables_test.dart
index 2b02bad..c4149e4 100644
--- a/tests/lib/mirrors/class_mirror_type_variables_test.dart
+++ b/tests/lib/mirrors/class_mirror_type_variables_test.dart
@@ -7,9 +7,9 @@
import "package:expect/expect.dart";
class C<R,S,T> {
- R foo(R r) => r;
- S bar(S s) => s;
- T baz(T t) => t;
+ R foo(R r) => r;
+ S bar(S s) => s;
+ T baz(T t) => t;
}
class NoTypeParams {}
@@ -18,10 +18,7 @@
ClassMirror cm;
cm = reflectClass(C);
Expect.equals(3, cm.typeVariables.length);
- Expect.equals(true, cm.typeVariables.containsKey(const Symbol("R")));
- Expect.equals(true, cm.typeVariables.containsKey(const Symbol("S")));
- Expect.equals(true, cm.typeVariables.containsKey(const Symbol("T")));
- var values = cm.typeVariables.values;
+ var values = cm.typeVariables;
values.forEach((e) {
Expect.equals(true, e is TypeVariableMirror);
});
diff --git a/tests/lib/mirrors/equality_dart2js_test.dart b/tests/lib/mirrors/equality_dart2js_test.dart
deleted file mode 100644
index 15c036d..0000000
--- a/tests/lib/mirrors/equality_dart2js_test.dart
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2013, 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 test.class_equality_test;
-
-import 'dart:mirrors';
-
-import 'package:expect/expect.dart';
-
-class A<T> {}
-class B extends A<int> {}
-
-class BadEqualityHash {
- int count = 0;
- bool operator ==(other) => true;
- int get hashCode => count++;
-}
-
-checkEquality(List<Map> equivalenceClasses) {
- for (var equivalenceClass in equivalenceClasses) {
- equivalenceClass.forEach((name, member) {
- equivalenceClass.forEach((otherName, otherMember) {
- // Reflexivity, symmetry and transitivity.
- Expect.equals(member,
- otherMember,
- "$name == $otherName");
- Expect.equals(member.hashCode,
- otherMember.hashCode,
- "$name.hashCode == $otherName.hashCode");
- });
- for (var otherEquivalenceClass in equivalenceClasses) {
- if (otherEquivalenceClass == equivalenceClass) continue;
- otherEquivalenceClass.forEach((otherName, otherMember) {
- Expect.notEquals(member,
- otherMember,
- "$name != $otherName"); // Exclusion.
- // Hash codes may or may not be equal.
- });
- }
- });
- }
-}
-
-void subroutine() {
-}
-
-main() {
- LibraryMirror thisLibrary =
- currentMirrorSystem()
- .findLibrary(const Symbol('test.class_equality_test'))
- .single;
-
- var o1 = new Object();
- var o2 = new Object();
-
- var badEqualityHash1 = new BadEqualityHash();
- var badEqualityHash2 = new BadEqualityHash();
-
- checkEquality([
- {'reflect(o1)' : reflect(o1),
- 'reflect(o1), again' : reflect(o1)},
-
- {'reflect(o2)' : reflect(o2),
- 'reflect(o2), again' : reflect(o2)},
-
- {'reflect(badEqualityHash1)' : reflect(badEqualityHash1),
- 'reflect(badEqualityHash1), again' : reflect(badEqualityHash1)},
-
- {'reflect(badEqualityHash2)' : reflect(badEqualityHash2),
- 'reflect(badEqualityHash2), again' : reflect(badEqualityHash2)},
-
- {'reflect(true)' : reflect(true),
- 'reflect(true), again' : reflect(true)},
-
- {'reflect(false)' : reflect(false),
- 'reflect(false), again' : reflect(false)},
-
- {'reflect(null)' : reflect(null),
- 'reflect(null), again' : reflect(null)},
-
- {'reflect(3.5+4.5)' : reflect(3.5+4.5),
- 'reflect(6.5+1.5)' : reflect(6.5+1.5)},
-
- {'reflect(3+4)' : reflect(3+4),
- 'reflect(6+1)' : reflect(6+1)},
-
- {'reflect("foo")' : reflect("foo"),
- 'reflect("foo"), again' : reflect("foo")},
-
- {'currentMirrorSystem().voidType' : currentMirrorSystem().voidType},
-
- {'currentMirrorSystem().dynamicType' : currentMirrorSystem().dynamicType,
- 'thisLibrary.functions[#main].returnType' :
- thisLibrary.functions[const Symbol('main')].returnType},
-
- {'reflectClass(A)' : reflectClass(A),
- 'thisLibrary.classes[#A]' : thisLibrary.classes[const Symbol('A')],
- 'reflect(new A<int>()).type.originalDeclaration' :
- reflect(new A<int>()).type.originalDeclaration},
-
- {'reflectClass(B)' : reflectClass(B),
- 'thisLibrary.classes[#B]' : thisLibrary.classes[const Symbol('B')],
- 'reflect(new B()).type' : reflect(new B()).type},
-
- {'thisLibrary' : thisLibrary,
- 'reflectClass(A).owner' : reflectClass(A).owner,
- 'reflectClass(B).owner' : reflectClass(B).owner,
- 'reflect(new A()).type.owner' : reflect(new A()).type.owner,
- 'reflect(new A()).type.owner' : reflect(new A()).type.owner},
- ]);
-}
diff --git a/tests/lib/mirrors/equality_test.dart b/tests/lib/mirrors/equality_test.dart
index 1a08b59..1b3b798 100644
--- a/tests/lib/mirrors/equality_test.dart
+++ b/tests/lib/mirrors/equality_test.dart
@@ -2,6 +2,13 @@
// 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.
+// This tests uses the multi-test "ok" feature:
+// none: Trimmed behaviour. Passing on the VM.
+// 01: Trimmed version for dart2js.
+// 02: Full version passing in the VM.
+//
+// TODO(rmacnak,ahe): Remove multi-test when VM and dart2js are on par.
+
library test.class_equality_test;
import 'dart:mirrors';
@@ -88,9 +95,11 @@
{'reflect("foo")' : reflect("foo"),
'reflect("foo"), again' : reflect("foo")},
- {'currentMirrorSystem().voidType' : currentMirrorSystem().voidType,
- 'thisLibrary.functions[#subroutine].returnType' :
- thisLibrary.functions[const Symbol('subroutine')].returnType},
+ {'currentMirrorSystem().voidType' : currentMirrorSystem().voidType}, /// 01: ok
+
+ {'currentMirrorSystem().voidType' : currentMirrorSystem().voidType, /// 02: ok
+ 'thisLibrary.functions[#subroutine].returnType' : /// 02: ok
+ thisLibrary.functions[const Symbol('subroutine')].returnType}, /// 02: ok
{'currentMirrorSystem().dynamicType' : currentMirrorSystem().dynamicType,
'thisLibrary.functions[#main].returnType' :
@@ -101,8 +110,8 @@
'reflect(new A<int>()).type.originalDeclaration' :
reflect(new A<int>()).type.originalDeclaration},
- {'reflectClass(B).superclass' : reflectClass(B).superclass,
- 'reflect(new A<int>()).type' : reflect(new A<int>()).type},
+ {'reflectClass(B).superclass' : reflectClass(B).superclass, /// 02: ok
+ 'reflect(new A<int>()).type' : reflect(new A<int>()).type}, /// 02: ok
{'reflectClass(B)' : reflectClass(B),
'thisLibrary.classes[#B]' : thisLibrary.classes[const Symbol('B')],
@@ -112,6 +121,6 @@
'reflectClass(A).owner' : reflectClass(A).owner,
'reflectClass(B).owner' : reflectClass(B).owner,
'reflect(new A()).type.owner' : reflect(new A()).type.owner,
- 'reflect(new A()).type.owner' : reflect(new A()).type.owner},
+ 'reflect(new B()).type.owner' : reflect(new B()).type.owner},
]);
}
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index e5e2c2f..d1f05d2 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -10,7 +10,9 @@
class A<T> {}
class B extends A {} // Same as class B extends A<dynamic>.
-class C extends A<num, int> {} // Same as class C extends A<dynamic>.
+class C extends A
+<num, int> // TODO(zarah): Should be "01: static warning".
+{} // Same as class C extends A<dynamic>.
class D extends A<int> {}
class E<S> extends A<S> {}
class F<R> extends A<int> {}
@@ -19,27 +21,22 @@
typeParameters(mirror, parameterNames) {
Expect.listEquals(parameterNames.map((n) => new Symbol(n)).toList(),
- mirror.typeVariables.keys.toList());
+ mirror.typeVariables.map((v) => v.simpleName).toList());
}
typeArguments(mirror, argumentMirrors) {
- Expect.listEquals(argumentMirrors,
- mirror.typeArguments.values.toList());
- if (!mirror.isOriginalDeclaration) {
- Expect.listEquals(mirror.typeVariables.keys.toList(),
- mirror.typeArguments.keys.toList());
- }
+ Expect.listEquals(argumentMirrors, mirror.typeArguments);
}
main() {
// Declarations.
- typeParameters(reflectClass(A), ['T']);
- typeParameters(reflectClass(B), []);
- typeParameters(reflectClass(C), []);
- typeParameters(reflectClass(D), []);
- typeParameters(reflectClass(E), ['S']);
- typeParameters(reflectClass(F), ['R']);
- typeParameters(reflectClass(G), []);
+ typeParameters(reflectClass(A), ['T']); /// 01: ok
+ typeParameters(reflectClass(B), []); /// 01: ok
+ typeParameters(reflectClass(C), []); /// 01: ok
+ typeParameters(reflectClass(D), []); /// 01: ok
+ typeParameters(reflectClass(E), ['S']); /// 01: ok
+ typeParameters(reflectClass(F), ['R']); /// 01: ok
+ typeParameters(reflectClass(G), []); /// 01: ok
typeArguments(reflectClass(A), []);
typeArguments(reflectClass(B), []);
@@ -66,32 +63,32 @@
Expect.equals(reflectClass(G), reflectClass(G).originalDeclaration);
// Instantiations.
- typeParameters(reflect(new A<num>()).type, ['T']);
- typeParameters(reflect(new B<num>()).type, []);
- typeParameters(reflect(new C()).type, []);
- typeParameters(reflect(new D()).type, []);
- typeParameters(reflect(new E()).type, ['S']);
- typeParameters(reflect(new F<num>()).type, ['R']);
- typeParameters(reflect(new G()).type, []);
- typeParameters(reflect(new H()).type, ['A', 'B', 'C']);
+ typeParameters(reflect(new A<num>()).type, ['T']); /// 01: ok
+ typeParameters(reflect(new B<num>()).type, []); /// 01: ok
+ typeParameters(reflect(new C()).type, []); /// 01: ok
+ typeParameters(reflect(new D()).type, []); /// 01: ok
+ typeParameters(reflect(new E()).type, ['S']); /// 01: ok
+ typeParameters(reflect(new F<num>()).type, ['R']); /// 01: ok
+ typeParameters(reflect(new G()).type, []); /// 01: ok
+ typeParameters(reflect(new H()).type, ['A', 'B', 'C']); /// 01: ok
var numMirror = reflectClass(num);
var dynamicMirror = currentMirrorSystem().dynamicType;
typeArguments(reflect(new A<num>()).type, [numMirror]);
- typeArguments(reflect(new A<dynamic>()).type, [dynamicMirror]);
- typeArguments(reflect(new A()).type, [dynamicMirror]);
+ typeArguments(reflect(new A<dynamic>()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new A()).type, [dynamicMirror]); /// 01: ok
typeArguments(reflect(new B()).type, []);
typeArguments(reflect(new C()).type, []);
typeArguments(reflect(new D()).type, []);
typeArguments(reflect(new E<num>()).type, [numMirror]);
- typeArguments(reflect(new E<dynamic>()).type, [dynamicMirror]);
- typeArguments(reflect(new E()).type, [dynamicMirror]);
+ typeArguments(reflect(new E<dynamic>()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new E()).type, [dynamicMirror]); /// 01: ok
typeArguments(reflect(new F<num>()).type, [numMirror]);
- typeArguments(reflect(new F<dynamic>()).type, [dynamicMirror]);
- typeArguments(reflect(new F()).type, [dynamicMirror]);
+ typeArguments(reflect(new F<dynamic>()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new F()).type, [dynamicMirror]); /// 01: ok
typeArguments(reflect(new G()).type, []);
- typeArguments(reflect(new H<dynamic, num, dynamic>()).type,
- [dynamicMirror, numMirror, dynamicMirror]);
+ typeArguments(reflect(new H<dynamic, num, dynamic>()).type, /// 01: ok
+ [dynamicMirror, numMirror, dynamicMirror]); /// 01: ok
Expect.isFalse(reflect(new A<num>()).type.isOriginalDeclaration);
Expect.isTrue(reflect(new B()).type.isOriginalDeclaration);
@@ -100,7 +97,7 @@
Expect.isFalse(reflect(new E<num>()).type.isOriginalDeclaration);
Expect.isFalse(reflect(new F<num>()).type.isOriginalDeclaration);
Expect.isTrue(reflect(new G()).type.isOriginalDeclaration);
- Expect.isFalse(reflect(new H()).type.isOriginalDeclaration);
+ Expect.isFalse(reflect(new H()).type.isOriginalDeclaration); /// 01: ok
Expect.equals(reflectClass(A),
reflect(new A<num>()).type.originalDeclaration);
@@ -133,8 +130,8 @@
reflect(new F<num>()).type.originalDeclaration);
Expect.equals(reflect(new G()).type,
reflect(new G()).type.originalDeclaration);
- Expect.notEquals(reflect(new H()).type,
- reflect(new H()).type.originalDeclaration);
+ Expect.notEquals(reflect(new H()).type, /// 01: ok
+ reflect(new H()).type.originalDeclaration); /// 01: ok
// Library members are all uninstantaited generics or non-generics.
currentMirrorSystem().libraries.values.forEach((libraryMirror) {
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index df1f9b0..b86acd6 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -45,7 +45,7 @@
equals("DNU"));
expect(instMirror.invoke(const Symbol("m"), []).reflectee,
equals("DNU")); // Wrong arity.
- // TODO(rmacnak): Implement access to private members.
+ // TODO(rmacnak): Implement access to private members.
// expect(instMirror.invoke(const Symbol("_n"), [3, 4]).reflectee,
// equals(7));
@@ -240,7 +240,7 @@
expect(classMirror.qualifiedName, equals(const Symbol('MirrorsTest.Class')));
if (!isDart2js) { // TODO(ahe): Implement this in dart2js.
- TypeVariableMirror typeVariable = classMirror.typeVariables.values.single;
+ TypeVariableMirror typeVariable = classMirror.typeVariables.single;
expect(typeVariable.simpleName, equals(const Symbol('T')));
expect(typeVariable.qualifiedName,
equals(const Symbol('MirrorsTest.Class.T')));
diff --git a/tests/lib/mirrors/parameter_dart2js_test.dart b/tests/lib/mirrors/parameter_dart2js_test.dart
deleted file mode 100644
index aa5cdee..0000000
--- a/tests/lib/mirrors/parameter_dart2js_test.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/// Test of [ParameterMirror].
-library test.parameter_test;
-
-@MirrorsUsed(targets: 'test.parameter_test', override: '*')
-import 'dart:mirrors';
-
-import 'stringify.dart';
-
-class B {
- B();
- B.foo(int x);
- B.bar(int z, x);
-}
-
-main() {
- var constructors = reflectClass(B).constructors;
-
- expect('{B: Method(s(B) in s(B), constructor), '
- 'B.bar: Method(s(B.bar) in s(B), constructor), '
- 'B.foo: Method(s(B.foo) in s(B), constructor)}',
- constructors);
-
- var unnamedConstructor = constructors[new Symbol('B')];
-
- expect('[]', unnamedConstructor.parameters);
- expect('Class(s(B) in s(test.parameter_test), top-level)',
- unnamedConstructor.returnType);
-
- var fooConstructor = constructors[new Symbol('B.foo')];
- expect('[Parameter(s(x) in s(B.foo),'
- ' type = Class(s(int) in s(dart.core), top-level))]',
- fooConstructor.parameters);
- expect('Class(s(B) in s(test.parameter_test), top-level)',
- fooConstructor.returnType);
-
- var barConstructor = constructors[new Symbol('B.bar')];
- expect('[Parameter(s(z) in s(B.bar),'
- ' type = Class(s(int) in s(dart.core), top-level)), '
- 'Parameter(s(x) in s(B.bar),'
- ' type = Type(s(dynamic), top-level))]',
- barConstructor.parameters);
- expect('Class(s(B) in s(test.parameter_test), top-level)',
- barConstructor.returnType);
-
- print(constructors);
-}
diff --git a/tests/lib/mirrors/parameter_test.dart b/tests/lib/mirrors/parameter_test.dart
index 6a86c53..5e3518b 100644
--- a/tests/lib/mirrors/parameter_test.dart
+++ b/tests/lib/mirrors/parameter_test.dart
@@ -2,7 +2,13 @@
// 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.
-/// Test of [ParameterMirror].
+// This tests uses the multi-test "ok" feature:
+// none: Desired behaviour, passing on the VM.
+// 01: Trimmed version for dart2js.
+//
+// TODO(rmacnak,ahe): Remove multi-test when VM and dart2js are on par.
+
+/** Test of [ParameterMirror]. */
library test.parameter_test;
@MirrorsUsed(targets: 'test.parameter_test', override: '*')
@@ -26,9 +32,9 @@
get x => _x;
set x(final value) { _x = value; }
- grault([int x]);
- garply({int y});
- waldo(int z);
+ grault([int x]) {}
+ garply({int y}) {}
+ waldo(int z) {}
}
class C <S extends int, T> {
@@ -71,6 +77,9 @@
expect('Class(s(B) in s(test.parameter_test), top-level)',
barConstructor.returnType);
+ // dart2js stops testing here.
+ return; /// 01: ok
+
MethodMirror bazConstructor = constructors[const Symbol('B.baz')];
expect('Method(s(B.baz) in s(B), constructor)', bazConstructor);
expect('[Parameter(s(x) in s(B.baz), final,'
diff --git a/tests/lib/mirrors/typearguments_mirror_test.dart b/tests/lib/mirrors/typearguments_mirror_test.dart
new file mode 100644
index 0000000..855d842
--- /dev/null
+++ b/tests/lib/mirrors/typearguments_mirror_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, 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 lib;
+
+import 'package:expect/expect.dart';
+import 'stringify.dart';
+import 'dart:mirrors';
+
+class Foo<T> {}
+class Bar<T, R> {}
+
+main() {
+ var cm = reflectClass(Foo);
+ var cm1 = reflect((new Foo<String>())).type;
+
+ Expect.notEquals(cm, cm1);
+ Expect.isFalse(cm1.isOriginalDeclaration);
+ Expect.isTrue(cm.isOriginalDeclaration);
+
+ Expect.equals(cm, cm1.originalDeclaration);
+
+ Expect.equals(cm, reflectClass(Foo));
+ Expect.equals(cm, reflectClass((new Foo().runtimeType)));
+ print((reflect(new Foo()).type).runtimeType);
+ print(cm.runtimeType);
+ Expect.equals(cm1, reflect(new Foo<String>()).type);
+
+ expect('[]', cm.typeArguments);
+ expect('[Class(s(String) in s(dart.core), top-level)]', cm1.typeArguments);
+
+ cm = reflect(new Bar<List, Set>()).type;
+ cm1 = reflect(new Bar<List, Set<String>>()).type;
+
+ var cm2 = reflect(new Bar<List<String>, Set>()).type;
+ var cm3 = reflect(new Bar<List<String>, Set<String>>()).type;
+
+ expect('[Class(s(List) in s(dart.core), top-level),'
+ ' Class(s(Set) in s(dart.core), top-level)]', cm.typeArguments);
+ expect('[Class(s(List) in s(dart.core), top-level),'
+ ' Class(s(Set) in s(dart.core), top-level)]', cm1.typeArguments);
+ expect('[Class(s(List) in s(dart.core), top-level),'
+ ' Class(s(Set) in s(dart.core), top-level)]', cm2.typeArguments);
+ expect('[Class(s(List) in s(dart.core), top-level),'
+ ' Class(s(Set) in s(dart.core), top-level)]', cm3.typeArguments);
+
+ expect('[Class(s(String) in s(dart.core), top-level)]',
+ cm1.typeArguments[1].typeArguments);
+ expect('[Class(s(String) in s(dart.core), top-level)]',
+ cm2.typeArguments[0].typeArguments);
+ expect('[Class(s(String) in s(dart.core), top-level)]',
+ cm3.typeArguments[0].typeArguments);
+ expect('[Class(s(String) in s(dart.core), top-level)]',
+ cm3.typeArguments[1].typeArguments);
+
+ var cm4 = reflect(new Bar<Bar<List, Set>, String>()).type;
+
+ expect('[Class(s(Bar) in s(lib), top-level),'
+ ' Class(s(String) in s(dart.core), top-level)]',
+ cm4.typeArguments);
+ expect('[Class(s(List) in s(dart.core), top-level), '
+ 'Class(s(Set) in s(dart.core), top-level)]',
+ cm4.typeArguments[0].typeArguments);
+}
diff --git a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
index 77f226b..9994988 100644
--- a/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
+++ b/tests/lib/mirrors/typevariable_mirror_metadata_test.dart
@@ -32,17 +32,17 @@
main() {
ClassMirror cm;
cm = reflectClass(A);
- checkMetadata(cm.typeVariables[const Symbol('S')], []);
- checkMetadata(cm.typeVariables[const Symbol('T')], [m1, m2]);
+ checkMetadata(cm.typeVariables[0], []);
+ checkMetadata(cm.typeVariables[1], [m1, m2]);
// Check for conflicts.
checkMetadata(cm.methods[const Symbol('T')], [m3]);
cm = reflectClass(B);
- checkMetadata(cm.typeVariables[const Symbol('T')], [m3]);
+ checkMetadata(cm.typeVariables[0], [m3]);
// Check for conflicts.
checkMetadata(cm.members[const Symbol('T')], [m1, m2]);
TypedefMirror tm = reflectClass(Predicate);
FunctionTypeMirror ftm = tm.referent;
- checkMetadata(ftm.typeVariables[const Symbol('G')], [m1, m2]);
+ checkMetadata(ftm.typeVariables[0], [m1, m2]);
}
diff --git a/tests/standalone/io/file_error_test.dart b/tests/standalone/io/file_error_test.dart
index d8dc8aa..8b1049a 100644
--- a/tests/standalone/io/file_error_test.dart
+++ b/tests/standalone/io/file_error_test.dart
@@ -130,29 +130,29 @@
});
}
-bool checkFullPathOnNonExistentDirectoryException(e) {
+bool checkResolveSymbolicLinksOnNonExistentDirectoryException(e) {
Expect.isTrue(e is FileException);
Expect.isTrue(e.osError != null);
- Expect.isTrue(e.toString().indexOf("Cannot retrieve full path") != -1);
+ Expect.isTrue(e.toString().indexOf("Cannot resolve symbolic links") != -1);
// File not not found has error code 2 on all supported platforms.
Expect.equals(2, e.osError.errorCode);
return true;
}
-void testFullPathOnNonExistentDirectory() {
+void testResolveSymbolicLinksOnNonExistentDirectory() {
asyncStart();
Directory temp = tempDir();
var file = new File("${temp.path}/nonExistentDirectory");
// Full path non-existent directory should throw exception.
- Expect.throws(() => file.fullPathSync(),
- (e) => checkFullPathOnNonExistentDirectoryException(e));
+ Expect.throws(() => file.resolveSymbolicLinksSync(),
+ (e) => checkResolveSymbolicLinksOnNonExistentDirectoryException(e));
- var fullPathFuture = file.fullPath();
- fullPathFuture.then((path) => Expect.fail("Unreachable code $path"))
+ var resolvedFuture = file.resolveSymbolicLinks();
+ resolvedFuture.then((path) => Expect.fail("Unreachable code $path"))
.catchError((error) {
- checkFullPathOnNonExistentDirectoryException(error);
+ checkResolveSymbolicLinksOnNonExistentDirectoryException(error);
temp.deleteSync(recursive: true);
asyncEnd();
});
@@ -424,7 +424,7 @@
testDeleteNonExistent();
testLengthNonExistent();
testCreateInNonExistentDirectory();
- testFullPathOnNonExistentDirectory();
+ testResolveSymbolicLinksOnNonExistentDirectory();
testReadAsBytesNonExistent();
testReadAsTextNonExistent();
testReadAsLinesNonExistent();
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index 14e4780..1c5f860 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -920,16 +920,6 @@
}
}
- static void testOpenFile() {
- var name = getFilename("tests/vm/data/fixed_length_file");
- var f = new File(name);
- Expect.isTrue(f.existsSync());
- name = f.fullPathSync();
- var g = new File(name);
- Expect.isTrue(g.existsSync());
- Expect.equals(name, g.fullPathSync());
- }
-
static void testReadAsBytes() {
asyncTestStarted();
var name = getFilename("tests/vm/data/fixed_length_file");
@@ -1269,7 +1259,6 @@
testPositionSync();
testOpenDirectoryAsFile();
testOpenDirectoryAsFileSync();
- testOpenFile();
testReadAsBytesSync();
testReadAsBytesSyncEmptyFile();
testReadAsTextSync();
diff --git a/tests/standalone/io/resolve_symbolic_links_test.dart b/tests/standalone/io/resolve_symbolic_links_test.dart
new file mode 100644
index 0000000..485f84e
--- /dev/null
+++ b/tests/standalone/io/resolve_symbolic_links_test.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2013, 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.
+//
+// Dart test program for testing FileSystemEntity.resolveSymbolicLinks
+
+import "package:expect/expect.dart";
+import "package:path/path.dart";
+import "package:async_helper/async_helper.dart";
+import 'dart:async';
+import 'dart:io';
+
+main() {
+ String testsDir = dirname(dirname(dirname(Platform.script)));
+ // All of these tests test that resolveSymbolicLinks gives a path
+ // that points to the same place as the original, and that it removes
+ // all links, .., and . segments, and that it produces an absolute path.
+ asyncTest(() => testFile(join(
+ testsDir, 'standalone', 'io', 'resolve_symbolic_links_test.dart')));
+ asyncTest(() => testFile(join(testsDir, 'standalone', 'io', '..', 'io',
+ 'resolve_symbolic_links_test.dart')));
+
+ asyncTest(() => testDir(join(testsDir, 'standalone', 'io')));
+ asyncTest(() => testDir(join(testsDir, 'lib', '..', 'standalone', 'io')));
+ // Test a relative path.
+ asyncTest(() => testDir('.'));
+ if (Platform.isWindows) {
+ asyncTest(() =>testFile(join('\\\\?\\$testsDir', 'standalone', 'io',
+ 'resolve_symbolic_links_test.dart')));
+ asyncTest(() => testDir('\\\\?\\$testsDir'));
+ }
+ asyncTest(() => new Directory('').createTemp().then((tempDir) {
+ String temp = tempDir.path;
+ return makeEntities(temp).then((_) => Future.wait(
+ [testFile(join(temp, 'dir1', 'file1')),
+ testFile(join(temp, 'link1', 'file2')),
+ testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
+ testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
+ testLink(join(temp, 'link1'))]))
+ .then((_) {
+ if (Platform.isWindows) {
+ // Windows applies '..' to a link without resolving the link first.
+ return Future.wait([
+ testFile(join(
+ temp, 'dir1', '..', 'link1', '..', 'dir1', 'dir2', 'file2')),
+ testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir1')),
+ testLink(join(temp, 'link1', '..', 'link1'))]);
+ } else {
+ // Non-Windows platforms resolve the link before adding the '..'.
+ return Future.wait([
+ testFile(join(
+ temp, 'dir1', '..', 'link1', '..', 'dir2', 'file2')),
+ testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir2')),
+ testLink(join(temp, 'link1', '..', '..', 'link1'))]);
+ }
+ })
+ .then((_) {
+ Directory.current = temp;
+ return Future.wait([
+ testFile('dir1/dir2/file2'), // Test forward slashes on Windows too.
+ testFile('link1/file2'),
+ testFile(join('dir1', '..', 'dir1', '.', 'file1')),
+ testDir('.'),
+ testLink('link1')]);
+ })
+ .then((_) {
+ Directory.current = 'link1';
+ if (Platform.isWindows) {
+ return Future.wait([
+ testFile('file2'),
+ // Windows applies '..' to a link without resolving the link first.
+ testFile('..\\dir1\\file1'),
+ testLink('.'),
+ testDir('..'),
+ testLink('..\\link1')]);
+ } else {
+ return Future.wait([
+ testFile('file2'),
+ // On non-Windows the link is changed to dir1/dir2 before .. happens.
+ testFile('../dir2/file2'),
+ testDir('.'),
+ testDir('..'),
+ testLink('../../link1')]);
+ }
+ })
+ .whenComplete(() {
+ Directory.current = testsDir;
+ tempDir.delete(recursive: true);
+ });
+ }));
+}
+
+Future makeEntities(String temp) {
+ return new Directory(join(temp, 'dir1', 'dir2')).create(recursive: true)
+ .then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
+ .then((_) => new File(join(temp, 'dir1', 'file1')).create())
+ .then((_) => new Link(join(temp, 'link1'))
+ .create(join(temp, 'dir1', 'dir2')));
+}
+
+Future testFile(String name) {
+ // We test that f.resolveSymbolicLinks points to the same place
+ // as f, because the actual resolved path is not easily predictable.
+ // The location of the temp directory varies from system to system,
+ // and its path includes symbolic links on some systems.
+ //Expect.isTrue(FileSystemEntity.identicalSync(name,
+ // new File(name).resolveSymbolicLinksSync()));
+ return new File(name).resolveSymbolicLinks().then((String resolved) {
+ //Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
+ Expect.isTrue(isAbsolute(resolved));
+ // Test that resolveSymbolicLinks removes all links, .., and . segments.
+ Expect.isFalse(resolved.contains('..'));
+ Expect.isFalse(resolved.contains('./'));
+ Expect.isFalse(resolved.contains('link1'));
+ });
+}
+
+Future testDir(String name) {
+ Expect.isTrue(FileSystemEntity.identicalSync(name,
+ new Directory(name).resolveSymbolicLinksSync()));
+ return new Directory(name).resolveSymbolicLinks().then((String resolved) {
+ Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
+ Expect.isTrue(isAbsolute(resolved));
+ // Test that resolveSymbolicLinks removes all links, .., and . segments.
+ Expect.isFalse(resolved.contains('..'));
+ Expect.isFalse(resolved.contains('./'));
+ Expect.isFalse(resolved.contains('link1'));
+ });
+}
+
+Future testLink(String name) {
+ Expect.isFalse(FileSystemEntity.identicalSync(name,
+ new Link(name).resolveSymbolicLinksSync()));
+ Expect.isTrue(FileSystemEntity.identicalSync(new Link(name).targetSync(),
+ new Link(name).resolveSymbolicLinksSync()));
+ return new Link(name).resolveSymbolicLinks().then((String resolved) {
+ Expect.isFalse(FileSystemEntity.identicalSync(name, resolved));
+ Expect.isTrue(isAbsolute(resolved));
+ // Test that resolveSymbolicLinks removes all links, .., and . segments.
+ Expect.isFalse(resolved.contains('..'));
+ Expect.isFalse(resolved.contains('./'));
+ Expect.isFalse(resolved.contains('link1'));
+ return new Link(name).target()
+ .then((targetName) => FileSystemEntity.identical(targetName, resolved))
+ .then((identical) => Expect.isTrue(identical));
+ });
+}
diff --git a/tests/standalone/vmservice/field_script.dart b/tests/standalone/vmservice/field_script.dart
new file mode 100644
index 0000000..824a502
--- /dev/null
+++ b/tests/standalone/vmservice/field_script.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2013, 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 unknown_command_script;
+
+import 'dart:io';
+import 'dart:typed_data';
+
+class Banana {
+ final Float32List final_fixed_length_list = new Float32List(4);
+ Float32List fixed_length_list = new Float32List(4);
+ String name = '';
+ var a = 44;
+}
+
+
+class BadBanana {
+ final Float32List final_fixed_length_list;
+ final List fixed_length_array = new List(3);
+ num v;
+ const c = 4;
+ BadBanana() : final_fixed_length_list = new Float32List(1);
+ BadBanana.variable() : final_fixed_length_list = new Float32List(2);
+}
+
+main() {
+ for (int i = 0; i < 2000; i++) {
+ Banana b = new Banana();
+ b.name = 'Banana';
+ BadBanana bb = new BadBanana();
+ bb.v = 1.0;
+ }
+ var bb = new BadBanana.variable();
+ bb.v = 2.0;
+ var b = new Banana();
+ b.a = 'foo';
+ print(''); // Print blank line to signal that we are ready.
+ // Wait until signaled from spawning test.
+ stdin.first.then((_) => exit(0));
+}
diff --git a/tests/standalone/vmservice/isolate_bad_class_test.dart b/tests/standalone/vmservice/isolate_bad_class_test.dart
index 4d84afa..8e0b2d3 100644
--- a/tests/standalone/vmservice/isolate_bad_class_test.dart
+++ b/tests/standalone/vmservice/isolate_bad_class_test.dart
@@ -45,7 +45,7 @@
test.makeRequest().then((_) {
var badCollectionRequest =
new BadCollectionTest(port, test._isolateId,
- 'classes').makeRequest();
+ 'foobar').makeRequest();
var nullCollectionRequest =
new NullCollectionTest(port, test._isolateId,
'classes').makeRequest();
diff --git a/tests/standalone/vmservice/isolate_bad_function_test.dart b/tests/standalone/vmservice/isolate_bad_function_test.dart
deleted file mode 100644
index 3b6c414..0000000
--- a/tests/standalone/vmservice/isolate_bad_function_test.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013, 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 isolate_bad_function_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class NullCollectionTest extends VmServiceRequestHelper {
- NullCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection/-99');
-
- onRequestCompleted(Map reply) {
- Expect.equals('null', reply['type']);
- }
-}
-
-class BadCollectionTest extends VmServiceRequestHelper {
- BadCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection');
-
- onRequestCompleted(Map reply) {
- Expect.equals('error', reply['type']);
- }
-}
-
-class IsolateListTest extends VmServiceRequestHelper {
- IsolateListTest(port) : super('http://127.0.0.1:$port/isolates');
-
- int _isolateId;
- onRequestCompleted(Map reply) {
- IsolateListTester tester = new IsolateListTester(reply);
- tester.checkIsolateCount(1);
- tester.checkIsolateNameContains('unknown_isolate_command_script.dart');
- _isolateId = reply['members'][0]['id'];
- }
-}
-
-main() {
- var process = new TestLauncher('unknown_isolate_command_script.dart');
- process.launch().then((port) {
- var test = new IsolateListTest(port);
- test.makeRequest().then((_) {
- var badCollectionRequest =
- new BadCollectionTest(port, test._isolateId,
- 'functions').makeRequest();
- var nullCollectionRequest =
- new NullCollectionTest(port, test._isolateId,
- 'functions').makeRequest();
- var requests = Future.wait([badCollectionRequest, nullCollectionRequest]);
- requests.then((_) {
- process.requestExit();
- });
- });
- });
-}
diff --git a/tests/standalone/vmservice/isolate_bad_library_test.dart b/tests/standalone/vmservice/isolate_bad_library_test.dart
deleted file mode 100644
index c7d2c54..0000000
--- a/tests/standalone/vmservice/isolate_bad_library_test.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2013, 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 isolate_bad_library_test;
-
-import 'dart:async';
-import 'test_helper.dart';
-import 'package:expect/expect.dart';
-
-class NullCollectionTest extends VmServiceRequestHelper {
- NullCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection/-100');
-
- onRequestCompleted(Map reply) {
- Expect.equals('null', reply['type']);
- }
-}
-
-class BadCollectionTest extends VmServiceRequestHelper {
- BadCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection');
-
- onRequestCompleted(Map reply) {
- Expect.equals('error', reply['type']);
- }
-}
-
-class IsolateListTest extends VmServiceRequestHelper {
- IsolateListTest(port) : super('http://127.0.0.1:$port/isolates');
-
- int _isolateId;
- onRequestCompleted(Map reply) {
- IsolateListTester tester = new IsolateListTester(reply);
- tester.checkIsolateCount(1);
- tester.checkIsolateNameContains('unknown_isolate_command_script.dart');
- _isolateId = reply['members'][0]['id'];
- }
-}
-
-main() {
- var process = new TestLauncher('unknown_isolate_command_script.dart');
- process.launch().then((port) {
- var test = new IsolateListTest(port);
- test.makeRequest().then((_) {
- var nullCollectionRequest =
- new NullCollectionTest(port, test._isolateId,
- 'libraries').makeRequest();
- var requests = Future.wait([nullCollectionRequest]);
- requests.then((_) {
- process.requestExit();
- });
- });
- });
-}
diff --git a/tests/standalone/vmservice/isolate_bad_code_test.dart b/tests/standalone/vmservice/isolate_bad_object_test.dart
similarity index 76%
rename from tests/standalone/vmservice/isolate_bad_code_test.dart
rename to tests/standalone/vmservice/isolate_bad_object_test.dart
index fc6ef68..b7d2ef5 100644
--- a/tests/standalone/vmservice/isolate_bad_code_test.dart
+++ b/tests/standalone/vmservice/isolate_bad_object_test.dart
@@ -9,8 +9,8 @@
import 'package:expect/expect.dart';
class NullCollectionTest extends VmServiceRequestHelper {
- NullCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection/50');
+ NullCollectionTest(port, id) :
+ super('http://127.0.0.1:$port/isolates/$id/objects/50');
onRequestCompleted(Map reply) {
Expect.equals('null', reply['type']);
@@ -18,8 +18,8 @@
}
class BadCollectionTest extends VmServiceRequestHelper {
- BadCollectionTest(port, id, collection) :
- super('http://127.0.0.1:$port/isolates/$id/$collection');
+ BadCollectionTest(port, id) :
+ super('http://127.0.0.1:$port/isolates/$id/objects');
onRequestCompleted(Map reply) {
Expect.equals('error', reply['type']);
@@ -44,11 +44,9 @@
var test = new IsolateListTest(port);
test.makeRequest().then((_) {
var badCollectionRequest =
- new BadCollectionTest(port, test._isolateId,
- 'codes').makeRequest();
+ new BadCollectionTest(port, test._isolateId).makeRequest();
var nullCollectionRequest =
- new NullCollectionTest(port, test._isolateId,
- 'codes').makeRequest();
+ new NullCollectionTest(port, test._isolateId).makeRequest();
var requests = Future.wait([badCollectionRequest, nullCollectionRequest]);
requests.then((_) {
process.requestExit();
diff --git a/tests/standalone/vmservice/isolate_class_field_test.dart b/tests/standalone/vmservice/isolate_class_field_test.dart
new file mode 100644
index 0000000..68877a4
--- /dev/null
+++ b/tests/standalone/vmservice/isolate_class_field_test.dart
@@ -0,0 +1,189 @@
+// Copyright (c) 2013, 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 isolate_class_list_test;
+
+import 'dart:async';
+import 'test_helper.dart';
+import 'package:expect/expect.dart';
+
+class BananaClassTest {
+ int port;
+ int isolate_id;
+ int class_id;
+ BananaClassTest(this.port, this.isolate_id, this.class_id);
+
+ _testFieldA(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('a', field['user_name']);
+ Expect.equals('a', field['name']);
+ Expect.equals(false, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals('dynamic', field['guard_class']);
+ Expect.equals(true, field['guard_nullable']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ _testFieldFinalFixedLengthList(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('final_fixed_length_list', field['user_name']);
+ Expect.equals('final_fixed_length_list', field['name']);
+ Expect.equals('Float32List', field['guard_class']['user_name']);
+ Expect.equals(true, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals(4, field['guard_length']);
+ }
+
+ _testFieldFixedLengthList(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('fixed_length_list', field['user_name']);
+ Expect.equals('fixed_length_list', field['name']);
+ Expect.equals(false, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals('Float32List', field['guard_class']['user_name']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ _testFieldName(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('name', field['user_name']);
+ Expect.equals('name', field['name']);
+ Expect.equals(false, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals('String', field['guard_class']['user_name']);
+ Expect.equals(false, field['guard_nullable']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ Future makeRequest() {
+ var fields = ['final_fixed_length_list', 'fixed_length_list', 'name', 'a'];
+ var helper =
+ new ClassFieldRequestHelper(port, isolate_id, class_id, fields);
+ return helper.makeRequest().then((_) {
+ _testFieldA(helper.fields['a']);
+ _testFieldFinalFixedLengthList(helper.fields['final_fixed_length_list']);
+ _testFieldFixedLengthList(helper.fields['fixed_length_list']);
+ _testFieldName(helper.fields['name']);
+ });
+ }
+}
+
+class BadBananaClassTest {
+ int port;
+ int isolate_id;
+ int class_id;
+ BadBananaClassTest(this.port, this.isolate_id, this.class_id);
+
+ _testFieldV(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('v', field['user_name']);
+ Expect.equals('v', field['name']);
+ Expect.equals(false, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals('double', field['guard_class']['user_name']);
+ Expect.equals(true, field['guard_nullable']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ _testFieldC(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('c', field['user_name']);
+ Expect.equals('c', field['name']);
+ Expect.equals(true, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(true, field['const']);
+ Expect.equals('int', field['guard_class']['user_name']);
+ Expect.equals(false, field['guard_nullable']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ _testFieldFinalFixedLengthList(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('final_fixed_length_list', field['user_name']);
+ Expect.equals('final_fixed_length_list', field['name']);
+ Expect.equals('Float32List', field['guard_class']['user_name']);
+ Expect.equals(true, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals('variable', field['guard_length']);
+ }
+
+ _testFieldFixedLengthArray(Map field) {
+ Expect.equals('Field', field['type']);
+ Expect.equals('fixed_length_array', field['user_name']);
+ Expect.equals('fixed_length_array', field['name']);
+ Expect.equals('List', field['guard_class']['user_name']);
+ Expect.equals(true, field['final']);
+ Expect.equals(false, field['static']);
+ Expect.equals(false, field['const']);
+ Expect.equals(3, field['guard_length']);
+ }
+
+ Future makeRequest() {
+ var fields = ['final_fixed_length_list', 'fixed_length_array', 'v', 'c'];
+ var helper =
+ new ClassFieldRequestHelper(port, isolate_id, class_id, fields);
+ return helper.makeRequest().then((_) {
+ _testFieldV(helper.fields['v']);
+ _testFieldC(helper.fields['c']);
+ _testFieldFinalFixedLengthList(helper.fields['final_fixed_length_list']);
+ _testFieldFixedLengthArray(helper.fields['fixed_length_array']);
+ });
+ }
+}
+
+class ClassTableTest extends VmServiceRequestHelper {
+ ClassTableTest(port, id) :
+ super('http://127.0.0.1:$port/isolates/$id/classes/');
+
+ int banana_class_id;
+ int bad_banana_class_id;
+
+ onRequestCompleted(Map reply) {
+ ClassTableHelper helper = new ClassTableHelper(reply);
+ Expect.isTrue(helper.classExists('Banana'));
+ banana_class_id = helper.classId('Banana');
+ Expect.isTrue(helper.classExists('BadBanana'));
+ bad_banana_class_id = helper.classId('BadBanana');
+ }
+}
+
+class IsolateListTest extends VmServiceRequestHelper {
+ IsolateListTest(port) : super('http://127.0.0.1:$port/isolates');
+
+ int _isolateId;
+ onRequestCompleted(Map reply) {
+ IsolateListTester tester = new IsolateListTester(reply);
+ tester.checkIsolateCount(1);
+ tester.checkIsolateNameContains('field_script.dart');
+ _isolateId = tester.checkIsolateNameContains('field_script');
+ }
+}
+
+main() {
+ var process = new TestLauncher('field_script.dart');
+ process.launch().then((port) {
+ var test = new IsolateListTest(port);
+ test.makeRequest().then((_) {
+ var classTableTest = new ClassTableTest(port, test._isolateId);
+ classTableTest.makeRequest().then((_) {
+ var bananaClassTest =
+ new BananaClassTest(port, test._isolateId,
+ classTableTest.banana_class_id);
+ var badBananaClassTest =
+ new BadBananaClassTest(port, test._isolateId,
+ classTableTest.bad_banana_class_id);
+ Future.wait([bananaClassTest.makeRequest(),
+ badBananaClassTest.makeRequest()]).then((_) {
+ process.requestExit();
+ });
+ });
+ });
+ });
+}
diff --git a/tests/standalone/vmservice/isolate_class_test.dart b/tests/standalone/vmservice/isolate_class_test.dart
index 3f9064e..9650443 100644
--- a/tests/standalone/vmservice/isolate_class_test.dart
+++ b/tests/standalone/vmservice/isolate_class_test.dart
@@ -22,7 +22,7 @@
class LibraryTest extends VmServiceRequestHelper {
LibraryTest(port, id, libId) :
- super('http://127.0.0.1:$port/isolates/$id/libraries/$libId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$libId');
int _classId;
onRequestCompleted(Map reply) {
@@ -37,11 +37,11 @@
class RootLibraryTest extends VmServiceRequestHelper {
RootLibraryTest(port, id) :
- super('http://127.0.0.1:$port/isolates/$id/libraries');
+ super('http://127.0.0.1:$port/isolates/$id/library');
int _libId;
onRequestCompleted(Map reply) {
- Expect.equals('@Library', reply['type']);
+ Expect.equals('Library', reply['type']);
Expect.equals('isolate_stacktrace_command_script', reply['name']);
_libId = reply['id'];
}
diff --git a/tests/standalone/vmservice/isolate_code_test.dart b/tests/standalone/vmservice/isolate_code_test.dart
index 8ce58dd..4df1e69 100644
--- a/tests/standalone/vmservice/isolate_code_test.dart
+++ b/tests/standalone/vmservice/isolate_code_test.dart
@@ -10,7 +10,7 @@
class CodeATest extends VmServiceRequestHelper {
CodeATest(port, id, codeId) :
- super('http://127.0.0.1:$port/isolates/$id/codes/$codeId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$codeId');
onRequestCompleted(Map reply) {
Expect.equals('Code', reply['type']);
@@ -21,11 +21,11 @@
class CodeCTest extends VmServiceRequestHelper {
CodeCTest(port, id, codeId) :
- super('http://127.0.0.1:$port/isolates/$id/codes/$codeId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$codeId');
onRequestCompleted(Map reply) {
Expect.equals('Code', reply['type']);
- Expect.equals('C.c', reply['function']['name']);
+ Expect.equals('C.c', reply['function']['user_name']);
Expect.isTrue(reply['disassembly'].length > 0);
}
}
diff --git a/tests/standalone/vmservice/isolate_function_test.dart b/tests/standalone/vmservice/isolate_function_test.dart
index 369616b..4831b61 100644
--- a/tests/standalone/vmservice/isolate_function_test.dart
+++ b/tests/standalone/vmservice/isolate_function_test.dart
@@ -10,17 +10,17 @@
class MethodTest extends VmServiceRequestHelper {
MethodTest(port, id, functionId) :
- super('http://127.0.0.1:$port/isolates/$id/functions/$functionId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$functionId');
onRequestCompleted(Map reply) {
Expect.equals('Function', reply['type']);
- Expect.equals('C.c', reply['name']);
+ Expect.equals('C.c', reply['user_name']);
Expect.equals(false, reply['is_static']);
}
}
class FunctionTest extends VmServiceRequestHelper {
FunctionTest(port, id, functionId) :
- super('http://127.0.0.1:$port/isolates/$id/functions/$functionId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$functionId');
onRequestCompleted(Map reply) {
Expect.equals('Function', reply['type']);
diff --git a/tests/standalone/vmservice/isolate_library_test.dart b/tests/standalone/vmservice/isolate_library_test.dart
index 31d269b..d27f403 100644
--- a/tests/standalone/vmservice/isolate_library_test.dart
+++ b/tests/standalone/vmservice/isolate_library_test.dart
@@ -10,7 +10,7 @@
class LibraryTest extends VmServiceRequestHelper {
LibraryTest(port, id, libId) :
- super('http://127.0.0.1:$port/isolates/$id/libraries/$libId');
+ super('http://127.0.0.1:$port/isolates/$id/objects/$libId');
onRequestCompleted(Map reply) {
Expect.equals('Library', reply['type']);
@@ -20,11 +20,11 @@
class RootLibraryTest extends VmServiceRequestHelper {
RootLibraryTest(port, id) :
- super('http://127.0.0.1:$port/isolates/$id/libraries');
+ super('http://127.0.0.1:$port/isolates/$id/library');
int _libId;
onRequestCompleted(Map reply) {
- Expect.equals('@Library', reply['type']);
+ Expect.equals('Library', reply['type']);
Expect.equals('isolate_stacktrace_command_script', reply['name']);
_libId = reply['id'];
}
diff --git a/tests/standalone/vmservice/test_helper.dart b/tests/standalone/vmservice/test_helper.dart
index 325ecb1..8157648 100644
--- a/tests/standalone/vmservice/test_helper.dart
+++ b/tests/standalone/vmservice/test_helper.dart
@@ -25,21 +25,21 @@
.fold(new BytesBuilder(), (b, d) => b..add(d))
.then((builder) {
print('** GET: $uri');
- _requestCompleted(builder.takeBytes(), response);
+ return _requestCompleted(builder.takeBytes(), response);
});
}).catchError((error) {
onRequestFailed(error);
});
}
- void _requestCompleted(List<int> data, HttpClientResponse response) {
+ Future _requestCompleted(List<int> data, HttpClientResponse response) {
Expect.equals(200, response.statusCode, 'Invalid HTTP Status Code');
var replyAsString;
try {
replyAsString = UTF8.decode(data);
} catch (e) {
onRequestFailed(e);
- return;
+ return null;
}
print('** Response: $replyAsString');
var reply;
@@ -47,28 +47,30 @@
reply = JSON.decode(replyAsString);
} catch (e) {
onRequestFailed(e);
- return;
+ return null;
}
if (reply is! Map) {
onRequestFailed('Reply was not a map: $reply');
- return;
+ return null;
}
if (reply['type'] == null) {
onRequestFailed('Reply does not contain a type key: $reply');
- return;
+ return null;
}
+ var r;
try {
- onRequestCompleted(reply);
+ r = onRequestCompleted(reply);
} catch (e) {
- onRequestFailed('Test callback failed: $e');
+ r = onRequestFailed('Test callback failed: $e');
}
+ return r;
}
- void onRequestFailed(dynamic error) {
+ Future onRequestFailed(dynamic error) {
Expect.fail('Failed to make request: $error');
}
- void onRequestCompleted(Map response);
+ Future onRequestCompleted(Map response);
}
class TestLauncher {
@@ -179,3 +181,76 @@
Expect.isTrue(exists, 'No isolate with id: $id');
}
}
+
+class ClassTableHelper {
+ final Map classTable;
+
+ ClassTableHelper(this.classTable) {
+ Expect.equals('ClassList', classTable['type'], 'Not a ClassTable.');
+ }
+
+ bool classExists(String user_name) {
+ List members = classTable['members'];
+ for (var i = 0; i < members.length; i++) {
+ Map klass = members[i];
+ if (klass['user_name'] == user_name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int classId(String user_name) {
+ List members = classTable['members'];
+ for (var i = 0; i < members.length; i++) {
+ Map klass = members[i];
+ if (klass['user_name'] == user_name) {
+ return klass['id'];
+ }
+ }
+ return -1;
+ }
+}
+
+class FieldRequestHelper extends VmServiceRequestHelper {
+ FieldRequestHelper(port, isolate_id, field_id) :
+ super('http://127.0.0.1:$port/isolates/$isolate_id/objects/$field_id');
+ Map field;
+ onRequestCompleted(Map reply) {
+ Expect.equals('Field', reply['type']);
+ field = reply;
+ return new Future.value(this);
+ }
+}
+
+class ClassFieldRequestHelper extends VmServiceRequestHelper {
+ final List<String> fieldNames;
+ int port_;
+ int isolate_id_;
+ ClassFieldRequestHelper(port, isolate_id, class_id, this.fieldNames) :
+ super('http://127.0.0.1:$port/isolates/$isolate_id/classes/$class_id') {
+ port_ = port;
+ isolate_id_ = isolate_id;
+ }
+ final Map<String, Map> fields = new Map<String, Map>();
+
+ onRequestCompleted(Map reply) {
+ Expect.equals('Class', reply['type']);
+ List<Map> class_fields = reply['fields'];
+ List<Future> requests = new List<Future>();
+ fieldNames.forEach((fn) {
+ class_fields.forEach((f) {
+ if (f['user_name'] == fn) {
+ var request = new FieldRequestHelper(port_, isolate_id_, f['id']);
+ requests.add(request.makeRequest());
+ }
+ });
+ });
+ return Future.wait(requests).then((a) {
+ a.forEach((FieldRequestHelper field) {
+ fields[field.field['user_name']] = field.field;
+ });
+ return this;
+ });
+ }
+}
diff --git a/tests/standalone/vmservice/unknown_isolate_command_test.dart b/tests/standalone/vmservice/unknown_isolate_command_test.dart
index b6abf0b..4ab81d2 100644
--- a/tests/standalone/vmservice/unknown_isolate_command_test.dart
+++ b/tests/standalone/vmservice/unknown_isolate_command_test.dart
@@ -2,17 +2,18 @@
// 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 unknown_isolate_command_test;
+library isolate_class_table_test;
+import 'dart:async';
import 'test_helper.dart';
import 'package:expect/expect.dart';
-class UnknownRequestTest extends VmServiceRequestHelper {
- UnknownRequestTest(port, id) :
- super('http://127.0.0.1:$port/isolates/$id/badrequest');
+class ClassTableTest extends VmServiceRequestHelper {
+ ClassTableTest(port, id) :
+ super('http://127.0.0.1:$port/isolates/$id/classes');
onRequestCompleted(Map reply) {
- Expect.equals('error', reply['type']);
+ ClassTableHelper helper = new ClassTableHelper(reply);
}
}
@@ -23,19 +24,18 @@
onRequestCompleted(Map reply) {
IsolateListTester tester = new IsolateListTester(reply);
tester.checkIsolateCount(1);
- tester.checkIsolateNameContains('unknown_isolate_command_script.dart');
- _isolateId = reply['members'][0]['id'];
+ tester.checkIsolateNameContains('field_script.dart');
+ _isolateId = tester.checkIsolateNameContains('field_script');
}
}
-
main() {
- var process = new TestLauncher('unknown_isolate_command_script.dart');
+ var process = new TestLauncher('field_script.dart');
process.launch().then((port) {
var test = new IsolateListTest(port);
test.makeRequest().then((_) {
- var unknownRequestTest = new UnknownRequestTest(port, test._isolateId);
- unknownRequestTest.makeRequest().then((_) {
+ var classTableTest = new ClassTableTest(port, test._isolateId);
+ classTableTest.makeRequest().then((_) {
process.requestExit();
});
});
diff --git a/tools/VERSION b/tools/VERSION
index 1d4fee3..017668a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 7
-BUILD 4
-PATCH 1
+BUILD 5
+PATCH 0
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
index 53a5d27..2c407d8 100644
--- a/tools/bots/cross-vm.py
+++ b/tools/bots/cross-vm.py
@@ -24,8 +24,8 @@
sys.stdout.flush()
bot.RunProcess(args)
-def tarball_name(arch, mode):
- return 'cross_build_%s_%s.tar.bz2' % (arch, mode)
+def tarball_name(arch, mode, revision):
+ return 'cross_build_%s_%s_%s.tar.bz2' % (arch, mode, revision)
def record_names(name, arch, mode):
return ('record_%s_%s_%s.json' % (name, arch, mode),
@@ -33,8 +33,8 @@
def cross_compiling_builder(arch, mode):
build_py = os.path.join('tools', 'build.py')
-
- tarball = tarball_name(arch, mode)
+ revision = int(os.environ['BUILDBOT_GOT_REVISION'])
+ tarball = tarball_name(arch, mode, revision)
temporary_files = [tarball]
bot.Clobber()
try:
@@ -76,7 +76,8 @@
'--time', '--compiler=none', '--runtime=vm', '--write-debug-log',
'--mode=' + mode, '--arch=' + arch]
- tarball = tarball_name(arch, mode)
+ revision = int(os.environ['BUILDBOT_GOT_REVISION'])
+ tarball = tarball_name(arch, mode, revision)
temporary_files = [tarball]
bot.Clobber()
try:
diff --git a/tools/dom/docs/test/docs_test.dart b/tools/dom/docs/test/docs_test.dart
index 8f8dda8..6664aca 100644
--- a/tools/dom/docs/test/docs_test.dart
+++ b/tools/dom/docs/test/docs_test.dart
@@ -15,6 +15,8 @@
final testJsonPath = path.normalize(path.join(scriptDir, 'test.json'));
main() {
+ // Some tests take more than the default 20 second unittest timeout.
+ unittestConfiguration.timeout = null;
group('docs', () {
var oldJson = new File(json_path);
var testJson = new File(testJsonPath);
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart
index 994d0f2..dd92951 100644
--- a/tools/testing/dart/co19_test.dart
+++ b/tools/testing/dart/co19_test.dart
@@ -27,15 +27,21 @@
import "../../../tests/co19/test_config.dart";
-const List<String> COMMON_ARGUMENTS = const <String>['--report'];
+const List<String> COMMON_ARGUMENTS =
+ const <String>['--report', '--progress=diff', 'co19'];
const List<List<String>> COMMAND_LINES = const <List<String>>[
const <String>['-mrelease,debug', '-rvm', '-cnone'],
const <String>['-mrelease,debug', '-rvm', '-cnone', '--checked'],
const <String>['-mrelease', '-rnone', '-cdartanalyzer'],
- const <String>['-mrelease', '-rvm', '-cdart2dart'],
- const <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk'],
- const <String>['-mrelease', '-rd8', '-cdart2js', '--use-sdk', '--checked']];
+ const <String>['-mrelease', '-rnone', '-cdart2analyzer'],
+ const <String>['-mrelease', '-rvm', '-cdart2dart', '--use-sdk'],
+ const <String>['-mrelease', '-rd8', '-cdart2js', '--use-sdk'],
+ const <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk',
+ '--minified'],
+ const <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk',
+ '--checked'],
+];
void main() {
Options options = new Options();
@@ -51,8 +57,6 @@
arguments.addAll(COMMON_ARGUMENTS);
arguments.addAll(options.arguments);
arguments.addAll(commandLine);
- arguments.add('co19');
- arguments.add('--progress=diff');
configurations.addAll(optionsParser.parse(arguments));
}