Verison 0.5.9.0 .
svn merge -r 22721:22870 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@22879 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index bbb6447..5d3392c 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -215,6 +215,8 @@
status = ProcessBot(name, 'pub')
elif name.startswith('vm-android'):
status = ProcessBot(name, 'android')
+ elif name.startswith('cross') or name.startswith('target'):
+ status = ProcessBot(name, 'cross-vm')
else:
status = ProcessBot(name, 'compiler')
diff --git a/compiler/java/com/google/dart/compiler/parser/DartParser.java b/compiler/java/com/google/dart/compiler/parser/DartParser.java
index 0f60a71..cd5728a 100644
--- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
+++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
@@ -212,6 +212,7 @@
"new",
"null",
"return",
+ "rethrow",
"super",
"switch",
"this",
@@ -4435,8 +4436,8 @@
// TODO(zundel): Possibly we could use Token.IDENTIFIER too, but it is used
// in so many places, it might make recovery worse rather than better.
@Terminals(tokens={Token.IF, Token.SWITCH, Token.WHILE, Token.DO, Token.FOR,
- Token.VAR, Token.FINAL, Token.CONTINUE, Token.BREAK, Token.RETURN, Token.THROW,
- Token.TRY, Token.SEMICOLON })
+ Token.VAR, Token.FINAL, Token.CONTINUE, Token.BREAK, Token.RETHROW,
+ Token.RETURN, Token.THROW, Token.TRY, Token.SEMICOLON })
private DartStatement parseNonLabelledStatement() {
// Try to parse as function declaration.
if (looksLikeFunctionDeclarationOrExpression()) {
@@ -4524,6 +4525,11 @@
case THROW:
return parseExpressionStatement();
+ case RETHROW:
+ consume(Token.RETHROW);
+ beginExpressionStatement();
+ return done(new DartExprStmt(new DartThrowExpression(null)));
+
case TRY:
return parseTryStatement();
diff --git a/compiler/java/com/google/dart/compiler/parser/Token.java b/compiler/java/com/google/dart/compiler/parser/Token.java
index 9f3bbfe..53b3dde 100644
--- a/compiler/java/com/google/dart/compiler/parser/Token.java
+++ b/compiler/java/com/google/dart/compiler/parser/Token.java
@@ -105,6 +105,7 @@
IF("if", 0),
IN("in", 0),
NEW("new", 0),
+ RETHROW("rethrow", 0),
RETURN("return", 0),
SUPER("super", 0),
SWITCH("switch", 0),
diff --git a/pkg/http/lib/src/byte_stream.dart b/pkg/http/lib/src/byte_stream.dart
index eba08d4..20f78747 100644
--- a/pkg/http/lib/src/byte_stream.dart
+++ b/pkg/http/lib/src/byte_stream.dart
@@ -35,5 +35,5 @@
toBytes().then((bytes) => decodeString(bytes, encoding));
Stream<String> toStringStream([Encoding encoding=Encoding.UTF_8]) =>
- map((bytes) => decodeString(bytes, encoding));
+ transform(new StringDecoder(encoding));
}
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index d99b9be..ba5c968 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -95,13 +95,13 @@
/// Converts [bytes] into a [String] according to [encoding].
String decodeString(List<int> bytes, Encoding encoding) {
// TODO(nweiz): implement this once issue 6284 is fixed.
- return new String.fromCharCodes(bytes);
+ return decodeUtf8(bytes);
}
/// Converts [string] into a byte array according to [encoding].
List<int> encodeString(String string, Encoding encoding) {
// TODO(nweiz): implement this once issue 6284 is fixed.
- return string.codeUnits;
+ return encodeUtf8(string);
}
/// A regular expression that matches strings that are composed entirely of
diff --git a/pkg/intl/lib/date_format.dart b/pkg/intl/lib/date_format.dart
index ce79f2f..202ae1b 100644
--- a/pkg/intl/lib/date_format.dart
+++ b/pkg/intl/lib/date_format.dart
@@ -534,6 +534,15 @@
}
/**
+ * Return the [DateSymbol] information for the locale. This can be useful
+ * to find lists like the names of weekdays or months in a locale, but
+ * the structure of this data may change, and it's generally better to go
+ * through the [format] and [parse] APIs. If the locale isn't present, or
+ * is uninitialized, returns null;
+ */
+ DateSymbols get dateSymbols => dateTimeSymbols[_locale];
+
+ /**
* Set the locale. If the locale can't be found, we also look up
* based on alternative versions, e.g. if we have no 'en_CA' we will
* look for 'en' as a fallback. It will also translate en-ca into en_CA.
diff --git a/pkg/intl/test/date_time_format_test_core.dart b/pkg/intl/test/date_time_format_test_core.dart
index 7e007e4..d4a03c1 100644
--- a/pkg/intl/test/date_time_format_test_core.dart
+++ b/pkg/intl/test/date_time_format_test_core.dart
@@ -349,4 +349,10 @@
var knownResult = knownDefault.format(someDate);
expect(result, knownResult);
});
+
+ test('Get symbols', () {
+ var emptyFormat = new DateFormat(null, "en_US");
+ var symbols = emptyFormat.dateSymbols;
+ expect(symbols.NARROWWEEKDAYS, ['S', 'M', 'T', 'W', 'T', 'F', 'S']);
+ });
}
diff --git a/pkg/serialization/lib/serialization.dart b/pkg/serialization/lib/serialization.dart
index 5865840..a95ee3f 100644
--- a/pkg/serialization/lib/serialization.dart
+++ b/pkg/serialization/lib/serialization.dart
@@ -258,8 +258,13 @@
bool get selfDescribing {
// TODO(alanknight): Should this be moved to the format?
// TODO(alanknight): Allow self-describing in the presence of CustomRule.
+ // TODO(alanknight): Don't do duplicate work creating a writer and
+ // serialization here and then re-creating when we actually serialize.
if (_selfDescribing != null) return _selfDescribing;
- _selfDescribing = !rules.any((x) => x is CustomRule && x is! SymbolRule);
+ var meta = ruleSerialization();
+ var w = meta.newWriter();
+ _selfDescribing = !rules.any((rule) =>
+ meta.rulesFor(rule, w, create: false).isEmpty);
return _selfDescribing;
}
@@ -338,6 +343,7 @@
addRule(new ListRuleEssential());
addRule(new MapRule());
addRule(new SymbolRule());
+ addRule(new DateTimeRule());
}
/**
@@ -394,7 +400,7 @@
* Return the list of SerializationRule that apply to [object]. For
* internal use, but public because it's used in testing.
*/
- Iterable<SerializationRule> rulesFor(object, Writer w) {
+ Iterable<SerializationRule> rulesFor(object, Writer w, {create : true}) {
// This has a couple of edge cases.
// 1) The owning object may have indicated we should use a different
// rule than the default.
@@ -422,7 +428,7 @@
(each) => each.appliesTo(target, w));
if (applicable.isEmpty) {
- return [addRuleFor(target)];
+ return create ? [addRuleFor(target)] : applicable;
}
if (applicable.length == 1) return applicable;
@@ -466,7 +472,8 @@
..addRule(new NamedObjectRule())
..addRule(new MirrorRule())
..addRuleFor(new MirrorRule())
- ..addRuleFor(new SymbolRule());
+ ..addRuleFor(new SymbolRule())
+ ..addRuleFor(new DateTimeRule());
meta.namedObjects = namedObjects;
return meta;
}
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 53c0f72..4ffe966 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -492,6 +492,18 @@
bool get hasVariableLengthEntries => false;
}
+/** A hard-coded rule for DateTime. */
+class DateTimeRule extends CustomRule {
+ bool appliesTo(instance, _) => instance is DateTime;
+ List getState(DateTime date) => [date.millisecondsSinceEpoch, date.isUtc];
+ create(List state) =>
+ new DateTime.fromMillisecondsSinceEpoch(state[0], isUtc: state[1]);
+ void setState(date, state) {}
+ // Let the system know we don't have to store a length for these.
+ int get dataLength => 2;
+ bool get hasVariableLengthEntries => false;
+}
+
/** Create a lazy list/map that will inflate its items on demand in [r]. */
_lazy(l, Reader r) {
if (l is List) return new _LazyList(l, r);
@@ -561,7 +573,7 @@
// These operations, and other inherited methods that iterate over the whole
// list will work, but may be expensive, and are probably
// best avoided.
- List get _inflated => _raw.map(_reader.inflateReference);
+ Iterable get _inflated => _raw.map(_reader.inflateReference);
Iterator get iterator => _inflated.iterator;
indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index eeca085..1b79206 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -144,15 +144,14 @@
test('date', () {
var date = new DateTime.now();
- var s = new Serialization()
- ..addRuleFor(date,
- constructorFields : ["year", "month", "day", "hour", "minute",
- "second", "millisecond", "isUtc"])
- .configureForMaps();
- var state = states(date, s).first;
- expect(state["year"],date.year);
- expect(state["isUtc"],date.isUtc);
- expect(state["millisecond"], date.millisecond);
+ var utcDate = new DateTime.utc(date.year, date.month, date.day,
+ date.hour, date.minute, date.second, date.millisecond);
+ var s = new Serialization();
+ var out = s.write([date, utcDate]);
+ expect(s.selfDescribing, isTrue);
+ var input = s.read(out);
+ expect(input.first, date);
+ expect(input.last, utcDate);
});
test('Iteration helpers', () {
@@ -220,7 +219,7 @@
var w = new Writer(s, const InternalMapFormat());
w.trace = new Trace(w);
w.write(n1);
- expect(w.states.length, 6); // prims, lists, essential lists, basic, symbol
+ expect(w.states.length, 7); // prims, lists * 2, basic, symbol, date
var children = 0, name = 1, parent = 2;
var nodeRule = s.rules.firstWhere((x) => x is BasicRule);
List rootNode = w.states[nodeRule.number].where(
diff --git a/pkg/webdriver/lib/webdriver.dart b/pkg/webdriver/lib/webdriver.dart
index 724332d9..e257bd6 100644
--- a/pkg/webdriver/lib/webdriver.dart
+++ b/pkg/webdriver/lib/webdriver.dart
@@ -285,11 +285,12 @@
var value = null;
// For some reason we get a bunch of NULs on the end
// of the text and the json.parse blows up on these, so
- // strip them with trim().
+ // strip them.
// These NULs can be seen in the TCP packet, so it is not
// an issue with character encoding; it seems to be a bug
// in WebDriver stack.
- results = new String.fromCharCodes(body).trim();
+ results = new String.fromCharCodes(body)
+ .replaceAll(new RegExp('\u{0}*\$'), '');
if (!successCodes.contains(rsp.statusCode)) {
_failRequest(completer,
'Unexpected response ${rsp.statusCode}; $results');
diff --git a/runtime/bin/filter.cc b/runtime/bin/filter.cc
index 2193603..d864c34 100644
--- a/runtime/bin/filter.cc
+++ b/runtime/bin/filter.cc
@@ -135,9 +135,16 @@
Dart_ThrowException(DartUtils::NewInternalError(
"Failed to get 'flush' parameter"));
}
+ Dart_Handle end_obj = Dart_GetNativeArgument(args, 2);
+ bool end;
+ if (Dart_IsError(Dart_BooleanValue(end_obj, &end))) {
+ Dart_ThrowException(DartUtils::NewInternalError(
+ "Failed to get 'end' parameter"));
+ }
intptr_t read = filter->Processed(filter->processed_buffer(),
filter->processed_buffer_size(),
- flush);
+ flush,
+ end);
if (read < 0) {
// Error, end filter.
EndFilter(filter_obj, filter);
@@ -216,10 +223,14 @@
intptr_t ZLibDeflateFilter::Processed(uint8_t* buffer,
intptr_t length,
- bool flush) {
+ bool flush,
+ bool end) {
stream_.avail_out = length;
stream_.next_out = buffer;
- switch (deflate(&stream_, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
+ switch (deflate(&stream_,
+ end ? Z_FINISH : flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
+ case Z_STREAM_END:
+ case Z_BUF_ERROR:
case Z_OK: {
intptr_t processed = length - stream_.avail_out;
if (processed == 0) {
@@ -232,13 +243,6 @@
}
}
- case Z_STREAM_END:
- case Z_BUF_ERROR:
- // We processed all available input data.
- delete[] current_buffer_;
- current_buffer_ = NULL;
- return 0;
-
default:
case Z_STREAM_ERROR:
// An error occoured.
@@ -279,10 +283,12 @@
intptr_t ZLibInflateFilter::Processed(uint8_t* buffer,
intptr_t length,
- bool flush) {
+ bool flush,
+ bool end) {
stream_.avail_out = length;
stream_.next_out = buffer;
- switch (inflate(&stream_, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
+ switch (inflate(&stream_,
+ end ? Z_FINISH : flush ? Z_SYNC_FLUSH : Z_NO_FLUSH)) {
case Z_STREAM_END:
case Z_BUF_ERROR:
case Z_OK: {
diff --git a/runtime/bin/filter.h b/runtime/bin/filter.h
index fcfaa0e..4c59759 100644
--- a/runtime/bin/filter.h
+++ b/runtime/bin/filter.h
@@ -26,7 +26,10 @@
* a delete[] call.
*/
virtual bool Process(uint8_t* data, intptr_t length) = 0;
- virtual intptr_t Processed(uint8_t* buffer, intptr_t length, bool finish) = 0;
+ virtual intptr_t Processed(uint8_t* buffer,
+ intptr_t length,
+ bool finish,
+ bool end) = 0;
static Dart_Handle SetFilterPointerNativeField(Dart_Handle filter,
Filter* filter_pointer);
@@ -57,7 +60,10 @@
virtual bool Init();
virtual bool Process(uint8_t* data, intptr_t length);
- virtual intptr_t Processed(uint8_t* buffer, intptr_t length, bool finish);
+ virtual intptr_t Processed(uint8_t* buffer,
+ intptr_t length,
+ bool finish,
+ bool end);
private:
const bool gzip_;
@@ -75,7 +81,10 @@
virtual bool Init();
virtual bool Process(uint8_t* data, intptr_t length);
- virtual intptr_t Processed(uint8_t* buffer, intptr_t length, bool finish);
+ virtual intptr_t Processed(uint8_t* buffer,
+ intptr_t length,
+ bool finish,
+ bool end);
private:
uint8_t* current_buffer_;
diff --git a/runtime/bin/filter_patch.dart b/runtime/bin/filter_patch.dart
index 5a04241..b549aaf 100644
--- a/runtime/bin/filter_patch.dart
+++ b/runtime/bin/filter_patch.dart
@@ -6,7 +6,8 @@
class _FilterImpl extends NativeFieldWrapperClass1 implements _Filter {
void process(List<int> data) native "Filter_Process";
- List<int> processed({bool flush: true}) native "Filter_Processed";
+ List<int> processed({bool flush: true, bool end: false})
+ native "Filter_Processed";
void end() native "Filter_End";
}
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 38bc31a..4678ba6 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -28,7 +28,7 @@
V(Filter_CreateZLibInflate, 1) \
V(Filter_End, 1) \
V(Filter_Process, 2) \
- V(Filter_Processed, 2) \
+ V(Filter_Processed, 3) \
V(InternetAddress_Fixed, 1) \
V(Platform_NumberOfProcessors, 0) \
V(Platform_OperatingSystem, 0) \
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 035b2e6..2b1f1c7 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -80,10 +80,8 @@
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
}
const Bigint& big = Bigint::Handle(BigintOperations::NewFromDouble(val));
- if (BigintOperations::FitsIntoSmi(big)) {
- return BigintOperations::ToSmi(big);
- } else if (BigintOperations::FitsIntoMint(big)) {
- return Mint::New(BigintOperations::ToMint(big));
+ if (BigintOperations::FitsIntoMint(big)) {
+ return Integer::New(BigintOperations::ToMint(big));
} else {
return big.raw();
}
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index cdbaf24..05f693c 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -258,10 +258,8 @@
Integer& result = Integer::Handle(); \
if (value > static_cast<uint64_t>(Mint::kMaxValue)) { \
result = BigintOperations::NewFromUint64(value); \
- } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { \
- result = Mint::New(value); \
} else { \
- result = Smi::New(value); \
+ result = Integer::New(value); \
} \
return result.raw(); \
} \
@@ -409,10 +407,8 @@
}
if (value > static_cast<uint64_t>(Mint::kMaxValue)) {
return BigintOperations::NewFromUint64(value);
- } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) {
- return Mint::New(value);
}
- return Smi::New(value);
+ return Integer::New(value);
}
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 5604c26..d496837 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -243,10 +243,6 @@
EmitIType(ADDIU, rs, rt, imm_value);
}
- void adds(FRegister fd, FRegister fs, FRegister ft) {
- EmitFpuRType(COP1, FMT_S, ft, fs, fd, COP1_ADD);
- }
-
void addu(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, ADDU);
}
@@ -272,6 +268,18 @@
EmitBranchDelayNop();
}
+ // Branch on floating point false.
+ void bc1f(Label* l) {
+ EmitFpuBranch(false, l);
+ EmitBranchDelayNop();
+ }
+
+ // Branch on floating point true.
+ void bc1t(Label* l) {
+ EmitFpuBranch(true, l);
+ EmitBranchDelayNop();
+ }
+
// Branch if equal.
void beq(Register rs, Register rt, Label* l) {
ASSERT(!in_delay_slot_);
@@ -369,6 +377,62 @@
BREAK << kFunctionShift);
}
+ // FPU compare, always false.
+ void cfd(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F);
+ }
+
+ // FPU compare, true if unordered, i.e. one is NaN.
+ void cund(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UN);
+ }
+
+ // FPU compare, true if equal.
+ void ceqd(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_EQ);
+ }
+
+ // FPU compare, true if unordered or equal.
+ void cueqd(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UEQ);
+ }
+
+ // FPU compare, true if less than.
+ void coltd(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLT);
+ }
+
+ // FPU compare, true if unordered or less than.
+ void cultd(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULT);
+ }
+
+ // FPU compare, true if less or equal.
+ void coled(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLE);
+ }
+
+ // FPU compare, true if unordered or less or equal.
+ void culed(FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULE);
+ }
+
void clo(Register rd, Register rs) {
EmitRType(SPECIAL2, rs, rd, rd, 0, CLO);
}
@@ -377,10 +441,36 @@
EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ);
}
+ // Converts a 32-bit signed int in fs to a double in fd.
+ void cvtdw(FRegister fd, FRegister fs) {
+ ASSERT(EvenFPURegister(fd));
+ EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D);
+ }
+
+ // Converts a 64-bit signed int in fs to a double in fd.
+ void cvtdl(FRegister fd, FRegister fs) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(fd));
+ EmitFpuRType(COP1, FMT_L, F0, fs, fd, COP1_CVT_D);
+ }
+
+ void cvtwd(FRegister fd, FRegister fs) {
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(fd));
+ EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_W);
+ }
+
void div(Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, R0, 0, DIV);
}
+ void divd(FRegister fd, FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV);
+ }
+
void divu(Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, R0, 0, DIVU);
}
@@ -477,6 +567,13 @@
fs << kFsShift);
}
+ void muld(FRegister fd, FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL);
+ }
+
void mult(Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, R0, 0, MULT);
}
@@ -532,6 +629,12 @@
EmitRType(SPECIAL, rs, rt, rd, 0, SLTU);
}
+ void sqrtd(FRegister fd, FRegister fs) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_SQRT);
+ }
+
void sra(Register rd, Register rt, int sa) {
EmitRType(SPECIAL, R0, rt, rd, sa, SRA);
}
@@ -548,6 +651,13 @@
EmitRType(SPECIAL, rs, rt, rd, 0, SRLV);
}
+ void subd(FRegister fd, FRegister fs, FRegister ft) {
+ ASSERT(EvenFPURegister(fd));
+ ASSERT(EvenFPURegister(fs));
+ ASSERT(EvenFPURegister(ft));
+ EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB);
+ }
+
void subu(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, SUBU);
}
@@ -994,6 +1104,28 @@
}
}
+ void EmitFpuBranch(bool kind, Label *label) {
+ const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
+ if (label->IsBound()) {
+ // Relative destination from an instruction after the branch.
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ const uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ Emit(COP1 << kOpcodeShift |
+ COP1_BC << kCop1SubShift |
+ b16 |
+ dest_off);
+ } else {
+ const int position = buffer_.Size();
+ const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
+ Emit(COP1 << kOpcodeShift |
+ COP1_BC << kCop1SubShift |
+ b16 |
+ dest_off);
+ label->LinkTo(position);
+ }
+ }
+
static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
static int DecodeBranchOffset(int32_t instr);
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index f4cdcdc..1dc7d33 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -1203,23 +1203,6 @@
}
-ASSEMBLER_TEST_GENERATE(Adds, assembler) {
- __ LoadImmediate(F0, 1.0f);
- __ LoadImmediate(F2, 2.0f);
- __ adds(F4, F0, F2);
- __ mfc1(V0, F4);
- __ Ret();
-}
-
-
-ASSEMBLER_TEST_RUN(Adds, test) {
- typedef double (*SimpleCode)();
- EXPECT(test != NULL);
- double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
- EXPECT_FLOAT_EQ(3.0, res, 0.001);
-}
-
-
ASSEMBLER_TEST_GENERATE(Movd, assembler) {
__ LoadImmediate(F0, 1.0);
__ movd(F2, F0);
@@ -1237,22 +1220,6 @@
}
-ASSEMBLER_TEST_GENERATE(Movs, assembler) {
- __ LoadImmediate(F0, 1.0f);
- __ movd(F2, F0);
- __ mfc1(V0, F2);
- __ Ret();
-}
-
-
-ASSEMBLER_TEST_RUN(Movs, test) {
- typedef double (*SimpleCode)();
- EXPECT(test != NULL);
- double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
- EXPECT_FLOAT_EQ(1.0, res, 0.001);
-}
-
-
ASSEMBLER_TEST_GENERATE(Sdc1Ldc1, assembler) {
__ AddImmediate(SP, -8 * kWordSize);
__ LoadImmediate(T1, ~(8 - 1));
@@ -1274,60 +1241,424 @@
}
-ASSEMBLER_TEST_GENERATE(Swc1Lwc1, assembler) {
- __ AddImmediate(SP, -1 * kWordSize);
- __ LoadImmediate(F0, 1.0f);
- __ swc1(F0, Address(SP));
- __ lwc1(F1, Address(SP));
- __ mfc1(V0, F1);
- __ AddImmediate(SP, 1 * kWordSize);
- __ Ret();
-}
-
-ASSEMBLER_TEST_RUN(Swc1Lwc1, test) {
- typedef double (*SimpleCode)();
- EXPECT(test != NULL);
- double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
- EXPECT_FLOAT_EQ(1.0, res, 0.001);
-}
-
-
-ASSEMBLER_TEST_GENERATE(Adds_NaN, assembler) {
- __ LoadImmediate(F0, 1.0f);
- __ LoadImmediate(T0, 0x7f800001); // NaN
- __ mtc1(T0, F2);
- __ adds(F4, F0, F2);
+ASSEMBLER_TEST_GENERATE(Addd_NaN, assembler) {
+ __ LoadImmediate(F0, 1.0);
+ // Double non-signaling NaN is 0x7FF8000000000000.
+ __ LoadImmediate(T0, 0x7FF80000);
+ __ mtc1(ZR, F2); // Load upper bits of NaN.
+ __ mtc1(T0, F3); // Load lower bits of NaN.
+ __ addd(F4, F0, F2);
__ mfc1(V0, F4);
+ __ mfc1(V1, F5);
__ Ret();
}
-ASSEMBLER_TEST_RUN(Adds_NaN, test) {
+ASSEMBLER_TEST_RUN(Addd_NaN, test) {
typedef double (*SimpleCode)();
EXPECT(test != NULL);
- float res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
EXPECT_EQ(isnan(res), true);
}
-ASSEMBLER_TEST_GENERATE(Adds_Inf, assembler) {
+ASSEMBLER_TEST_GENERATE(Addd_Inf, assembler) {
__ LoadImmediate(F0, 1.0f);
- __ LoadImmediate(T0, 0x7f800000); // +inf
- __ mtc1(T0, F2);
- __ adds(F4, F0, F2);
+ __ LoadImmediate(T0, 0x7FF00000); // +inf
+ __ mtc1(ZR, F2);
+ __ mtc1(T0, F3);
+ __ addd(F4, F0, F2);
__ mfc1(V0, F4);
+ __ mfc1(V1, F5);
__ Ret();
}
-ASSEMBLER_TEST_RUN(Adds_Inf, test) {
+ASSEMBLER_TEST_RUN(Addd_Inf, test) {
typedef double (*SimpleCode)();
EXPECT(test != NULL);
- float res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
EXPECT_EQ(isfinite(res), false);
}
+ASSEMBLER_TEST_GENERATE(Subd, assembler) {
+ __ LoadImmediate(F0, 2.5);
+ __ LoadImmediate(F2, 1.5);
+ __ subd(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ mfc1(V1, F5);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Subd, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Muld, assembler) {
+ __ LoadImmediate(F0, 6.0);
+ __ LoadImmediate(F2, 7.0);
+ __ muld(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ mfc1(V1, F5);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Muld, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(42.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Divd, assembler) {
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 7.0);
+ __ divd(F4, F0, F2);
+ __ mfc1(V0, F4);
+ __ mfc1(V1, F5);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Divd, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(6.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Sqrtd, assembler) {
+ __ LoadImmediate(F0, 36.0);
+ __ sqrtd(F4, F0);
+ __ mfc1(V0, F4);
+ __ mfc1(V1, F5);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Sqrtd, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(6.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CUN, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(T0, 0x7FF80000);
+ __ mtc1(ZR, F2);
+ __ mtc1(T0, F3);
+ __ LoadImmediate(V0, 42);
+ __ cund(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CUN, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CUN_not_taken, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 42.0);
+ __ LoadImmediate(V0, 42);
+ __ cund(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CUN_not_taken, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CEq, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.5);
+ __ LoadImmediate(F2, 42.5);
+ __ LoadImmediate(V0, 42);
+ __ ceqd(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CEq, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CEq_not_taken, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 42.5);
+ __ LoadImmediate(V0, 42);
+ __ ceqd(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CEq_not_taken, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CEq_false, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 42.5);
+ __ LoadImmediate(V0, 42);
+ __ ceqd(F0, F2);
+ __ bc1f(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CEq_false, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CEq_false_not_taken, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.5);
+ __ LoadImmediate(F2, 42.5);
+ __ LoadImmediate(V0, 42);
+ __ ceqd(F0, F2);
+ __ bc1f(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CEq_false_not_taken, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1COLT, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 42.5);
+ __ LoadImmediate(V0, 42);
+ __ coltd(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1COLT, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1COLT_not_taken, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.5);
+ __ LoadImmediate(F2, 42.0);
+ __ LoadImmediate(V0, 42);
+ __ coltd(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1COLT_not_taken, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1COLE, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.0);
+ __ LoadImmediate(F2, 42.0);
+ __ LoadImmediate(V0, 42);
+ __ coled(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1COLE, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1COLE_not_taken, assembler) {
+ Label is_true;
+
+ __ LoadImmediate(F0, 42.5);
+ __ LoadImmediate(F2, 42.0);
+ __ LoadImmediate(V0, 42);
+ __ coled(F0, F2);
+ __ bc1t(&is_true);
+ __ mov(V0, ZR);
+ __ Bind(&is_true);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1COLE_not_taken, test) {
+ typedef int (*SimpleCode)();
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtDW, assembler) {
+ __ LoadImmediate(T0, 42);
+ __ mtc1(T0, F0);
+ __ cvtdw(F2, F0);
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtDW, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(42.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtDW_neg, assembler) {
+ __ LoadImmediate(T0, -42);
+ __ mtc1(T0, F0);
+ __ cvtdw(F2, F0);
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtDW_neg, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(-42.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtDL, assembler) {
+ __ LoadImmediate(T0, 0x1);
+ __ mtc1(ZR, F0);
+ __ mtc1(T0, F1); // D0 <- 0x100000000 = 4294967296
+ __ cvtdl(F2, F0);
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtDL, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(4294967296.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtDL_neg, assembler) {
+ __ LoadImmediate(T0, 0xffffffff);
+ __ mtc1(T0, F0);
+ __ mtc1(T0, F1); // D0 <- 0xffffffffffffffff = -1
+ __ cvtdl(F2, F0);
+ __ mfc1(V0, F2);
+ __ mfc1(V1, F3);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtDL_neg, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(-1.0, res, 0.001);
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtWD, assembler) {
+ __ LoadImmediate(F0, 42.0);
+ __ cvtwd(F2, F0);
+ __ mfc1(V0, F2);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtWD, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Cop1CvtWD_neg, assembler) {
+ __ LoadImmediate(F0, -42.0);
+ __ cvtwd(F2, F0);
+ __ mfc1(V0, F2);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtWD_neg, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
// Called from assembler_test.cc.
// RA: return address.
// A0: context.
diff --git a/runtime/vm/bigint_operations.cc b/runtime/vm/bigint_operations.cc
index 0e5e7c9..118a836 100644
--- a/runtime/vm/bigint_operations.cc
+++ b/runtime/vm/bigint_operations.cc
@@ -664,6 +664,9 @@
int64_t BigintOperations::ToMint(const Bigint& bigint) {
+ if (bigint.IsZero()) {
+ return 0;
+ }
ASSERT(FitsIntoMint(bigint));
int64_t value = AbsToUint64(bigint);
if (bigint.IsNegative()) {
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index c614a9c..8d74e7b 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -815,6 +815,17 @@
}
+// Gets called from debug stub when code reaches a breakpoint
+// at the stub call to update the ic cache on equality comparison
+// with null.
+DEFINE_RUNTIME_ENTRY(BreakpointEqualNullHandler, 0) {
+ ASSERT(arguments.ArgCount() ==
+ kBreakpointEqualNullHandlerRuntimeEntry.argument_count());
+ ASSERT(isolate->debugger() != NULL);
+ isolate->debugger()->SignalBpReached();
+}
+
+
// Gets called from debug stub when code reaches a breakpoint.
DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 0) {
ASSERT(arguments.ArgCount() ==
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index a7d81d1..512d6da 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -28,6 +28,7 @@
DECLARE_RUNTIME_ENTRY(BreakpointStaticHandler);
DECLARE_RUNTIME_ENTRY(BreakpointReturnHandler);
DECLARE_RUNTIME_ENTRY(BreakpointDynamicHandler);
+DECLARE_RUNTIME_ENTRY(BreakpointEqualNullHandler);
DECLARE_RUNTIME_ENTRY(CloneContext);
DECLARE_RUNTIME_ENTRY(Deoptimize);
DECLARE_RUNTIME_ENTRY(FixCallersTarget);
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index 1748d0e..32f608b 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -249,6 +249,8 @@
kInstrBits = 26,
kBreakCodeShift = 6,
kBreakCodeBits = 20,
+ kFpuCCShift = 8,
+ kFpuCCBits = 3,
kBranchOffsetMask = 0x0000ffff,
};
@@ -376,15 +378,32 @@
enum Cop1Function {
- COP1_ADD = 0,
- COP1_MOV = 6,
+ COP1_ADD = 0x00,
+ COP1_SUB = 0x01,
+ COP1_MUL = 0x02,
+ COP1_DIV = 0x03,
+ COP1_SQRT = 0x04,
+ COP1_MOV = 0x06,
+ COP1_CVT_D = 0x21,
+ COP1_CVT_W = 0x24,
+ COP1_C_F = 0x30,
+ COP1_C_UN = 0x31,
+ COP1_C_EQ = 0x32,
+ COP1_C_UEQ = 0x33,
+ COP1_C_OLT = 0x34,
+ COP1_C_ULT = 0x35,
+ COP1_C_OLE = 0x36,
+ COP1_C_ULE = 0x37,
};
+
enum Cop1Sub {
COP1_MF = 0,
COP1_MT = 4,
+ COP1_BC = 8,
};
+
enum Format {
FMT_S = 16,
FMT_D = 17,
@@ -393,6 +412,7 @@
FMT_PS = 22,
};
+
class Instr {
public:
enum {
@@ -519,6 +539,10 @@
return static_cast<Format>(Bits(kFmtShift, kFmtBits));
}
+ inline int32_t FpuCCField() const {
+ return Bits(kFpuCCShift, kFpuCCBits);
+ }
+
// Instructions are read out of a code stream. The only way to get a
// reference to an instruction is to convert a pc. There is no way
// to allocate or create instances of class Instr.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index db0b878..aa6738a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2488,17 +2488,18 @@
static Dart_Handle NewExternalTypedData(
+ Isolate* isolate,
intptr_t cid,
void* data,
intptr_t length,
void* peer,
Dart_WeakPersistentHandleFinalizer callback) {
CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
- const ExternalTypedData& obj = ExternalTypedData::Handle(
- ExternalTypedData::New(cid,
- reinterpret_cast<uint8_t*>(data),
- length));
- return reinterpret_cast<Dart_Handle>(obj.AddFinalizer(peer, callback));
+ const ExternalTypedData& result = ExternalTypedData::Handle(
+ isolate,
+ ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length));
+ result.AddFinalizer(peer, callback);
+ return Api::NewHandle(isolate, result.raw());
}
@@ -2507,7 +2508,8 @@
intptr_t length,
void* peer,
Dart_WeakPersistentHandleFinalizer cb) {
- Dart_Handle ext_data = NewExternalTypedData(kExternalTypedDataUint8ArrayCid,
+ Dart_Handle ext_data = NewExternalTypedData(isolate,
+ kExternalTypedDataUint8ArrayCid,
data,
length,
peer,
@@ -2600,73 +2602,85 @@
case kByteData:
return NewExternalByteData(isolate, data, length, peer, callback);
case kInt8:
- return NewExternalTypedData(kExternalTypedDataInt8ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataInt8ArrayCid,
data,
length,
peer,
callback);
case kUint8:
- return NewExternalTypedData(kExternalTypedDataUint8ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataUint8ArrayCid,
data,
length,
peer,
callback);
case kUint8Clamped:
- return NewExternalTypedData(kExternalTypedDataUint8ClampedArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataUint8ClampedArrayCid,
data,
length,
peer,
callback);
case kInt16:
- return NewExternalTypedData(kExternalTypedDataInt16ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataInt16ArrayCid,
data,
length,
peer,
callback);
case kUint16:
- return NewExternalTypedData(kExternalTypedDataUint16ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataUint16ArrayCid,
data,
length,
peer,
callback);
case kInt32:
- return NewExternalTypedData(kExternalTypedDataInt32ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataInt32ArrayCid,
data,
length,
peer,
callback);
case kUint32:
- return NewExternalTypedData(kExternalTypedDataUint32ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataUint32ArrayCid,
data,
length,
peer,
callback);
case kInt64:
- return NewExternalTypedData(kExternalTypedDataInt64ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataInt64ArrayCid,
data,
length,
peer,
callback);
case kUint64:
- return NewExternalTypedData(kExternalTypedDataUint64ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataUint64ArrayCid,
data,
length,
peer,
callback);
case kFloat32:
- return NewExternalTypedData(kExternalTypedDataFloat32ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataFloat32ArrayCid,
data,
length,
peer,
callback);
case kFloat64:
- return NewExternalTypedData(kExternalTypedDataFloat64ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataFloat64ArrayCid,
data,
length,
peer,
callback);
case kFloat32x4:
- return NewExternalTypedData(kExternalTypedDataFloat32x4ArrayCid,
+ return NewExternalTypedData(isolate,
+ kExternalTypedDataFloat32x4ArrayCid,
data,
length,
peer,
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index b3e96e6..047df63 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -1379,12 +1379,15 @@
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
- obj = Dart_NewExternalTypedData(kFloat32x4,
- data,
- 10,
- &peer,
- ExternalTypedDataCallbackFinalizer);
- CheckFloat32x4Data(obj);
+ // Push a scope so that we can collect the local handle created as part of
+ // Dart_NewExternalTypedData.
+ Dart_EnterScope();
+ {
+ Dart_Handle lcl = Dart_NewExternalTypedData(
+ kFloat32x4, data, 10, &peer, ExternalTypedDataCallbackFinalizer);
+ CheckFloat32x4Data(lcl);
+ }
+ Dart_ExitScope();
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
EXPECT(peer == 42);
}
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index cb63b40..a470b0a 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -58,7 +58,7 @@
next_(NULL) {
ASSERT(!func.IsNull());
ASSERT((func.token_pos() <= token_pos_) &&
- (token_pos_ < func.end_token_pos()));
+ (token_pos_ <= func.end_token_pos()));
}
@@ -583,6 +583,15 @@
}
+static bool IsSafePoint(PcDescriptors::Kind kind) {
+ return ((kind == PcDescriptors::kIcCall) ||
+ (kind == PcDescriptors::kFuncCall) ||
+ (kind == PcDescriptors::kClosureCall) ||
+ (kind == PcDescriptors::kReturn) ||
+ (kind == PcDescriptors::kEqualNull));
+}
+
+
CodeBreakpoint::CodeBreakpoint(const Function& func, intptr_t pc_desc_index)
: function_(func.raw()),
pc_desc_index_(pc_desc_index),
@@ -601,10 +610,7 @@
pc_ = desc.PC(pc_desc_index);
ASSERT(pc_ != 0);
breakpoint_kind_ = desc.DescriptorKind(pc_desc_index);
- ASSERT((breakpoint_kind_ == PcDescriptors::kIcCall) ||
- (breakpoint_kind_ == PcDescriptors::kFuncCall) ||
- (breakpoint_kind_ == PcDescriptors::kClosureCall) ||
- (breakpoint_kind_ == PcDescriptors::kReturn));
+ ASSERT(IsSafePoint(breakpoint_kind_));
}
@@ -675,6 +681,15 @@
StubCode::BreakpointClosureEntryPoint());
break;
}
+ case PcDescriptors::kEqualNull: {
+ const Code& code =
+ Code::Handle(Function::Handle(function_).unoptimized_code());
+ saved_bytes_.target_address_ =
+ CodePatcher::GetStaticCallTargetAt(pc_, code);
+ CodePatcher::PatchStaticCallAt(pc_, code,
+ StubCode::BreakpointEqNullEntryPoint());
+ break;
+ }
case PcDescriptors::kReturn:
PatchFunctionReturn();
break;
@@ -696,7 +711,8 @@
break;
}
case PcDescriptors::kFuncCall:
- case PcDescriptors::kClosureCall: {
+ case PcDescriptors::kClosureCall:
+ case PcDescriptors::kEqualNull: {
const Code& code =
Code::Handle(Function::Handle(function_).unoptimized_code());
CodePatcher::PatchStaticCallAt(pc_, code,
@@ -882,11 +898,7 @@
bpt->Enable();
continue;
}
- PcDescriptors::Kind kind = desc.DescriptorKind(i);
- if ((kind == PcDescriptors::kIcCall) ||
- (kind == PcDescriptors::kFuncCall) ||
- (kind == PcDescriptors::kClosureCall) ||
- (kind == PcDescriptors::kReturn)) {
+ if (IsSafePoint(desc.DescriptorKind(i))) {
bpt = new CodeBreakpoint(target_function, i);
RegisterCodeBreakpoint(bpt);
bpt->Enable();
@@ -1028,18 +1040,20 @@
}
-CodeBreakpoint* Debugger::MakeCodeBreakpoint(const Function& func,
- intptr_t first_token_pos,
- intptr_t last_token_pos) {
+// Given a function and a token position range, return the best fit
+// token position to set a breakpoint.
+// If multiple possible breakpoint positions are within the given range,
+// the one with the lowest machine code address is picked.
+// If no possible breakpoint location exists in the given range, the closest
+// token position after the range is returned.
+intptr_t Debugger::ResolveBreakpointPos(const Function& func,
+ intptr_t first_token_pos,
+ intptr_t last_token_pos) {
ASSERT(func.HasCode());
ASSERT(!func.HasOptimizedCode());
Code& code = Code::Handle(func.unoptimized_code());
ASSERT(!code.IsNull());
PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
- // We attempt to find the PC descriptor that is closest to the
- // beginning of the token range, in terms of native code address. If we
- // don't find a PC descriptor within the given range, we pick the
- // nearest one to the beginning of the range, in terms of token position.
intptr_t best_fit_index = -1;
intptr_t best_fit = INT_MAX;
uword lowest_pc = kUwordMax;
@@ -1048,14 +1062,13 @@
intptr_t desc_token_pos = desc.TokenPos(i);
ASSERT(desc_token_pos >= 0);
if (desc_token_pos < first_token_pos) {
+ // This descriptor is before the given range.
continue;
}
- PcDescriptors::Kind kind = desc.DescriptorKind(i);
- if ((kind == PcDescriptors::kIcCall) ||
- (kind == PcDescriptors::kFuncCall) ||
- (kind == PcDescriptors::kClosureCall) ||
- (kind == PcDescriptors::kReturn)) {
+ if (IsSafePoint(desc.DescriptorKind(i))) {
if ((desc_token_pos - first_token_pos) < best_fit) {
+ // So far, this descriptor has the closest token position to the
+ // beginning of the range.
best_fit = desc_token_pos - first_token_pos;
ASSERT(best_fit >= 0);
best_fit_index = i;
@@ -1063,6 +1076,8 @@
if ((first_token_pos <= desc_token_pos) &&
(desc_token_pos <= last_token_pos) &&
(desc.PC(i) < lowest_pc)) {
+ // This descriptor is within the token position range and so
+ // far has the lowest code address.
lowest_pc = desc.PC(i);
lowest_pc_index = i;
}
@@ -1076,26 +1091,31 @@
best_fit_index = lowest_pc_index;
}
if (best_fit_index >= 0) {
- CodeBreakpoint* bpt = GetCodeBreakpoint(desc.PC(best_fit_index));
- // We should only ever have one code breakpoint at the same address.
- if (bpt != NULL) {
- return bpt;
- }
-
- bpt = new CodeBreakpoint(func, best_fit_index);
- if (FLAG_verbose_debug) {
- OS::Print("Setting breakpoint in function '%s' "
- "(%s:%"Pd") (Token %"Pd") (PC %#"Px")\n",
- String::Handle(func.name()).ToCString(),
- String::Handle(bpt->SourceUrl()).ToCString(),
- bpt->LineNumber(),
- bpt->token_pos(),
- bpt->pc());
- }
- RegisterCodeBreakpoint(bpt);
- return bpt;
+ return desc.TokenPos(best_fit_index);
}
- return NULL;
+ return -1;
+}
+
+
+void Debugger::MakeCodeBreakpointsAt(const Function& func,
+ intptr_t token_pos,
+ SourceBreakpoint* bpt) {
+ ASSERT(!func.HasOptimizedCode());
+ Code& code = Code::Handle(func.unoptimized_code());
+ ASSERT(!code.IsNull());
+ PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+ for (int i = 0; i < desc.Length(); i++) {
+ intptr_t desc_token_pos = desc.TokenPos(i);
+ if ((desc_token_pos == token_pos) && IsSafePoint(desc.DescriptorKind(i))) {
+ CodeBreakpoint* code_bpt = GetCodeBreakpoint(desc.PC(i));
+ if (code_bpt == NULL) {
+ // No code breakpoint for this code exists; create one.
+ code_bpt = new CodeBreakpoint(func, i);
+ RegisterCodeBreakpoint(code_bpt);
+ }
+ code_bpt->set_src_bpt(bpt);
+ }
+ }
}
@@ -1107,69 +1127,66 @@
// The given token position is not within the target function.
return NULL;
}
- DeoptimizeWorld();
- ASSERT(!target_function.HasOptimizedCode());
-
- CodeBreakpoint* cbpt = NULL;
- SourceBreakpoint* source_bpt = NULL;
+ intptr_t breakpoint_pos = -1;
+ Function& closure = Function::Handle(isolate_);
+ if (target_function.HasImplicitClosureFunction()) {
+ // There is a closurized version of this function.
+ closure = target_function.ImplicitClosureFunction();
+ }
+ // Determine actual breakpoint location if the function or an
+ // implicit closure of the function has been compiled already.
if (target_function.HasCode()) {
- cbpt = MakeCodeBreakpoint(target_function, first_token_pos, last_token_pos);
- if (cbpt != NULL) {
- if (cbpt->src_bpt() != NULL) {
- // There is already a source breakpoint for the location.
- ASSERT(cbpt->src_bpt() ==
- GetSourceBreakpoint(target_function, cbpt->token_pos()));
- return cbpt->src_bpt();
- }
- // No source breakpoint exists yet that is associated with the code
- // breakpoint we found. (This is an internal breakpoint.) Adjust
- // the breakpoint location to the actual position where breakpoint
- // got set.
- first_token_pos = cbpt->token_pos();
- }
+ DeoptimizeWorld();
+ ASSERT(!target_function.HasOptimizedCode());
+ breakpoint_pos =
+ ResolveBreakpointPos(target_function, first_token_pos, last_token_pos);
+ } else if (!closure.IsNull() && closure.HasCode()) {
+ DeoptimizeWorld();
+ ASSERT(!closure.HasOptimizedCode());
+ breakpoint_pos =
+ ResolveBreakpointPos(closure, first_token_pos, last_token_pos);
} else {
- source_bpt = GetSourceBreakpoint(target_function, first_token_pos);
+ // This function has not been compiled yet. Set a pending
+ // breakpoint to be resolved later.
+ SourceBreakpoint* source_bpt =
+ GetSourceBreakpoint(target_function, first_token_pos);
if (source_bpt != NULL) {
- // A source breakpoint for this uncompiled location already
- // exists.
+ // A pending source breakpoint for this uncompiled location
+ // already exists.
+ if (FLAG_verbose_debug) {
+ OS::Print("Pending breakpoint for uncompiled function"
+ " '%s' at line %"Pd" already exists\n",
+ target_function.ToFullyQualifiedCString(),
+ source_bpt->LineNumber());
+ }
return source_bpt;
}
- }
- source_bpt = new SourceBreakpoint(nextId(), target_function, first_token_pos);
- RegisterSourceBreakpoint(source_bpt);
- if (FLAG_verbose_debug && !target_function.HasCode()) {
- OS::Print("Registering breakpoint for "
- "uncompiled function '%s' at line %"Pd"\n",
- target_function.ToFullyQualifiedCString(),
- source_bpt->LineNumber());
- }
-
- if (cbpt != NULL) {
- ASSERT(cbpt->src_bpt() == NULL);
- cbpt->set_src_bpt(source_bpt);
- SignalBpResolved(source_bpt);
- } else {
+ source_bpt =
+ new SourceBreakpoint(nextId(), target_function, first_token_pos);
+ RegisterSourceBreakpoint(source_bpt);
if (FLAG_verbose_debug) {
- OS::Print("Failed to set breakpoint at '%s' line %"Pd"\n",
- String::Handle(source_bpt->SourceUrl()).ToCString(),
+ OS::Print("Registering pending breakpoint for "
+ "uncompiled function '%s' at line %"Pd"\n",
+ target_function.ToFullyQualifiedCString(),
source_bpt->LineNumber());
}
+ source_bpt->Enable();
+ return source_bpt;
}
-
- if (target_function.HasImplicitClosureFunction()) {
- // There is a closurized version of this function. If the closure
- // is already compiled, we need to set a code breakpoint in its
- // code.
- const Function& closure =
- Function::Handle(target_function.ImplicitClosureFunction());
- if (closure.HasCode()) {
- ASSERT(!closure.HasOptimizedCode());
- CodeBreakpoint* closure_bpt =
- MakeCodeBreakpoint(closure, first_token_pos, last_token_pos);
- if ((closure_bpt != NULL) && (closure_bpt->src_bpt() == NULL)) {
- closure_bpt->set_src_bpt(source_bpt);
- }
- }
+ ASSERT(breakpoint_pos != -1);
+ SourceBreakpoint* source_bpt =
+ GetSourceBreakpoint(target_function, breakpoint_pos);
+ if (source_bpt != NULL) {
+ // A source breakpoint for this location already exists.
+ return source_bpt;
+ }
+ source_bpt = new SourceBreakpoint(nextId(), target_function, breakpoint_pos);
+ RegisterSourceBreakpoint(source_bpt);
+ if (target_function.HasCode()) {
+ MakeCodeBreakpointsAt(target_function, breakpoint_pos, source_bpt);
+ }
+ if (!closure.IsNull() && closure.HasCode()) {
+ MakeCodeBreakpointsAt(closure, breakpoint_pos, source_bpt);
}
source_bpt->Enable();
return source_bpt;
@@ -1209,8 +1226,8 @@
SourceBreakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
intptr_t line_number) {
- Library& lib = Library::Handle();
- Script& script = Script::Handle();
+ Library& lib = Library::Handle(isolate_);
+ Script& script = Script::Handle(isolate_);
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate_->object_store()->libraries());
for (int i = 0; i < libs.Length(); i++) {
@@ -1237,8 +1254,15 @@
}
return NULL;
}
- const Function& func =
- Function::Handle(lib.LookupFunctionInScript(script, first_token_idx));
+
+ Function& func = Function::Handle(isolate_);
+ while (first_token_idx <= last_token_idx) {
+ func = lib.LookupFunctionInScript(script, first_token_idx);
+ if (!func.IsNull()) {
+ break;
+ }
+ first_token_idx++;
+ }
if (func.IsNull()) {
if (FLAG_verbose_debug) {
OS::Print("No executable code at line %"Pd" in '%s'\n",
@@ -1599,12 +1623,20 @@
// by checking that signature_function() is not null.
const Class& receiver_class = Class::Handle(receiver.clazz());
if (receiver_class.IsSignatureClass()) {
- func_to_instrument = Closure::function(Instance::Cast(receiver));
+ Function& closure_func =
+ Function::Handle(Closure::function(Instance::Cast(receiver)));
+ if (IsDebuggable(closure_func)) {
+ func_to_instrument = closure_func.raw();
+ }
}
// If the receiver is not a closure, then the runtime will attempt
// to invoke the "call" method on the object if one exists.
// TODO(hausner): find call method and intrument it for stepping.
}
+ } else if (bpt->breakpoint_kind_ == PcDescriptors::kEqualNull) {
+ // This is just a call to the runtime, not Dart code. Stepping
+ // into not possible, just treat like StepOver.
+ func_to_instrument = bpt->function();
} else {
ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn);
// Treat like stepping out to caller.
@@ -1684,13 +1716,11 @@
OS::Print("Enable pending breakpoint for function '%s'\n",
String::Handle(lookup_function.name()).ToCString());
}
- // Set breakpoint in newly compiled code of function func.
- CodeBreakpoint* cbpt =
- MakeCodeBreakpoint(func, bpt->token_pos(), func.end_token_pos());
- if (cbpt != NULL) {
- cbpt->set_src_bpt(bpt);
- SignalBpResolved(bpt);
- }
+ intptr_t bp_pos =
+ ResolveBreakpointPos(func, bpt->token_pos(), func.end_token_pos());
+ bpt->set_token_pos(bp_pos);
+ MakeCodeBreakpointsAt(func, bp_pos, bpt);
+ SignalBpResolved(bpt);
}
bpt->Enable(); // Enables the code breakpoint as well.
}
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index a7d3685..d184d3b 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -28,6 +28,7 @@
RawFunction* function() const { return function_; }
intptr_t token_pos() const { return token_pos_; }
+ void set_token_pos(intptr_t value) { token_pos_ = value; }
intptr_t id() const { return id_; }
RawScript* SourceCode();
@@ -49,7 +50,7 @@
const intptr_t id_;
RawFunction* function_;
- const intptr_t token_pos_;
+ intptr_t token_pos_;
intptr_t line_number_;
bool is_enabled_;
@@ -317,6 +318,9 @@
kStepOut
};
+ intptr_t ResolveBreakpointPos(const Function& func,
+ intptr_t first_token_pos,
+ intptr_t last_token_pos);
void DeoptimizeWorld();
void InstrumentForStepping(const Function& target_function);
SourceBreakpoint* SetBreakpoint(const Function& target_function,
@@ -328,10 +332,9 @@
void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
SourceBreakpoint* GetSourceBreakpoint(const Function& func,
intptr_t token_pos);
- CodeBreakpoint* MakeCodeBreakpoint(const Function& func,
- intptr_t first_token_pos,
- intptr_t last_token_pos);
-
+ void MakeCodeBreakpointsAt(const Function& func,
+ intptr_t token_pos,
+ SourceBreakpoint* bpt);
// Returns NULL if no breakpoint exists for the given address.
CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index 81f35be..8c672b3 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -486,10 +486,66 @@
Format(instr, "add.'fmt 'fd, 'fs, 'ft");
break;
}
+ case COP1_SUB: {
+ Format(instr, "sub.'fmt 'fd, 'fs, 'ft");
+ break;
+ }
+ case COP1_MUL: {
+ Format(instr, "mul.'fmt 'fd, 'fs, 'ft");
+ break;
+ }
+ case COP1_DIV: {
+ Format(instr, "div.'fmt 'fd, 'fs, 'ft");
+ break;
+ }
+ case COP1_SQRT: {
+ Format(instr, "sqrt.'fmt 'fd, 'fs");
+ break;
+ }
case COP1_MOV: {
Format(instr, "mov.'fmt 'fd, 'fs");
break;
}
+ case COP1_C_F: {
+ Format(instr, "c.f.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_UN: {
+ Format(instr, "c.un.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_EQ: {
+ Format(instr, "c.eq.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_UEQ: {
+ Format(instr, "c.ueq.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_OLT: {
+ Format(instr, "c.olt.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_ULT: {
+ Format(instr, "c.ult.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_OLE: {
+ Format(instr, "c.ole.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_C_ULE: {
+ Format(instr, "c.ule.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_CVT_D: {
+ Format(instr, "cvt.d.'fmt 'fd, 'fs");
+ break;
+ }
+ case COP1_CVT_W: {
+ Format(instr, "cvt.w.'fmt 'fd, 'fs");
+ break;
+ }
default: {
Unknown(instr);
break;
@@ -514,6 +570,15 @@
}
break;
}
+ case COP1_BC: {
+ ASSERT(instr->Bit(17) == 0);
+ if (instr->Bit(16) == 1) { // Branch on true.
+ Format(instr, "bc1t 'dest");
+ } else { // Branch on false.
+ Format(instr, "bc1f 'dest");
+ }
+ break;
+ }
default: {
Unknown(instr);
break;
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 5142280..bd43c7a 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2277,44 +2277,24 @@
}
return;
}
- // The type arguments are uninstantiated. The generated pseudo code:
- // t1 = InstantiatorTypeArguments();
- // t2 = ExtractConstructorTypeArguments(t1);
- // t1 = ExtractConstructorInstantiator(t1);
- // t_n <- t2
- // t_n+1 <- t1
- // Use expression_temp_var and node->allocated_object_var() locals to keep
- // intermediate results around (t1 and t2 above).
+ // The type arguments are uninstantiated. We use expression_temp_var to save
+ // the instantiator type arguments becuase they have two uses.
ASSERT(owner()->parsed_function().expression_temp_var() != NULL);
- const LocalVariable& t1 = *owner()->parsed_function().expression_temp_var();
- const LocalVariable& t2 = node->allocated_object_var();
+ const LocalVariable& temp = *owner()->parsed_function().expression_temp_var();
const Class& instantiator_class = Class::Handle(
owner()->parsed_function().function().Owner());
Value* instantiator_type_arguments = BuildInstantiatorTypeArguments(
node->token_pos(), instantiator_class, NULL);
Value* stored_instantiator =
- Bind(BuildStoreTemp(t1, instantiator_type_arguments));
- // t1: instantiator type arguments.
+ Bind(BuildStoreTemp(temp, instantiator_type_arguments));
- Value* extract_type_arguments = Bind(
+ Value* type_arguments_val = Bind(
new ExtractConstructorTypeArgumentsInstr(
node->token_pos(),
node->type_arguments(),
instantiator_class,
stored_instantiator));
- Do(BuildStoreTemp(t2, extract_type_arguments));
- // t2: extracted constructor type arguments.
- Value* load_instantiator = Bind(BuildLoadLocal(t1));
-
- Value* extract_instantiator =
- Bind(new ExtractConstructorInstantiatorInstr(node,
- instantiator_class,
- load_instantiator));
- Do(BuildStoreTemp(t1, extract_instantiator));
- // t2: extracted constructor type arguments.
- // t1: extracted constructor instantiator.
- Value* type_arguments_val = Bind(BuildLoadLocal(t2));
if (call_arguments != NULL) {
ASSERT(type_arguments == NULL);
call_arguments->Add(PushArgument(type_arguments_val));
@@ -2323,7 +2303,12 @@
*type_arguments = type_arguments_val;
}
- Value* instantiator_val = Bind(BuildLoadLocal(t1));
+ Value* load_instantiator = Bind(BuildLoadLocal(temp));
+ Value* instantiator_val =
+ Bind(new ExtractConstructorInstantiatorInstr(node,
+ instantiator_class,
+ load_instantiator));
+
if (call_arguments != NULL) {
ASSERT(instantiator == NULL);
call_arguments->Add(PushArgument(instantiator_val));
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 05fd9f0..d3f7d7d 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -1082,10 +1082,16 @@
non_inlined_variants_.is_empty()) {
// If it is the last variant use a check class or check smi
// instruction which can deoptimize, followed unconditionally by the
- // body.
+ // body. Check a redefinition of the receiver, to prevent the check
+ // from being hoisted.
+ RedefinitionInstr* redefinition =
+ new RedefinitionInstr(new Value(receiver));
+ redefinition->set_ssa_temp_index(
+ owner_->caller_graph()->alloc_ssa_temp_index());
+ cursor = AppendInstruction(cursor, redefinition);
if (inlined_variants_[i].cid == kSmiCid) {
CheckSmiInstr* check_smi =
- new CheckSmiInstr(new Value(receiver), call_->deopt_id());
+ new CheckSmiInstr(new Value(redefinition), call_->deopt_id());
check_smi->InheritDeoptTarget(call_);
cursor = AppendInstruction(cursor, check_smi);
} else {
@@ -1098,7 +1104,7 @@
new_checks.AddReceiverCheck(inlined_variants_[i].cid,
*inlined_variants_[i].target);
CheckClassInstr* check_class =
- new CheckClassInstr(new Value(receiver),
+ new CheckClassInstr(new Value(redefinition),
call_->deopt_id(),
new_checks);
check_class->InheritDeoptTarget(call_);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 988dc4f..9d93594 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -424,7 +424,7 @@
// Pass left in R1 and right in R0.
compiler->GenerateCall(token_pos,
&StubCode::EqualityWithNullArgLabel(),
- PcDescriptors::kOther,
+ PcDescriptors::kEqualNull,
locs);
}
__ Bind(&check_ne);
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index eba6a8c2..8e43726 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -404,7 +404,7 @@
__ LoadObject(ic_data_reg, equality_ic_data);
compiler->GenerateCall(token_pos,
&StubCode::EqualityWithNullArgLabel(),
- PcDescriptors::kOther,
+ PcDescriptors::kEqualNull,
locs);
__ Drop(2);
}
@@ -3748,9 +3748,21 @@
for (intptr_t i = 0; i < InputCount(); i++) {
__ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg());
}
+ // For pow-function return NAN if exponent is NAN.
+ Label do_call, skip_call;
+ if (recognized_kind() == MethodRecognizer::kDoublePow) {
+ XmmRegister exp = locs()->in(1).fpu_reg();
+ __ comisd(exp, exp);
+ __ j(PARITY_ODD, &do_call, Assembler::kNearJump); // NaN -> false;
+ // Exponent is NaN, return NaN.
+ __ movsd(locs()->out().fpu_reg(), exp);
+ __ jmp(&skip_call, Assembler::kNearJump);
+ }
+ __ Bind(&do_call);
__ CallRuntime(TargetFunction());
__ fstpl(Address(ESP, 0));
__ movsd(locs()->out().fpu_reg(), Address(ESP, 0));
+ __ Bind(&skip_call);
__ leave();
}
@@ -4508,6 +4520,18 @@
Location left = locs()->in(0);
Location right = locs()->in(1);
+ if (left.IsConstant() && right.IsConstant()) {
+ // TODO(srdjan): Determine why this instruction was not eliminated.
+ bool result = (left.constant().raw() == right.constant().raw());
+ if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
+ result = !result;
+ }
+ __ movl(locs()->out().reg(),
+ Immediate(reinterpret_cast<int32_t>(
+ Smi::New(result ? if_true_ : if_false_))));
+ return;
+ }
+
ASSERT(!left.IsConstant() || !right.IsConstant());
// Clear upper part of the out register. We are going to use setcc on it
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 71180ed..c07ff89 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -418,7 +418,7 @@
// Pass left in A1 and right in A0.
compiler->GenerateCall(token_pos,
&StubCode::EqualityWithNullArgLabel(),
- PcDescriptors::kOther,
+ PcDescriptors::kEqualNull,
locs);
}
__ Bind(&check_ne);
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 68f2bd0..f089bed 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -201,6 +201,18 @@
Location left = locs()->in(0);
Location right = locs()->in(1);
+ if (left.IsConstant() && right.IsConstant()) {
+ // TODO(srdjan): Determine why this instruction was not eliminated.
+ bool result = (left.constant().raw() == right.constant().raw());
+ if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
+ result = !result;
+ }
+ __ movq(locs()->out().reg(),
+ Immediate(reinterpret_cast<int64_t>(
+ Smi::New(result ? if_true_ : if_false_))));
+ return;
+ }
+
ASSERT(!left.IsConstant() || !right.IsConstant());
// Clear upper part of the out register. We are going to use setcc on it
@@ -547,7 +559,7 @@
__ LoadObject(ic_data_reg, equality_ic_data);
compiler->GenerateCall(token_pos,
&StubCode::EqualityWithNullArgLabel(),
- PcDescriptors::kOther,
+ PcDescriptors::kEqualNull,
locs);
__ Drop(2);
}
@@ -3787,8 +3799,20 @@
ASSERT(locs()->in(1).fpu_reg() == XMM2);
__ movaps(XMM1, locs()->in(1).fpu_reg());
}
+ // For pow-function return NAN if exponent is NAN.
+ Label do_call, skip_call;
+ if (recognized_kind() == MethodRecognizer::kDoublePow) {
+ XmmRegister exp = locs()->in(1).fpu_reg();
+ __ comisd(exp, exp);
+ __ j(PARITY_ODD, &do_call, Assembler::kNearJump); // NaN -> false;
+ // Exponent is NaN, return NaN.
+ __ movaps(locs()->out().fpu_reg(), exp);
+ __ jmp(&skip_call, Assembler::kNearJump);
+ }
+ __ Bind(&do_call);
__ CallRuntime(TargetFunction());
__ movaps(locs()->out().fpu_reg(), XMM0);
+ __ Bind(&skip_call);
__ leave();
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index d445f17..fe15ff3 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -270,7 +270,9 @@
void DeferredMint::Materialize() {
RawMint** mint_slot = reinterpret_cast<RawMint**>(slot());
ASSERT(!Smi::IsValid64(value()));
- *mint_slot = Mint::New(value());
+ Mint& mint = Mint::Handle();
+ mint ^= Integer::New(value());
+ *mint_slot = mint.raw();
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr("materializing mint at %"Px": %"Pd64"\n",
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ee4543b..f620fe3 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7099,6 +7099,7 @@
case PcDescriptors::kFuncCall: return "fn-call ";
case PcDescriptors::kClosureCall: return "closure-call ";
case PcDescriptors::kReturn: return "return ";
+ case PcDescriptors::kEqualNull: return "equal-null ";
case PcDescriptors::kOther: return "other ";
}
UNREACHABLE();
@@ -10590,7 +10591,8 @@
if ((cnt + right_value) >= Smi::kBits) {
if ((cnt + right_value) >= Mint::kBits) {
return BigintOperations::ShiftLeft(
- Bigint::Handle(AsBigint()), right_value);
+ Bigint::Handle(BigintOperations::NewFromSmi(*this)),
+ right_value);
} else {
int64_t left_64 = left_value;
return Integer::New(left_64 << right_value);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 2173395..b5406ff 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2438,6 +2438,7 @@
kFuncCall, // Call to known target, e.g. static call.
kClosureCall, // Closure call.
kReturn, // Return from function.
+ kEqualNull, // Stub for comparison with null.
kOther
};
@@ -3931,12 +3932,14 @@
// Return the most compact presentation of an integer.
RawInteger* AsValidInteger() const;
- // Return an integer in the form of a RawBigint.
- RawBigint* AsBigint() const;
RawInteger* ArithmeticOp(Token::Kind operation, const Integer& other) const;
RawInteger* BitOp(Token::Kind operation, const Integer& other) const;
+ private:
+ // Return an integer in the form of a RawBigint.
+ RawBigint* AsBigint() const;
+
OBJECT_IMPLEMENTATION(Integer, Number);
friend class Class;
};
@@ -4046,13 +4049,18 @@
virtual int CompareWith(const Integer& other) const;
- static RawMint* New(int64_t value, Heap::Space space = Heap::kNew);
- static RawMint* NewCanonical(int64_t value);
-
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawMint));
}
+ protected:
+ // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
+ friend class Integer;
+
+ static RawMint* New(int64_t value, Heap::Space space = Heap::kNew);
+
+ static RawMint* NewCanonical(int64_t value);
+
private:
void set_value(int64_t value) const;
@@ -4088,13 +4096,17 @@
return RoundedAllocationSize(sizeof(RawBigint) + (len * kBytesPerElement));
}
+ RawBigint* ArithmeticOp(Token::Kind operation, const Bigint& other) const;
+
+ protected:
+ // Only Integer::NewXXX is allowed to call Bigint::NewXXX directly.
+ friend class Integer;
+
static RawBigint* New(const String& str, Heap::Space space = Heap::kNew);
// Returns a canonical Bigint object allocated in the old gen space.
static RawBigint* NewCanonical(const String& str);
- RawBigint* ArithmeticOp(Token::Kind operation, const Bigint& other) const;
-
private:
Chunk GetChunkAt(intptr_t i) const {
return *ChunkAddr(i);
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 4b027c9..29ae58d 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -236,10 +236,10 @@
Smi& c = Smi::Handle(Smi::New(-1));
- Mint& mint1 = Mint::Handle(
- Mint::New(DART_2PART_UINT64_C(0x7FFFFFFF, 100)));
- Mint& mint2 = Mint::Handle(
- Mint::New(-DART_2PART_UINT64_C(0x7FFFFFFF, 100)));
+ Mint& mint1 = Mint::Handle();
+ mint1 ^= Integer::New(DART_2PART_UINT64_C(0x7FFFFFFF, 100));
+ Mint& mint2 = Mint::Handle();
+ mint2 ^= Integer::New(-DART_2PART_UINT64_C(0x7FFFFFFF, 100));
EXPECT_EQ(-1, a.CompareWith(mint1));
EXPECT_EQ(1, a.CompareWith(mint2));
EXPECT_EQ(-1, c.CompareWith(mint1));
@@ -307,7 +307,7 @@
{ Mint& med = Mint::Handle();
EXPECT(med.IsNull());
int64_t v = DART_2PART_UINT64_C(1, 0);
- med = Mint::New(v);
+ med ^= Integer::New(v);
EXPECT_EQ(v, med.value());
const String& smi_str = String::Handle(String::New("1"));
const String& mint1_str = String::Handle(String::New("2147419168"));
@@ -323,24 +323,28 @@
EXPECT(!i.IsZero());
EXPECT(i.IsNegative());
}
- Integer& i = Integer::Handle(Mint::New(DART_2PART_UINT64_C(1, 0)));
+ Integer& i = Integer::Handle(Integer::New(DART_2PART_UINT64_C(1, 0)));
EXPECT(i.IsMint());
EXPECT(!i.IsZero());
EXPECT(!i.IsNegative());
- Integer& i1 = Integer::Handle(Mint::New(DART_2PART_UINT64_C(1010, 0)));
- Mint& i2 = Mint::Handle(Mint::New(DART_2PART_UINT64_C(1010, 0)));
+ Integer& i1 = Integer::Handle(Integer::New(DART_2PART_UINT64_C(1010, 0)));
+ Mint& i2 = Mint::Handle();
+ i2 ^= Integer::New(DART_2PART_UINT64_C(1010, 0));
EXPECT(i1.Equals(i2));
EXPECT(!i.Equals(i1));
int64_t test = DART_2PART_UINT64_C(1010, 0);
EXPECT_EQ(test, i2.value());
- Mint& a = Mint::Handle(Mint::New(DART_2PART_UINT64_C(5, 0)));
- Mint& b = Mint::Handle(Mint::New(DART_2PART_UINT64_C(3, 0)));
+ Mint& a = Mint::Handle();
+ a ^= Integer::New(DART_2PART_UINT64_C(5, 0));
+ Mint& b = Mint::Handle();
+ b ^= Integer::New(DART_2PART_UINT64_C(3, 0));
EXPECT_EQ(1, a.CompareWith(b));
EXPECT_EQ(-1, b.CompareWith(a));
EXPECT_EQ(0, a.CompareWith(a));
- Mint& c = Mint::Handle(Mint::New(-DART_2PART_UINT64_C(3, 0)));
+ Mint& c = Mint::Handle();
+ c ^= Integer::New(-DART_2PART_UINT64_C(3, 0));
Smi& smi1 = Smi::Handle(Smi::New(4));
Smi& smi2 = Smi::Handle(Smi::New(-4));
EXPECT_EQ(1, a.CompareWith(smi1));
@@ -357,9 +361,12 @@
EXPECT_EQ(-1, c.CompareWith(big1));
EXPECT_EQ(1, c.CompareWith(big2));
- int64_t mint_value = DART_2PART_UINT64_C(0x7FFFFFFF, 100);
- Mint& mint1 = Mint::Handle(Mint::NewCanonical(mint_value));
- Mint& mint2 = Mint::Handle(Mint::NewCanonical(mint_value));
+ int64_t mint_value = DART_2PART_UINT64_C(0x7FFFFFFF, 64);
+ const String& mint_string = String::Handle(String::New("0x7FFFFFFF00000064"));
+ Mint& mint1 = Mint::Handle();
+ mint1 ^= Integer::NewCanonical(mint_string);
+ Mint& mint2 = Mint::Handle();
+ mint2 ^= Integer::NewCanonical(mint_string);
EXPECT_EQ(mint1.value(), mint_value);
EXPECT_EQ(mint2.value(), mint_value);
EXPECT_EQ(mint1.raw(), mint2.raw());
@@ -440,7 +447,7 @@
EXPECT(b.IsNull());
const char* cstr = "18446744073709551615000";
const String& test = String::Handle(String::New(cstr));
- b = Bigint::NewCanonical(test);
+ b ^= Integer::NewCanonical(test);
const char* str = b.ToCString();
EXPECT_STREQ(cstr, str);
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 6d4710c2..393e261 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -559,6 +559,7 @@
for (int i = 0; i < kNumberOfFRegisters; i++) {
fregisters_[i] = 0.0;
}
+ fcsr_ = 0;
}
@@ -1375,31 +1376,134 @@
if (instr->HasFormat()) {
// If the rs field is a valid format, then the function field identifies the
// instruction.
+ double fs_val = get_fregister_double(instr->FsField());
+ double ft_val = get_fregister_double(instr->FtField());
+ uint32_t cc, fcsr_cc;
+ cc = instr->FpuCCField();
+ fcsr_cc = get_fcsr_condition_bit(cc);
switch (instr->Cop1FunctionField()) {
case COP1_ADD: {
// Format(instr, "add.'fmt 'fd, 'fs, 'ft");
- if (instr->FormatField() == FMT_S) {
- float fs_val = get_fregister_float(instr->FsField());
- float ft_val = get_fregister_float(instr->FtField());
- set_fregister_float(instr->FdField(), fs_val + ft_val);
- } else {
- ASSERT(instr->FormatField() == FMT_D); // Only S and D supported.
- double fs_val = get_fregister_double(instr->FsField());
- double ft_val = get_fregister_double(instr->FtField());
- set_fregister_double(instr->FdField(), fs_val + ft_val);
- }
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), fs_val + ft_val);
+ break;
+ }
+ case COP1_SUB: {
+ // Format(instr, "sub.'fmt 'fd, 'fs, 'ft");
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), fs_val - ft_val);
+ break;
+ }
+ case COP1_MUL: {
+ // Format(instr, "mul.'fmt 'fd, 'fs, 'ft");
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), fs_val * ft_val);
+ break;
+ }
+ case COP1_DIV: {
+ // Format(instr, "div.'fmt 'fd, 'fs, 'ft");
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), fs_val / ft_val);
+ break;
+ }
+ case COP1_SQRT: {
+ // Format(instr, "sqrt.'fmt 'fd, 'fs");
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), sqrt(fs_val));
break;
}
case COP1_MOV: {
// Format(instr, "mov.'fmt 'fd, 'fs");
- ASSERT(instr->FtField() == F0);
- if (instr->FormatField() == FMT_S) {
- float fs_val = get_fregister_float(instr->FsField());
- set_fregister_float(instr->FdField(), fs_val);
- } else {
- ASSERT(instr->FormatField() == FMT_D);
- double fs_val = get_fregister_double(instr->FsField());
- set_fregister_double(instr->FdField(), fs_val);
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ set_fregister_double(instr->FdField(), fs_val);
+ break;
+ }
+ case COP1_C_F: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc, false);
+ break;
+ }
+ case COP1_C_UN: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc, isnan(fs_val) || isnan(ft_val));
+ break;
+ }
+ case COP1_C_EQ: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc, (fs_val == ft_val));
+ break;
+ }
+ case COP1_C_UEQ: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc,
+ (fs_val == ft_val) || isnan(fs_val) || isnan(ft_val));
+ break;
+ }
+ case COP1_C_OLT: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc, (fs_val < ft_val));
+ break;
+ }
+ case COP1_C_ULT: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc,
+ (fs_val < ft_val) || isnan(fs_val) || isnan(ft_val));
+ break;
+ }
+ case COP1_C_OLE: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc, (fs_val <= ft_val));
+ break;
+ }
+ case COP1_C_ULE: {
+ ASSERT(instr->FormatField() == FMT_D); // Only D supported.
+ ASSERT(instr->FdField() == F0);
+ set_fcsr_bit(fcsr_cc,
+ (fs_val <= ft_val) || isnan(fs_val) || isnan(ft_val));
+ break;
+ }
+ case COP1_CVT_D: {
+ switch (instr->FormatField()) {
+ case FMT_W: {
+ int32_t fs_int = get_fregister(instr->FsField());
+ double fs_dbl = static_cast<double>(fs_int);
+ set_fregister_double(instr->FdField(), fs_dbl);
+ break;
+ }
+ case FMT_L: {
+ int64_t fs_int = get_fregister_long(instr->FsField());
+ double fs_dbl = static_cast<double>(fs_int);
+ set_fregister_double(instr->FdField(), fs_dbl);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ break;
+ }
+ case COP1_CVT_W: {
+ switch (instr->FormatField()) {
+ case FMT_D: {
+ double fs_dbl = get_fregister_double(instr->FsField());
+ int32_t fs_int = static_cast<int32_t>(fs_dbl);
+ set_fregister(instr->FdField(), fs_int);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
}
break;
}
@@ -1426,6 +1530,18 @@
set_fregister(instr->FsField(), rt_val);
break;
}
+ case COP1_BC: {
+ ASSERT(instr->Bit(17) == 0);
+ uint32_t cc, fcsr_cc;
+ cc = instr->Bits(18, 3);
+ fcsr_cc = get_fcsr_condition_bit(cc);
+ if (instr->Bit(16) == 1) { // Branch on true.
+ DoBranch(instr, test_fcsr_bit(fcsr_cc), false);
+ } else { // Branch on false.
+ DoBranch(instr, !test_fcsr_bit(fcsr_cc), false);
+ }
+ break;
+ }
default: {
OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
UnimplementedInstruction(instr);
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index 5cee182..eca271d 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -61,6 +61,26 @@
int32_t get_hi_register() const { return hi_reg_; }
int32_t get_lo_register() const { return lo_reg_; }
+ int32_t get_fcsr_condition_bit(int32_t cc) const {
+ if (cc == 0) {
+ return 23;
+ } else {
+ return 24 + cc;
+ }
+ }
+
+ void set_fcsr_bit(uint32_t cc, bool value) {
+ if (value) {
+ fcsr_ |= (1 << cc);
+ } else {
+ fcsr_ &= ~(1 << cc);
+ }
+ }
+
+ bool test_fcsr_bit(uint32_t cc) {
+ return fcsr_ & (1 << cc);
+ }
+
// Accessor to the internal simulator stack top.
uword StackTop() const;
@@ -109,6 +129,7 @@
int32_t registers_[kNumberOfCpuRegisters];
int32_t fregisters_[kNumberOfFRegisters];
+ int32_t fcsr_;
uword pc_;
// Simulator support.
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 66e90c9..8476450 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -233,7 +233,8 @@
void CheckMint(int64_t value) {
StackZone zone(Isolate::Current());
- const Mint& mint = Mint::Handle(Mint::New(value));
+ Mint& mint = Mint::Handle();
+ mint ^= Integer::New(value);
ApiNativeScope scope;
Dart_CObject* mint_cobject = SerializeAndDeserializeMint(mint);
// On 64-bit platforms mints always require 64-bits as the smi range
@@ -371,7 +372,8 @@
MessageWriter writer(&buffer, &zone_allocator);
const char* cstr = "0x270FFFFFFFFFFFFFD8F0";
const String& str = String::Handle(String::New(cstr));
- const Bigint& bigint = Bigint::Handle(Bigint::NewCanonical(str));
+ Bigint& bigint = Bigint::Handle();
+ bigint ^= Integer::NewCanonical(str);
writer.WriteMessage(bigint);
intptr_t buffer_len = writer.BytesWritten();
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 79e9d7b..520855c 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -64,6 +64,7 @@
V(OptimizeFunction) \
V(BreakpointDynamic) \
V(EqualityWithNullArg) \
+ V(BreakpointEqNull) \
// class StubEntry is used to describe stub methods generated in dart to
// abstract out common code executed from generated dart code.
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 558ad90..c8b023a 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1552,6 +1552,12 @@
}
+void StubCode::GenerateBreakpointEqNullStub(Assembler* assembler) {
+ // TODO(hausner): implement this stub.
+ __ Branch(&StubCode::EqualityWithNullArgLabel());
+}
+
+
void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
// TODO(hausner): implement this stub.
__ Branch(&StubCode::CallClosureFunctionLabel());
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 90f5da4..9cf56c4 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1708,7 +1708,18 @@
}
-// EDX: Arguments descriptor array.
+// ECX: ICData
+void StubCode::GenerateBreakpointEqNullStub(Assembler* assembler) {
+ __ EnterStubFrame();
+ __ pushl(ECX);
+ __ CallRuntime(kBreakpointEqualNullHandlerRuntimeEntry);
+ __ popl(ECX);
+ __ LeaveFrame();
+ __ jmp(&StubCode::EqualityWithNullArgLabel());
+}
+
+
+// EDX: Arguments descriptor array.
void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
__ EnterStubFrame();
__ pushl(EDX); // Push arguments descriptor.
@@ -1719,8 +1730,8 @@
}
-// EDX: Arguments descriptor array.
-// TOS(0): return address (Dart code).
+// EDX: Arguments descriptor array.
+// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index b985b5a..5ff35e0 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1702,6 +1702,10 @@
GenerateNArgsCheckInlineCacheStub(assembler, 1);
}
+void StubCode::GenerateBreakpointEqNullStub(Assembler* assembler) {
+ // TODO(hausner): implement this stub.
+ __ Branch(&StubCode::EqualityWithNullArgLabel());
+}
void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
// TODO(hausner): implement this stub.
@@ -1894,7 +1898,8 @@
// Return the current stack pointer address, used to stack alignment
// checks.
void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
- __ Unimplemented("GetStackPointer Stub");
+ __ Ret();
+ __ delay_slot()->mov(V0, SP);
}
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 692aa0e..4905f2b 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1685,6 +1685,18 @@
}
+// RBX: ICData.
+// TOS(0): return address (Dart code).
+void StubCode::GenerateBreakpointEqNullStub(Assembler* assembler) {
+ __ EnterStubFrame();
+ __ pushq(RBX); // Preserve ICData.
+ __ CallRuntime(kBreakpointClosureHandlerRuntimeEntry);
+ __ popq(RBX); // Restore arguments descriptor.
+ __ LeaveFrame();
+ __ jmp(&StubCode::EqualityWithNullArgLabel());
+}
+
+
// R10: Arguments descriptor array.
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointClosureStub(Assembler* assembler) {
diff --git a/sdk/lib/_collection_dev/arrays.dart b/sdk/lib/_collection_dev/arrays.dart
index 662fa49..deaa169 100644
--- a/sdk/lib/_collection_dev/arrays.dart
+++ b/sdk/lib/_collection_dev/arrays.dart
@@ -20,7 +20,7 @@
}
}
- static bool areEqual(List a, Object b) {
+ static bool areEqual(List a, var b) {
if (identical(a, b)) return true;
if (!(b is List)) return false;
int length = a.length;
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index b9b83e2..fff0b37 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -390,11 +390,20 @@
scopeVariables.add(element);
}
+ void registerNeedsThis() {
+ if (closureData.thisElement != null) {
+ useLocal(closureData.thisElement);
+ }
+ }
+
visit(Node node) => node.accept(this);
visitNode(Node node) => node.visitChildren(this);
visitVariableDefinitions(VariableDefinitions node) {
+ if (node.type != null) {
+ visit(node.type);
+ }
for (Link<Node> link = node.definitions.nodes;
!link.isEmpty;
link = link.tail) {
@@ -417,13 +426,38 @@
}
}
+ visitTypeAnnotation(TypeAnnotation node) {
+ Element member = currentElement.getEnclosingMember();
+ DartType type = elements.getType(node);
+ // TODO(karlklose,johnniwinther): if the type is null, the annotation is
+ // from a parameter which has been analyzed before the method has been
+ // resolved and the result has been thrown away.
+ if (compiler.enableTypeAssertions && type != null &&
+ type.containsTypeVariables) {
+ if (insideClosure && member.isFactoryConstructor()) {
+ // This is a closure in a factory constructor. Since there is no
+ // [:this:], we have to mark the type arguments as free variables to
+ // capture them in the closure.
+ type.forEachTypeVariable((variable) => useLocal(variable.element));
+ }
+ // TODO(karlklose): try to get rid of the isField check; there is a bug
+ // with type variable use in field initializer (in both modes).
+ if (member.isInstanceMember() && !member.isField()) {
+ // In checked mode, using a type variable in a type annotation may lead
+ // to a runtime type check that needs to access the type argument and
+ // therefore the closure needs a this-element.
+ registerNeedsThis();
+ }
+ }
+ }
+
visitIdentifier(Identifier node) {
if (node.isThis()) {
- useLocal(closureData.thisElement);
+ registerNeedsThis();
} else {
Element element = elements[node];
if (element != null && element.kind == ElementKind.TYPE_VARIABLE) {
- useLocal(closureData.thisElement);
+ registerNeedsThis();
}
}
node.visitChildren(this);
@@ -435,9 +469,9 @@
useLocal(element);
} else if (node.receiver == null &&
Elements.isInstanceSend(node, elements)) {
- useLocal(closureData.thisElement);
+ registerNeedsThis();
} else if (node.isSuperCall) {
- useLocal(closureData.thisElement);
+ registerNeedsThis();
} else if (node.isParameterCheck) {
Element parameter = elements[node.receiver];
FunctionElement enclosing = parameter.enclosingElement;
@@ -461,6 +495,10 @@
if (Elements.isLocal(element)) {
mutatedVariables.add(element);
}
+ if (Elements.isLocal(element) &&
+ element.computeType(compiler).containsTypeVariables) {
+ registerNeedsThis();
+ }
super.visitSendSet(node);
}
@@ -497,7 +535,9 @@
if (outermostElement.isConstructor() || outermostElement.isField()) {
analyzeTypeVariables(type);
} else if (outermostElement.isInstanceMember()) {
- if (hasTypeVariable(type)) useLocal(closureData.thisElement);
+ if (hasTypeVariable(type)) {
+ registerNeedsThis();
+ }
}
}
@@ -669,6 +709,12 @@
});
}
+ // Compute the function type and check for type variables in return or
+ // parameter types.
+ if (element.computeType(compiler).containsTypeVariables) {
+ registerNeedsThis();
+ }
+
visitChildren();
});
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 32a9850..c2de002 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -360,20 +360,20 @@
pleaseReportCrash();
}
hasCrashed = true;
- throw;
+ rethrow;
} on CompilerCancelledException catch (ex) {
- throw;
+ rethrow;
} on StackOverflowError catch (ex) {
// We cannot report anything useful in this case, because we
// do not have enough stack space.
- throw;
+ rethrow;
} catch (ex) {
try {
unhandledExceptionOnElement(element);
} catch (doubleFault) {
// Ignoring exceptions in exception handling.
}
- throw;
+ rethrow;
} finally {
_currentElement = old;
}
@@ -613,7 +613,7 @@
} catch (doubleFault) {
// Ignoring exceptions in exception handling.
}
- throw;
+ rethrow;
} finally {
tracer.close();
totalCompileTime.stop();
@@ -725,12 +725,6 @@
interceptorsLibrary = scanBuiltinLibrary('_interceptors');
foreignLibrary = scanBuiltinLibrary('_foreign_helper');
isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper');
- // The helper library does not use the native language extension,
- // so we manually set the native classes this library defines.
- // TODO(ngeoffray): Enable annotations on these classes.
- ClassElement cls =
- isolateHelperLibrary.find(const SourceString('_WorkerStub'));
- cls.setNative('"Worker"');
assertMethod = jsHelperLibrary.find(const SourceString('assertHelper'));
identicalFunction = coreLibrary.find(const SourceString('identical'));
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
index 78febab..6dd95ef 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -14,6 +14,7 @@
import 'elements/elements.dart';
import 'elements/modelx.dart'
show ErroneousElementX,
+ ClassElementX,
CompilationUnitElementX,
LibraryElementX,
PrefixElementX,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index 8a2cab2..ecee2ba 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -118,6 +118,8 @@
*/
TypeVariableType get typeVariableOccurrence => null;
+ void forEachTypeVariable(f(TypeVariableType variable)) {}
+
TypeVariableType _findTypeVariableOccurrence(Link<DartType> types) {
for (Link<DartType> link = types; !link.isEmpty ; link = link.tail) {
TypeVariableType typeVariable = link.head.typeVariableOccurrence;
@@ -203,6 +205,10 @@
DartType get typeVariableOccurrence => this;
+ void forEachTypeVariable(f(TypeVariableType variable)) {
+ f(this);
+ }
+
accept(DartTypeVisitor visitor, var argument) {
return visitor.visitTypeVariableType(this, argument);
}
@@ -407,6 +413,12 @@
return _findTypeVariableOccurrence(typeArguments);
}
+ void forEachTypeVariable(f(TypeVariableType variable)) {
+ for (Link<DartType> link = typeArguments; !link.isEmpty; link = link.tail) {
+ link.head.forEachTypeVariable(f);
+ }
+ }
+
void visitChildren(DartTypeVisitor visitor, var argument) {
DartType.visitList(typeArguments, visitor, argument);
}
@@ -513,7 +525,12 @@
if (member != null) {
return createMember(receiver, declarer, member);
}
- for (DartType supertype in classElement.allSupertypes) {
+ assert(invariant(element, classElement.allSupertypes != null,
+ message: 'Supertypes not computed for $classElement'));
+ for (InterfaceType supertype in classElement.allSupertypes) {
+ // Skip mixin applications since their supertypes are also in the list of
+ // [allSupertypes].
+ if (supertype.element.isMixinApplication) continue;
declarer = supertype;
ClassElement lookupTarget = declarer.element;
member = lookupTarget.lookupLocalMember(name);
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index 31abe43..abcf627 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -164,8 +164,10 @@
Set<Element> result = new LinkedHashSet<Element>();
if (element.isGenerativeConstructor()) {
// When instantiating a class, we record a reference to the
- // constructor, not the class itself.
- element = element.getEnclosingClass().implementation;
+ // constructor, not the class itself. We must add all the
+ // instance members of the constructor's class (see below).
+ result.addAll(
+ allElementsResolvedFrom(element.getEnclosingClass().implementation));
}
if (element.isClass()) {
// If we see a class, add everything its instance members refer
@@ -187,7 +189,8 @@
result.add(type.element.implementation);
}
result.add(cls.implementation);
- } else if (Elements.isStaticOrTopLevel(element)) {
+ } else if (Elements.isStaticOrTopLevel(element)
+ || element.isConstructor()) {
result.addAll(DependencyCollector.collect(element, compiler));
}
// Other elements, in particular instance members, are ignored as
@@ -248,7 +251,7 @@
visitNode(Node node) {
node.visitChildren(this);
Element dependency = elements[node];
- if (dependency == null) return;
+ if (Elements.isUnresolved(dependency)) return;
dependencies.add(dependency.implementation);
}
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 14fc59e..cecab14 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -230,6 +230,7 @@
bool get isDeclaration;
bool get isSynthesized;
bool get isForwardingConstructor;
+ bool get isMixinApplication;
Element get implementation;
Element get declaration;
@@ -524,6 +525,29 @@
&& node.isCall
&& node.arguments.isEmpty;
}
+
+ static bool switchStatementHasContinue(SwitchStatement node,
+ TreeElements elements) {
+ for (SwitchCase switchCase in node.cases) {
+ for (Node labelOrCase in switchCase.labelsAndCases) {
+ Node label = labelOrCase.asLabel();
+ if (label != null) {
+ LabelElement labelElement = elements[label];
+ if (labelElement != null && labelElement.isContinueTarget) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ static bool switchStatementHasDefault(SwitchStatement node) {
+ for (SwitchCase switchCase in node.cases) {
+ if (switchCase.isDefaultCase) return true;
+ }
+ return false;
+ }
}
abstract class ErroneousElement extends Element implements FunctionElement {
@@ -550,6 +574,7 @@
Script get script;
PartOf get partTag;
+ void forEachLocalMember(f(Element element));
void addMember(Element element, DiagnosticListener listener);
void setPartOf(PartOf tag, DiagnosticListener listener);
bool get hasMembers;
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index dffa694..0cb0a4d 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -134,6 +134,8 @@
bool get isForwardingConstructor => false;
+ bool get isMixinApplication => false;
+
/**
* Returns the element which defines the implementation for the entity of this
* element.
@@ -472,6 +474,10 @@
library.addCompilationUnit(this);
}
+ void forEachLocalMember(f(Element element)) {
+ localMembers.forEach(f);
+ }
+
void addMember(Element element, DiagnosticListener listener) {
// Keep a list of top level members.
localMembers = localMembers.prepend(element);
@@ -2001,7 +2007,8 @@
bool isContinueTarget = false;
TargetElementX(this.statement, this.nestingLevel, Element enclosingElement)
- : super(const SourceString(""), ElementKind.STATEMENT, enclosingElement);
+ : super(const SourceString("target"),
+ ElementKind.STATEMENT, enclosingElement);
bool get isTarget => isBreakTarget || isContinueTarget;
LabelElement addLabel(Label label, String labelName) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 1278cd0..ca6d2d6 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -8,6 +8,58 @@
final ResolutionEnqueuer resolution;
final CodegenEnqueuer codegen;
+ /// A reverse map from name to *all* elements with that name, not
+ /// just instance members of instantiated classes.
+ final Map<String, Link<Element>> allElementsByName
+ = new Map<String, Link<Element>>();
+
+ void ensureAllElementsByName() {
+ if (!allElementsByName.isEmpty) return;
+
+ void addMemberByName(Element element) {
+ element = element.declaration;
+ String name = element.name.slowToString();
+ Link<Element> members = const Link<Element>();
+ if (element.isLibrary()) {
+ LibraryElementX library = element;
+ Uri uri = library.canonicalUri;
+ if (uri.scheme != 'dart' && !uri.path.startsWith('_')) {
+ members = library.localMembers;
+ // TODO(ahe): Is this right? Is this necessary?
+ name = library.getLibraryOrScriptName();
+ }
+ } else if (element.isClass() && !element.isMixinApplication) {
+ // TODO(ahe): Investigate what makes mixin applications crash
+ // this method.
+ ClassElementX cls = element;
+ cls.ensureResolved(compiler);
+ members = cls.localMembers;
+ for (var link = cls.computeTypeParameters(compiler);
+ !link.isEmpty;
+ link = link.tail) {
+ addMemberByName(link.head.element);
+ }
+ } else if (element.isConstructor()) {
+ SourceString source = Elements.deconstructConstructorName(
+ element.name, element.getEnclosingClass());
+ if (source == null) {
+ // source is null for unnamed constructors.
+ name = '';
+ } else {
+ name = source.slowToString();
+ }
+ }
+ allElementsByName[name] = allElementsByName.putIfAbsent(
+ name, () => const Link<Element>()).prepend(element);
+ for (var link = members; !link.isEmpty; link = link.tail) {
+ addMemberByName(link.head);
+ }
+ }
+
+ compiler.libraries.values.forEach(addMemberByName);
+ }
+
+
String get name => 'Enqueue';
EnqueueTask(Compiler compiler)
@@ -29,9 +81,10 @@
final String name;
final Compiler compiler; // TODO(ahe): Remove this dependency.
final Function itemCompilationContextCreator;
- final Map<String, Link<Element>> instanceMembersByName;
- final Set<ClassElement> seenClasses;
- final Universe universe;
+ final Map<String, Link<Element>> instanceMembersByName
+ = new Map<String, Link<Element>>();
+ final Set<ClassElement> seenClasses = new Set<ClassElement>();
+ final Universe universe = new Universe();
bool queueIsClosed = false;
EnqueueTask task;
@@ -39,10 +92,7 @@
Enqueuer(this.name, this.compiler,
ItemCompilationContext itemCompilationContextCreator())
- : this.itemCompilationContextCreator = itemCompilationContextCreator,
- instanceMembersByName = new Map<String, Link<Element>>(),
- universe = new Universe(),
- seenClasses = new Set<ClassElement>();
+ : this.itemCompilationContextCreator = itemCompilationContextCreator;
/// Returns [:true:] if this enqueuer is the resolution enqueuer.
bool get isResolutionQueue => false;
@@ -272,6 +322,60 @@
});
}
+ /// Called when [:const Symbol(name):] is seen.
+ void registerConstSymbol(String name, TreeElements elements) {
+ // If dart:mirrors is loaded, a const symbol may be used to call a
+ // static/top-level method or accessor, instantiate a class, call
+ // an instance method or accessor with the given name.
+ if (compiler.mirrorSystemClass == null) return;
+
+ task.ensureAllElementsByName();
+
+ for (var link = task.allElementsByName[name];
+ link != null && !link.isEmpty;
+ link = link.tail) {
+ Element element = link.head;
+ if (Elements.isUnresolved(element)) {
+ // Ignore.
+ } else if (element.isConstructor()) {
+ ClassElement cls = element.declaration.getEnclosingClass();
+ registerInstantiatedType(cls.rawType, elements);
+ registerStaticUse(element.declaration);
+ } else if (element.impliesType()) {
+ // Don't enqueue classes, typedefs, and type variables.
+ } else if (Elements.isStaticOrTopLevel(element)) {
+ registerStaticUse(element.declaration);
+ } else if (element.isInstanceMember()) {
+ if (element.isFunction()) {
+ int arity =
+ element.asFunctionElement().requiredParameterCount(compiler);
+ Selector selector =
+ new Selector.call(element.name, element.getLibrary(), arity);
+ registerInvocation(element.name, selector);
+ } else if (element.isSetter()) {
+ Selector selector =
+ new Selector.setter(element.name, element.getLibrary());
+ registerInvokedSetter(element.name, selector);
+ } else if (element.isGetter()) {
+ Selector selector =
+ new Selector.getter(element.name, element.getLibrary());
+ registerInvokedGetter(element.name, selector);
+ } else if (element.isField()) {
+ Selector selector =
+ new Selector.setter(element.name, element.getLibrary());
+ registerInvokedSetter(element.name, selector);
+ selector =
+ new Selector.getter(element.name, element.getLibrary());
+ registerInvokedGetter(element.name, selector);
+ }
+ }
+ }
+ }
+
+ /// Called when [:new Symbol(...):] is seen.
+ void registerNewSymbol(TreeElements elements) {
+ }
+
processInstanceMembers(SourceString n, bool f(Element e)) {
String memberName = n.slowToString();
Link<Element> members = instanceMembersByName[memberName];
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 4833202..79ad151 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -90,12 +90,11 @@
HTypeList result = new HTypeList(node.inputs.length);
for (int i = 0; i < result.types.length; i++) {
result.types[i] = node.inputs[i].instructionType;
- assert(!result.types[i].isConflicting());
}
return result;
}
- factory HTypeList.fromDynamicInvocation(HInvokeDynamic node,
+ factory HTypeList.fromDynamicInvocation(HInvoke node,
Selector selector) {
HTypeList result;
int argumentsCount = node.inputs.length - 1;
@@ -116,7 +115,6 @@
for (int i = 0; i < result.types.length; i++) {
result.types[i] = node.inputs[i + startInvokeIndex].instructionType;
- assert(!result.types[i].isConflicting());
}
return result;
}
@@ -278,7 +276,6 @@
Element field,
HType type) {
assert(field.isField());
- assert(!type.isConflicting());
HType before = optimisticFieldType(field);
HType oldType = typeMap[field];
@@ -1133,11 +1130,11 @@
if (compiler.enableTypeAssertions) {
// We need to register is checks for assignments to fields.
- cls.forEachLocalMember((Element member) {
+ cls.forEachMember((Element enclosing, Element member) {
if (!member.isInstanceMember() || !member.isField()) return;
DartType type = member.computeType(compiler);
enqueuer.registerIsCheck(type, elements);
- });
+ }, includeSuperMembers: true);
}
}
@@ -1229,19 +1226,26 @@
void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) {
world.registerInstantiatedClass(compiler.boolClass, elements);
bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
+ bool inCheckedMode = compiler.enableTypeAssertions;
if (!type.isRaw || isTypeVariable) {
enqueueInResolution(getSetRuntimeTypeInfo(), elements);
enqueueInResolution(getGetRuntimeTypeInfo(), elements);
enqueueInResolution(getGetRuntimeTypeArgument(), elements);
+ if (inCheckedMode) {
+ enqueueInResolution(getAssertSubtype(), elements);
+ }
enqueueInResolution(getCheckSubtype(), elements);
if (isTypeVariable) {
- enqueueInResolution(getGetObjectIsSubtype(), elements);
+ enqueueInResolution(getCheckSubtypeOfRuntimeType(), elements);
+ if (inCheckedMode) {
+ enqueueInResolution(getAssertSubtypeOfRuntimeType(), elements);
+ }
}
world.registerInstantiatedClass(compiler.listClass, elements);
}
// [registerIsCheck] is also called for checked mode checks, so we
// need to register checked mode helpers.
- if (compiler.enableTypeAssertions) {
+ if (inCheckedMode) {
Element e = getCheckedModeHelper(type, typeCast: false);
if (e != null) world.addToWorkList(e);
// We also need the native variant of the check (for DOM types).
@@ -1327,8 +1331,8 @@
}
bool needsRti(ClassElement cls) {
- return rti.classesNeedingRti.contains(cls.declaration)
- || compiler.enabledRuntimeType;
+ return rti.classesNeedingRti.contains(cls.declaration) ||
+ compiler.enabledRuntimeType;
}
bool isDefaultNoSuchMethodImplementation(Element element) {
@@ -1437,7 +1441,7 @@
* Register a dynamic invocation and collect the provided types for the
* named selector.
*/
- void registerDynamicInvocation(HInvokeDynamic node, Selector selector) {
+ void registerDynamicInvocation(HInvoke node, Selector selector) {
HTypeList providedTypes =
new HTypeList.fromDynamicInvocation(node, selector);
argumentTypes.registerDynamicInvocation(providedTypes, selector);
@@ -1593,8 +1597,9 @@
* backend with implementation types (JSInt, JSString, ...).
*/
Element getCheckedModeHelper(DartType type, {bool typeCast}) {
- return compiler.findHelper(getCheckedModeHelperName(
- type, typeCast: typeCast, nativeCheckOnly: false));
+ SourceString name = getCheckedModeHelperName(
+ type, typeCast: typeCast, nativeCheckOnly: false);
+ return compiler.findHelper(name);
}
/**
@@ -1693,13 +1698,22 @@
}
} else {
if (nativeCheck) {
+ // TODO(karlklose): can we get rid of this branch when we use
+ // interceptors?
return typeCast
? const SourceString("interceptedTypeCast")
: const SourceString('interceptedTypeCheck');
} else {
- return typeCast
- ? const SourceString("propertyTypeCast")
- : const SourceString('propertyTypeCheck');
+ if (typeCast) {
+ return const SourceString("propertyTypeCast");
+ }
+ if (type.kind == TypeKind.INTERFACE && !type.isRaw) {
+ return const SourceString('assertSubtype');
+ } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+ return const SourceString('assertSubtypeOfRuntimeType');
+ } else {
+ return const SourceString('propertyTypeCheck');
+ }
}
}
}
@@ -1782,8 +1796,17 @@
return compiler.findHelper(const SourceString('checkSubtype'));
}
- Element getGetObjectIsSubtype() {
- return compiler.findHelper(const SourceString('objectIsSubtype'));
+ Element getAssertSubtype() {
+ return compiler.findHelper(const SourceString('assertSubtype'));
+ }
+
+ Element getCheckSubtypeOfRuntimeType() {
+ return compiler.findHelper(const SourceString('checkSubtypeOfRuntimeType'));
+ }
+
+ Element getAssertSubtypeOfRuntimeType() {
+ return compiler.findHelper(
+ const SourceString('assertSubtypeOfRuntimeType'));
}
Element getThrowNoSuchMethod() {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 04c2515..a1f1c9a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -312,10 +312,10 @@
js.for_('var i = 0', 'i < fields.length', 'i++', [
js.if_('i != 0', js('str += ", "')),
- js('var field = fields[i]'),
- js('field = generateAccessor(field, prototype)'),
- js('str += field'),
- js('body += ("this." + field + " = " + field + ";\\n")')
+ js('var field = generateAccessor(fields[i], prototype)'),
+ js('var parameter = "parameter_" + field'),
+ js('str += parameter'),
+ js('body += ("this." + field + " = " + parameter + ";\\n")')
]),
js('str += (") {" + body + "}\\nreturn " + cls)'),
@@ -796,6 +796,8 @@
js('newIsolate.prototype = isolatePrototype'),
js('isolatePrototype.constructor = newIsolate'),
js('newIsolate.${namer.isolatePropertiesName} = isolateProperties'),
+ // TODO(ahe): Only copy makeConstantList when it is used.
+ js('newIsolate.makeConstantList = oldIsolate.makeConstantList'),
]..addAll(copyFinishClasses)
..addAll([
@@ -2189,8 +2191,7 @@
addedMakeConstantList = true;
emitMakeConstantList(eagerBuffer);
}
- CodeBuffer buffer =
- bufferForElement(constant.computeType(compiler).element, eagerBuffer);
+ CodeBuffer buffer = bufferForConstant(constant, eagerBuffer);
jsAst.Expression init = js('$isolateProperties.$name = #',
constantInitializerExpression(constant));
buffer.write(jsAst.prettyPrint(init, compiler));
@@ -2523,9 +2524,7 @@
if (classes == backend.interceptedClasses) {
// I.e. this is the general interceptor.
- // TODO(9556): Remove 'holders'. The general interceptor is used on type
- // checks and needs to handle 'native' classes for 'holders'.
- hasNative = true;
+ hasNative = compiler.enqueuer.codegen.nativeEnqueuer.hasNativeClasses();
}
jsAst.Block block = new jsAst.Block.empty();
@@ -3051,6 +3050,35 @@
return deferredBuffer;
}
+ bool firstDeferredConstant = true;
+
+ /**
+ * Returns the appropriate buffer for [constant]. If [constant] is
+ * itself an instance of a deferred type (or built from constants
+ * that are instances of deferred types) attempting to use
+ * [constant] before the deferred type has been loaded will not
+ * work, and [constant] itself must be deferred.
+ */
+ CodeBuffer bufferForConstant(Constant constant, CodeBuffer eagerBuffer) {
+ var queue = new Queue()..add(constant);
+ while (!queue.isEmpty) {
+ constant = queue.removeFirst();
+ if (isDeferred(constant.computeType(compiler).element)) {
+ emitDeferredPreambleWhenEmpty(deferredBuffer);
+ if (firstDeferredConstant) {
+ deferredBuffer.write(
+ '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
+ deferredBuffer.write(
+ 'old${namer.CURRENT_ISOLATE}$_=${_}${namer.CURRENT_ISOLATE}$N');
+ }
+ firstDeferredConstant = false;
+ return deferredBuffer;
+ }
+ queue.addAll(constant.getDependencies());
+ }
+ return eagerBuffer;
+ }
+
void emitDeferredCode(CodeBuffer buffer) {
if (buffer.isEmpty) return;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 81e68be..fae1efc 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -4,7 +4,7 @@
library js_backend;
-import 'dart:collection' show LinkedHashMap;
+import 'dart:collection' show LinkedHashMap, Queue;
import '../closure.dart';
import '../../compiler.dart' as api;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index f2f3b73..f7adf4a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -322,7 +322,8 @@
if (type is FunctionType) {
// The parameter type is a function type either directly or through
// typedef(s).
- int arity = type.computeArity();
+ FunctionType functionType = type;
+ int arity = functionType.computeArity();
statements.add(
js('$name = $closureConverter($name, $arity)').toStatement());
break;
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index 934044a..4d6d4c1 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -15,6 +15,7 @@
String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
_symbolMapToStringMap(Map<Symbol, dynamic> map) {
+ if (map == null) return null;
var result = new Map<String, dynamic>();
map.forEach((Symbol key, value) {
result[_symbolToString(key)] = value;
@@ -22,7 +23,7 @@
return result;
}
-patch void print(var object) {
+patch void print(Object object) {
Primitives.printString(object.toString());
}
@@ -104,7 +105,8 @@
}
patch class double {
- patch static double parse(String source, [int handleError(String source)]) {
+ patch static double parse(String source,
+ [double handleError(String source)]) {
return Primitives.parseDouble(source, handleError);
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index 927e82a..d5dccf6 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -5,7 +5,8 @@
library _interceptors;
import 'dart:collection';
-import 'dart:_collection-dev';
+import 'dart:_collection-dev' hide Symbol;
+import "dart:_collection-dev" as _symbol_dev show Symbol;
import 'dart:_js_helper' show allMatchesInStringUnchecked,
Null,
JSSyntaxRegExp,
@@ -30,6 +31,17 @@
part 'js_number.dart';
part 'js_string.dart';
+String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
+
+_symbolMapToStringMap(Map<Symbol, dynamic> map) {
+ if (map == null) return null;
+ var result = new Map<String, dynamic>();
+ map.forEach((Symbol key, value) {
+ result[_symbolToString(key)] = value;
+ });
+ return result;
+}
+
/**
* Get the interceptor for [object]. Called by the compiler when it needs
* to emit a call to an intercepted method, that is a method that is
@@ -277,10 +289,11 @@
String toString() => Primitives.objectToString(this);
dynamic noSuchMethod(Invocation invocation) {
- throw new NoSuchMethodError(this,
- invocation.memberName,
- invocation.positionalArguments,
- invocation.namedArguments);
+ throw new NoSuchMethodError(
+ this,
+ _symbolToString(invocation.memberName),
+ invocation.positionalArguments,
+ _symbolMapToStringMap(invocation.namedArguments));
}
Type get runtimeType => getRuntimeType(this);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index bc7ea75..61120ea 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -237,13 +237,13 @@
}
patch class RawSocket {
- patch static Future<RawSocket> connect(String host, int port) {
+ patch static Future<RawSocket> connect(var host, int port) {
throw new UnsupportedError("RawSocket constructor");
}
}
patch class Socket {
- patch static Future<Socket> connect(String host, int port) {
+ patch static Future<Socket> connect(var host, int port) {
throw new UnsupportedError("Socket constructor");
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
index ebbb9fd..3c79299 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
@@ -107,7 +107,9 @@
* [_ManagerStub] - A handle held within one manager that allows interaction
* with another manager. A target manager may be addressed by zero or more
* [_ManagerStub]s.
- *
+ * TODO(ahe): The _ManagerStub concept is broken. It was an attempt
+ * to create a common interface between the native Worker class and
+ * _MainManagerStub.
*/
/**
@@ -183,10 +185,10 @@
Map<int, _IsolateContext> isolates;
/** Reference to the main [_Manager]. Null in the main [_Manager] itself. */
- _ManagerStub mainManager;
+ _MainManagerStub mainManager;
- /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */
- Map<int, _ManagerStub> managers;
+ /// Registry of active Web Workers. Only used in the main [_Manager].
+ Map<int, dynamic /* Worker */> managers;
/** The entry point given by [startRootIsolate]. */
final Function entry;
@@ -195,7 +197,7 @@
_nativeDetectEnvironment();
topEventLoop = new _EventLoop();
isolates = new Map<int, _IsolateContext>();
- managers = new Map<int, _ManagerStub>();
+ managers = new Map<int, dynamic>();
if (isWorker) { // "if we are not the main manager ourself" is the intent.
mainManager = new _MainManagerStub();
_nativeInitWorkerMessageHandler();
@@ -390,41 +392,17 @@
}
}
-/** An interface for a stub used to interact with a manager. */
-abstract class _ManagerStub {
- get id;
- void set id(int i);
- void set onmessage(Function f);
- void postMessage(msg);
- void terminate();
-}
-
/** A stub for interacting with the main manager. */
-class _MainManagerStub implements _ManagerStub {
- get id => 0;
- void set id(int i) { throw new UnimplementedError(); }
- void set onmessage(f) {
- throw new Exception("onmessage should not be set on MainManagerStub");
- }
+class _MainManagerStub {
void postMessage(msg) {
- JS("void", r"#.postMessage(#)", globalThis, msg);
+ // "self" is a way to refer to the global context object that
+ // works in HTML pages and in Web Workers. It does not work in d8
+ // and Firefox jsshell, because that would have been too easy.
+ //
+ // See: http://www.w3.org/TR/workers/#the-global-scope
+ // and: http://www.w3.org/TR/Window/#dfn-self-attribute
+ JS("void", r"self.postMessage(#)", msg);
}
- void terminate() {} // Nothing useful to do here.
-}
-
-/**
- * A stub for interacting with a manager built on a web worker. This
- * definition uses a 'hidden' type (* prefix on the native name) to
- * enforce that the type is defined dynamically only when web workers
- * are actually available.
- */
-// @Native("*Worker");
-class _WorkerStub implements _ManagerStub {
- get id => JS("", "#.id", this);
- void set id(i) { JS("void", "#.id = #", this, i); }
- void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
- void postMessage(msg) { JS("void", "#.postMessage(#)", this, msg); }
- void terminate() { JS("void", "#.terminate()", this); }
}
const String _SPAWNED_SIGNAL = "spawned";
@@ -439,6 +417,9 @@
static String thisScript = computeThisScript();
+ /// Associates an ID with a native worker object.
+ static final Expando<int> workerIds = new Expando<int>();
+
/**
* The src url for the script tag that loaded this code. Used to create
* JavaScript workers.
@@ -488,9 +469,6 @@
static computeGlobalThis() => JS('', 'function() { return this; }()');
- /** Starts a new worker with the given URL. */
- static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url);
-
/**
* Assume that [e] is a browser message event and extract its message data.
* We don't import the dom explicitly so, when workers are disabled, this
@@ -502,7 +480,7 @@
* Process messages on a worker, either to control the worker instance or to
* pass messages along to the isolate running in the worker.
*/
- static void _processWorkerMessage(sender, e) {
+ static void _processWorkerMessage(/* Worker */ sender, e) {
var msg = _deserializeMessage(_getEventData(e));
switch (msg['command']) {
case 'start':
@@ -537,9 +515,8 @@
_globalState.topEventLoop.run();
break;
case 'close':
- _log("Closing Worker");
- _globalState.managers.remove(sender.id);
- sender.terminate();
+ _globalState.managers.remove(workerIds[sender]);
+ JS('void', '#.terminate()', sender);
_globalState.topEventLoop.run();
break;
case 'log':
@@ -675,24 +652,26 @@
*/
static void _spawnWorker(functionName, uri, replyPort) {
if (uri == null) uri = thisScript;
- final worker = _newWorker(uri);
- worker.onmessage = JS('',
- 'function(e) { #(#, e); }',
- DART_CLOSURE_TO_JS(_processWorkerMessage),
- worker);
+ final worker = JS('var', 'new Worker(#)', uri);
+
+ var processWorkerMessageTrampoline =
+ JS('', 'function(e) { #(#, e); }',
+ DART_CLOSURE_TO_JS(_processWorkerMessage),
+ worker);
+ JS('void', '#.onmessage = #', worker, processWorkerMessageTrampoline);
var workerId = _globalState.nextManagerId++;
// We also store the id on the worker itself so that we can unregister it.
- worker.id = workerId;
+ workerIds[worker] = workerId;
_globalState.managers[workerId] = worker;
- worker.postMessage(_serializeMessage({
- 'command': 'start',
- 'id': workerId,
- // Note: we serialize replyPort twice because the child worker needs to
- // first deserialize the worker id, before it can correctly deserialize
- // the port (port deserialization is sensitive to what is the current
- // workerId).
- 'replyTo': _serializeMessage(replyPort),
- 'functionName': functionName }));
+ JS('void', '#.postMessage(#)', worker, _serializeMessage({
+ 'command': 'start',
+ 'id': workerId,
+ // Note: we serialize replyPort twice because the child worker needs to
+ // first deserialize the worker id, before it can correctly deserialize
+ // the port (port deserialization is sensitive to what is the current
+ // workerId).
+ 'replyTo': _serializeMessage(replyPort),
+ 'functionName': functionName }));
}
}
@@ -807,9 +786,9 @@
_globalState.mainManager.postMessage(workerMessage);
} else {
// Deliver the message only if the worker is still alive.
- _ManagerStub manager = _globalState.managers[_workerId];
+ /* Worker */ var manager = _globalState.managers[_workerId];
if (manager != null) {
- manager.postMessage(workerMessage);
+ JS('void', '#.postMessage(#)', manager, workerMessage);
}
}
});
@@ -939,13 +918,13 @@
map.values.forEach((e) => _dispatch(e));
}
- visitSendPort(SendPort port) {
+ visitSendPort(var port) {
if (port is _BufferingSendPort && port._port == null) {
ports.add(port._futurePort);
}
}
- visitIsolateSink(IsolateSink sink) {
+ visitIsolateSink(JsIsolateSink sink) {
visitSendPort(sink._port);
}
@@ -1010,7 +989,7 @@
}
}
- visitIsolateSink(IsolateSink sink) {
+ visitIsolateSink(JsIsolateSink sink) {
SendPort port = sink._port;
bool isClosed = sink._isClosed;
return ['isolateSink', visitSendPort(port), isClosed];
@@ -1053,10 +1032,10 @@
}
}
- IsolateSink visitIsolateSink(IsolateSink sink) {
+ IsolateSink visitIsolateSink(JsIsolateSink sink) {
SendPort port = sink._port;
bool isClosed = sink._isClosed;
- IsolateSink result = new JsIsolateSink.fromPort(visitSendPort(port));
+ JsIsolateSink result = new JsIsolateSink.fromPort(visitSendPort(port));
result._isClosed = isClosed;
return result;
}
@@ -1088,7 +1067,7 @@
IsolateSink deserializeIsolateSink(List list) {
SendPort port = deserializeSendPort(list[1]);
bool isClosed = list[2];
- IsolateSink result = new JsIsolateSink.fromPort(port);
+ JsIsolateSink result = new JsIsolateSink.fromPort(port);
result._isClosed = isClosed;
return result;
}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 8ac68cd..f5350d1 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -133,7 +133,15 @@
arguments = [object]..addAll(arguments);
receiver = interceptor;
}
- return JS("var", "#[#].apply(#, #)", receiver, name, receiver, arguments);
+ var method = JS('var', '#[#]', receiver, name);
+ if (JS('String', 'typeof #', method) == 'function') {
+ return JS("var", "#.apply(#, #)", method, receiver, arguments);
+ } else {
+ // In this case, receiver doesn't implement name. So we should
+ // invoke noSuchMethod instead (which will often throw a
+ // NoSuchMethodError).
+ return receiver.noSuchMethod(this);
+ }
}
/// This method is called by [InstanceMirror.delegate].
@@ -261,7 +269,7 @@
return JS('num', r'parseInt(#, #)', source, radix);
}
- static double parseDouble(String source, int handleError(String source)) {
+ static double parseDouble(String source, double handleError(String source)) {
checkString(source);
if (handleError == null) handleError = _throwFormatException;
// Notice that JS parseFloat accepts garbage at the end of the string.
@@ -517,7 +525,7 @@
static applyFunction(Function function,
List positionalArguments,
- Map<Symbol, dynamic> namedArguments) {
+ Map<String, dynamic> namedArguments) {
int argumentCount = 0;
StringBuffer buffer = new StringBuffer();
List arguments = [];
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
index e95d651..b6219e7 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
@@ -94,7 +94,9 @@
return this;
}
- double toDouble() => this;
+ // The return type is intentionally omitted to avoid type checker warnings
+ // from assigning JSNumber to double.
+ toDouble() => this;
String toStringAsFixed(int fractionDigits) {
checkNum(fractionDigits);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
index fd64f48..2085dc4 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
@@ -21,13 +21,17 @@
}
class TypeImpl implements Type {
- final String typeName;
- TypeImpl(this.typeName);
- toString() => typeName;
- int get hashCode => typeName.hashCode;
+ final String _typeName;
+
+ TypeImpl(this._typeName);
+
+ toString() => _typeName;
+
+ // TODO(ahe): This is a poor hashCode as it collides with its name.
+ int get hashCode => _typeName.hashCode;
+
bool operator ==(other) {
- if (other is !TypeImpl) return false;
- return typeName == other.typeName;
+ return (other is TypeImpl) && _typeName == other._typeName;
}
}
@@ -115,13 +119,13 @@
* against.
*/
bool checkSubtype(Object object, String isField, List checks, String asField) {
- if (object == null) return false;
+ if (object == null) return true;
var arguments = getRuntimeTypeInfo(object);
// Interceptor is needed for JSArray and native classes.
// TODO(sra): It could be a more specialized interceptor since [object] is not
// `null` or a primitive.
// TODO(9586): Move type info for static functions onto an interceptor.
- var interceptor = isJsFunction(object) ? object : getInterceptor(object);
+ var interceptor = getInterceptor(object);
bool isSubclass = getField(interceptor, isField);
// When we read the field and it is not there, [isSubclass] will be [:null:].
if (isSubclass == null || !isSubclass) return false;
@@ -130,6 +134,19 @@
return checkArguments(substitution, arguments, checks);
}
+Object assertSubtype(Object object, String isField, List checks,
+ String asField) {
+ if (!checkSubtype(object, isField, checks, asField)) {
+ // Shorten the field name to the class name and append the textual
+ // representation of the type arguments.
+ int prefixLength = JS_OPERATOR_IS_PREFIX().length;
+ String typeName = '${isField.substring(prefixLength, isField.length)}'
+ '${joinArguments(checks, 0)}';
+ throw new TypeErrorImplementation(object, typeName);
+ }
+ return object;
+}
+
/**
* Check that the types in the list [arguments] are subtypes of the types in
* list [checks] (at the respective positions), possibly applying [substitution]
@@ -170,7 +187,7 @@
* representation [t], which is a type representation as described in the
* comment on [isSubtype].
*/
-bool objectIsSubtype(Object o, var t) {
+bool checkSubtypeOfRuntimeType(Object o, var t) {
if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
// Get the runtime type information from the object here, because we may
// overwrite o with the interceptor below.
@@ -195,6 +212,13 @@
return isSubtype(type, t);
}
+Object assertSubtypeOfRuntimeType(Object object, var type) {
+ if (!checkSubtypeOfRuntimeType(object, type)) {
+ throw new TypeErrorImplementation(object, runtimeTypeToString(type));
+ }
+ return object;
+}
+
/**
* Check whether the type represented by [s] is a subtype of the type
* represented by [t].
@@ -220,6 +244,10 @@
// constructed from the type of [t].
var typeOfS = isJsArray(s) ? s[0] : s;
var typeOfT = isJsArray(t) ? t[0] : t;
+ // TODO(johnniwinther): replace this with the real function subtype test.
+ if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
+ return true;
+ }
// Check for a subtyping flag.
var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
if (getField(typeOfS, test) == null) return false;
diff --git a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
index dda7d3d..85b9ee5 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
@@ -5,60 +5,53 @@
// Patch library for dart:mirrors.
import 'dart:_foreign_helper' show JS;
-import "dart:_collection-dev" as _symbol_dev;
-
-// Yeah, seriously: mirrors in dart2js are experimental...
-const String _MIRROR_OPT_IN_MESSAGE = """
-
-This program is using an experimental feature called \"mirrors\". As
-currently implemented, mirrors do not work with minification, and will
-cause spurious errors depending on how code was optimized.
-
-The authors of this program are aware of these problems and have
-decided the thrill of using an experimental feature is outweighing the
-risks. Furthermore, the authors of this program understand that
-long-term, to fix the problems mentioned above, mirrors may have
-negative impact on size and performance of Dart programs compiled to
-JavaScript.
-""";
-
-bool _mirrorsEnabled = false;
+import 'dart:_collection-dev' as _symbol_dev;
+import 'dart:_js_helper' show createInvocationMirror;
+import 'dart:_interceptors' show getInterceptor;
patch class MirrorSystem {
- patch static String getName(Symbol symbol) {
- return _symbol_dev.Symbol.getName(symbol);
- }
+ patch static String getName(Symbol symbol) => _n(symbol);
}
-/**
- * Stub class for the mirror system.
- */
-patch MirrorSystem currentMirrorSystem() {
- _ensureEnabled();
- throw new UnsupportedError("MirrorSystem not implemented");
+class _MirrorSystem implements MirrorSystem {
}
+String _n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
+
+patch MirrorSystem currentMirrorSystem() => _currentMirrorSystem;
+
+final _MirrorSystem _currentMirrorSystem = new _MirrorSystem();
+
patch Future<MirrorSystem> mirrorSystemOf(SendPort port) {
- _ensureEnabled();
throw new UnsupportedError("MirrorSystem not implemented");
}
patch InstanceMirror reflect(Object reflectee) {
- if (!_mirrorsEnabled && (_MIRROR_OPT_IN_MESSAGE == reflectee)) {
- // Turn on mirrors and warn that it is an experimental feature.
- _mirrorsEnabled = true;
- print(reflectee);
- }
return new _InstanceMirror(reflectee);
}
-patch ClassMirror reflectClass(Type key) {
- throw new UnimplementedError('reflectClass is not yet implemented'
- 'in dart2js');
+final Expando<ClassMirror> _classMirrors = new Expando<ClassMirror>();
+
+patch ClassMirror reflectClass(Type key) => _reflectClass(key);
+
+// TODO(ahe): This is a workaround for http://dartbug.com/10543
+ClassMirror _reflectClass(Type key) {
+ String className = '$key';
+ var constructor = Primitives.getConstructor(className);
+ if (constructor == null) {
+ // Probably an intercepted class.
+ // TODO(ahe): How to handle intercepted classes?
+ throw new UnsupportedError('Cannot find class for: $className');
+ }
+ var mirror = _classMirrors[constructor];
+ if (mirror == null) {
+ mirror = new _ClassMirror(className, constructor);
+ _classMirrors[constructor] = mirror;
+ }
+ return mirror;
}
class _InstanceMirror extends InstanceMirror {
- static final Expando<ClassMirror> classMirrors = new Expando<ClassMirror>();
final reflectee;
@@ -66,43 +59,62 @@
bool get hasReflectee => true;
- ClassMirror get type {
- _ensureEnabled();
- String className = Primitives.objectTypeName(reflectee);
- var constructor = Primitives.getConstructor(className);
- var mirror = classMirrors[constructor];
- if (mirror == null) {
- mirror = new _ClassMirror(className, constructor);
- classMirrors[constructor] = mirror;
- }
- return mirror;
- }
+ ClassMirror get type => _reflectClass(reflectee.runtimeType);
- Future<InstanceMirror> invokeAsync(String memberName,
+ Future<InstanceMirror> invokeAsync(Symbol memberName,
List<Object> positionalArguments,
[Map<String,Object> namedArguments]) {
- _ensureEnabled();
+ if (namedArguments != null && !namedArguments.isEmpty) {
+ throw new UnsupportedError('Named arguments are not implemented');
+ }
+ return
+ new Future<InstanceMirror>(
+ () => invoke(memberName, positionalArguments, namedArguments));
+ }
+
+ InstanceMirror invoke(Symbol memberName,
+ List positionalArguments,
+ [Map<Symbol,dynamic> namedArguments]) {
if (namedArguments != null && !namedArguments.isEmpty) {
throw new UnsupportedError('Named arguments are not implemented');
}
// Copy the list to ensure that it can safely be passed to
// JavaScript.
var jsList = new List.from(positionalArguments);
- var mangledName = '${memberName}\$${positionalArguments.length}';
- var method = JS('var', '#[#]', reflectee, mangledName);
- var completer = new Completer<InstanceMirror>();
- // TODO(ahe): [Completer] or [Future] should have API to create a
- // delayed action. Simulating with a [Timer].
- Timer.run(() {
- if (JS('String', 'typeof #', method) == 'function') {
- var result =
- JS('var', '#.apply(#, #)', method, reflectee, jsList);
- completer.complete(new _InstanceMirror(result));
- } else {
- completer.completeError('not a method $memberName');
- }
- });
- return completer.future;
+ return _invoke(
+ memberName, JSInvocationMirror.METHOD,
+ '${_n(memberName)}\$${positionalArguments.length}', jsList);
+ }
+
+ InstanceMirror _invoke(Symbol name,
+ int type,
+ String mangledName,
+ List arguments) {
+ // TODO(ahe): Get the argument names.
+ List<String> argumentNames = [];
+ Invocation invocation = createInvocationMirror(
+ _n(name), mangledName, type, arguments, argumentNames);
+
+ return new _InstanceMirror(delegate(invocation));
+ }
+
+ Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
+ return new Future<InstanceMirror>(() => setField(fieldName, value));
+ }
+
+ InstanceMirror setField(Symbol fieldName, Object arg) {
+ _invoke(
+ fieldName, JSInvocationMirror.SETTER, 'set\$${_n(fieldName)}', [arg]);
+ return new _InstanceMirror(arg);
+ }
+
+ InstanceMirror getField(Symbol fieldName) {
+ return _invoke(
+ fieldName, JSInvocationMirror.GETTER, 'get\$${_n(fieldName)}', []);
+ }
+
+ Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
+ return new Future<InstanceMirror>(() => getField(fieldName));
}
delegate(Invocation invocation) {
@@ -117,13 +129,7 @@
final _jsConstructor;
_ClassMirror(this._name, this._jsConstructor) {
- _ensureEnabled();
}
String toString() => 'ClassMirror($_name)';
}
-
-_ensureEnabled() {
- if (_mirrorsEnabled) return;
- throw new UnsupportedError('dart:mirrors is an experimental feature');
-}
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 8dec81c..e196afa 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -971,7 +971,7 @@
_typeVariableType.element.bound,
mirrors.compiler.objectClass.computeType(mirrors.compiler));
- bool operator ==(Object other) {
+ bool operator ==(var other) {
if (identical(this, other)) {
return true;
}
@@ -1671,9 +1671,13 @@
List<DeclarationMirror> get members {
// TODO(ahe): Should return an immutable List.
- return _element.localMembers.toList().map(
- (m) => _convertElementToMembers(_library, m))
- .fold([], (a, b) => a..addAll(b)).toList();
+ // TODO(johnniwinther): make sure that these are returned in declaration
+ // order.
+ List<DeclarationMirror> members= <DeclarationMirror>[];
+ _element.forEachLocalMember((m) {
+ members.addAll(_convertElementToMembers(_library, m));
+ });
+ return members;
}
Uri get uri => _element.script.uri;
@@ -1688,7 +1692,7 @@
class BackDoor {
/// Return the compilation units comprising [library].
static List<Mirror> compilationUnitsOf(Dart2JsLibraryMirror library) {
- return library._element.compilationUnits.toList().map(
+ return library._library.compilationUnits.toList().map(
(cu) => new Dart2JsCompilationUnitMirror(cu, library)).toList();
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 627055d..4dc4f9c 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -725,8 +725,9 @@
Element e = element.buildScope().lookup(new SourceString(name));
if (e == null) return null;
if (e is! ClassElement) return null;
- e.ensureResolved(compiler);
- return e.computeType(compiler);
+ ClassElement cls = e;
+ cls.ensureResolved(compiler);
+ return cls.computeType(compiler);
}
NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
@@ -943,7 +944,7 @@
// TODO(ngeoffray): For static methods, we could pass a method with a
// defined arity.
Element helper = builder.backend.getClosureConverter();
- builder.pushInvokeHelper2(helper, local, arity, HType.UNKNOWN);
+ builder.pushInvokeStatic(nativeBody, helper, [local, arity]);
HInstruction closure = builder.pop();
return closure;
}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 7e1beaa..c6a7a9a 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -198,11 +198,33 @@
String patchParameterText =
patchParameter.parseNode(compiler).toString();
if (originParameterText != patchParameterText) {
- error(originParameter.parseNode(compiler),
- MessageKind.PATCH_PARAMETER_MISMATCH,
- {'methodName': origin.name,
- 'originParameter': originParameterText,
- 'patchParameter': patchParameterText});
+ compiler.reportErrorCode(
+ originParameter.parseNode(compiler),
+ MessageKind.PATCH_PARAMETER_MISMATCH,
+ {'methodName': origin.name,
+ 'originParameter': originParameterText,
+ 'patchParameter': patchParameterText});
+ compiler.reportMessage(
+ compiler.spanFromSpannable(patchParameter),
+ MessageKind.PATCH_POINT_TO_PARAMETER.error(
+ {'parameterName': patchParameter.name}),
+ Diagnostic.INFO);
+ }
+ DartType originParameterType = originParameter.computeType(compiler);
+ DartType patchParameterType = patchParameter.computeType(compiler);
+ if (originParameterType != patchParameterType) {
+ compiler.reportErrorCode(
+ originParameter.parseNode(compiler),
+ MessageKind.PATCH_PARAMETER_TYPE_MISMATCH,
+ {'methodName': origin.name,
+ 'parameterName': originParameter.name,
+ 'originParameterType': originParameterType,
+ 'patchParameterType': patchParameterType});
+ compiler.reportMessage(
+ compiler.spanFromSpannable(patchParameter),
+ MessageKind.PATCH_POINT_TO_PARAMETER.error(
+ {'parameterName': patchParameter.name}),
+ Diagnostic.INFO);
}
originParameters = originParameters.tail;
@@ -2054,16 +2076,6 @@
return target;
}
- DartType resolveTypeTest(Node argument) {
- TypeAnnotation node = argument.asTypeAnnotation();
- if (node == null) {
- // node is of the form !Type.
- node = argument.asSend().receiver.asTypeAnnotation();
- if (node == null) compiler.cancel("malformed send");
- }
- return resolveTypeRequired(node);
- }
-
static Selector computeSendSelector(Send node,
LibraryElement library,
Element element) {
@@ -2196,15 +2208,16 @@
bool resolvedArguments = false;
if (node.isOperator) {
String operatorString = node.selector.asOperator().source.stringValue;
- if (operatorString == 'is' || operatorString == 'as') {
- assert(node.arguments.tail.isEmpty);
- DartType type = resolveTypeTest(node.arguments.head);
+ if (operatorString == 'is') {
+ DartType type = resolveTypeRequired(node.typeAnnotationFromIsCheck);
if (type != null) {
- if (operatorString == 'as') {
- compiler.enqueuer.resolution.registerAsCheck(type, mapping);
- } else {
- compiler.enqueuer.resolution.registerIsCheck(type, mapping);
- }
+ compiler.enqueuer.resolution.registerIsCheck(type, mapping);
+ }
+ resolvedArguments = true;
+ } else if (operatorString == 'as') {
+ DartType type = resolveTypeRequired(node.arguments.head);
+ if (type != null) {
+ compiler.enqueuer.resolution.registerAsCheck(type, mapping);
}
resolvedArguments = true;
} else if (identical(operatorString, '?')) {
@@ -2275,12 +2288,16 @@
Element element = scope.lookup(new SourceString(typeName));
if (element == null) return null;
if (element is! ClassElement) return null;
- element.ensureResolved(compiler);
- return element.computeType(compiler);
+ ClassElement cls = element;
+ cls.ensureResolved(compiler);
+ return cls.computeType(compiler);
}
visitSendSet(SendSet node) {
+ bool oldSendIsMemberAccess = sendIsMemberAccess;
+ sendIsMemberAccess = node.isPropertyAccess || node.isCall;
Element target = resolveSend(node);
+ sendIsMemberAccess = oldSendIsMemberAccess;
Element setter = target;
Element getter = target;
SourceString operatorName = node.assignmentOperator.source;
@@ -2511,11 +2528,6 @@
Node selector = node.send.selector;
FunctionElement constructor = resolveConstructor(node);
final bool isSymbolConstructor = constructor == compiler.symbolConstructor;
- if (!node.isConst() && isSymbolConstructor) {
- compiler.reportWarningCode(
- node.newToken, MessageKind.NON_CONST_BLOAT,
- {'name': compiler.symbolClass.name});
- }
resolveSelector(node.send, constructor);
resolveArguments(node.send.argumentsNode);
useElement(node.send, constructor);
@@ -2547,35 +2559,46 @@
includeBackendMembers: false,
includeSuperMembers: true);
- if (node.isConst() && isSymbolConstructor) {
- Node argumentNode = node.send.arguments.head;
- Constant name = compiler.metadataHandler.compileNodeWithDefinitions(
- argumentNode, mapping, isConst: true);
- if (!name.isString()) {
- DartType type = name.computeType(compiler);
- compiler.reportErrorCode(argumentNode, MessageKind.STRING_EXPECTED,
- {'type': type});
+ if (isSymbolConstructor) {
+ if (node.isConst()) {
+ Node argumentNode = node.send.arguments.head;
+ Constant name = compiler.metadataHandler.compileNodeWithDefinitions(
+ argumentNode, mapping, isConst: true);
+ if (!name.isString()) {
+ DartType type = name.computeType(compiler);
+ compiler.reportErrorCode(argumentNode, MessageKind.STRING_EXPECTED,
+ {'type': type});
+ } else {
+ StringConstant stringConstant = name;
+ String nameString = stringConstant.toDartString().slowToString();
+ if (validateSymbol(argumentNode, nameString)) {
+ world.registerConstSymbol(nameString, mapping);
+ }
+ }
} else {
- StringConstant stringConstant = name;
- validateSymbol(argumentNode,
- stringConstant.toDartString().slowToString());
+ compiler.reportWarningCode(
+ node.newToken, MessageKind.NON_CONST_BLOAT,
+ {'name': compiler.symbolClass.name});
+ world.registerNewSymbol(mapping);
}
}
return null;
}
- void validateSymbol(Node node, String name) {
- if (name.isEmpty) return;
+ bool validateSymbol(Node node, String name) {
+ if (name.isEmpty) return true;
if (name.startsWith('_')) {
compiler.reportErrorCode(node, MessageKind.PRIVATE_IDENTIFIER,
{'value': name});
- return;
+ return false;
}
if (!symbolValidationPattern.hasMatch(name)) {
compiler.reportErrorCode(node, MessageKind.INVALID_SYMBOL,
{'value': name});
+ return false;
}
+ return true;
}
@@ -2715,10 +2738,6 @@
if (!target.statement.isValidContinueTarget()) {
error(node.target, MessageKind.INVALID_CONTINUE);
}
- // TODO(lrn): Handle continues to switch cases.
- if (target.statement is SwitchCase) {
- unimplemented(node, "continue to switch case");
- }
label.setContinueTarget();
mapping[node.target] = label;
}
@@ -2898,19 +2917,8 @@
}
}
- TargetElement targetElement =
- new TargetElementX(switchCase,
- statementScope.nestingLevel,
- enclosingElement);
- if (mapping[switchCase] != null) {
- // TODO(ahe): Talk to Lasse about this.
- mapping.remove(switchCase);
- }
- mapping[switchCase] = targetElement;
-
- LabelElement labelElement =
- new LabelElementX(label, labelName,
- targetElement, enclosingElement);
+ TargetElement targetElement = getOrCreateTargetElement(switchCase);
+ LabelElement labelElement = targetElement.addLabel(label, labelName);
mapping[label] = labelElement;
continueLabels[labelName] = labelElement;
}
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 2a6edb6..7708cac 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -700,6 +700,9 @@
if (optional('<', token.next)) {
if (token.next is BeginGroupToken) {
BeginGroupToken beginGroup = token.next;
+ if (beginGroup.endGroup == null) {
+ listener.unmatched(beginGroup);
+ }
token = beginGroup.endGroup;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
index a60e697..0ef2257 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -215,9 +215,13 @@
// Returns whether an invocation of [selector] on [receiver] will throw a
// [ArgumentError] if the argument is not of the right type.
- bool willThrowArgumentError(Selector selector, HInstruction receiver) {
+ bool willThrowArgumentError(Selector selector,
+ HInstruction receiver,
+ HType speculativeType) {
if (receiver != null && (receiver.isInteger() || receiver.isString())) {
- return selector.isOperator() && selector.name != const SourceString('==');
+ return selector.isOperator()
+ && selector.name != const SourceString('==')
+ && (speculativeType.isNumber() && !speculativeType.isInteger());
}
return false;
}
@@ -290,7 +294,7 @@
receiverSelectorOnThrow = selector;
willThrow = true;
}
- } else if (willThrowArgumentError(selector, receiver)) {
+ } else if (willThrowArgumentError(selector, receiver, speculativeType)) {
willThrow = true;
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index df17528..1722f9f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -361,8 +361,15 @@
HInstruction readLocal(Element element) {
if (isAccessedDirectly(element)) {
if (directLocals[element] == null) {
- builder.compiler.internalError("Cannot find value $element",
- element: element);
+ if (element.isTypeVariable()) {
+ builder.compiler.internalError(
+ "Runtime type information not available for $element",
+ element: builder.compiler.currentElement);
+ } else {
+ builder.compiler.internalError(
+ "Cannot find value $element",
+ element: element);
+ }
}
return directLocals[element];
} else if (isStoredInClosureField(element)) {
@@ -533,7 +540,7 @@
}
}
- void enterLoopUpdates(Loop node) {
+ void enterLoopUpdates(Node node) {
// If there are declared boxed loop variables then the updates might have
// access to the box and we must switch to a new box before executing the
// updates.
@@ -736,6 +743,9 @@
continueInstruction = new HContinue(target);
} else {
continueInstruction = new HContinue.toLabel(label);
+ // Switch case continue statements must be handled by the
+ // [SwitchCaseJumpHandler].
+ assert(label.target.statement is! SwitchCase);
}
LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
builder.close(continueInstruction);
@@ -783,6 +793,90 @@
}
}
+/// Special [JumpHandler] implementation used to handle continue statements
+/// targeting switch cases.
+class SwitchCaseJumpHandler extends TargetJumpHandler {
+ /// Map from switch case targets to indices used to encode the flow of the
+ /// switch case loop.
+ final Map<TargetElement, int> targetIndexMap = new Map<TargetElement, int>();
+
+ SwitchCaseJumpHandler(SsaBuilder builder,
+ TargetElement target,
+ SwitchStatement node)
+ : super(builder, target) {
+ // The switch case indices must match those computed in
+ // [SsaBuilder.buildSwitchCaseConstants].
+ // Switch indices are 1-based so we can bypass the synthetic loop when no
+ // cases match simply by branching on the index (which defaults to null).
+ int switchIndex = 1;
+ for (SwitchCase switchCase in node.cases) {
+ for (Node labelOrCase in switchCase.labelsAndCases) {
+ Node label = labelOrCase.asLabel();
+ if (label != null) {
+ LabelElement labelElement = builder.elements[label];
+ if (labelElement != null && labelElement.isContinueTarget) {
+ TargetElement continueTarget = labelElement.target;
+ targetIndexMap[continueTarget] = switchIndex;
+ assert(builder.jumpTargets[continueTarget] == null);
+ builder.jumpTargets[continueTarget] = this;
+ }
+ }
+ }
+ switchIndex++;
+ }
+ }
+
+ void generateBreak([LabelElement label]) {
+ if (label == null) {
+ // Creates a special break instruction for the synthetic loop generated
+ // for a switch statement with continue statements. See
+ // [SsaBuilder.buildComplexSwitchStatement] for detail.
+
+ HInstruction breakInstruction =
+ new HBreak(target, breakSwitchContinueLoop: true);
+ LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+ builder.close(breakInstruction);
+ jumps.add(new JumpHandlerEntry(breakInstruction, locals));
+ } else {
+ super.generateBreak(label);
+ }
+ }
+
+ bool isContinueToSwitchCase(LabelElement label) {
+ return label != null && targetIndexMap.containsKey(label.target);
+ }
+
+ void generateContinue([LabelElement label]) {
+ if (isContinueToSwitchCase(label)) {
+ // Creates the special instructions 'label = i; continue l;' used in
+ // switch statements with continue statements. See
+ // [SsaBuilder.buildComplexSwitchStatement] for detail.
+
+ assert(label != null);
+ HInstruction value = builder.graph.addConstantInt(
+ targetIndexMap[label.target],
+ builder.constantSystem);
+ builder.localsHandler.updateLocal(target, value);
+
+ assert(label.target.labels.contains(label));
+ HInstruction continueInstruction = new HContinue(target);
+ LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
+ builder.close(continueInstruction);
+ jumps.add(new JumpHandlerEntry(continueInstruction, locals));
+ } else {
+ super.generateContinue(label);
+ }
+ }
+
+ void close() {
+ // The mapping from TargetElement to JumpHandler is no longer needed.
+ for (TargetElement target in targetIndexMap.keys) {
+ builder.jumpTargets.remove(target);
+ }
+ super.close();
+ }
+}
+
class SsaBuilder extends ResolvedVisitor implements Visitor {
final SsaBuilderTask builder;
final JavaScriptBackend backend;
@@ -1044,18 +1138,18 @@
Node currentNode) {
assert(invariant(function, function.isImplementation));
- List<HInstruction> compiledArguments = new List<HInstruction>();
- bool succeeded;
+ List<HInstruction> compiledArguments;
bool isInstanceMember = function.isInstanceMember();
if (isInstanceMember) {
assert(providedArguments != null);
+ compiledArguments = new List<HInstruction>();
compiledArguments.add(providedArguments[0]);
// [providedArguments] contains the arguments given in our
// internal order (see [addDynamicSendArgumentsToList]). So we
// call [Selector.addArgumentsToList] only for getting the
// default values of the optional parameters.
- succeeded = selector.addArgumentsToList(
+ bool succeeded = selector.addArgumentsToList(
argumentsNodes,
compiledArguments,
function,
@@ -1072,16 +1166,13 @@
compiledArguments[i] = providedArguments[argumentIndex++];
}
}
+ // The caller of [enterInlinedMethod] has ensured the selector
+ // matches the element.
+ assert(succeeded);
} else {
- assert(providedArguments == null);
- succeeded = addStaticSendArgumentsToList(selector,
- argumentsNodes,
- function,
- compiledArguments);
+ assert(providedArguments != null);
+ compiledArguments = providedArguments;
}
- // The caller of [enterInlinedMethod] has ensured the selector
- // matches the element.
- assert(succeeded);
// Create the inlining state after evaluating the arguments, that
// may have an impact on the state of the current method.
@@ -1097,13 +1188,6 @@
compiledArguments[argumentIndex++]);
}
- FunctionSignature signature = function.computeSignature(compiler);
- signature.orderedForEachParameter((Element parameter) {
- HInstruction argument = compiledArguments[argumentIndex++];
- newLocalsHandler.updateLocal(parameter, argument);
- potentiallyCheckType(argument, parameter.computeType(compiler));
- });
-
if (function.isConstructor()) {
ClassElement enclosing = function.getEnclosingClass();
if (backend.needsRti(enclosing)) {
@@ -1124,6 +1208,16 @@
}
}
+ // Check the type of the arguments. This must be done after setting up the
+ // type variables in the [localsHandler] because the checked types may
+ // contain type variables.
+ FunctionSignature signature = function.computeSignature(compiler);
+ signature.orderedForEachParameter((Element parameter) {
+ HInstruction argument = compiledArguments[argumentIndex++];
+ newLocalsHandler.updateLocal(parameter, argument);
+ potentiallyCheckType(argument, parameter.computeType(compiler));
+ });
+
// TODO(kasperl): Bad smell. We shouldn't be constructing elements here.
returnElement = new ElementX(const SourceString("result"),
ElementKind.VARIABLE,
@@ -1191,7 +1285,8 @@
PartialFunctionElement function = element;
bool canBeInlined = backend.canBeInlined[function];
if (canBeInlined == false) return false;
- if (!selector.applies(function, compiler)) return false;
+ assert(selector != null || Elements.isStaticOrTopLevel(element));
+ if (selector != null && !selector.applies(function, compiler)) return false;
// Don't inline operator== methods if the parameter can be null.
if (element.name == const SourceString('==')) {
@@ -1214,9 +1309,26 @@
if (!canBeInlined) return false;
}
+ // We cannot inline methods with type variables in the signature in checked
+ // mode, because we currently do not have access to the type variables
+ // through the locals.
+ // TODO(karlklose): remove this and enable inlining of these methods.
+ if (compiler.enableTypeAssertions &&
+ element.computeType(compiler).containsTypeVariables) {
+ return false;
+ }
+
assert(canBeInlined);
InliningState state = enterInlinedMethod(
function, selector, argumentsNodes, providedArguments, currentNode);
+ // Add an explicit null check on the receiver. We use [element]
+ // to get the same name in the NoSuchMethodError message as if we had
+ // called it.
+ if (element.isInstanceMember()
+ && (selector.mask == null || selector.mask.isNullable)) {
+ addWithPosition(
+ new HFieldGet(element, providedArguments[0]), currentNode);
+ }
inlinedFrom(element, () {
functionExpression.body.accept(this);
});
@@ -1668,6 +1780,18 @@
open(block);
+ // Add the type parameters of the class as parameters of this method. This
+ // must be done before adding the normal parameters, because their types
+ // may contain references to type variables.
+ var enclosing = element.enclosingElement;
+ if ((element.isConstructor() || element.isGenerativeConstructorBody())
+ && backend.needsRti(enclosing)) {
+ enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
+ HParameterValue param = addParameter(typeVariable.element);
+ localsHandler.directLocals[typeVariable.element] = param;
+ });
+ }
+
if (element is FunctionElement) {
FunctionElement functionElement = element;
FunctionSignature signature = functionElement.computeSignature(compiler);
@@ -1704,24 +1828,35 @@
// Otherwise it is a lazy initializer which does not have parameters.
assert(element is VariableElement);
}
+ }
- // Add the type parameters of the class as parameters of this
- // method.
- var enclosing = element.enclosingElement;
- if ((element.isConstructor() || element.isGenerativeConstructorBody())
- && backend.needsRti(enclosing)) {
- enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
- HParameterValue param = addParameter(typeVariable.element);
- localsHandler.directLocals[typeVariable.element] = param;
- });
+ HInstruction buildTypeConversion(Compiler compiler, HInstruction original,
+ DartType type, int kind) {
+ if (type == null) return original;
+ if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) {
+ HType subtype = new HType.subtype(type, compiler);
+ if (type.isRaw) {
+ return new HTypeConversion(type, kind, subtype, original);
+ }
+ HInstruction representations = buildTypeArgumentRepresentations(type);
+ add(representations);
+ return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
+ original, representations);
+ } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+ HType subtype = original.instructionType;
+ HInstruction typeVariable = addTypeVariableReference(type);
+ return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
+ original, typeVariable);
+ } else {
+ return original.convertType(compiler, type, kind);
}
}
- HInstruction potentiallyCheckType(
- HInstruction original, DartType type,
+ HInstruction potentiallyCheckType(HInstruction original, DartType type,
{ int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
if (!compiler.enableTypeAssertions) return original;
- HInstruction other = original.convertType(compiler, type, kind);
+ HInstruction other =
+ buildTypeConversion(compiler, original, type, kind);
if (other != original) add(other);
return other;
}
@@ -1896,7 +2031,7 @@
assert(!isAborted());
HBasicBlock previousBlock = close(new HGoto());
- JumpHandler jumpHandler = createJumpHandler(node);
+ JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(
jumpHandler.target,
jumpHandler.labels());
@@ -2513,14 +2648,7 @@
push(instruction);
} else {
if (element.isGetter()) {
- Selector selector = elements.getSelector(send);
- if (tryInlineMethod(
- element, selector, const Link<Node>(), null, send)) {
- return;
- }
- }
- if (element.isGetter()) {
- push(buildInvokeStatic(element, <HInstruction>[]));
+ pushInvokeStatic(send, element, <HInstruction>[]);
} else {
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HStatic].
@@ -2581,11 +2709,11 @@
}
if (Elements.isStaticOrTopLevelField(element)) {
if (element.isSetter()) {
- var instruction = buildInvokeStatic(element,
- <HInstruction>[value], HType.UNKNOWN);
- addWithPosition(instruction, location);
+ pushInvokeStatic(location, element, <HInstruction>[value]);
+ pop();
} else {
- value = potentiallyCheckType(value, element.computeType(compiler));
+ value =
+ potentiallyCheckType(value, element.computeType(compiler));
addWithPosition(new HStaticStore(element, value), location);
}
stack.add(value);
@@ -2601,8 +2729,8 @@
if (value.sourceElement == null) {
value.sourceElement = element;
}
- HInstruction checked = potentiallyCheckType(
- value, element.computeType(compiler));
+ HInstruction checked =
+ potentiallyCheckType(value, element.computeType(compiler));
if (!identical(checked, value)) {
pop();
stack.add(checked);
@@ -2618,54 +2746,6 @@
return interceptor;
}
- void pushInvokeHelper0(Element helper, HType type) {
- List<HInstruction> inputs = <HInstruction>[];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
- void pushInvokeHelper1(Element helper, HInstruction a0, HType type) {
- List<HInstruction> inputs = <HInstruction>[a0];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
- void pushInvokeHelper2(Element helper,
- HInstruction a0,
- HInstruction a1,
- HType type) {
- List<HInstruction> inputs = <HInstruction>[a0, a1];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
- void pushInvokeHelper3(Element helper,
- HInstruction a0,
- HInstruction a1,
- HInstruction a2,
- HType type) {
- List<HInstruction> inputs = <HInstruction>[a0, a1, a2];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
- void pushInvokeHelper4(Element helper,
- HInstruction a0,
- HInstruction a1,
- HInstruction a2,
- HInstruction a3,
- HType type) {
- List<HInstruction> inputs = <HInstruction>[a0, a1, a2, a3];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
- void pushInvokeHelper5(Element helper,
- HInstruction a0,
- HInstruction a1,
- HInstruction a2,
- HInstruction a3,
- HInstruction a4,
- HType type) {
- List<HInstruction> inputs = <HInstruction>[a0, a1, a2, a3, a4];
- push(buildInvokeStatic(helper, inputs, type));
- }
-
HForeign createForeign(String code,
HType type,
List<HInstruction> inputs) {
@@ -2673,7 +2753,7 @@
}
HInstruction getRuntimeTypeInfo(HInstruction target) {
- pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target, HType.UNKNOWN);
+ pushInvokeStatic(null, backend.getGetRuntimeTypeInfo(), [target]);
return pop();
}
@@ -2736,18 +2816,10 @@
}
void visitIsSend(Send node) {
- Node argument = node.arguments.head;
visit(node.receiver);
HInstruction expression = pop();
- TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
- bool isNot = false;
- // TODO(ngeoffray): Duplicating pattern in resolver. We should
- // add a new kind of node.
- if (typeAnnotation == null) {
- typeAnnotation = argument.asSend().receiver;
- isNot = true;
- }
- DartType type = elements.getType(typeAnnotation);
+ bool isNot = node.isIsNotCheck;
+ DartType type = elements.getType(node.typeAnnotationFromIsCheck);
if (type.isMalformed) {
String reasons = Types.fetchReasonsFromMalformedType(type);
if (compiler.enableTypeAssertions) {
@@ -2755,23 +2827,30 @@
} else {
generateRuntimeError(node, '$type is malformed: $reasons');
}
- return;
+ } else {
+ HInstruction instruction = buildIsNode(node, type, expression);
+ if (isNot) {
+ add(instruction);
+ instruction = new HNot(instruction);
+ }
+ push(instruction);
}
+ }
- HInstruction instruction;
+ HInstruction buildIsNode(Node node, DartType type, HInstruction expression) {
if (type.kind == TypeKind.TYPE_VARIABLE) {
HInstruction runtimeType = addTypeVariableReference(type);
- Element helper = backend.getGetObjectIsSubtype();
+ Element helper = backend.getCheckSubtypeOfRuntimeType();
List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
- HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN);
- add(call);
- instruction = new HIs(type, <HInstruction>[expression, call],
- HIs.VARIABLE_CHECK);
+ pushInvokeStatic(null, helper, inputs, HType.BOOLEAN);
+ HInstruction call = pop();
+ return new HIs(type, <HInstruction>[expression, call],
+ HIs.VARIABLE_CHECK);
} else if (RuntimeTypes.hasTypeArguments(type)) {
Element element = type.element;
Element helper = backend.getCheckSubtype();
HInstruction representations =
- buildTypeArgumentRepresentations(type);
+ buildTypeArgumentRepresentations(type);
add(representations);
String operator =
backend.namer.operatorIs(backend.getImplementationClass(element));
@@ -2784,18 +2863,13 @@
isFieldName,
representations,
asFieldName];
- HInstruction call = buildInvokeStatic(helper, inputs, HType.BOOLEAN);
- add(call);
- instruction = new HIs(type, <HInstruction>[expression, call],
- HIs.COMPOUND_CHECK);
+ pushInvokeStatic(node, helper, inputs, HType.BOOLEAN);
+ HInstruction call = pop();
+ return
+ new HIs(type, <HInstruction>[expression, call], HIs.COMPOUND_CHECK);
} else {
- instruction = new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK);
+ return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK);
}
- if (isNot) {
- add(instruction);
- instruction = new HNot(instruction);
- }
- push(instruction);
}
void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) {
@@ -2959,7 +3033,7 @@
compiler.cancel(
'Isolate library and compiler mismatch', node: node);
}
- pushInvokeHelper0(element, HType.UNKNOWN);
+ pushInvokeStatic(null, element, [], HType.UNKNOWN);
}
}
@@ -2981,7 +3055,7 @@
}
List<HInstruction> inputs = <HInstruction>[];
addGenericSendArgumentsToList(link, inputs);
- push(buildInvokeStatic(element, inputs, HType.UNKNOWN));
+ pushInvokeStatic(node, element, inputs, HType.UNKNOWN);
}
}
@@ -3124,12 +3198,13 @@
Constant kindConstant =
constantSystem.createInt(selector.invocationMirrorKind);
- pushInvokeHelper5(createInvocationMirror,
- graph.addConstant(nameConstant),
+ pushInvokeStatic(null,
+ createInvocationMirror,
+ [graph.addConstant(nameConstant),
graph.addConstant(internalNameConstant),
graph.addConstant(kindConstant),
argumentsInstruction,
- argumentNamesInstruction,
+ argumentNamesInstruction],
HType.UNKNOWN);
var inputs = <HInstruction>[pop()];
@@ -3195,10 +3270,11 @@
HInstruction substitution = createForeign('#[#]', HType.UNKNOWN,
<HInstruction>[target, substitutionName]);
add(substitution);
- pushInvokeHelper3(backend.getGetRuntimeTypeArgument(),
- target,
+ pushInvokeStatic(null,
+ backend.getGetRuntimeTypeArgument(),
+ [target,
substitution,
- graph.addConstantInt(index, constantSystem),
+ graph.addConstantInt(index, constantSystem)],
HType.UNKNOWN);
return pop();
}
@@ -3208,14 +3284,19 @@
*/
HInstruction addTypeVariableReference(TypeVariableType type) {
Element member = currentElement;
- if (member.enclosingElement.isClosure()) {
+ bool isClosure = member.enclosingElement.isClosure();
+ if (isClosure) {
ClosureClassElement closureClass = member.enclosingElement;
member = closureClass.methodElement;
member = member.getOutermostEnclosingMemberOrTopLevel();
}
- if (member.isConstructor()
- || member.isGenerativeConstructorBody()
- || member.isField()) {
+ if (isClosure && member.isFactoryConstructor()) {
+ // The type variable is used from a closure in a factory constructor. The
+ // value of the type argument is stored as a local on the closure itself.
+ return localsHandler.readLocal(type.element);
+ } else if (member.isConstructor() ||
+ member.isGenerativeConstructorBody() ||
+ member.isField()) {
// The type variable is stored in a parameter of the method.
return localsHandler.readLocal(type.element);
} else if (member.isInstanceMember()) {
@@ -3280,8 +3361,12 @@
// Set the runtime type information on the object.
Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo();
- add(buildInvokeStatic(typeInfoSetterElement,
- <HInstruction>[newObject, typeInfo], HType.UNKNOWN));
+ pushInvokeStatic(
+ null,
+ typeInfoSetterElement,
+ <HInstruction>[newObject, typeInfo],
+ HType.UNKNOWN);
+ pop();
}
/**
@@ -3289,19 +3374,20 @@
*
* Invariant: [type] must not be malformed in checked mode.
*/
- visitNewSend(Send node, InterfaceType type) {
- assert(invariant(node,
+ handleNewSend(NewExpression node, InterfaceType type) {
+ Send send = node.send;
+ assert(invariant(send,
!compiler.enableTypeAssertions || !type.isMalformed,
message: '$type is malformed in checked mode'));
bool isListConstructor = false;
computeType(element) {
- Element originalElement = elements[node];
+ Element originalElement = elements[send];
if (Elements.isFixedListConstructorCall(
- originalElement, node, compiler)) {
+ originalElement, send, compiler)) {
isListConstructor = true;
return HType.FIXED_ARRAY;
} else if (Elements.isGrowableListConstructorCall(
- originalElement, node, compiler)) {
+ originalElement, send, compiler)) {
isListConstructor = true;
return HType.EXTENDABLE_ARRAY;
} else if (element.isGenerativeConstructor()) {
@@ -3312,14 +3398,14 @@
}
}
- Element constructor = elements[node];
- Selector selector = elements.getSelector(node);
+ Element constructor = elements[send];
+ Selector selector = elements.getSelector(send);
if (constructor.isForwardingConstructor) {
compiler.unimplemented('forwarded constructor in named mixin application',
element: constructor.getEnclosingClass());
}
if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) {
- compiler.internalError("Unresolved element: $constructor", node: node);
+ compiler.internalError("Unresolved element: $constructor", node: send);
}
FunctionElement functionElement = constructor;
constructor = functionElement.redirectionTarget;
@@ -3328,33 +3414,33 @@
if (isSymbolConstructor) {
constructor = compiler.symbolValidatedConstructor;
- assert(invariant(node, constructor != null,
+ assert(invariant(send, constructor != null,
message: 'Constructor Symbol.validated is missing'));
selector = compiler.symbolValidatedConstructorSelector;
- assert(invariant(node, selector != null,
+ assert(invariant(send, selector != null,
message: 'Constructor Symbol.validated is missing'));
}
var inputs = <HInstruction>[];
// TODO(5347): Try to avoid the need for calling [implementation] before
// calling [addStaticSendArgumentsToList].
- bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
+ bool succeeded = addStaticSendArgumentsToList(selector, send.arguments,
constructor.implementation,
inputs);
if (!succeeded) {
- generateWrongArgumentCountError(node, constructor, node.arguments);
+ generateWrongArgumentCountError(send, constructor, send.arguments);
return;
}
ClassElement cls = constructor.getEnclosingClass();
if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) {
- generateAbstractClassInstantiationError(node, cls.name.slowToString());
+ generateAbstractClassInstantiationError(send, cls.name.slowToString());
return;
}
if (backend.needsRti(cls)) {
Link<DartType> typeVariable = cls.typeVariables;
type.typeArguments.forEach((DartType argument) {
- inputs.add(analyzeTypeArgument(argument, node));
+ inputs.add(analyzeTypeArgument(argument, send));
typeVariable = typeVariable.tail;
});
// Also add null to non-provided type variables to call the
@@ -3369,16 +3455,15 @@
compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements);
}
HType elementType = computeType(constructor);
- HInstruction newInstance =
- buildInvokeStatic(constructor, inputs, elementType);
- pushWithPosition(newInstance, node);
+ pushInvokeStatic(node, constructor, inputs, elementType);
+ HInstruction newInstance = stack.last;
// The List constructor forwards to a Dart static method that does
// not know about the type argument. Therefore we special case
// this constructor to have the setRuntimeTypeInfo called where
// the 'new' is done.
if (isListConstructor && backend.needsRti(compiler.listClass)) {
- handleListConstructor(type, node, newInstance);
+ handleListConstructor(type, send, newInstance);
}
}
@@ -3402,13 +3487,6 @@
}
compiler.ensure(!element.isGenerativeConstructor());
if (element.isFunction()) {
- bool isIdenticalFunction = element == compiler.identicalFunction;
-
- if (!isIdenticalFunction
- && tryInlineMethod(element, selector, node.arguments, null, node)) {
- return;
- }
-
var inputs = <HInstruction>[];
// TODO(5347): Try to avoid the need for calling [implementation] before
// calling [addStaticSendArgumentsToList].
@@ -3420,25 +3498,12 @@
return;
}
- if (isIdenticalFunction) {
+ if (element == compiler.identicalFunction) {
pushWithPosition(new HIdentity(inputs[0], inputs[1]), node);
return;
}
- HInvokeStatic instruction =
- buildInvokeStatic(element, inputs, HType.UNKNOWN);
- HType returnType =
- new HType.inferredReturnTypeForElement(element, compiler);
- if (returnType.isUnknown()) {
- // TODO(ngeoffray): Only do this if knowing the return type is
- // useful.
- returnType =
- builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange(
- currentElement, element);
- }
- if (returnType != null) instruction.instructionType = returnType;
-
- pushWithPosition(instruction, node);
+ pushInvokeStatic(node, element, inputs);
} else {
generateGetter(node, element);
List<HInstruction> inputs = <HInstruction>[pop()];
@@ -3464,10 +3529,13 @@
} else if (element.isTypeVariable()) {
HInstruction value =
addTypeVariableReference(element.computeType(compiler));
- pushInvokeHelper1(backend.getRuntimeTypeToString(),
- value, HType.STRING);
- pushInvokeHelper1(backend.getCreateRuntimeType(),
- pop(), HType.UNKNOWN);
+ pushInvokeStatic(node,
+ backend.getRuntimeTypeToString(),
+ [value],
+ HType.STRING);
+ pushInvokeStatic(node,
+ backend.getCreateRuntimeType(),
+ [pop(), value]);
} else {
internalError('unexpected element kind $element', node: node);
}
@@ -3496,7 +3564,7 @@
void generateError(Node node, String message, Element helper) {
HInstruction errorMessage = addConstantString(node, message);
- pushInvokeHelper1(helper, errorMessage, HType.UNKNOWN);
+ pushInvokeStatic(node, helper, [errorMessage]);
}
void generateRuntimeError(Node node, String message) {
@@ -3546,8 +3614,9 @@
} else {
existingNamesList = graph.addConstantNull(constantSystem);
}
- pushInvokeHelper4(
- helper, receiver, name, arguments, existingNamesList, HType.UNKNOWN);
+ pushInvokeStatic(diagnosticNode,
+ helper,
+ [receiver, name, arguments, existingNamesList]);
}
/**
@@ -3574,11 +3643,12 @@
HInstruction typeString = addConstantString(node, type.toString());
HInstruction reasonsString = addConstantString(node, reasons);
Element helper = backend.getThrowMalformedSubtypeError();
- pushInvokeHelper3(helper, value, typeString, reasonsString, HType.UNKNOWN);
+ pushInvokeStatic(node, helper, [value, typeString, reasonsString]);
}
visitNewExpression(NewExpression node) {
Element element = elements[node.send];
+ final bool isSymbolConstructor = element == compiler.symbolConstructor;
if (!Elements.isErroneousElement(element)) {
FunctionElement function = element;
element = function.redirectionTarget;
@@ -3598,6 +3668,12 @@
ConstantHandler handler = compiler.constantHandler;
Constant constant = handler.compileNodeWithDefinitions(node, elements);
stack.add(graph.addConstant(constant));
+ if (isSymbolConstructor) {
+ ConstructedConstant symbol = constant;
+ StringConstant stringConstant = symbol.fields.single;
+ String nameString = stringConstant.toDartString().slowToString();
+ compiler.enqueuer.codegen.registerConstSymbol(nameString, elements);
+ }
} else {
DartType type = elements.getType(node);
if (compiler.enableTypeAssertions && type.isMalformed) {
@@ -3608,13 +3684,7 @@
} else {
// TODO(karlklose): move this type registration to the codegen.
compiler.codegenWorld.instantiatedTypes.add(type);
- Send send = node.send;
- Element constructor = elements[send];
- Selector selector = elements.getSelector(send);
- if (!tryInlineMethod(
- constructor, selector, send.arguments, null, node)) {
- visitNewSend(send, type);
- }
+ handleNewSend(node, type);
}
}
}
@@ -3645,12 +3715,20 @@
}
}
- bool isThisSend(Send send) {
- if (send.isPrefix || send.isPostfix) return false;
- Node receiver = send.receiver;
- if (receiver == null) return true;
- Identifier identifier = receiver.asIdentifier();
- return identifier != null && identifier.isThis();
+ bool isOptimizableOperation(Send node, Selector selector, Element element) {
+ ClassElement cls = element.getEnclosingClass();
+ if (isOptimizableOperationOnIndexable(selector, element)) return true;
+ if (!backend.interceptedClasses.contains(cls)) return false;
+ if (selector.isOperator()) return true;
+ if (selector.isSetter()) return true;
+ if (selector.isIndex()) return true;
+ if (selector.isIndexSet()) return true;
+ if (element == backend.jsArrayAdd
+ || element == backend.jsArrayRemoveLast
+ || element == backend.jsStringSplit) {
+ return true;
+ }
+ return false;
}
Element element = compiler.world.locateSingleElement(selector);
@@ -3659,14 +3737,7 @@
&& (node.asSend() != null)
&& !(element.isGetter() && selector.isCall())
&& !(element.isFunction() && selector.isGetter())
- // This check is to ensure we don't regress compared to our
- // previous limited inlining. We currently don't want to
- // inline methods on intercepted classes because the
- // optimizers apply their own optimizations on these methods.
- && (!backend.interceptedClasses.contains(element.getEnclosingClass())
- || isThisSend(node))
- // Avoid inlining optimizable operations on indexables.
- && !isOptimizableOperationOnIndexable(selector, element)) {
+ && !isOptimizableOperation(node, selector, element)) {
Send send = node.asSend();
Link<Node> nodes = send.isPropertyAccess ? null : send.arguments;
if (tryInlineMethod(element, selector, nodes, arguments, node)) {
@@ -3701,18 +3772,35 @@
}
}
- HInstruction buildInvokeStatic(Element element,
- List<HInstruction> inputs,
- [HType type = null]) {
+ void pushInvokeStatic(Node location,
+ Element element,
+ List<HInstruction> arguments,
+ [HType type = null]) {
+ if (tryInlineMethod(element, null, null, arguments, location)) {
+ return;
+ }
+
if (type == null) {
type = new HType.inferredReturnTypeForElement(element, compiler);
+ if (type.isUnknown()) {
+ // TODO(ngeoffray): Only do this if knowing the return type is
+ // useful.
+ type =
+ builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange(
+ currentElement, element);
+ if (type == null) type = HType.UNKNOWN;
+ }
}
// TODO(5346): Try to avoid the need for calling [declaration] before
// creating an [HInvokeStatic].
HInstruction instruction =
- new HInvokeStatic(element.declaration, inputs, type);
+ new HInvokeStatic(element.declaration, arguments, type);
instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
- return instruction;
+ if (location == null) {
+ push(instruction);
+ } else {
+ pushWithPosition(instruction, location);
+ }
}
HInstruction buildInvokeSuper(Selector selector,
@@ -3732,6 +3820,7 @@
HInstruction instruction = new HInvokeSuper(
element,
currentNonClosureClass,
+ selector,
inputs,
isSetter: selector.isSetter() || selector.isIndexSet());
instruction.instructionType =
@@ -4109,13 +4198,22 @@
* Creates a [JumpHandler] for a statement. The node must be a jump
* target. If there are no breaks or continues targeting the statement,
* a special "null handler" is returned.
+ *
+ * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
+ * to distinguish the synthetized loop created for a switch statement with
+ * continue statements from simple switch statements.
*/
- JumpHandler createJumpHandler(Statement node) {
+ JumpHandler createJumpHandler(Statement node, {bool isLoopJump}) {
TargetElement element = elements[node];
if (element == null || !identical(element.statement, node)) {
// No breaks or continues to this node.
return new NullJumpHandler(compiler);
}
+ if (isLoopJump && node is SwitchStatement) {
+ // Create a special jump handler for loops created for switch statements
+ // with continue statements.
+ return new SwitchCaseJumpHandler(this, element, node);
+ }
return new JumpHandler(this, element);
}
@@ -4242,7 +4340,7 @@
add(keyValuePairs);
HType mapType = new HType.nonNullSubtype(
backend.mapLiteralClass.computeType(compiler), compiler);
- pushInvokeHelper1(backend.getMapMaker(), keyValuePairs, mapType);
+ pushInvokeStatic(node, backend.getMapMaker(), [keyValuePairs], mapType);
}
visitLiteralMapEntry(LiteralMapEntry node) {
@@ -4254,59 +4352,7 @@
visit(node.expression);
}
- visitSwitchStatement(SwitchStatement node) {
- if (tryBuildConstantSwitch(node)) return;
-
- LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
- HBasicBlock startBlock = openNewBlock();
- visit(node.expression);
- HInstruction expression = pop();
- if (node.cases.isEmpty) {
- return;
- }
-
- Link<Node> cases = node.cases.nodes;
- JumpHandler jumpHandler = createJumpHandler(node);
-
- buildSwitchCases(cases, expression);
-
- HBasicBlock lastBlock = lastOpenedBlock;
-
- // Create merge block for break targets.
- HBasicBlock joinBlock = new HBasicBlock();
- List<LocalsHandler> caseHandlers = <LocalsHandler>[];
- jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
- instruction.block.addSuccessor(joinBlock);
- caseHandlers.add(locals);
- });
- if (!isAborted()) {
- // The current flow is only aborted if the switch has a default that
- // aborts (all previous cases must abort, and if there is no default,
- // it's possible to miss all the cases).
- caseHandlers.add(localsHandler);
- goto(current, joinBlock);
- }
- if (caseHandlers.length != 0) {
- graph.addBlock(joinBlock);
- open(joinBlock);
- if (caseHandlers.length == 1) {
- localsHandler = caseHandlers[0];
- } else {
- localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock);
- }
- } else {
- // The joinblock is not used.
- joinBlock = null;
- }
- startBlock.setBlockFlow(
- new HLabeledBlockInformation.implicit(
- new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)),
- elements[node]),
- joinBlock);
- jumpHandler.close();
- }
-
- bool tryBuildConstantSwitch(SwitchStatement node) {
+ Map<CaseMatch,Constant> buildSwitchCaseConstants(SwitchStatement node) {
Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
// First check whether all case expressions are compile-time constants,
// and all have the same type that doesn't override operator==.
@@ -4319,18 +4365,12 @@
if (labelOrCase is CaseMatch) {
CaseMatch match = labelOrCase;
Constant constant =
- compiler.constantHandler.tryCompileNodeWithDefinitions(
- match.expression, elements);
- if (constant == null) {
- compiler.reportWarning(match.expression,
- MessageKind.NOT_A_COMPILE_TIME_CONSTANT.error());
- failure = true;
- continue;
- }
+ compiler.constantHandler.compileNodeWithDefinitions(
+ match.expression, elements, isConst: true);
if (firstConstantType == null) {
firstConstantType = constant.computeType(compiler);
if (nonPrimitiveTypeOverridesEquals(constant)) {
- compiler.reportWarning(match.expression,
+ compiler.reportError(match.expression,
MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS.error());
failure = true;
}
@@ -4338,36 +4378,258 @@
DartType constantType =
constant.computeType(compiler);
if (constantType != firstConstantType) {
- compiler.reportWarning(match.expression,
+ compiler.reportError(match.expression,
MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL.error());
failure = true;
}
}
constants[labelOrCase] = constant;
- } else {
- compiler.reportWarning(node, "Unsupported: Labels on cases");
- failure = true;
}
}
}
- if (failure) {
- return false;
+ return constants;
+ }
+
+ visitSwitchStatement(SwitchStatement node) {
+ Map<CaseMatch,Constant> constants = buildSwitchCaseConstants(node);
+
+ // The switch case indices must match those computed in
+ // [SwitchCaseJumpHandler].
+ bool hasContinue = false;
+ Map<SwitchCase, int> caseIndex = new Map<SwitchCase, int>();
+ int switchIndex = 1;
+ bool hasDefault = false;
+ for (SwitchCase switchCase in node.cases) {
+ for (Node labelOrCase in switchCase.labelsAndCases) {
+ Node label = labelOrCase.asLabel();
+ if (label != null) {
+ LabelElement labelElement = elements[label];
+ if (labelElement != null && labelElement.isContinueTarget) {
+ hasContinue = true;
+ }
+ }
+ }
+ if (switchCase.isDefaultCase) {
+ hasDefault = true;
+ }
+ caseIndex[switchCase] = switchIndex;
+ switchIndex++;
}
+ if (!hasContinue) {
+ // If the switch statement has no switch cases targeted by continue
+ // statements we encode the switch statement directly.
+ buildSimpleSwitchStatement(node, constants);
+ } else {
+ buildComplexSwitchStatement(node, constants, caseIndex, hasDefault);
+ }
+ }
+
+ /**
+ * Builds a simple switch statement which does not handle uses of continue
+ * statements to labeled switch cases.
+ */
+ void buildSimpleSwitchStatement(SwitchStatement node,
+ Map<CaseMatch, Constant> constants) {
+ JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
+ HInstruction buildExpression() {
+ visit(node.expression);
+ return pop();
+ }
+ Iterable<Constant> getConstants(SwitchCase switchCase) {
+ List<Constant> constantList = <Constant>[];
+ for (Node labelOrCase in switchCase.labelsAndCases) {
+ if (labelOrCase is CaseMatch) {
+ constantList.add(constants[labelOrCase]);
+ }
+ }
+ return constantList;
+ }
+ bool isDefaultCase(SwitchCase switchCase) {
+ return switchCase.isDefaultCase;
+ }
+ void buildSwitchCase(SwitchCase node) {
+ visit(node.statements);
+ }
+ handleSwitch(node,
+ jumpHandler,
+ buildExpression,
+ node.cases,
+ getConstants,
+ isDefaultCase,
+ buildSwitchCase);
+ jumpHandler.close();
+ }
+
+ /**
+ * Builds a switch statement that can handle arbitrary uses of continue
+ * statements to labeled switch cases.
+ */
+ void buildComplexSwitchStatement(SwitchStatement node,
+ Map<CaseMatch, Constant> constants,
+ Map<SwitchCase, int> caseIndex,
+ bool hasDefault) {
+ // If the switch statement has switch cases targeted by continue
+ // statements we create the following encoding:
+ //
+ // switch (e) {
+ // l_1: case e0: s_1; break;
+ // l_2: case e1: s_2; continue l_i;
+ // ...
+ // l_n: default: s_n; continue l_j;
+ // }
+ //
+ // is encoded as
+ //
+ // var target;
+ // switch (e) {
+ // case e1: target = 1; break;
+ // case e2: target = 2; break;
+ // ...
+ // default: target = n; break;
+ // }
+ // l: while (true) {
+ // switch (target) {
+ // case 1: s_1; break l;
+ // case 2: s_2; target = i; continue l;
+ // ...
+ // case n: s_n; target = j; continue l;
+ // }
+ // }
+
+ TargetElement switchTarget = elements[node];
+ HInstruction initialValue = graph.addConstantNull(constantSystem);
+ localsHandler.updateLocal(switchTarget, initialValue);
+
+ JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
+ var switchCases = node.cases;
+ if (!hasDefault) {
+ // Use [:null:] as the marker for a synthetic default clause.
+ // The synthetic default is added because otherwise, there would be no
+ // good place to give a default value to the local.
+ switchCases = node.cases.nodes.toList()..add(null);
+ }
+ HInstruction buildExpression() {
+ visit(node.expression);
+ return pop();
+ }
+ Iterable<Constant> getConstants(SwitchCase switchCase) {
+ List<Constant> constantList = <Constant>[];
+ if (switchCase != null) {
+ for (Node labelOrCase in switchCase.labelsAndCases) {
+ if (labelOrCase is CaseMatch) {
+ constantList.add(constants[labelOrCase]);
+ }
+ }
+ }
+ return constantList;
+ }
+ bool isDefaultCase(SwitchCase switchCase) {
+ return switchCase == null || switchCase.isDefaultCase;
+ }
+ void buildSwitchCase(SwitchCase switchCase) {
+ if (switchCase != null) {
+ // Generate 'target = i; break;' for switch case i.
+ int index = caseIndex[switchCase];
+ HInstruction value = graph.addConstantInt(index, constantSystem);
+ localsHandler.updateLocal(switchTarget, value);
+ } else {
+ // Generate synthetic default case 'target = null; break;'.
+ HInstruction value = graph.addConstantNull(constantSystem);
+ localsHandler.updateLocal(switchTarget, value);
+ }
+ jumpTargets[switchTarget].generateBreak();
+ }
+ handleSwitch(node,
+ jumpHandler,
+ buildExpression,
+ switchCases,
+ getConstants,
+ isDefaultCase,
+ buildSwitchCase);
+ jumpHandler.close();
+
+ HInstruction buildCondition() =>
+ graph.addConstantBool(true, constantSystem);
+
+ void buildSwitch() {
+ HInstruction buildExpression() {
+ return localsHandler.readLocal(switchTarget);
+ }
+ Iterable<Constant> getConstants(SwitchCase switchCase) {
+ return <Constant>[constantSystem.createInt(caseIndex[switchCase])];
+ }
+ void buildSwitchCase(SwitchCase switchCase) {
+ visit(switchCase.statements);
+ if (!isAborted()) {
+ // Ensure that we break the loop if the case falls through. (This
+ // is only possible for the last case.)
+ jumpTargets[switchTarget].generateBreak();
+ }
+ }
+ // Pass a [NullJumpHandler] because the target for the contained break
+ // is not the generated switch statement but instead the loop generated
+ // in the call to [handleLoop] below.
+ handleSwitch(node,
+ new NullJumpHandler(compiler),
+ buildExpression, node.cases, getConstants,
+ (_) => false, // No case is default.
+ buildSwitchCase);
+ }
+
+ void buildLoop() {
+ handleLoop(node,
+ () {},
+ buildCondition,
+ () {},
+ buildSwitch);
+ }
+
+ if (hasDefault) {
+ buildLoop();
+ } else {
+ // If the switch statement has no default case, surround the loop with
+ // a test of the target.
+ void buildCondition() {
+ push(createForeign('#', HType.BOOLEAN,
+ [localsHandler.readLocal(switchTarget)]));
+ }
+ handleIf(node, buildCondition, buildLoop, () => {});
+ }
+ }
+
+ /**
+ * Creates a switch statement.
+ *
+ * [jumpHandler] is the [JumpHandler] for the created switch statement.
+ * [buildExpression] creates the switch expression.
+ * [switchCases] must be either an [Iterable] of [SwitchCase] nodes or
+ * a [Link] or a [NodeList] of [SwitchCase] nodes.
+ * [getConstants] returns the set of constants for a switch case.
+ * [isDefaultCase] returns [:true:] if the provided switch case should be
+ * considered default for the created switch statement.
+ * [buildSwitchCase] creates the statements for the switch case.
+ */
+ void handleSwitch(Node errorNode,
+ JumpHandler jumpHandler,
+ HInstruction buildExpression(),
+ var switchCases,
+ Iterable<Constant> getConstants(SwitchCase switchCase),
+ bool isDefaultCase(SwitchCase switchCase),
+ void buildSwitchCase(SwitchCase switchCase)) {
+ Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
// TODO(ngeoffray): Handle switch-instruction in bailout code.
work.allowSpeculativeOptimization = false;
// Then build a switch structure.
HBasicBlock expressionStart = openNewBlock();
- visit(node.expression);
- HInstruction expression = pop();
- if (node.cases.isEmpty) {
- return true;
+ HInstruction expression = buildExpression();
+ if (switchCases.isEmpty) {
+ return;
}
HBasicBlock expressionEnd = current;
HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
HBasicBlock expressionBlock = close(switchInstruction);
- JumpHandler jumpHandler = createJumpHandler(node);
LocalsHandler savedLocals = localsHandler;
List<List<Constant>> matchExpressions = <List<Constant>>[];
@@ -4375,24 +4637,21 @@
bool hasDefault = false;
Element getFallThroughErrorElement = backend.getFallThroughError();
HasNextIterator<Node> caseIterator =
- new HasNextIterator<Node>(node.cases.iterator);
+ new HasNextIterator<Node>(switchCases.iterator);
while (caseIterator.hasNext) {
SwitchCase switchCase = caseIterator.next();
List<Constant> caseConstants = <Constant>[];
HBasicBlock block = graph.addNewBlock();
- for (Node labelOrCase in switchCase.labelsAndCases) {
- if (labelOrCase is CaseMatch) {
- Constant constant = constants[labelOrCase];
- caseConstants.add(constant);
- HConstant hConstant = graph.addConstant(constant);
- switchInstruction.inputs.add(hConstant);
- hConstant.usedBy.add(switchInstruction);
- expressionBlock.addSuccessor(block);
- }
+ for (Constant constant in getConstants(switchCase)) {
+ caseConstants.add(constant);
+ HConstant hConstant = graph.addConstant(constant);
+ switchInstruction.inputs.add(hConstant);
+ hConstant.usedBy.add(switchInstruction);
+ expressionBlock.addSuccessor(block);
}
matchExpressions.add(caseConstants);
- if (switchCase.isDefaultCase) {
+ if (isDefaultCase(switchCase)) {
// An HSwitch has n inputs and n+1 successors, the last being the
// default case.
expressionBlock.addSuccessor(block);
@@ -4400,9 +4659,9 @@
}
open(block);
localsHandler = new LocalsHandler.from(savedLocals);
- visit(switchCase.statements);
+ buildSwitchCase(switchCase);
if (!isAborted() && caseIterator.hasNext) {
- pushInvokeHelper0(getFallThroughErrorElement, HType.UNKNOWN);
+ pushInvokeStatic(switchCase, getFallThroughErrorElement, []);
HInstruction error = pop();
closeAndGotoExit(new HThrow(error));
}
@@ -4423,6 +4682,10 @@
instruction.block.addSuccessor(joinBlock);
caseHandlers.add(locals);
});
+ jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) {
+ assert(invariant(errorNode, false,
+ message: 'Continue cannot target a switch.'));
+ });
if (!isAborted()) {
current.close(new HGoto());
lastOpenedBlock.addSuccessor(joinBlock);
@@ -4462,7 +4725,6 @@
joinBlock);
jumpHandler.close();
- return true;
}
bool nonPrimitiveTypeOverridesEquals(Constant constant) {
@@ -4500,110 +4762,6 @@
return classElement.lookupMember(dartMethodName);
}
-
- // Recursively build an if/else structure to match the cases.
- void buildSwitchCases(Link<Node> cases, HInstruction expression,
- [int encounteredCaseTypes = 0]) {
- final int NO_TYPE = 0;
- final int INT_TYPE = 1;
- final int STRING_TYPE = 2;
- final int CONFLICT_TYPE = 3;
- int combine(int type1, int type2) => type1 | type2;
-
- SwitchCase node = cases.head;
- // Called for the statements on all but the last case block.
- // Ensures that a user expecting a fallthrough gets an error.
- void visitStatementsAndAbort() {
- visit(node.statements);
- if (!isAborted()) {
- compiler.reportWarning(node, 'Missing break at end of switch case');
- Element element =
- compiler.findHelper(const SourceString("getFallThroughError"));
- pushInvokeHelper0(element, HType.UNKNOWN);
- HInstruction error = pop();
- closeAndGotoExit(new HThrow(error));
- }
- }
-
- Link<Node> skipLabels(Link<Node> labelsAndCases) {
- while (!labelsAndCases.isEmpty && labelsAndCases.head is Label) {
- labelsAndCases = labelsAndCases.tail;
- }
- return labelsAndCases;
- }
-
- Link<Node> labelsAndCases = skipLabels(node.labelsAndCases.nodes);
- if (labelsAndCases.isEmpty) {
- // Default case with no expressions.
- if (!node.isDefaultCase) {
- compiler.internalError("Case with no expression and not default",
- node: node);
- }
- visit(node.statements);
- // This must be the final case (otherwise "default" would be invalid),
- // so we don't need to check for fallthrough.
- return;
- }
-
- // Recursively build the test conditions. Leaves the result on the
- // expression stack.
- void buildTests(Link<Node> remainingCases) {
- // Build comparison for one case expression.
- void left() {
- CaseMatch match = remainingCases.head;
- // TODO(lrn): Move the constant resolution to the resolver, so
- // we can report an error before reaching the backend.
- Constant constant =
- compiler.constantHandler.tryCompileNodeWithDefinitions(
- match.expression, elements);
- if (constant != null) {
- stack.add(graph.addConstant(constant));
- } else {
- visit(match.expression);
- }
- push(new HIdentity(pop(), expression));
- }
-
- // If this is the last expression, just return it.
- Link<Node> tail = skipLabels(remainingCases.tail);
- if (tail.isEmpty) {
- left();
- return;
- }
-
- void right() {
- buildTests(tail);
- }
- SsaBranchBuilder branchBuilder =
- new SsaBranchBuilder(this, remainingCases.head);
- branchBuilder.handleLogicalAndOr(left, right, isAnd: false);
- }
-
- if (node.isDefaultCase) {
- // Default case must be last.
- assert(cases.tail.isEmpty);
- // Perform the tests until one of them match, but then always execute the
- // statements.
- // TODO(lrn): Stop performing tests when all expressions are compile-time
- // constant strings or integers.
- handleIf(node, () { buildTests(labelsAndCases); }, (){}, null);
- visit(node.statements);
- } else {
- if (cases.tail.isEmpty) {
- handleIf(node,
- () { buildTests(labelsAndCases); },
- () { visit(node.statements); },
- null);
- } else {
- handleIf(node,
- () { buildTests(labelsAndCases); },
- () { visitStatementsAndAbort(); },
- () { buildSwitchCases(cases.tail, expression,
- encounteredCaseTypes); });
- }
- }
- }
-
visitSwitchCase(SwitchCase node) {
compiler.internalError('SsaBuilder.visitSwitchCase');
}
@@ -4659,8 +4817,7 @@
HInstruction oldRethrowableException = rethrowableException;
rethrowableException = exception;
- pushInvokeHelper1(
- backend.getExceptionUnwrapper(), exception, HType.UNKNOWN);
+ pushInvokeStatic(node, backend.getExceptionUnwrapper(), [exception]);
HInvokeStatic unwrappedException = pop();
tryInstruction.exception = exception;
Link<Node> link = node.catchBlocks.nodes;
@@ -4700,7 +4857,7 @@
}
// TODO(karlkose): support type arguments here.
condition = new HIs(type, <HInstruction>[unwrappedException],
- HIs.RAW_CHECK, nullOk: true);
+ HIs.RAW_CHECK);
push(condition);
}
}
@@ -4730,8 +4887,7 @@
}
Node trace = catchBlock.trace;
if (trace != null) {
- pushInvokeHelper1(
- backend.getTraceFromException(), exception, HType.UNKNOWN);
+ pushInvokeStatic(trace, backend.getTraceFromException(), [exception]);
HInstruction traceInstruction = pop();
localsHandler.updateLocal(elements[trace], traceInstruction);
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 9a3cd73..48d4466 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -630,10 +630,7 @@
void use(HInstruction argument) {
if (isGenerateAtUseSite(argument)) {
visitExpression(argument);
- } else if (argument is HCheck && argument.isControlFlow()) {
- // A [HCheck] that has control flow can never be used as an
- // expression and may not have a name. Therefore we just use the
- // checked instruction.
+ } else if (argument is HCheck && !variableNames.hasName(argument)) {
HCheck check = argument;
use(check.checkedInput);
} else {
@@ -779,6 +776,7 @@
case HLoopBlockInformation.FOR_LOOP:
case HLoopBlockInformation.WHILE_LOOP:
case HLoopBlockInformation.FOR_IN_LOOP:
+ case HLoopBlockInformation.SWITCH_CONTINUE_LOOP:
HBlockInformation initialization = info.initializer;
int initializationType = TYPE_STATEMENT;
if (initialization != null) {
@@ -931,7 +929,13 @@
instruction: condition.conditionExpression);
}
attachLocationRange(loop, info.sourcePosition, info.endSourcePosition);
- pushStatement(wrapIntoLabels(loop, info.labels));
+ js.Statement result = loop;
+ if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) {
+ String continueLabelString =
+ backend.namer.implicitContinueLabelName(info.target);
+ result = new js.LabeledStatement(continueLabelString, result);
+ }
+ pushStatement(wrapIntoLabels(result, info.labels));
return true;
}
@@ -973,15 +977,15 @@
result = new js.LabeledStatement(labelName, result);
}
}
- TargetElement target = labeledBlockInfo.target;
- if (target.isSwitch) {
- // This is an extra block around a switch that is generated
- // as a nested if/else chain. We add an extra break target
- // so that case code can break.
- String labelName = backend.namer.implicitBreakLabelName(target);
- result = new js.LabeledStatement(labelName, result);
- breakAction[target] = implicitBreakWithLabel;
- }
+ }
+ TargetElement target = labeledBlockInfo.target;
+ if (target.isSwitch) {
+ // This is an extra block around a switch that is generated
+ // as a nested if/else chain. We add an extra break target
+ // so that case code can break.
+ String labelName = backend.namer.implicitBreakLabelName(target);
+ result = new js.LabeledStatement(labelName, result);
+ breakAction[target] = implicitBreakWithLabel;
}
currentContainer = body;
@@ -1337,7 +1341,12 @@
} else {
TargetElement target = node.target;
if (!tryCallAction(breakAction, target)) {
- pushStatement(new js.Break(null), node);
+ if (node.breakSwitchContinueLoop) {
+ pushStatement(new js.Break(
+ backend.namer.implicitContinueLabelName(target)), node);
+ } else {
+ pushStatement(new js.Break(null), node);
+ }
}
}
}
@@ -1354,7 +1363,12 @@
} else {
TargetElement target = node.target;
if (!tryCallAction(continueAction, target)) {
- pushStatement(new js.Continue(null), node);
+ if (target.statement is SwitchStatement) {
+ pushStatement(new js.Continue(
+ backend.namer.implicitContinueLabelName(target)), node);
+ } else {
+ pushStatement(new js.Continue(null), node);
+ }
}
}
}
@@ -1651,6 +1665,8 @@
new js.PropertyAccess.field(prototype, methodName);
push(jsPropertyCall(
method, "call", visitArguments(node.inputs, start: 0)), node);
+ // Register this invocation to collect the types used at all call sites.
+ backend.registerDynamicInvocation(node, node.selector);
}
world.registerStaticUse(superMethod);
}
@@ -2447,81 +2463,87 @@
}
void visitTypeConversion(HTypeConversion node) {
- if (node.isChecked) {
- if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
- js.Expression test = generateTest(node);
- js.Block oldContainer = currentContainer;
- js.Statement body = new js.Block.empty();
- currentContainer = body;
- if (node.isArgumentTypeCheck) {
- generateThrowWithHelper('iae', node.checkedInput);
- } else if (node.isReceiverTypeCheck) {
- use(node.checkedInput);
- String methodName =
- backend.namer.invocationName(node.receiverTypeCheckSelector);
- js.Expression call = jsPropertyCall(pop(), methodName, []);
- pushStatement(new js.Throw(call));
- }
- currentContainer = oldContainer;
- body = unwrapStatement(body);
- pushStatement(new js.If.noElse(test, body), node);
- return;
+ if (!node.isChecked) {
+ use(node.checkedInput);
+ return;
+ }
+ if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
+ js.Expression test = generateTest(node);
+ js.Block oldContainer = currentContainer;
+ js.Statement body = new js.Block.empty();
+ currentContainer = body;
+ if (node.isArgumentTypeCheck) {
+ generateThrowWithHelper('iae', node.checkedInput);
+ } else if (node.isReceiverTypeCheck) {
+ use(node.checkedInput);
+ String methodName =
+ backend.namer.invocationName(node.receiverTypeCheckSelector);
+ js.Expression call = jsPropertyCall(pop(), methodName, []);
+ pushStatement(new js.Throw(call));
}
+ currentContainer = oldContainer;
+ body = unwrapStatement(body);
+ pushStatement(new js.If.noElse(test, body), node);
+ return;
+ }
- assert(node.isCheckedModeCheck || node.isCastTypeCheck);
- DartType type = node.typeExpression;
+ assert(node.isCheckedModeCheck || node.isCastTypeCheck);
+ DartType type = node.typeExpression;
if (type.kind == TypeKind.FUNCTION) {
// TODO(5022): We currently generate $isFunction checks for
// function types.
world.registerIsCheck(
compiler.functionClass.computeType(compiler), work.resolutionTree);
}
- world.registerIsCheck(type, work.resolutionTree);
+ world.registerIsCheck(type, work.resolutionTree);
- // TODO(kasperl): For now, we ignore type checks against type
- // variables. This is clearly wrong.
- if (type.kind == TypeKind.TYPE_VARIABLE) {
- use(node.checkedInput);
- return;
- }
-
- FunctionElement helperElement;
- if (node.isBooleanConversionCheck) {
- helperElement =
- compiler.findHelper(const SourceString('boolConversionCheck'));
- } else {
- helperElement = backend.getCheckedModeHelper(type,
- typeCast: node.isCastTypeCheck);
- }
- world.registerStaticUse(helperElement);
- List<js.Expression> arguments = <js.Expression>[];
- use(node.checkedInput);
- arguments.add(pop());
- int parameterCount =
- helperElement.computeSignature(compiler).parameterCount;
- // TODO(johnniwinther): Refactor this to avoid using the parameter count
- // to determine how the helper should be called.
- if (parameterCount == 2) {
- // 2 arguments implies that the method is either [propertyTypeCheck]
- // or [propertyTypeCast].
- assert(!type.isMalformed);
- String additionalArgument = backend.namer.operatorIs(type.element);
- arguments.add(js.string(additionalArgument));
- } else if (parameterCount == 3) {
- // 3 arguments implies that the method is [malformedTypeCheck].
- assert(type.isMalformed);
- String reasons = Types.fetchReasonsFromMalformedType(type);
- arguments.add(js.string('$type'));
- // TODO(johnniwinther): Handle escaping correctly.
- arguments.add(js.string(reasons));
- } else {
- assert(!type.isMalformed);
- }
- String helperName = backend.namer.isolateAccess(helperElement);
- push(new js.Call(new js.VariableUse(helperName), arguments));
+ FunctionElement helperElement;
+ if (node.isBooleanConversionCheck) {
+ helperElement =
+ compiler.findHelper(const SourceString('boolConversionCheck'));
} else {
- use(node.checkedInput);
+ helperElement = backend.getCheckedModeHelper(type,
+ typeCast: node.isCastTypeCheck);
}
+ world.registerStaticUse(helperElement);
+ List<js.Expression> arguments = <js.Expression>[];
+ use(node.checkedInput);
+ arguments.add(pop());
+ int parameterCount =
+ helperElement.computeSignature(compiler).parameterCount;
+ // TODO(johnniwinther): Refactor this to avoid using the parameter count
+ // to determine how the helper should be called.
+ if (node.typeExpression.kind == TypeKind.TYPE_VARIABLE) {
+ assert(parameterCount == 2);
+ use(node.typeRepresentation);
+ arguments.add(pop());
+ } else if (parameterCount == 2) {
+ // 2 arguments implies that the method is either [propertyTypeCheck],
+ // [propertyTypeCast] or [assertObjectIsSubtype].
+ assert(!type.isMalformed);
+ String additionalArgument = backend.namer.operatorIs(type.element);
+ arguments.add(js.string(additionalArgument));
+ } else if (parameterCount == 3) {
+ // 3 arguments implies that the method is [malformedTypeCheck].
+ assert(type.isMalformed);
+ String reasons = Types.fetchReasonsFromMalformedType(type);
+ arguments.add(js.string('$type'));
+ // TODO(johnniwinther): Handle escaping correctly.
+ arguments.add(js.string(reasons));
+ } else if (parameterCount == 4) {
+ Element element = type.element;
+ String isField = backend.namer.operatorIs(element);
+ arguments.add(js.string(isField));
+ use(node.typeRepresentation);
+ arguments.add(pop());
+ String asField = backend.namer.substitutionName(element);
+ arguments.add(js.string(asField));
+ } else {
+ assert(!type.isMalformed);
+ // No additional arguments needed.
+ }
+ String helperName = backend.namer.isolateAccess(helperElement);
+ push(new js.Call(new js.VariableUse(helperName), arguments));
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 7dccbc9..2eb8faa 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -791,7 +791,9 @@
static const int IS_TYPECODE = 28;
static const int INVOKE_DYNAMIC_TYPECODE = 29;
- HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[];
+ HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[] {
+ assert(inputs.every((e) => e != null));
+ }
int get hashCode => id;
@@ -799,6 +801,7 @@
void setUseGvn() { _useGvn = true; }
void updateInput(int i, HInstruction insn) {
+ assert(insn != null);
inputs[i] = insn;
}
@@ -952,6 +955,7 @@
// Change all uses of [oldInput] by [this] to [newInput]. Also
// updates the [usedBy] of [oldInput] and [newInput].
void changeUse(HInstruction oldInput, HInstruction newInput) {
+ assert(newInput != null);
for (int i = 0; i < inputs.length; i++) {
if (identical(inputs[i], oldInput)) {
inputs[i] = newInput;
@@ -1086,6 +1090,8 @@
} else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
// Boolean conversion checks work on non-nullable booleans.
return new HTypeConversion(type, kind, HType.BOOLEAN, this);
+ } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.isRaw) {
+ throw 'creating compound check to $type (this = ${this})';
} else {
HType subtype = new HType.subtype(type, compiler);
return new HTypeConversion(type, kind, subtype, this);
@@ -1127,6 +1133,12 @@
HInstruction get checkedInput => inputs[0];
bool isJsStatement() => true;
bool canThrow() => true;
+
+ HInstruction unwrap() {
+ var checked = checkedInput;
+ while (checked is HCheck) checked = checked.checkedInput;
+ return checked;
+ }
}
class HBailoutTarget extends HInstruction {
@@ -1242,6 +1254,16 @@
}
static const int ARGUMENTS_OFFSET = 1;
bool canThrow() => true;
+
+ /**
+ * Returns whether this call is on an intercepted method.
+ */
+ bool get isInterceptedCall {
+ // We know it's a selector call if it follows the interceptor
+ // calling convention, which adds the actual receiver as a
+ // parameter to the call.
+ return inputs.length - 2 == selector.argumentCount;
+ }
}
abstract class HInvokeDynamic extends HInvoke {
@@ -1265,16 +1287,6 @@
}
/**
- * Returns whether this call is on an intercepted method.
- */
- bool get isInterceptedCall {
- // We know it's a selector call if it follows the interceptor
- // calling convention, which adds the actual receiver as a
- // parameter to the call.
- return inputs.length - 2 == selector.argumentCount;
- }
-
- /**
* Returns whether this call is on an interceptor object.
*/
bool isCallOnInterceptor(Compiler compiler) {
@@ -1369,8 +1381,13 @@
/** The class where the call to super is being done. */
final ClassElement caller;
final bool isSetter;
+ final Selector selector;
- HInvokeSuper(Element element, this.caller, inputs, {this.isSetter})
+ HInvokeSuper(Element element,
+ this.caller,
+ this.selector,
+ inputs,
+ {this.isSetter})
: super(element, inputs, HType.UNKNOWN);
toString() => 'invoke super: ${element.name}';
accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
@@ -1667,7 +1684,7 @@
instructionType = HType.INTEGER;
}
accept(HVisitor visitor) => visitor.visitBitNot(this);
-
+
UnaryOperation operation(ConstantSystem constantSystem)
=> constantSystem.bitNot;
int typeCode() => HInstruction.BIT_NOT_TYPECODE;
@@ -1696,8 +1713,16 @@
}
class HBreak extends HJump {
- HBreak(TargetElement target) : super(target);
- HBreak.toLabel(LabelElement label) : super.toLabel(label);
+ /**
+ * Signals that this is a special break instruction for the synthetic loop
+ * generatedfor a switch statement with continue statements. See
+ * [SsaBuilder.buildComplexSwitchStatement] for detail.
+ */
+ final bool breakSwitchContinueLoop;
+ HBreak(TargetElement target, {bool this.breakSwitchContinueLoop: false})
+ : super(target);
+ HBreak.toLabel(LabelElement label)
+ : breakSwitchContinueLoop = false, super.toLabel(label);
toString() => (label != null) ? 'break ${label.labelName}' : 'break';
accept(HVisitor visitor) => visitor.visitBreak(this);
}
@@ -2132,7 +2157,6 @@
HInstruction get value => inputs[2];
}
-// TODO(karlklose): use this class to represent type conversions as well.
class HIs extends HInstruction {
/// A check against a raw type: 'o is int', 'o is A'.
static const int RAW_CHECK = 0;
@@ -2199,6 +2223,23 @@
instructionType = type;
}
+ HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
+ HType type, HInstruction input,
+ HInstruction typeRepresentation)
+ : super(<HInstruction>[input, typeRepresentation]),
+ receiverTypeCheckSelector = null {
+ sourceElement = input.sourceElement;
+ instructionType = type;
+ }
+
+ bool get hasTypeRepresentation => inputs.length > 1;
+ HInstruction get typeRepresentation => inputs[1];
+
+ HInstruction convertType(Compiler compiler, DartType type, int kind) {
+ if (typeExpression == type) return this;
+ return super.convertType(compiler, type, kind);
+ }
+
bool get isChecked => kind != NO_CHECK;
bool get isCheckedModeCheck {
return kind == CHECKED_MODE_CHECK
@@ -2462,6 +2503,8 @@
int visitFor(For node) => HLoopBlockInformation.FOR_LOOP;
int visitDoWhile(DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
int visitForIn(ForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
+ int visitSwitchStatement(SwitchStatement node) =>
+ HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
}
class HLoopBlockInformation implements HStatementInformation {
@@ -2469,6 +2512,7 @@
static const int FOR_LOOP = 1;
static const int DO_WHILE_LOOP = 2;
static const int FOR_IN_LOOP = 3;
+ static const int SWITCH_CONTINUE_LOOP = 4;
static const int NOT_A_LOOP = -1;
final int kind;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 2d9c62a..09df7c1 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -606,7 +606,9 @@
HInstruction visitTypeConversion(HTypeConversion node) {
HInstruction value = node.inputs[0];
DartType type = node.typeExpression;
- if (type != null && !type.isRaw) return node;
+ if (type != null && (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE)) {
+ return node;
+ }
HType convertedType = node.instructionType;
if (convertedType.isUnknown()) return node;
HType combinedType = value.instructionType.intersection(
@@ -723,9 +725,15 @@
// interceptor.
HInstruction value = node.inputs.last;
if (compiler.enableTypeAssertions) {
+ DartType type = field.computeType(compiler);
+ if (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE) {
+ // We cannot generate the correct type representation here, so don't
+ // inline this access.
+ return node;
+ }
HInstruction other = value.convertType(
compiler,
- field.computeType(compiler),
+ type,
HTypeConversion.CHECKED_MODE_CHECK);
if (other != value) {
node.block.addBefore(node, other);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
index fa67e88..aef770f 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
@@ -222,13 +222,6 @@
}
}
- HInstruction unwrap(instruction) {
- do {
- instruction = instruction.checkedInput;
- } while (instruction is HCheck);
- return instruction;
- }
-
void markAsLiveInEnvironment(HInstruction instruction,
LiveEnvironment environment) {
if (generateAtUseSite.contains(instruction)) {
@@ -239,7 +232,8 @@
// checked instruction live. The checked instruction and the
// [HCheck] will share the same live ranges.
if (instruction is HCheck) {
- HInstruction checked = unwrap(instruction);
+ HCheck check = instruction;
+ HInstruction checked = check.unwrap();
if (!generateAtUseSite.contains(checked)) {
environment.add(checked, instructionId);
}
@@ -253,7 +247,8 @@
// Special case the HCheck instruction to have the same live
// interval as the instruction it is checking.
if (instruction is HCheck) {
- HInstruction checked = unwrap(instruction);
+ HCheck check = instruction;
+ HInstruction checked = check.unwrap();
if (!generateAtUseSite.contains(checked)) {
liveIntervals.putIfAbsent(checked, () => new LiveInterval());
// Unconditionally force the live ranges of the HCheck to
@@ -625,17 +620,15 @@
* Returns whether [instruction] needs a name. Instructions that
* have no users or that are generated at use site do not need a name.
*/
- bool needsName(HInstruction instruction) {
+ bool needsName(instruction) {
if (instruction is HThis) return false;
if (instruction is HParameterValue) return true;
if (instruction.usedBy.isEmpty) return false;
if (generateAtUseSite.contains(instruction)) return false;
- // A [HCheck] instruction that has control flow needs a name only if its
- // checked input needs a name (for example, a checked [HConstant] does not
- // need a name).
- if (instruction is HCheck && instruction.isControlFlow()) {
- HCheck check = instruction;
- return needsName(instruction.checkedInput);
+ // A [HCheck] instruction needs a name only if its
+ // checked input does not have a fixed name or value.
+ if (instruction is HCheck) {
+ return !instruction.unwrap().isCodeMotionInvariant();
}
return true;
}
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index 659e7b0..a2216cd 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -369,6 +369,20 @@
bool get isParameterCheck =>
isOperator && identical(selector.asOperator().source.stringValue, '?');
+ bool get isIsNotCheck {
+ return isOperator
+ && identical(selector.asOperator().source.stringValue, 'is')
+ && arguments.head.asSend() != null;
+ }
+
+ TypeAnnotation get typeAnnotationFromIsCheck {
+ assert(isOperator
+ && identical(selector.asOperator().source.stringValue, 'is'));
+ return isIsNotCheck
+ ? arguments.head.asSend().receiver
+ : arguments.head;
+ }
+
Token getBeginToken() {
if (isPrefix && !isIndex) return selector.getBeginToken();
return firstBeginToken(receiver, selector);
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 68e22f1..2bd8266 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -867,8 +867,12 @@
* Get the inferred concrete type of [element].
*/
TypeMask getTypeOfElement(Element element) {
- if (!element.isParameter()) return null;
- return concreteTypeToTypeMask(inferredParameterTypes[element]);
+ if (element.isParameter()) {
+ return concreteTypeToTypeMask(inferredParameterTypes[element]);
+ } else if (element.isField()) {
+ return concreteTypeToTypeMask(inferredFieldTypes[element]);
+ }
+ // TODO(polux): handle field parameters
}
/**
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 0e25098..658ce4e 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -115,6 +115,10 @@
bool get isNullable => true;
+ TypeMask intersection(TypeMask other, Compiler compiler) {
+ return other;
+ }
+
String toString() => '$name sentinel type mask';
}
@@ -343,13 +347,13 @@
bool wasAnalyzed = analyzeCount.containsKey(element);
if (wasAnalyzed) {
recompiles++;
- recomputeWatch.start();
+ if (compiler.verbose) recomputeWatch.start();
}
bool changed =
compiler.withCurrentElement(element, () => analyze(element));
if (optimismState == RETRY) return true; // Abort.
analyzed++;
- if (wasAnalyzed) {
+ if (wasAnalyzed && compiler.verbose) {
recomputeWatch.stop();
}
checkAnalyzedAll();
@@ -1001,22 +1005,20 @@
if (!arguments.named.isEmpty) return null;
if (arguments.positional.length > 1) return null;
- switch (selector.name) {
- case const SourceString('*'):
- case const SourceString('+'):
- case const SourceString('%'):
- case const SourceString('remainder'):
+ SourceString name = selector.name;
+ if (name == const SourceString('*')
+ || name == const SourceString('+')
+ || name == const SourceString('%')
+ || name == const SourceString('remainder')) {
return arguments.hasOnePositionalArgumentWithType(intType)
? intType
: null;
-
- case const SourceString('-'):
- if (arguments.hasNoArguments()) return intType;
- if (arguments.hasOnePositionalArgumentWithType(intType)) return intType;
- return null;
-
- case const SourceString('abs'):
- return arguments.hasNoArguments() ? intType : null;
+ } else if (name == const SourceString('-')) {
+ if (arguments.hasNoArguments()) return intType;
+ if (arguments.hasOnePositionalArgumentWithType(intType)) return intType;
+ return null;
+ } else if (name == const SourceString('abs')) {
+ return arguments.hasNoArguments() ? intType : null;
}
return null;
}
@@ -1246,6 +1248,26 @@
return union.containsAll(compiler) ? dynamicType : union;
}
}
+
+ TypeMask narrowType(TypeMask type,
+ DartType annotation,
+ {bool isNullable: true}) {
+ if (annotation.isDynamic) return type;
+ if (annotation.isMalformed) return type;
+ if (annotation.element == compiler.objectClass) return type;
+ TypeMask otherType;
+ if (annotation.kind == TypeKind.TYPEDEF
+ || annotation.kind == TypeKind.FUNCTION) {
+ otherType = functionType;
+ } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+ return type;
+ } else {
+ assert(annotation.kind == TypeKind.INTERFACE);
+ otherType = new TypeMask.nonNullSubtype(annotation);
+ }
+ if (isNullable) otherType = otherType.nullable();
+ return type.intersection(otherType, compiler);
+ }
}
/**
@@ -1417,6 +1439,8 @@
bool visitingInitializers = false;
bool isConstructorRedirect = false;
+ bool accumulateIsChecks = false;
+ List<Send> isChecks;
int loopLevel = 0;
SideEffects sideEffects = new SideEffects.empty();
@@ -2007,32 +2031,68 @@
return new ArgumentsTypes(positional, named);
}
+ void potentiallyAddIsCheck(Send node) {
+ if (!accumulateIsChecks) return;
+ if (!Elements.isLocal(elements[node.receiver])) return;
+ isChecks.add(node);
+ }
+
+ void updateIsChecks(List<Node> tests, {bool usePositive}) {
+ if (tests == null) return;
+ for (Send node in tests) {
+ if (node.isIsNotCheck) {
+ if (usePositive) continue;
+ } else {
+ if (!usePositive) continue;
+ }
+ DartType type = elements.getType(node.typeAnnotationFromIsCheck);
+ Element element = elements[node.receiver];
+ TypeMask existing = locals.use(element);
+ TypeMask newType = inferrer.narrowType(existing, type, isNullable: false);
+ locals.update(element, newType);
+ }
+ }
+
TypeMask visitOperatorSend(Send node) {
Operator op = node.selector;
if (const SourceString("[]") == op.source) {
return visitDynamicSend(node);
- } else if (const SourceString("&&") == op.source ||
- const SourceString("||") == op.source) {
+ } else if (const SourceString("&&") == op.source) {
+ bool oldAccumulateIsChecks = accumulateIsChecks;
+ accumulateIsChecks = true;
+ if (isChecks == null) isChecks = <Send>[];
+ visit(node.receiver);
+ accumulateIsChecks = oldAccumulateIsChecks;
+ if (!accumulateIsChecks) isChecks = null;
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ updateIsChecks(isChecks, usePositive: true);
+ visit(node.arguments.head);
+ locals.merge(saved);
+ return inferrer.boolType;
+ } else if (const SourceString("||") == op.source) {
visit(node.receiver);
LocalsHandler saved = new LocalsHandler.from(locals);
+ updateIsChecks(isChecks, usePositive: false);
+ bool oldAccumulateIsChecks = accumulateIsChecks;
+ accumulateIsChecks = false;
visit(node.arguments.head);
- saved.merge(locals);
- locals = saved;
+ accumulateIsChecks = oldAccumulateIsChecks;
+ locals.merge(saved);
return inferrer.boolType;
} else if (const SourceString("!") == op.source) {
+ bool oldAccumulateIsChecks = accumulateIsChecks;
+ accumulateIsChecks = false;
node.visitChildren(this);
+ accumulateIsChecks = oldAccumulateIsChecks;
return inferrer.boolType;
} else if (const SourceString("is") == op.source) {
+ potentiallyAddIsCheck(node);
node.visitChildren(this);
return inferrer.boolType;
} else if (const SourceString("as") == op.source) {
- node.visitChildren(this);
+ TypeMask receiverType = visit(node.receiver);
DartType type = elements.getType(node.arguments.head);
- if (type.isDynamic) return inferrer.dynamicType;
- if (type.kind == TypeKind.TYPEDEF) {
- return inferrer.functionType.nullable();
- }
- return new TypeMask.subtype(type);
+ return inferrer.narrowType(receiverType, type);
} else if (node.isParameterCheck) {
node.visitChildren(this);
return inferrer.boolType;
@@ -2201,12 +2261,14 @@
}
TypeMask visitConditional(Conditional node) {
- node.condition.accept(this);
+ List<Send> tests = handleCondition(node.condition);
LocalsHandler saved = new LocalsHandler.from(locals);
- TypeMask firstType = node.thenExpression.accept(this);
+ updateIsChecks(tests, usePositive: true);
+ TypeMask firstType = visit(node.thenExpression);
LocalsHandler thenLocals = locals;
locals = saved;
- TypeMask secondType = node.elseExpression.accept(this);
+ updateIsChecks(tests, usePositive: false);
+ TypeMask secondType = visit(node.elseExpression);
locals.merge(thenLocals);
TypeMask type = inferrer.computeLUB(firstType, secondType);
return type;
@@ -2227,12 +2289,26 @@
return inferrer.dynamicType;
}
+ List<Send> handleCondition(Node node) {
+ bool oldAccumulateIsChecks = accumulateIsChecks;
+ List<Send> oldIsChecks = isChecks;
+ List<Send> tests = <Send>[];
+ accumulateIsChecks = true;
+ isChecks = tests;
+ visit(node);
+ accumulateIsChecks = oldAccumulateIsChecks;
+ isChecks = oldIsChecks;
+ return tests;
+ }
+
TypeMask visitIf(If node) {
- visit(node.condition);
+ List<Send> tests = handleCondition(node.condition);
LocalsHandler saved = new LocalsHandler.from(locals);
+ updateIsChecks(tests, usePositive: true);
visit(node.thenPart);
LocalsHandler thenLocals = locals;
locals = saved;
+ updateIsChecks(tests, usePositive: false);
visit(node.elsePart);
locals.merge(thenLocals);
return inferrer.dynamicType;
@@ -2243,7 +2319,8 @@
bool changed = false;
do {
LocalsHandler saved = new LocalsHandler.from(locals);
- visit(node.condition);
+ List<Send> tests = handleCondition(node.condition);
+ updateIsChecks(tests, usePositive: true);
visit(node.body);
changed = saved.merge(locals);
locals = saved;
@@ -2258,7 +2335,8 @@
do {
LocalsHandler saved = new LocalsHandler.from(locals);
visit(node.body);
- visit(node.condition);
+ List<Send> tests = handleCondition(node.condition);
+ updateIsChecks(tests, usePositive: true);
changed = saved.merge(locals);
locals = saved;
} while (changed);
@@ -2272,7 +2350,8 @@
loopLevel++;
do {
LocalsHandler saved = new LocalsHandler.from(locals);
- visit(node.condition);
+ List<Send> tests = handleCondition(node.condition);
+ updateIsChecks(tests, usePositive: true);
visit(node.body);
visit(node.update);
changed = saved.merge(locals);
@@ -2358,4 +2437,45 @@
void internalError(String reason, {Node node}) {
compiler.internalError(reason, node: node);
}
+
+ TypeMask visitSwitchStatement(SwitchStatement node) {
+ visit(node.parenthesizedExpression);
+
+ if (Elements.switchStatementHasContinue(node, elements)) {
+ // If the switch statement has a continue, we conservatively
+ // visit all cases and update [locals] until we have reached a
+ // fixed point.
+ bool changed;
+ do {
+ changed = false;
+ for (Node switchCase in node.cases) {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ visit(switchCase);
+ changed = saved.merge(locals) || changed;
+ locals = saved;
+ }
+ } while (changed);
+ } else {
+ LocalsHandler saved = new LocalsHandler.from(locals);
+ // If there is a default case, the current values of the local
+ // variable might be overwritten, so we don't need the current
+ // [locals] for the join block.
+ LocalsHandler result = Elements.switchStatementHasDefault(node)
+ ? null
+ : new LocalsHandler.from(locals);
+
+ for (Node switchCase in node.cases) {
+ locals = saved;
+ visit(switchCase);
+ if (result == null) {
+ result = locals;
+ } else {
+ result.merge(locals);
+ }
+ }
+
+ locals = result;
+ }
+ return inferrer.dynamicType;
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 189c326..7dcebd8 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -465,6 +465,10 @@
"Patch method parameter '#{patchParameter}' doesn't match "
"'#{originParameter}' on origin method #{methodName}.");
+ static const PATCH_PARAMETER_TYPE_MISMATCH = const MessageKind(
+ "Patch method parameter '#{parameterName}' type #{patchParameterType} "
+ "doesn't match #{originParameterType} on origin method #{methodName}.");
+
static const PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION = const MessageKind(
"External method without an implementation.");
@@ -483,6 +487,9 @@
static const PATCH_POINT_TO_CONSTRUCTOR = const MessageKind(
"Info: This is the constructor patch '#{constructorName}'.");
+ static const PATCH_POINT_TO_PARAMETER = const MessageKind(
+ "Info: This is the patch parameter '#{parameterName}'.");
+
static const PATCH_NON_EXISTING = const MessageKind(
"Error: Origin does not exist for patch '#{name}'.");
diff --git a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
index 87d3fb3..fd46a37 100644
--- a/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
+++ b/sdk/lib/_internal/compiler/samples/leap/leap_server.dart
@@ -39,8 +39,8 @@
handle() {
response.done
- ..then(onClosed)
- ..catchError(onError);
+ .then(onClosed)
+ .catchError(onError);
String path = request.uri.path;
if (path == '/') return redirect('/$landingPage');
@@ -62,7 +62,7 @@
} else if (path.endsWith('.appcache')) {
response.headers.set(CONTENT_TYPE, 'text/cache-manifest');
}
- f.openRead().pipe(response);
+ f.openRead().pipe(response).catchError(onError);
});
}
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index 359c77b..edfffba 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -238,18 +238,22 @@
if (dirExists(path.join(root.dir, '.git')) && gitInstalled) {
// List all files that aren't gitignored, including those not checked
// in to Git.
- return git.run(["ls-files", "--cached", "--others",
- "--exclude-standard", beneath]).then((files) {
+ return git.run(
+ ["ls-files", "--cached", "--others", "--exclude-standard", beneath],
+ workingDir: root.dir).then((files) {
// Git always prints files relative to the project root, but we want
- // them relative to the working directory.
- return files.map((file) => path.join(root.dir, file));
+ // them relative to the working directory. It also prints forward
+ // slashes on Windows which we normalize away for easier testing.
+ return files.map((file) => path.normalize(path.join(root.dir, file)));
});
}
- // Skip directories and broken symlinks.
- return listDir(beneath, recursive: true).where(fileExists);
+ return listDir(beneath, recursive: true);
}).then((files) {
return files.where((file) {
+ // Skip directories and broken symlinks.
+ if (!fileExists(file)) return false;
+
var relative = path.relative(file, from: beneath);
if (_BLACKLISTED_FILES.contains(path.basename(relative))) return false;
return !path.split(relative).any(_BLACKLISTED_DIRS.contains);
diff --git a/sdk/lib/_internal/pub/test/package_files_test.dart b/sdk/lib/_internal/pub/test/package_files_test.dart
new file mode 100644
index 0000000..36e6832
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/package_files_test.dart
@@ -0,0 +1,224 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lock_file_test;
+
+import 'dart:io';
+
+import 'package:pathos/path.dart' as path;
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../lib/src/entrypoint.dart';
+import '../lib/src/io.dart';
+import '../lib/src/system_cache.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
+
+var root;
+var entrypoint;
+
+main() {
+ initConfig();
+
+ group('not in a git repo', () {
+ setUp(() {
+ d.appDir([]).create();
+ scheduleEntrypoint();
+ });
+
+
+ integration('lists files recursively', () {
+ d.dir(appPath, [
+ d.file('file1.txt', 'contents'),
+ d.file('file2.txt', 'contents'),
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents'),
+ d.file('subfile2.txt', 'subcontents')
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(), completion(unorderedEquals([
+ path.join(root, 'pubspec.yaml'),
+ path.join(root, 'file1.txt'),
+ path.join(root, 'file2.txt'),
+ path.join(root, 'subdir', 'subfile1.txt'),
+ path.join(root, 'subdir', 'subfile2.txt')
+ ])));
+ });
+ });
+
+ commonTests();
+ });
+
+ group('with git', () {
+ setUp(() {
+ ensureGit();
+ d.git(appPath, [d.appPubspec([])]).create();
+ scheduleEntrypoint();
+ });
+
+ integration("includes files that are or aren't checked in", () {
+ d.dir(appPath, [
+ d.file('file1.txt', 'contents'),
+ d.file('file2.txt', 'contents'),
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents'),
+ d.file('subfile2.txt', 'subcontents')
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(), completion(unorderedEquals([
+ path.join(root, 'pubspec.yaml'),
+ path.join(root, 'file1.txt'),
+ path.join(root, 'file2.txt'),
+ path.join(root, 'subdir', 'subfile1.txt'),
+ path.join(root, 'subdir', 'subfile2.txt')
+ ])));
+ });
+ });
+
+ integration("ignores files that are gitignored", () {
+ d.dir(appPath, [
+ d.file('.gitignore', '*.txt'),
+ d.file('file1.txt', 'contents'),
+ d.file('file2.text', 'contents'),
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents'),
+ d.file('subfile2.text', 'subcontents')
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(), completion(unorderedEquals([
+ path.join(root, 'pubspec.yaml'),
+ path.join(root, '.gitignore'),
+ path.join(root, 'file2.text'),
+ path.join(root, 'subdir', 'subfile2.text')
+ ])));
+ });
+ });
+
+ commonTests();
+ });
+}
+
+void scheduleEntrypoint() {
+ schedule(() {
+ root = path.join(sandboxDir, appPath);
+ entrypoint = new Entrypoint(root, new SystemCache.withSources(root));
+ }, 'initializing entrypoint');
+
+ currentSchedule.onComplete.schedule(() {
+ entrypoint = null;
+ }, 'nulling entrypoint');
+}
+
+void commonTests() {
+ integration('ignores broken symlinks', () {
+ // Windows requires us to symlink to a directory that actually exists.
+ d.dir(appPath, [d.dir('target')]).create();
+ scheduleSymlink(path.join(appPath, 'target'), path.join(appPath, 'link'));
+ schedule(() => deleteEntry(path.join(sandboxDir, appPath, 'target')));
+
+ schedule(() {
+ expect(entrypoint.packageFiles(),
+ completion(equals([path.join(root, 'pubspec.yaml')])));
+ });
+ });
+
+ integration('ignores pubspec.lock files', () {
+ d.dir(appPath, [
+ d.file('pubspec.lock'),
+ d.dir('subdir', [d.file('pubspec.lock')])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(),
+ completion(equals([path.join(root, 'pubspec.yaml')])));
+ });
+ });
+
+ integration('ignores packages directories', () {
+ d.dir(appPath, [
+ d.dir('packages', [d.file('file.txt', 'contents')]),
+ d.dir('subdir', [
+ d.dir('packages', [d.file('subfile.txt', 'subcontents')]),
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(),
+ completion(equals([path.join(root, 'pubspec.yaml')])));
+ });
+ });
+
+ integration('allows pubspec.lock directories', () {
+ d.dir(appPath, [
+ d.dir('pubspec.lock', [
+ d.file('file.txt', 'contents'),
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(), completion(unorderedEquals([
+ path.join(root, 'pubspec.yaml'),
+ path.join(root, 'pubspec.lock', 'file.txt')
+ ])));
+ });
+ });
+
+ group('and "beneath"', () {
+ integration('only lists files beneath the given root', () {
+ d.dir(appPath, [
+ d.file('file1.txt', 'contents'),
+ d.file('file2.txt', 'contents'),
+ d.dir('subdir', [
+ d.file('subfile1.txt', 'subcontents'),
+ d.file('subfile2.txt', 'subcontents'),
+ d.dir('subsubdir', [
+ d.file('subsubfile1.txt', 'subsubcontents'),
+ d.file('subsubfile2.txt', 'subsubcontents'),
+ ])
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(beneath: path.join(root, 'subdir')),
+ completion(unorderedEquals([
+ path.join(root, 'subdir', 'subfile1.txt'),
+ path.join(root, 'subdir', 'subfile2.txt'),
+ path.join(root, 'subdir', 'subsubdir', 'subsubfile1.txt'),
+ path.join(root, 'subdir', 'subsubdir', 'subsubfile2.txt')
+ ])));
+ });
+ });
+
+ integration("doesn't care if the root is blacklisted", () {
+ d.dir(appPath, [
+ d.file('file1.txt', 'contents'),
+ d.file('file2.txt', 'contents'),
+ d.dir('packages', [
+ d.file('subfile1.txt', 'subcontents'),
+ d.file('subfile2.txt', 'subcontents'),
+ d.dir('subsubdir', [
+ d.file('subsubfile1.txt', 'subsubcontents'),
+ d.file('subsubfile2.txt', 'subsubcontents')
+ ])
+ ])
+ ]).create();
+
+ schedule(() {
+ expect(entrypoint.packageFiles(beneath: path.join(root, 'packages')),
+ completion(unorderedEquals([
+ path.join(root, 'packages', 'subfile1.txt'),
+ path.join(root, 'packages', 'subfile2.txt'),
+ path.join(root, 'packages', 'subsubdir', 'subsubfile1.txt'),
+ path.join(root, 'packages', 'subsubdir', 'subsubfile2.txt')
+ ])));
+ });
+ });
+ });
+}
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 0abee99..95835e3 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -854,6 +854,11 @@
void resume();
/**
+ * Returns true if the [StreamSubscription] is paused.
+ */
+ bool get isPaused;
+
+ /**
* Returns a future that handles the [onDone] and [onError] callbacks.
*
* This method *overwrites* the existing [onDone] and [onError] callbacks
@@ -1145,6 +1150,8 @@
if (_isSubscribed) _subscription.resume();
}
+ bool get isPaused => _isSubscribed ? _subscription.isPaused : false;
+
void cancel() {
if (_isSubscribed) {
StreamSubscription subscription = _subscription;
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 3bc32c5..e089f6c 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -175,6 +175,11 @@
_subscription.resume();
}
+ bool get isPaused {
+ if (_subscription == null) return false;
+ return _subscription.isPaused;
+ }
+
void cancel() {
if (_subscription != null) {
_subscription.cancel();
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 1279426..fc77a39 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -760,6 +760,19 @@
// BSD-style license that can be found in the LICENSE file.
+@DocsEditable
+@DomName('Canvas2DContextAttributes')
+class Canvas2DContextAttributes native "Canvas2DContextAttributes" {
+
+ @DomName('Canvas2DContextAttributes.alpha')
+ @DocsEditable
+ bool alpha;
+}
+// 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.
+
+
@DomName('HTMLCanvasElement')
class CanvasElement extends Element implements CanvasImageSource native "HTMLCanvasElement" {
@@ -966,15 +979,6 @@
@DocsEditable
-@DomName('CanvasProxy')
-class CanvasProxy native "CanvasProxy" {
-}
-// 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.
-
-
-@DocsEditable
/**
* A rendering context for a canvas element.
*
@@ -1159,6 +1163,10 @@
@DocsEditable
void fillText(String text, num x, num y, [num maxWidth]) native;
+ @DomName('CanvasRenderingContext2D.getContextAttributes')
+ @DocsEditable
+ Canvas2DContextAttributes getContextAttributes() native;
+
@DomName('CanvasRenderingContext2D.getImageData')
@DocsEditable
@Creates('ImageData|=Object')
@@ -1599,6 +1607,23 @@
@DomName('Comment')
class Comment extends CharacterData native "Comment" {
}
+// 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.
+
+
+@DocsEditable
+@DomName('Composition')
+class Composition native "Composition" {
+
+ @DomName('Composition.caret')
+ @DocsEditable
+ final Range caret;
+
+ @DomName('Composition.text')
+ @DocsEditable
+ final Node text;
+}
// 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.
@@ -1830,6 +1855,19 @@
@DocsEditable
+@DomName('CSS')
+class Css native "CSS" {
+
+ @DomName('CSS.supports')
+ @DocsEditable
+ bool supports(String conditionText_OR_property, [String value]) native;
+}
+// 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.
+
+
+@DocsEditable
@DomName('CSSCharsetRule')
class CssCharsetRule extends CssRule native "CSSCharsetRule" {
@@ -2082,6 +2120,10 @@
@DocsEditable
static const int STYLE_RULE = 1;
+ @DomName('CSSRule.SUPPORTS_RULE')
+ @DocsEditable
+ static const int SUPPORTS_RULE = 12;
+
@DomName('CSSRule.UNKNOWN_RULE')
@DocsEditable
static const int UNKNOWN_RULE = 0;
@@ -5422,6 +5464,33 @@
@DocsEditable
+@DomName('CSSSupportsRule')
+class CssSupportsRule extends CssRule native "CSSSupportsRule" {
+
+ @DomName('CSSSupportsRule.conditionText')
+ @DocsEditable
+ final String conditionText;
+
+ @DomName('CSSSupportsRule.cssRules')
+ @DocsEditable
+ @Returns('_CssRuleList')
+ @Creates('_CssRuleList')
+ final List<CssRule> cssRules;
+
+ @DomName('CSSSupportsRule.deleteRule')
+ @DocsEditable
+ void deleteRule(int index) native;
+
+ @DomName('CSSSupportsRule.insertRule')
+ @DocsEditable
+ int insertRule(String rule, int index) native;
+}
+// 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.
+
+
+@DocsEditable
@DomName('CSSUnknownRule')
class CssUnknownRule extends CssRule native "CSSUnknownRule" {
}
@@ -12495,6 +12564,43 @@
// BSD-style license that can be found in the LICENSE file.
+@DocsEditable
+@DomName('InputMethodContext')
+class InputMethodContext native "InputMethodContext" {
+
+ @DomName('InputMethodContext.composition')
+ @DocsEditable
+ final Composition composition;
+
+ @DomName('InputMethodContext.enabled')
+ @DocsEditable
+ bool enabled;
+
+ @DomName('InputMethodContext.locale')
+ @DocsEditable
+ final String locale;
+
+ @DomName('InputMethodContext.confirmComposition')
+ @DocsEditable
+ void confirmComposition() native;
+
+ @DomName('InputMethodContext.open')
+ @DocsEditable
+ bool open() native;
+
+ @DomName('InputMethodContext.setCaretRectangle')
+ @DocsEditable
+ void setCaretRectangle(Node anchor, int x, int y, int w, int h) native;
+
+ @DomName('InputMethodContext.setExclusionRectangle')
+ @DocsEditable
+ void setExclusionRectangle(Node anchor, int x, int y, int w, int h) native;
+}
+// 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.
+
+
@DomName('KeyboardEvent')
class KeyboardEvent extends UIEvent native "KeyboardEvent" {
@@ -12749,21 +12855,6 @@
@DocsEditable
String type;
}
-// 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.
-
-
-@DocsEditable
-@DomName('LocalMediaStream')
-@SupportedBrowser(SupportedBrowser.CHROME)
-@Experimental
-class LocalMediaStream extends MediaStream implements EventTarget native "LocalMediaStream" {
-
- @DomName('LocalMediaStream.stop')
- @DocsEditable
- void stop() native;
-}
// 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.
@@ -12844,6 +12935,14 @@
// 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.
+// WARNING: Do not edit - generated code.
+
+
+typedef void MidiErrorCallback(DomError error);
+// 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.
+
@DocsEditable
@DomName('HTMLMapElement')
@@ -13716,6 +13815,10 @@
@DocsEditable
void removeTrack(MediaStreamTrack track) native;
+ @DomName('MediaStream.stop')
+ @DocsEditable
+ void stop() native;
+
@DomName('MediaStream.onaddtrack')
@DocsEditable
Stream<Event> get onAddTrack => addTrackEvent.forTarget(this);
@@ -14137,6 +14240,79 @@
@DocsEditable
+@DomName('MIDIConnectionEvent')
+class MidiConnectionEvent extends Event native "MIDIConnectionEvent" {
+
+ @DomName('MIDIConnectionEvent.port')
+ @DocsEditable
+ final MidiPort port;
+}
+// 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.
+
+
+@DocsEditable
+@DomName('MIDIMessageEvent')
+class MidiMessageEvent extends Event native "MIDIMessageEvent" {
+
+ @DomName('MIDIMessageEvent.data')
+ @DocsEditable
+ final Uint8List data;
+
+ @DomName('MIDIMessageEvent.receivedTime')
+ @DocsEditable
+ final num receivedTime;
+}
+// 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.
+
+
+@DocsEditable
+@DomName('MIDIPort')
+class MidiPort extends EventTarget native "MIDIPort" {
+
+ @DomName('MIDIPort.id')
+ @DocsEditable
+ final String id;
+
+ @DomName('MIDIPort.manufacturer')
+ @DocsEditable
+ final String manufacturer;
+
+ @DomName('MIDIPort.name')
+ @DocsEditable
+ final String name;
+
+ @DomName('MIDIPort.type')
+ @DocsEditable
+ final String type;
+
+ @DomName('MIDIPort.version')
+ @DocsEditable
+ final String version;
+
+ @JSName('addEventListener')
+ @DomName('MIDIPort.addEventListener')
+ @DocsEditable
+ void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native;
+
+ @DomName('MIDIPort.dispatchEvent')
+ @DocsEditable
+ bool dispatchEvent(Event event) native;
+
+ @JSName('removeEventListener')
+ @DomName('MIDIPort.removeEventListener')
+ @DocsEditable
+ void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
+}
+// 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.
+
+
+@DocsEditable
@DomName('MimeType')
class MimeType native "MimeType" {
@@ -14730,7 +14906,7 @@
*
* The user can also pass in Maps to the audio or video parameters to specify
* mandatory and optional constraints for the media stream. Not passing in a
- * map, but passing in `true` will provide a LocalMediaStream with audio or
+ * map, but passing in `true` will provide a MediaStream with audio or
* video capabilities, but without any additional constraints. The particular
* constraint names for audio and video are still in flux, but as of this
* writing, here is an example providing more constraints.
@@ -14750,8 +14926,8 @@
@DomName('Navigator.webkitGetUserMedia')
@SupportedBrowser(SupportedBrowser.CHROME)
@Experimental
- Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
- var completer = new Completer<LocalMediaStream>();
+ Future<MediaStream> getUserMedia({audio: false, video: false}) {
+ var completer = new Completer<MediaStream>();
var options = {
'audio': audio,
'video': video
@@ -14911,7 +15087,7 @@
// WARNING: Do not edit - generated code.
-typedef void _NavigatorUserMediaSuccessCallback(LocalMediaStream stream);
+typedef void _NavigatorUserMediaSuccessCallback(MediaStream stream);
// 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.
@@ -16126,26 +16302,38 @@
@DocsEditable
final PerformanceTiming timing;
+ @DomName('Performance.clearMarks')
+ @DocsEditable
+ void clearMarks(String markName) native;
+
+ @DomName('Performance.clearMeasures')
+ @DocsEditable
+ void clearMeasures(String measureName) native;
+
+ @DomName('Performance.getEntries')
+ @DocsEditable
+ List<PerformanceEntry> getEntries() native;
+
+ @DomName('Performance.getEntriesByName')
+ @DocsEditable
+ List<PerformanceEntry> getEntriesByName(String name, String entryType) native;
+
+ @DomName('Performance.getEntriesByType')
+ @DocsEditable
+ List<PerformanceEntry> getEntriesByType(String entryType) native;
+
+ @DomName('Performance.mark')
+ @DocsEditable
+ void mark(String markName) native;
+
+ @DomName('Performance.measure')
+ @DocsEditable
+ void measure(String measureName, String startMark, String endMark) native;
+
@DomName('Performance.now')
@DocsEditable
num now() native;
- @JSName('webkitClearMarks')
- @DomName('Performance.webkitClearMarks')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void clearMarks(String markName) native;
-
- @JSName('webkitClearMeasures')
- @DomName('Performance.webkitClearMeasures')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void clearMeasures(String measureName) native;
-
@JSName('webkitClearResourceTimings')
@DomName('Performance.webkitClearResourceTimings')
@DocsEditable
@@ -16154,46 +16342,6 @@
@Experimental
void clearResourceTimings() native;
- @JSName('webkitGetEntries')
- @DomName('Performance.webkitGetEntries')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntries() native;
-
- @JSName('webkitGetEntriesByName')
- @DomName('Performance.webkitGetEntriesByName')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntriesByName(String name, String entryType) native;
-
- @JSName('webkitGetEntriesByType')
- @DomName('Performance.webkitGetEntriesByType')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntriesByType(String entryType) native;
-
- @JSName('webkitMark')
- @DomName('Performance.webkitMark')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void mark(String markName) native;
-
- @JSName('webkitMeasure')
- @DomName('Performance.webkitMeasure')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void measure(String measureName, String startMark, String endMark) native;
-
@JSName('webkitSetResourceTimingBufferSize')
@DomName('Performance.webkitSetResourceTimingBufferSize')
@DocsEditable
@@ -16233,23 +16381,6 @@
@DocsEditable
-@DomName('PerformanceEntryList')
-class PerformanceEntryList native "PerformanceEntryList" {
-
- @DomName('PerformanceEntryList.length')
- @DocsEditable
- final int length;
-
- @DomName('PerformanceEntryList.item')
- @DocsEditable
- PerformanceEntry item(int index) native;
-}
-// 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.
-
-
-@DocsEditable
@DomName('PerformanceMark')
class PerformanceMark extends PerformanceEntry native "PerformanceMark" {
}
@@ -17830,6 +17961,10 @@
@DocsEditable
final String blockedUri;
+ @DomName('SecurityPolicyViolationEvent.columnNumber')
+ @DocsEditable
+ final int columnNumber;
+
@JSName('documentURI')
@DomName('SecurityPolicyViolationEvent.documentURI')
@DocsEditable
@@ -18680,6 +18815,159 @@
// BSD-style license that can be found in the LICENSE file.
+@DocsEditable
+@DomName('SpeechSynthesis')
+class SpeechSynthesis native "SpeechSynthesis" {
+
+ @DomName('SpeechSynthesis.paused')
+ @DocsEditable
+ final bool paused;
+
+ @DomName('SpeechSynthesis.pending')
+ @DocsEditable
+ final bool pending;
+
+ @DomName('SpeechSynthesis.speaking')
+ @DocsEditable
+ final bool speaking;
+
+ @DomName('SpeechSynthesis.cancel')
+ @DocsEditable
+ void cancel() native;
+
+ @DomName('SpeechSynthesis.getVoices')
+ @DocsEditable
+ List<SpeechSynthesisVoice> getVoices() native;
+
+ @DomName('SpeechSynthesis.pause')
+ @DocsEditable
+ void pause() native;
+
+ @DomName('SpeechSynthesis.resume')
+ @DocsEditable
+ void resume() native;
+
+ @DomName('SpeechSynthesis.speak')
+ @DocsEditable
+ void speak(SpeechSynthesisUtterance utterance) native;
+}
+// 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.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisEvent')
+class SpeechSynthesisEvent extends Event native "SpeechSynthesisEvent" {
+
+ @DomName('SpeechSynthesisEvent.charIndex')
+ @DocsEditable
+ final int charIndex;
+
+ @DomName('SpeechSynthesisEvent.elapsedTime')
+ @DocsEditable
+ final num elapsedTime;
+
+ @DomName('SpeechSynthesisEvent.name')
+ @DocsEditable
+ final String name;
+}
+// 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.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisUtterance')
+class SpeechSynthesisUtterance extends EventTarget native "SpeechSynthesisUtterance" {
+
+ @DomName('SpeechSynthesisUtterance.errorEvent')
+ @DocsEditable
+ static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
+
+ @DomName('SpeechSynthesisUtterance.pauseEvent')
+ @DocsEditable
+ static const EventStreamProvider<Event> pauseEvent = const EventStreamProvider<Event>('pause');
+
+ @DomName('SpeechSynthesisUtterance.SpeechSynthesisUtterance')
+ @DocsEditable
+ factory SpeechSynthesisUtterance([String text]) {
+ if (?text) {
+ return SpeechSynthesisUtterance._create_1(text);
+ }
+ return SpeechSynthesisUtterance._create_2();
+ }
+ static SpeechSynthesisUtterance _create_1(text) => JS('SpeechSynthesisUtterance', 'new SpeechSynthesisUtterance(#)', text);
+ static SpeechSynthesisUtterance _create_2() => JS('SpeechSynthesisUtterance', 'new SpeechSynthesisUtterance()');
+
+ @DomName('SpeechSynthesisUtterance.lang')
+ @DocsEditable
+ String lang;
+
+ @DomName('SpeechSynthesisUtterance.pitch')
+ @DocsEditable
+ num pitch;
+
+ @DomName('SpeechSynthesisUtterance.rate')
+ @DocsEditable
+ num rate;
+
+ @DomName('SpeechSynthesisUtterance.text')
+ @DocsEditable
+ String text;
+
+ @DomName('SpeechSynthesisUtterance.voice')
+ @DocsEditable
+ SpeechSynthesisVoice voice;
+
+ @DomName('SpeechSynthesisUtterance.volume')
+ @DocsEditable
+ num volume;
+
+ @DomName('SpeechSynthesisUtterance.onerror')
+ @DocsEditable
+ Stream<Event> get onError => errorEvent.forTarget(this);
+
+ @DomName('SpeechSynthesisUtterance.onpause')
+ @DocsEditable
+ Stream<Event> get onPause => pauseEvent.forTarget(this);
+}
+// 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.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisVoice')
+class SpeechSynthesisVoice native "SpeechSynthesisVoice" {
+
+ @JSName('default')
+ @DomName('SpeechSynthesisVoice.default')
+ @DocsEditable
+ final bool defaultValue;
+
+ @DomName('SpeechSynthesisVoice.lang')
+ @DocsEditable
+ final String lang;
+
+ @DomName('SpeechSynthesisVoice.localService')
+ @DocsEditable
+ final bool localService;
+
+ @DomName('SpeechSynthesisVoice.name')
+ @DocsEditable
+ final String name;
+
+ @JSName('voiceURI')
+ @DomName('SpeechSynthesisVoice.voiceURI')
+ @DocsEditable
+ final String voiceUri;
+}
+// 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.
+
+
/**
* The type used by the
* [Window.localStorage] and [Window.sessionStorage] properties.
@@ -21430,6 +21718,11 @@
@DocsEditable
static const int TEMPORARY = 0;
+ @JSName('CSS')
+ @DomName('Window.CSS')
+ @DocsEditable
+ final Css css;
+
@DomName('Window.applicationCache')
@DocsEditable
final ApplicationCache applicationCache;
@@ -21581,6 +21874,10 @@
@DocsEditable
final Storage sessionStorage;
+ @DomName('Window.speechSynthesis')
+ @DocsEditable
+ final SpeechSynthesis speechSynthesis;
+
@DomName('Window.status')
@DocsEditable
String status;
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index d9f4473..6c139d5 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -953,6 +953,27 @@
// 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.
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('Canvas2DContextAttributes')
+class Canvas2DContextAttributes extends NativeFieldWrapperClass1 {
+ Canvas2DContextAttributes.internal();
+
+ @DomName('Canvas2DContextAttributes.alpha')
+ @DocsEditable
+ bool get alpha native "Canvas2DContextAttributes_alpha_Getter";
+
+ @DomName('Canvas2DContextAttributes.alpha')
+ @DocsEditable
+ void set alpha(bool value) native "Canvas2DContextAttributes_alpha_Setter";
+
+}
+// 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.
+
@DomName('HTMLCanvasElement')
class CanvasElement extends _Element_Merged implements CanvasImageSource {
@@ -1165,19 +1186,6 @@
@DocsEditable
-@DomName('CanvasProxy')
-class CanvasProxy extends NativeFieldWrapperClass1 {
- CanvasProxy.internal();
-
-}
-// 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
/**
* A rendering context for a canvas element.
*
@@ -1515,6 +1523,10 @@
void _fillText_2(text, x, y) native "CanvasRenderingContext2D__fillText_2_Callback";
+ @DomName('CanvasRenderingContext2D.getContextAttributes')
+ @DocsEditable
+ Canvas2DContextAttributes getContextAttributes() native "CanvasRenderingContext2D_getContextAttributes_Callback";
+
@DomName('CanvasRenderingContext2D.getImageData')
@DocsEditable
ImageData getImageData(num sx, num sy, num sw, num sh) native "CanvasRenderingContext2D_getImageData_Callback";
@@ -1954,6 +1966,27 @@
Comment.internal() : super.internal();
}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('Composition')
+class Composition extends NativeFieldWrapperClass1 {
+ Composition.internal();
+
+ @DomName('Composition.caret')
+ @DocsEditable
+ Range get caret native "Composition_caret_Getter";
+
+ @DomName('Composition.text')
+ @DocsEditable
+ Node get text native "Composition_text_Getter";
+
+}
// 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.
@@ -2054,7 +2087,7 @@
@DomName('Console.markTimeline')
@DocsEditable
- void markTimeline() native "Console_markTimeline_Callback";
+ void markTimeline(Object arg) native "Console_markTimeline_Callback";
@DomName('Console.profile')
@DocsEditable
@@ -2078,7 +2111,7 @@
@DomName('Console.timeStamp')
@DocsEditable
- void timeStamp() native "Console_timeStamp_Callback";
+ void timeStamp(Object arg) native "Console_timeStamp_Callback";
@DomName('Console.trace')
@DocsEditable
@@ -2203,6 +2236,33 @@
@DocsEditable
+@DomName('CSS')
+class Css extends NativeFieldWrapperClass1 {
+ Css.internal();
+
+ bool supports(String conditionText_OR_property, [String value]) {
+ if ((conditionText_OR_property is String || conditionText_OR_property == null) && (value is String || value == null)) {
+ return _supports_1(conditionText_OR_property, value);
+ }
+ if ((conditionText_OR_property is String || conditionText_OR_property == null) && !?value) {
+ return _supports_2(conditionText_OR_property);
+ }
+ throw new ArgumentError("Incorrect number or type of arguments");
+ }
+
+ bool _supports_1(conditionText_OR_property, value) native "DOMWindowCSS__supports_1_Callback";
+
+ bool _supports_2(conditionText_OR_property) native "DOMWindowCSS__supports_2_Callback";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
@DomName('CSSCharsetRule')
class CssCharsetRule extends CssRule {
CssCharsetRule.internal() : super.internal();
@@ -2508,6 +2568,10 @@
@DocsEditable
static const int STYLE_RULE = 1;
+ @DomName('CSSRule.SUPPORTS_RULE')
+ @DocsEditable
+ static const int SUPPORTS_RULE = 12;
+
@DomName('CSSRule.UNKNOWN_RULE')
@DocsEditable
static const int UNKNOWN_RULE = 0;
@@ -5865,6 +5929,35 @@
@DocsEditable
+@DomName('CSSSupportsRule')
+class CssSupportsRule extends CssRule {
+ CssSupportsRule.internal() : super.internal();
+
+ @DomName('CSSSupportsRule.conditionText')
+ @DocsEditable
+ String get conditionText native "CSSSupportsRule_conditionText_Getter";
+
+ @DomName('CSSSupportsRule.cssRules')
+ @DocsEditable
+ List<CssRule> get cssRules native "CSSSupportsRule_cssRules_Getter";
+
+ @DomName('CSSSupportsRule.deleteRule')
+ @DocsEditable
+ void deleteRule(int index) native "CSSSupportsRule_deleteRule_Callback";
+
+ @DomName('CSSSupportsRule.insertRule')
+ @DocsEditable
+ int insertRule(String rule, int index) native "CSSSupportsRule_insertRule_Callback";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
@DomName('CSSUnknownRule')
class CssUnknownRule extends CssRule {
CssUnknownRule.internal() : super.internal();
@@ -13182,6 +13275,51 @@
// 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.
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('InputMethodContext')
+class InputMethodContext extends NativeFieldWrapperClass1 {
+ InputMethodContext.internal();
+
+ @DomName('InputMethodContext.composition')
+ @DocsEditable
+ Composition get composition native "InputMethodContext_composition_Getter";
+
+ @DomName('InputMethodContext.enabled')
+ @DocsEditable
+ bool get enabled native "InputMethodContext_enabled_Getter";
+
+ @DomName('InputMethodContext.enabled')
+ @DocsEditable
+ void set enabled(bool value) native "InputMethodContext_enabled_Setter";
+
+ @DomName('InputMethodContext.locale')
+ @DocsEditable
+ String get locale native "InputMethodContext_locale_Getter";
+
+ @DomName('InputMethodContext.confirmComposition')
+ @DocsEditable
+ void confirmComposition() native "InputMethodContext_confirmComposition_Callback";
+
+ @DomName('InputMethodContext.open')
+ @DocsEditable
+ bool open() native "InputMethodContext_open_Callback";
+
+ @DomName('InputMethodContext.setCaretRectangle')
+ @DocsEditable
+ void setCaretRectangle(Node anchor, int x, int y, int w, int h) native "InputMethodContext_setCaretRectangle_Callback";
+
+ @DomName('InputMethodContext.setExclusionRectangle')
+ @DocsEditable
+ void setExclusionRectangle(Node anchor, int x, int y, int w, int h) native "InputMethodContext_setExclusionRectangle_Callback";
+
+}
+// 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.
+
@DomName('KeyboardEvent')
class KeyboardEvent extends UIEvent {
@@ -13499,25 +13637,6 @@
void set type(String value) native "HTMLLinkElement_type_Setter";
}
-// 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
-@DomName('LocalMediaStream')
-@SupportedBrowser(SupportedBrowser.CHROME)
-@Experimental
-class LocalMediaStream extends MediaStream implements EventTarget {
- LocalMediaStream.internal() : super.internal();
-
- @DomName('LocalMediaStream.stop')
- @DocsEditable
- void stop() native "LocalMediaStream_stop_Callback";
-
-}
// 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.
@@ -13629,6 +13748,14 @@
// WARNING: Do not edit - generated code.
+typedef void MidiErrorCallback(DomError error);
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
@DocsEditable
@DomName('HTMLMapElement')
class MapElement extends _Element_Merged {
@@ -14659,6 +14786,10 @@
@DocsEditable
void removeTrack(MediaStreamTrack track) native "MediaStream_removeTrack_Callback";
+ @DomName('MediaStream.stop')
+ @DocsEditable
+ void stop() native "MediaStream_stop_Callback";
+
@DomName('MediaStream.onaddtrack')
@DocsEditable
Stream<Event> get onAddTrack => addTrackEvent.forTarget(this);
@@ -15119,6 +15250,89 @@
@DocsEditable
+@DomName('MIDIConnectionEvent')
+class MidiConnectionEvent extends Event {
+ MidiConnectionEvent.internal() : super.internal();
+
+ @DomName('MIDIConnectionEvent.port')
+ @DocsEditable
+ MidiPort get port native "MIDIConnectionEvent_port_Getter";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('MIDIMessageEvent')
+class MidiMessageEvent extends Event {
+ MidiMessageEvent.internal() : super.internal();
+
+ @DomName('MIDIMessageEvent.data')
+ @DocsEditable
+ Uint8List get data native "MIDIMessageEvent_data_Getter";
+
+ @DomName('MIDIMessageEvent.receivedTime')
+ @DocsEditable
+ num get receivedTime native "MIDIMessageEvent_receivedTime_Getter";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('MIDIPort')
+class MidiPort extends EventTarget {
+ MidiPort.internal() : super.internal();
+
+ @DomName('MIDIPort.id')
+ @DocsEditable
+ String get id native "MIDIPort_id_Getter";
+
+ @DomName('MIDIPort.manufacturer')
+ @DocsEditable
+ String get manufacturer native "MIDIPort_manufacturer_Getter";
+
+ @DomName('MIDIPort.name')
+ @DocsEditable
+ String get name native "MIDIPort_name_Getter";
+
+ @DomName('MIDIPort.type')
+ @DocsEditable
+ String get type native "MIDIPort_type_Getter";
+
+ @DomName('MIDIPort.version')
+ @DocsEditable
+ String get version native "MIDIPort_version_Getter";
+
+ @DomName('MIDIPort.addEventListener')
+ @DocsEditable
+ void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_addEventListener_Callback";
+
+ @DomName('MIDIPort.dispatchEvent')
+ @DocsEditable
+ bool dispatchEvent(Event event) native "MIDIPort_dispatchEvent_Callback";
+
+ @DomName('MIDIPort.removeEventListener')
+ @DocsEditable
+ void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_removeEventListener_Callback";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
@DomName('MimeType')
class MimeType extends NativeFieldWrapperClass1 {
MimeType.internal();
@@ -15692,7 +15906,7 @@
*
* The user can also pass in Maps to the audio or video parameters to specify
* mandatory and optional constraints for the media stream. Not passing in a
- * map, but passing in `true` will provide a LocalMediaStream with audio or
+ * map, but passing in `true` will provide a MediaStream with audio or
* video capabilities, but without any additional constraints. The particular
* constraint names for audio and video are still in flux, but as of this
* writing, here is an example providing more constraints.
@@ -15712,8 +15926,8 @@
@DomName('Navigator.webkitGetUserMedia')
@SupportedBrowser(SupportedBrowser.CHROME)
@Experimental
- Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
- var completer = new Completer<LocalMediaStream>();
+ Future<MediaStream> getUserMedia({audio: false, video: false}) {
+ var completer = new Completer<MediaStream>();
var options = {
'audio': audio,
'video': video
@@ -15869,7 +16083,7 @@
// WARNING: Do not edit - generated code.
-typedef void _NavigatorUserMediaSuccessCallback(LocalMediaStream stream);
+typedef void _NavigatorUserMediaSuccessCallback(MediaStream stream);
// 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.
@@ -17210,24 +17424,38 @@
@DocsEditable
PerformanceTiming get timing native "Performance_timing_Getter";
+ @DomName('Performance.clearMarks')
+ @DocsEditable
+ void clearMarks(String markName) native "Performance_clearMarks_Callback";
+
+ @DomName('Performance.clearMeasures')
+ @DocsEditable
+ void clearMeasures(String measureName) native "Performance_clearMeasures_Callback";
+
+ @DomName('Performance.getEntries')
+ @DocsEditable
+ List<PerformanceEntry> getEntries() native "Performance_getEntries_Callback";
+
+ @DomName('Performance.getEntriesByName')
+ @DocsEditable
+ List<PerformanceEntry> getEntriesByName(String name, String entryType) native "Performance_getEntriesByName_Callback";
+
+ @DomName('Performance.getEntriesByType')
+ @DocsEditable
+ List<PerformanceEntry> getEntriesByType(String entryType) native "Performance_getEntriesByType_Callback";
+
+ @DomName('Performance.mark')
+ @DocsEditable
+ void mark(String markName) native "Performance_mark_Callback";
+
+ @DomName('Performance.measure')
+ @DocsEditable
+ void measure(String measureName, String startMark, String endMark) native "Performance_measure_Callback";
+
@DomName('Performance.now')
@DocsEditable
num now() native "Performance_now_Callback";
- @DomName('Performance.webkitClearMarks')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void clearMarks(String markName) native "Performance_webkitClearMarks_Callback";
-
- @DomName('Performance.webkitClearMeasures')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void clearMeasures(String measureName) native "Performance_webkitClearMeasures_Callback";
-
@DomName('Performance.webkitClearResourceTimings')
@DocsEditable
@SupportedBrowser(SupportedBrowser.CHROME)
@@ -17235,41 +17463,6 @@
@Experimental
void clearResourceTimings() native "Performance_webkitClearResourceTimings_Callback";
- @DomName('Performance.webkitGetEntries')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntries() native "Performance_webkitGetEntries_Callback";
-
- @DomName('Performance.webkitGetEntriesByName')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntriesByName(String name, String entryType) native "Performance_webkitGetEntriesByName_Callback";
-
- @DomName('Performance.webkitGetEntriesByType')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- List<PerformanceEntry> getEntriesByType(String entryType) native "Performance_webkitGetEntriesByType_Callback";
-
- @DomName('Performance.webkitMark')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void mark(String markName) native "Performance_webkitMark_Callback";
-
- @DomName('Performance.webkitMeasure')
- @DocsEditable
- @SupportedBrowser(SupportedBrowser.CHROME)
- @SupportedBrowser(SupportedBrowser.SAFARI)
- @Experimental
- void measure(String measureName, String startMark, String endMark) native "Performance_webkitMeasure_Callback";
-
@DomName('Performance.webkitSetResourceTimingBufferSize')
@DocsEditable
@SupportedBrowser(SupportedBrowser.CHROME)
@@ -17315,27 +17508,6 @@
@DocsEditable
-@DomName('PerformanceEntryList')
-class PerformanceEntryList extends NativeFieldWrapperClass1 {
- PerformanceEntryList.internal();
-
- @DomName('PerformanceEntryList.length')
- @DocsEditable
- int get length native "PerformanceEntryList_length_Getter";
-
- @DomName('PerformanceEntryList.item')
- @DocsEditable
- PerformanceEntry item(int index) native "PerformanceEntryList_item_Callback";
-
-}
-// 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
@DomName('PerformanceMark')
class PerformanceMark extends PerformanceEntry {
PerformanceMark.internal() : super.internal();
@@ -19013,6 +19185,10 @@
@DocsEditable
String get blockedUri native "SecurityPolicyViolationEvent_blockedURI_Getter";
+ @DomName('SecurityPolicyViolationEvent.columnNumber')
+ @DocsEditable
+ int get columnNumber native "SecurityPolicyViolationEvent_columnNumber_Getter";
+
@DomName('SecurityPolicyViolationEvent.documentURI')
@DocsEditable
String get documentUri native "SecurityPolicyViolationEvent_documentURI_Getter";
@@ -20032,6 +20208,195 @@
// 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.
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('SpeechSynthesis')
+class SpeechSynthesis extends NativeFieldWrapperClass1 {
+ SpeechSynthesis.internal();
+
+ @DomName('SpeechSynthesis.paused')
+ @DocsEditable
+ bool get paused native "SpeechSynthesis_paused_Getter";
+
+ @DomName('SpeechSynthesis.pending')
+ @DocsEditable
+ bool get pending native "SpeechSynthesis_pending_Getter";
+
+ @DomName('SpeechSynthesis.speaking')
+ @DocsEditable
+ bool get speaking native "SpeechSynthesis_speaking_Getter";
+
+ @DomName('SpeechSynthesis.cancel')
+ @DocsEditable
+ void cancel() native "SpeechSynthesis_cancel_Callback";
+
+ @DomName('SpeechSynthesis.getVoices')
+ @DocsEditable
+ List<SpeechSynthesisVoice> getVoices() native "SpeechSynthesis_getVoices_Callback";
+
+ @DomName('SpeechSynthesis.pause')
+ @DocsEditable
+ void pause() native "SpeechSynthesis_pause_Callback";
+
+ @DomName('SpeechSynthesis.resume')
+ @DocsEditable
+ void resume() native "SpeechSynthesis_resume_Callback";
+
+ @DomName('SpeechSynthesis.speak')
+ @DocsEditable
+ void speak(SpeechSynthesisUtterance utterance) native "SpeechSynthesis_speak_Callback";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisEvent')
+class SpeechSynthesisEvent extends Event {
+ SpeechSynthesisEvent.internal() : super.internal();
+
+ @DomName('SpeechSynthesisEvent.charIndex')
+ @DocsEditable
+ int get charIndex native "SpeechSynthesisEvent_charIndex_Getter";
+
+ @DomName('SpeechSynthesisEvent.elapsedTime')
+ @DocsEditable
+ num get elapsedTime native "SpeechSynthesisEvent_elapsedTime_Getter";
+
+ @DomName('SpeechSynthesisEvent.name')
+ @DocsEditable
+ String get name native "SpeechSynthesisEvent_name_Getter";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisUtterance')
+class SpeechSynthesisUtterance extends EventTarget {
+ SpeechSynthesisUtterance.internal() : super.internal();
+
+ @DomName('SpeechSynthesisUtterance.errorEvent')
+ @DocsEditable
+ static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
+
+ @DomName('SpeechSynthesisUtterance.pauseEvent')
+ @DocsEditable
+ static const EventStreamProvider<Event> pauseEvent = const EventStreamProvider<Event>('pause');
+
+ @DomName('SpeechSynthesisUtterance.SpeechSynthesisUtterance')
+ @DocsEditable
+ factory SpeechSynthesisUtterance([String text]) {
+ return SpeechSynthesisUtterance._create_1(text);
+ }
+
+ @DocsEditable
+ static SpeechSynthesisUtterance _create_1(text) native "SpeechSynthesisUtterance__create_1constructorCallback";
+
+ @DomName('SpeechSynthesisUtterance.lang')
+ @DocsEditable
+ String get lang native "SpeechSynthesisUtterance_lang_Getter";
+
+ @DomName('SpeechSynthesisUtterance.lang')
+ @DocsEditable
+ void set lang(String value) native "SpeechSynthesisUtterance_lang_Setter";
+
+ @DomName('SpeechSynthesisUtterance.pitch')
+ @DocsEditable
+ num get pitch native "SpeechSynthesisUtterance_pitch_Getter";
+
+ @DomName('SpeechSynthesisUtterance.pitch')
+ @DocsEditable
+ void set pitch(num value) native "SpeechSynthesisUtterance_pitch_Setter";
+
+ @DomName('SpeechSynthesisUtterance.rate')
+ @DocsEditable
+ num get rate native "SpeechSynthesisUtterance_rate_Getter";
+
+ @DomName('SpeechSynthesisUtterance.rate')
+ @DocsEditable
+ void set rate(num value) native "SpeechSynthesisUtterance_rate_Setter";
+
+ @DomName('SpeechSynthesisUtterance.text')
+ @DocsEditable
+ String get text native "SpeechSynthesisUtterance_text_Getter";
+
+ @DomName('SpeechSynthesisUtterance.text')
+ @DocsEditable
+ void set text(String value) native "SpeechSynthesisUtterance_text_Setter";
+
+ @DomName('SpeechSynthesisUtterance.voice')
+ @DocsEditable
+ SpeechSynthesisVoice get voice native "SpeechSynthesisUtterance_voice_Getter";
+
+ @DomName('SpeechSynthesisUtterance.voice')
+ @DocsEditable
+ void set voice(SpeechSynthesisVoice value) native "SpeechSynthesisUtterance_voice_Setter";
+
+ @DomName('SpeechSynthesisUtterance.volume')
+ @DocsEditable
+ num get volume native "SpeechSynthesisUtterance_volume_Getter";
+
+ @DomName('SpeechSynthesisUtterance.volume')
+ @DocsEditable
+ void set volume(num value) native "SpeechSynthesisUtterance_volume_Setter";
+
+ @DomName('SpeechSynthesisUtterance.onerror')
+ @DocsEditable
+ Stream<Event> get onError => errorEvent.forTarget(this);
+
+ @DomName('SpeechSynthesisUtterance.onpause')
+ @DocsEditable
+ Stream<Event> get onPause => pauseEvent.forTarget(this);
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('SpeechSynthesisVoice')
+class SpeechSynthesisVoice extends NativeFieldWrapperClass1 {
+ SpeechSynthesisVoice.internal();
+
+ @DomName('SpeechSynthesisVoice.default')
+ @DocsEditable
+ bool get defaultValue native "SpeechSynthesisVoice_default_Getter";
+
+ @DomName('SpeechSynthesisVoice.lang')
+ @DocsEditable
+ String get lang native "SpeechSynthesisVoice_lang_Getter";
+
+ @DomName('SpeechSynthesisVoice.localService')
+ @DocsEditable
+ bool get localService native "SpeechSynthesisVoice_localService_Getter";
+
+ @DomName('SpeechSynthesisVoice.name')
+ @DocsEditable
+ String get name native "SpeechSynthesisVoice_name_Getter";
+
+ @DomName('SpeechSynthesisVoice.voiceURI')
+ @DocsEditable
+ String get voiceUri native "SpeechSynthesisVoice_voiceURI_Getter";
+
+}
+// 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.
+
/**
* The type used by the
@@ -22795,6 +23160,10 @@
@DocsEditable
static const int TEMPORARY = 0;
+ @DomName('Window.CSS')
+ @DocsEditable
+ Css get css native "DOMWindow_CSS_Getter";
+
@DomName('Window.applicationCache')
@DocsEditable
ApplicationCache get applicationCache native "DOMWindow_applicationCache_Getter";
@@ -22970,6 +23339,10 @@
@DocsEditable
Storage get sessionStorage native "DOMWindow_sessionStorage_Getter";
+ @DomName('Window.speechSynthesis')
+ @DocsEditable
+ SpeechSynthesis get speechSynthesis native "DOMWindow_speechSynthesis_Getter";
+
@DomName('Window.status')
@DocsEditable
String get status native "DOMWindow_status_Getter";
diff --git a/sdk/lib/io/data_transformer.dart b/sdk/lib/io/data_transformer.dart
index 4a4001d..c7c53ad 100644
--- a/sdk/lib/io/data_transformer.dart
+++ b/sdk/lib/io/data_transformer.dart
@@ -18,8 +18,11 @@
* Get a chunk of processed data. When there are no more data available,
* [processed] will return [null]. Set [flush] to [false] for non-final
* calls to improve performance of some filters.
+ *
+ * The last call to [processed] should have [end] set to [true]. This will make
+ * sure a 'end' packet is written on the stream.
*/
- List<int> processed({bool flush: true});
+ List<int> processed({bool flush: true, bool end: false});
/**
* Mark the filter as closed. Always call this method for any filter created
@@ -62,7 +65,7 @@
if (_empty) _filter.process(const []);
try {
var out;
- while ((out = _filter.processed()) != null) {
+ while ((out = _filter.processed(end: true)) != null) {
sink.add(out);
}
} catch (e, s) {
diff --git a/sdk/lib/io/http_body.dart b/sdk/lib/io/http_body.dart
index 1ec6d17..b6e106b 100644
--- a/sdk/lib/io/http_body.dart
+++ b/sdk/lib/io/http_body.dart
@@ -41,22 +41,38 @@
implements StreamTransformer<HttpRequest, HttpRequestBody> {
var _transformer;
- HttpBodyHandler() : _transformer = new _HttpBodyHandlerTransformer();
+ /**
+ * Create a new [HttpBodyHandler] to be used with a [Stream]<[HttpRequest]>,
+ * e.g. a [HttpServer].
+ *
+ * If the page was served using different encoding than UTF-8, set
+ * [defaultEncoding] accordingly. This is required for parsing
+ * 'application/x-www-form-urlencoded' content correctly.
+ */
+ HttpBodyHandler({Encoding defaultEncoding: Encoding.UTF_8})
+ : _transformer = new _HttpBodyHandlerTransformer(defaultEncoding);
/**
* Process and parse an incoming [HttpRequest]. The returned [HttpRequestBody]
* contains a [response] field for accessing the [HttpResponse].
+ *
+ * See [HttpBodyHandler] constructor for more info on [defaultEncoding].
*/
- static Future<HttpRequestBody> processRequest(HttpRequest request) {
- return _HttpBodyHandler.processRequest(request);
+ static Future<HttpRequestBody> processRequest(
+ HttpRequest request,
+ {Encoding defaultEncoding: Encoding.UTF_8}) {
+ return _HttpBodyHandler.processRequest(request, defaultEncoding);
}
/**
* Process and parse an incoming [HttpClientResponse].
+ *
+ * See [HttpBodyHandler] constructor for more info on [defaultEncoding].
*/
static Future<HttpClientResponseBody> processResponse(
- HttpClientResponse response) {
- return _HttpBodyHandler.processResponse(response);
+ HttpClientResponse response,
+ {Encoding defaultEncoding: Encoding.UTF_8}) {
+ return _HttpBodyHandler.processResponse(response, defaultEncoding);
}
Stream<HttpRequestBody> bind(Stream<HttpRequest> stream) {
diff --git a/sdk/lib/io/http_body_impl.dart b/sdk/lib/io/http_body_impl.dart
index 736e86e..900dff5 100644
--- a/sdk/lib/io/http_body_impl.dart
+++ b/sdk/lib/io/http_body_impl.dart
@@ -6,15 +6,20 @@
class _HttpBodyHandlerTransformer
extends StreamEventTransformer<HttpRequest, HttpRequestBody> {
+ final Encoding _defaultEncoding;
+ _HttpBodyHandlerTransformer(this._defaultEncoding);
+
void handleData(HttpRequest request, EventSink<HttpRequestBody> sink) {
- HttpBodyHandler.processRequest(request)
+ _HttpBodyHandler.processRequest(request, _defaultEncoding)
.then(sink.add, onError: sink.addError);
}
}
class _HttpBodyHandler {
- static Future<HttpRequestBody> processRequest(HttpRequest request) {
- return process(request, request.headers)
+ static Future<HttpRequestBody> processRequest(
+ HttpRequest request,
+ Encoding defaultEncoding) {
+ return process(request, request.headers, defaultEncoding)
.then((body) => new _HttpRequestBody(request, body),
onError: (error) {
// Try to send BAD_REQUEST response.
@@ -26,13 +31,15 @@
}
static Future<HttpClientResponseBody> processResponse(
- HttpClientResponse response) {
- return process(response, response.headers)
+ HttpClientResponse response,
+ Encoding defaultEncoding) {
+ return process(response, response.headers, defaultEncoding)
.then((body) => new _HttpClientResponseBody(response, body));
}
static Future<HttpBody> process(Stream<List<int>> stream,
- HttpHeaders headers) {
+ HttpHeaders headers,
+ Encoding defaultEncoding) {
ContentType contentType = headers.contentType;
Future<HttpBody> asBinary() {
@@ -113,14 +120,11 @@
case "x-www-form-urlencoded":
return asText(Encoding.ASCII)
.then((body) {
- var map = _HttpUtils.splitQueryString(body.body);
+ var map = _HttpUtils.splitQueryString(
+ body.body, encoding: defaultEncoding);
var result = {};
- String parse(String s) {
- return _HttpUtils.decodeHttpEntityString(
- _HttpUtils.decodeUrlEncodedString(s));
- }
for (var key in map.keys) {
- result[parse(key)] = parse(map[key]);
+ result[key] = map[key];
}
return new _HttpBody(contentType, "form", result);
});
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 5983717..8153850 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -207,7 +207,7 @@
_set(HttpHeaders.CONTENT_TYPE, contentType.toString());
}
- void _add(String name, Object value) {
+ void _add(String name, value) {
var lowerCaseName = name.toLowerCase();
// TODO(sgjesse): Add immutable state throw HttpException is immutable.
if (lowerCaseName == HttpHeaders.CONTENT_LENGTH) {
@@ -250,13 +250,13 @@
}
} else if (lowerCaseName == HttpHeaders.HOST) {
if (value is String) {
- int pos = (value as String).indexOf(":");
+ int pos = value.indexOf(":");
if (pos == -1) {
_host = value;
_port = HttpClient.DEFAULT_HTTP_PORT;
} else {
if (pos > 0) {
- _host = (value as String).substring(0, pos);
+ _host = value.substring(0, pos);
} else {
_host = null;
}
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index a0f514d..73acb00 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -144,7 +144,7 @@
HttpConnectionInfo get connectionInfo => _httpConnection.connectionInfo;
X509Certificate get certificate {
- Socket socket = _httpConnection._socket;
+ var socket = _httpConnection._socket;
if (socket is SecureSocket) return socket.peerCertificate;
return null;
}
@@ -1071,6 +1071,7 @@
StreamSubscription _subscription;
final _HttpClient _httpClient;
bool _dispose = false;
+ bool closed = false;
Completer<_HttpIncoming> _nextResponseCompleter;
Future _streamFuture;
@@ -1090,10 +1091,11 @@
// stream paused until the response have been processed.
_subscription.pause();
// We assume the response is not here, until we have send the request.
- assert(_nextResponseCompleter != null);
- var completer = _nextResponseCompleter;
+ if (_nextResponseCompleter == null) {
+ throw new HttpException("Unexpected response.");
+ }
+ _nextResponseCompleter.complete(incoming);
_nextResponseCompleter = null;
- completer.complete(incoming);
},
onError: (error) {
if (_nextResponseCompleter != null) {
@@ -1102,11 +1104,19 @@
}
},
onDone: () {
+ if (_nextResponseCompleter != null) {
+ _nextResponseCompleter.completeError(new HttpException(
+ "Connection closed before response was received"));
+ _nextResponseCompleter = null;
+ }
close();
});
}
_HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
+ if (closed) {
+ throw new HttpException("Socket closed before request was sent");
+ }
// Start with pausing the parser.
_subscription.pause();
_ProxyCredentials proxyCreds; // Credentials used to authorize proxy.
@@ -1227,11 +1237,13 @@
}
void destroy() {
+ closed = true;
_httpClient._connectionClosed(this);
_socket.destroy();
}
void close() {
+ closed = true;
_httpClient._connectionClosed(this);
_streamFuture
// TODO(ajohnsen): Add timeout.
@@ -1407,10 +1419,19 @@
}
return _getConnection(uri.domain, port, proxyConf, isSecure)
.then((info) {
- return info.connection.send(uri,
- port,
- method.toUpperCase(),
- info.proxy);
+ send(info) {
+ return info.connection.send(uri,
+ port,
+ method.toUpperCase(),
+ info.proxy);
+ }
+ // If the connection was closed before the request was sent, create
+ // and use another connection.
+ if (info.connection.closed) {
+ return _getConnection(uri.domain, port, proxyConf, isSecure)
+ .then(send);
+ }
+ return send(info);
});
}
@@ -1590,6 +1611,10 @@
if (pos >= 0) {
option = option.substring(pos + 3);
}
+ pos = option.indexOf("/");
+ if (pos >= 0) {
+ option = option.substring(0, pos);
+ }
if (option.indexOf(":") == -1) option = "$option:1080";
return "PROXY $option";
}
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 61407df..af937e9 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -34,6 +34,7 @@
static const int LF = 10;
static const int CR = 13;
static const int SP = 32;
+ static const int AMPERSAND = 38;
static const int COMMA = 44;
static const int DASH = 45;
static const int SLASH = 47;
@@ -41,6 +42,7 @@
static const int ONE = 49;
static const int COLON = 58;
static const int SEMI_COLON = 59;
+ static const int EQUAL = 61;
}
@@ -195,10 +197,24 @@
_HttpParser._(this._requestParser) {
_controller = new StreamController<_HttpIncoming>(
- onListen: _updateParsePauseState,
- onPause: _updateParsePauseState,
- onResume: _updateParsePauseState,
- onCancel: _updateParsePauseState);
+ onListen: () {
+ _socketSubscription.resume();
+ _paused = false;
+ },
+ onPause: () {
+ _paused = true;
+ _pauseStateChanged();
+ },
+ onResume: () {
+ _paused = false;
+ _pauseStateChanged();
+ },
+ onCancel: () {
+ try {
+ _socketSubscription.cancel();
+ } catch (e) {
+ }
+ });
_reset();
}
@@ -226,6 +242,7 @@
onDone: () {
completer.complete(this);
});
+ _socketSubscription.pause();
return completer.future;
}
@@ -265,7 +282,9 @@
_index < _buffer.length &&
_state != _State.FAILURE &&
_state != _State.UPGRADED) {
- if (_paused) {
+ // Depending on _incoming, we either break on _bodyPaused or _paused.
+ if ((_incoming != null && _bodyPaused) ||
+ (_incoming == null && _paused)) {
_parserCalled = false;
return;
}
@@ -560,8 +579,9 @@
_uri_or_reason_phrase.clear();
if (_connectionUpgrade) {
_incoming.upgraded = true;
+ _parserCalled = false;
_controller.add(_incoming);
- break;
+ return;
}
if (_transferLength == 0 ||
(_messageType == _MessageType.RESPONSE &&
@@ -582,8 +602,9 @@
// indicated by close.
_state = _State.BODY;
}
+ _parserCalled = false;
_controller.add(_incoming);
- break;
+ return;
case _State.CHUNK_SIZE_STARTING_CR:
_expect(byte, _CharCode.CR);
@@ -862,58 +883,71 @@
void _createIncoming(int transferLength) {
assert(_incoming == null);
assert(_bodyController == null);
+ assert(!_bodyPaused);
+ var incoming;
_bodyController = new StreamController<List<int>>(
- onListen: _bodySubscriptionStateChange,
- onPause: _updateParsePauseState,
- onResume: _updateParsePauseState,
- onCancel: _bodySubscriptionStateChange);
- _incoming = new _HttpIncoming(
+ onListen: () {
+ if (incoming != _incoming) return;
+ assert(_bodyPaused);
+ _bodyPaused = false;
+ _pauseStateChanged();
+ },
+ onPause: () {
+ if (incoming != _incoming) return;
+ assert(!_bodyPaused);
+ _bodyPaused = true;
+ _pauseStateChanged();
+ },
+ onResume: () {
+ if (incoming != _incoming) return;
+ assert(_bodyPaused);
+ _bodyPaused = false;
+ _pauseStateChanged();
+ },
+ onCancel: () {
+ if (incoming != _incoming) return;
+ if (_socketSubscription != null) {
+ _socketSubscription.cancel();
+ }
+ _closeIncoming();
+ _controller.close();
+ });
+ incoming = _incoming = new _HttpIncoming(
_headers, transferLength, _bodyController.stream);
- _pauseParsing(); // Needed to handle detaching - don't start on the body!
+ _bodyPaused = true;
+ _pauseStateChanged();
}
void _closeIncoming() {
// Ignore multiple close (can happend in re-entrance).
if (_incoming == null) return;
var tmp = _incoming;
- _incoming = null;
tmp.close();
+ _incoming = null;
if (_bodyController != null) {
_bodyController.close();
_bodyController = null;
}
- _updateParsePauseState();
+ _bodyPaused = false;
+ _pauseStateChanged();
}
- void _continueParsing() {
- _paused = false;
- if (!_parserCalled && _buffer != null) _parse();
- }
-
- void _pauseParsing() {
- _paused = true;
- }
-
- void _bodySubscriptionStateChange() {
- if (_incoming != null && !_bodyController.hasListener) {
- _closeIncoming();
- } else {
- _updateParsePauseState();
+ void _pauseStateChanged() {
+ void update(bool pause) {
+ if (pause && !_socketSubscription.isPaused) {
+ _socketSubscription.pause();
+ } else if (!pause && _socketSubscription.isPaused) {
+ _socketSubscription.resume();
+ }
}
- }
- void _updateParsePauseState() {
- if (_bodyController != null) {
- if (_bodyController.hasListener && !_bodyController.isPaused) {
- _continueParsing();
- } else {
- _pauseParsing();
+ if (_incoming != null) {
+ if (!_bodyPaused && !_parserCalled) {
+ _parse();
}
} else {
- if (_controller.hasListener && !_controller.isPaused) {
- _continueParsing();
- } else {
- _pauseParsing();
+ if (!_paused && !_parserCalled) {
+ _parse();
}
}
}
@@ -957,7 +991,8 @@
// The current incoming connection.
_HttpIncoming _incoming;
StreamSubscription _socketSubscription;
- bool _paused = false;
+ bool _paused = true;
+ bool _bodyPaused = false;
Completer _pauseCompleter;
StreamController<_HttpIncoming> _controller;
StreamController<List<int>> _bodyController;
diff --git a/sdk/lib/io/http_utils.dart b/sdk/lib/io/http_utils.dart
index 8e957bf..82db7de 100644
--- a/sdk/lib/io/http_utils.dart
+++ b/sdk/lib/io/http_utils.dart
@@ -5,7 +5,9 @@
part of dart.io;
class _HttpUtils {
- static String decodeUrlEncodedString(String urlEncoded) {
+ static String decodeUrlEncodedString(
+ String urlEncoded,
+ {Encoding encoding: Encoding.UTF_8}) {
// First check the string for any encoding.
int index = 0;
bool encoded = false;
@@ -47,30 +49,62 @@
bytes.add(urlEncoded.codeUnitAt(i));
}
}
- return decodeUtf8(bytes);
+ return _decodeString(bytes, encoding);
}
- static Map<String, String> splitQueryString(String queryString) {
+ static Map<String, String> splitQueryString(
+ String queryString,
+ {Encoding encoding: Encoding.UTF_8}) {
Map<String, String> result = new Map<String, String>();
int currentPosition = 0;
- while (currentPosition < queryString.length) {
- int position = queryString.indexOf("=", currentPosition);
- if (position == -1) {
- break;
+ int length = queryString.length;
+
+ while (currentPosition < length) {
+
+ // Find the first equals character between current position and
+ // the provided end.
+ int indexOfEquals(int end) {
+ int index = currentPosition;
+ while (index < end) {
+ if (queryString.codeUnitAt(index) == _CharCode.EQUAL) return index;
+ index++;
+ }
+ return -1;
}
- String name = queryString.substring(currentPosition, position);
- currentPosition = position + 1;
- position = queryString.indexOf("&", currentPosition);
+
+ // Find the next separator (either & or ;), see
+ // http://www.w3.org/TR/REC-html40/appendix/notes.html#ampersands-in-uris
+ // relating the ; separator. If no separator is found returns
+ // the length of the query string.
+ int indexOfSeparator() {
+ int end = length;
+ int index = currentPosition;
+ while (index < end) {
+ int codeUnit = queryString.codeUnitAt(index);
+ if (codeUnit == _CharCode.AMPERSAND ||
+ codeUnit == _CharCode.SEMI_COLON) {
+ return index;
+ }
+ index++;
+ }
+ return end;
+ }
+
+ int seppos = indexOfSeparator();
+ int equalspos = indexOfEquals(seppos);
+ String name;
String value;
- if (position == -1) {
- value = queryString.substring(currentPosition);
- currentPosition = queryString.length;
+ if (equalspos == -1) {
+ name = queryString.substring(currentPosition, seppos);
+ value = '';
} else {
- value = queryString.substring(currentPosition, position);
- currentPosition = position + 1;
+ name = queryString.substring(currentPosition, equalspos);
+ value = queryString.substring(equalspos + 1, seppos);
}
- result[_HttpUtils.decodeUrlEncodedString(name)] =
- _HttpUtils.decodeUrlEncodedString(value);
+ currentPosition = seppos + 1; // This also works when seppos == length.
+ if (name == '') continue;
+ result[_HttpUtils.decodeUrlEncodedString(name, encoding: encoding)] =
+ _HttpUtils.decodeUrlEncodedString(value, encoding: encoding);
}
return result;
}
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index abf484b..d6e5f43 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -7,11 +7,72 @@
import 'dart:collection';
import 'dart:_collection-dev';
-import 'dart:html';
-import 'dart:html_common';
-import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
+import 'dart:_js_helper' show Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
import 'dart:_foreign_helper' show JS;
+// TODO(10691): migrate to ListMixin.
+class _Lists {
+
+ /**
+ * Returns the index in the array [a] of the given [element], starting
+ * the search at index [startIndex] to [endIndex] (exclusive).
+ * Returns -1 if [element] is not found.
+ */
+ static int indexOf(List a,
+ Object element,
+ int startIndex,
+ int endIndex) {
+ if (startIndex >= a.length) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < endIndex; i++) {
+ if (a[i] == element) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the last index in the array [a] of the given [element], starting
+ * the search at index [startIndex] to 0.
+ * Returns -1 if [element] is not found.
+ */
+ static int lastIndexOf(List a, Object element, int startIndex) {
+ if (startIndex < 0) {
+ return -1;
+ }
+ if (startIndex >= a.length) {
+ startIndex = a.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (a[i] == element) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns a sub list copy of this list, from [start] to
+ * [end] ([end] not inclusive).
+ * Returns an empty list if [length] is 0.
+ * It is an error if indices are not valid for the list, or
+ * if [end] is before [start].
+ */
+ static List getRange(List a, int start, int end, List accumulator) {
+ if (start < 0) throw new RangeError.value(start);
+ if (end < start) throw new RangeError.value(end);
+ if (end > a.length) throw new RangeError.value(end);
+ for (int i = start; i < end; i++) {
+ accumulator.add(a[i]);
+ }
+ return accumulator;
+ }
+}
/**
* Describes endianness to be used when accessing a sequence of bytes.
*/
@@ -27,39 +88,20 @@
final bool _littleEndian;
}
-@DocsEditable
-@DomName('ArrayBuffer')
-@SupportedBrowser(SupportedBrowser.CHROME)
-@SupportedBrowser(SupportedBrowser.FIREFOX)
-@SupportedBrowser(SupportedBrowser.IE, '10')
-@SupportedBrowser(SupportedBrowser.SAFARI)
class ByteBuffer native "ArrayBuffer" {
@JSName('byteLength')
- @DomName('ArrayBuffer.byteLength')
- @DocsEditable
final int lengthInBytes;
}
-@DomName('ArrayBufferView')
-@SupportedBrowser(SupportedBrowser.CHROME)
-@SupportedBrowser(SupportedBrowser.FIREFOX)
-@SupportedBrowser(SupportedBrowser.IE, '10')
-@SupportedBrowser(SupportedBrowser.SAFARI)
class TypedData native "ArrayBufferView" {
- @DomName('ArrayBufferView.buffer')
- @DocsEditable
@Creates('ByteBuffer')
@Returns('ByteBuffer|Null')
final ByteBuffer buffer;
@JSName('byteLength')
- @DomName('ArrayBufferView.byteLength')
- @DocsEditable
final int lengthInBytes;
@JSName('byteOffset')
- @DomName('ArrayBufferView.byteOffset')
- @DocsEditable
final int offsetInBytes;
@JSName('BYTES_PER_ELEMENT')
@@ -80,15 +122,9 @@
}
}
-@DocsEditable
-@DomName('DataView')
class ByteData extends TypedData native "DataView" {
- @DomName('DataView.DataView')
- @DocsEditable
factory ByteData(int length) => JS('ByteData', 'new DataView(#)', length);
- @DomName('DataView.DataView')
- @DocsEditable
factory ByteData.view(ByteBuffer buffer, [int byteOffset, int byteLength]) {
if (?byteLength) {
return ByteData._create_1(buffer, byteOffset, byteLength);
@@ -104,8 +140,6 @@
static ByteData _create_2(buffer, byteOffset) => JS('ByteData', 'new DataView(#,#)', buffer, byteOffset);
static ByteData _create_3(buffer) => JS('ByteData', 'new DataView(#)', buffer);
- @DomName('DataView.getFloat32')
- @DocsEditable
num getFloat32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getFloat32(byteOffset, endian._littleEndian);
@@ -113,8 +147,6 @@
@Returns('num')
num _getFloat32(int byteOffset, [bool littleEndian]) native;
- @DomName('DataView.getFloat64')
- @DocsEditable
num getFloat64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getFloat64(byteOffset, endian._littleEndian);
@@ -122,8 +154,6 @@
@Returns('num')
num _getFloat64(int byteOffset, [bool littleEndian]) native;
- @DomName('DataView.getInt16')
- @DocsEditable
int getInt16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getInt16(byteOffset, endian._littleEndian);
@@ -131,8 +161,6 @@
@Returns('int')
int _getInt16(int byteOffset, [bool littleEndian]) native;
- @DomName('DataView.getInt32')
- @DocsEditable
int getInt32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getInt32(byteOffset, endian._littleEndian);
@@ -140,17 +168,12 @@
@Returns('int')
int _getInt32(int byteOffset, [bool littleEndian]) native;
- @DocsEditable
int getInt64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) {
throw new UnsupportedError("Int64 accessor not supported by dart2js.");
}
- @DomName('DataView.getInt8')
- @DocsEditable
int getInt8(int byteOffset) native;
- @DomName('DataView.getUint16')
- @DocsEditable
int getUint16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getUint16(byteOffset, endian._littleEndian);
@@ -158,8 +181,6 @@
@Returns('int')
int _getUint16(int byteOffset, [bool littleEndian]) native;
- @DomName('DataView.getUint32')
- @DocsEditable
int getUint32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_getUint32(byteOffset, endian._littleEndian);
@@ -167,104 +188,73 @@
@Returns('int')
int _getUint32(int byteOffset, [bool littleEndian]) native;
- @DocsEditable
int getUint64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) {
throw new UnsupportedError("Uint64 accessor not supported by dart2js.");
}
- @DomName('DataView.getUint8')
- @DocsEditable
int getUint8(int byteOffset) native;
- @DomName('DataView.setFloat32')
- @DocsEditable
void setFloat32(int byteOffset, num value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setFloat32(byteOffset, value, endian._littleEndian);
@JSName('setFloat32')
void _setFloat32(int byteOffset, num value, [bool littleEndian]) native;
- @DomName('DataView.setFloat64')
- @DocsEditable
void setFloat64(int byteOffset, num value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setFloat64(byteOffset, value, endian._littleEndian);
@JSName('setFloat64')
void _setFloat64(int byteOffset, num value, [bool littleEndian]) native;
- @DomName('DataView.setInt16')
- @DocsEditable
void setInt16(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setInt16(byteOffset, value, endian._littleEndian);
@JSName('setInt16')
void _setInt16(int byteOffset, int value, [bool littleEndian]) native;
- @DomName('DataView.setInt32')
- @DocsEditable
void setInt32(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setInt32(byteOffset, value, endian._littleEndian);
@JSName('setInt32')
void _setInt32(int byteOffset, int value, [bool littleEndian]) native;
- @DocsEditable
void setInt64(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) {
throw new UnsupportedError("Int64 accessor not supported by dart2js.");
}
- @DomName('DataView.setInt8')
- @DocsEditable
void setInt8(int byteOffset, int value) native;
- @DomName('DataView.setUint16')
- @DocsEditable
void setUint16(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setUint16(byteOffset, value, endian._littleEndian);
@JSName('setUint16')
void _setUint16(int byteOffset, int value, [bool littleEndian]) native;
- @DomName('DataView.setUint32')
- @DocsEditable
void setUint32(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) =>
_setUint32(byteOffset, value, endian._littleEndian);
@JSName('setUint32')
void _setUint32(int byteOffset, int value, [bool littleEndian]) native;
- @DocsEditable
void setUint64(int byteOffset, int value, [Endianness endian=Endianness.BIG_ENDIAN]) {
throw new UnsupportedError("Uint64 accessor not supported by dart2js.");
}
- @DomName('DataView.setUint8')
- @DocsEditable
void setUint8(int byteOffset, int value) native;
}
-@DocsEditable
-@DomName('Float32Array')
class Float32List extends TypedData implements JavaScriptIndexingBehavior, List<double> native "Float32Array" {
- @DomName('Float32Array.Float32Array')
- @DocsEditable
factory Float32List(int length) =>
_TypedArrayFactoryProvider.createFloat32List(length);
- @DomName('Float32Array.fromList')
- @DocsEditable
factory Float32List.fromList(List<num> list) =>
_TypedArrayFactoryProvider.createFloat32List_fromList(list);
- @DomName('Float32Array.fromBuffer')
- @DocsEditable
factory Float32List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createFloat32List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
- @DomName('Float32Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
num operator[](int index) {
@@ -285,7 +275,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<num>(this);
+ return new ListIterator<num>(this);
}
num reduce(num combine(num value, num element)) {
@@ -380,11 +370,11 @@
}
int indexOf(num element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(num element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
num get first {
@@ -456,7 +446,7 @@
List<num> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <num>[]);
+ return _Lists.getRange(this, start, end, <num>[]);
}
Map<int, num> asMap() =>
@@ -472,29 +462,19 @@
// -- end List<num> mixins.
}
-@DocsEditable
-@DomName('Float64Array')
class Float64List extends TypedData implements JavaScriptIndexingBehavior, List<double> native "Float64Array" {
- @DomName('Float64Array.Float64Array')
- @DocsEditable
factory Float64List(int length) =>
_TypedArrayFactoryProvider.createFloat64List(length);
- @DomName('Float64Array.fromList')
- @DocsEditable
factory Float64List.fromList(List<num> list) =>
_TypedArrayFactoryProvider.createFloat64List_fromList(list);
- @DomName('Float64Array.fromBuffer')
- @DocsEditable
factory Float64List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createFloat64List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 8;
- @DomName('Float64Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
num operator[](int index) {
@@ -515,7 +495,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<num>(this);
+ return new ListIterator<num>(this);
}
num reduce(num combine(num value, num element)) {
@@ -610,11 +590,11 @@
}
int indexOf(num element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(num element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
num get first {
@@ -686,7 +666,7 @@
List<num> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <num>[]);
+ return _Lists.getRange(this, start, end, <num>[]);
}
Map<int, num> asMap() =>
@@ -702,29 +682,19 @@
// -- end List<num> mixins.
}
-@DocsEditable
-@DomName('Int16Array')
class Int16List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Int16Array" {
- @DomName('Int16Array.Int16Array')
- @DocsEditable
factory Int16List(int length) =>
_TypedArrayFactoryProvider.createInt16List(length);
- @DomName('Int16Array.fromList')
- @DocsEditable
factory Int16List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createInt16List_fromList(list);
- @DomName('Int16Array.fromBuffer')
- @DocsEditable
factory Int16List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt16List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 2;
- @DomName('Int16Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -745,7 +715,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -840,11 +810,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -916,7 +886,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -932,29 +902,19 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Int32Array')
class Int32List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Int32Array" {
- @DomName('Int32Array.Int32Array')
- @DocsEditable
factory Int32List(int length) =>
_TypedArrayFactoryProvider.createInt32List(length);
- @DomName('Int32Array.fromList')
- @DocsEditable
factory Int32List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createInt32List_fromList(list);
- @DomName('Int32Array.fromBuffer')
- @DocsEditable
factory Int32List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt32List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
- @DomName('Int32Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -975,7 +935,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -1070,11 +1030,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -1146,7 +1106,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -1162,29 +1122,19 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Int8Array')
class Int8List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Int8Array" {
- @DomName('Int8Array.Int8Array')
- @DocsEditable
factory Int8List(int length) =>
_TypedArrayFactoryProvider.createInt8List(length);
- @DomName('Int8Array.fromList')
- @DocsEditable
factory Int8List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createInt8List_fromList(list);
- @DomName('Int8Array.fromBuffer')
- @DocsEditable
factory Int8List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createInt8List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 1;
- @DomName('Int8Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -1205,7 +1155,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -1300,11 +1250,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -1376,7 +1326,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -1392,29 +1342,19 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Uint16Array')
class Uint16List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Uint16Array" {
- @DomName('Uint16Array.Uint16Array')
- @DocsEditable
factory Uint16List(int length) =>
_TypedArrayFactoryProvider.createUint16List(length);
- @DomName('Uint16Array.fromList')
- @DocsEditable
factory Uint16List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createUint16List_fromList(list);
- @DomName('Uint16Array.fromBuffer')
- @DocsEditable
factory Uint16List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint16List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 2;
- @DomName('Uint16Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -1435,7 +1375,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -1530,11 +1470,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -1606,7 +1546,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -1622,29 +1562,19 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Uint32Array')
class Uint32List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Uint32Array" {
- @DomName('Uint32Array.Uint32Array')
- @DocsEditable
factory Uint32List(int length) =>
_TypedArrayFactoryProvider.createUint32List(length);
- @DomName('Uint32Array.fromList')
- @DocsEditable
factory Uint32List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createUint32List_fromList(list);
- @DomName('Uint32Array.fromBuffer')
- @DocsEditable
factory Uint32List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint32List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 4;
- @DomName('Uint32Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -1665,7 +1595,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -1760,11 +1690,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -1836,7 +1766,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -1852,22 +1782,14 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Uint8ClampedArray')
class Uint8ClampedList extends Uint8List implements JavaScriptIndexingBehavior, List<int> native "Uint8ClampedArray" {
- @DomName('Uint8ClampedArray.Uint8ClampedArray')
- @DocsEditable
factory Uint8ClampedList(int length) =>
_TypedArrayFactoryProvider.createUint8ClampedList(length);
- @DomName('Uint8ClampedArray.fromList')
- @DocsEditable
factory Uint8ClampedList.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createUint8ClampedList_fromList(list);
- @DomName('Uint8ClampedArray.fromBuffer')
- @DocsEditable
factory Uint8ClampedList.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint8ClampedList_fromBuffer(buffer, byteOffset, length);
@@ -1892,7 +1814,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -1987,11 +1909,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -2063,7 +1985,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
@@ -2079,29 +2001,19 @@
// -- end List<int> mixins.
}
-@DocsEditable
-@DomName('Uint8Array')
class Uint8List extends TypedData implements JavaScriptIndexingBehavior, List<int> native "Uint8Array" {
- @DomName('Uint8Array.Uint8Array')
- @DocsEditable
factory Uint8List(int length) =>
_TypedArrayFactoryProvider.createUint8List(length);
- @DomName('Uint8Array.fromList')
- @DocsEditable
factory Uint8List.fromList(List<int> list) =>
_TypedArrayFactoryProvider.createUint8List_fromList(list);
- @DomName('Uint8Array.fromBuffer')
- @DocsEditable
factory Uint8List.view(ByteBuffer buffer, [int byteOffset, int length]) =>
_TypedArrayFactoryProvider.createUint8List_fromBuffer(buffer, byteOffset, length);
static const int BYTES_PER_ELEMENT = 1;
- @DomName('Uint8Array.length')
- @DocsEditable
int get length => JS("int", "#.length", this);
int operator[](int index) {
@@ -2122,7 +2034,7 @@
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
- return new FixedSizeListIterator<int>(this);
+ return new ListIterator<int>(this);
}
int reduce(int combine(int value, int element)) {
@@ -2217,11 +2129,11 @@
}
int indexOf(int element, [int start = 0]) =>
- Lists.indexOf(this, element, start, this.length);
+ _Lists.indexOf(this, element, start, this.length);
int lastIndexOf(int element, [int start]) {
if (start == null) start = length - 1;
- return Lists.lastIndexOf(this, element, start);
+ return _Lists.lastIndexOf(this, element, start);
}
int get first {
@@ -2293,7 +2205,7 @@
List<int> sublist(int start, [int end]) {
if (end == null) end = length;
- return Lists.getRange(this, start, end, <int>[]);
+ return _Lists.getRange(this, start, end, <int>[]);
}
Map<int, int> asMap() =>
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index c6b7b82..ece0a8c 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -180,6 +180,18 @@
@DocsEditable
final int playbackState;
+ @DomName('AudioBufferSourceNode.noteGrainOn')
+ @DocsEditable
+ void noteGrainOn(num when, num grainOffset, num grainDuration) native;
+
+ @DomName('AudioBufferSourceNode.noteOff')
+ @DocsEditable
+ void noteOff(num when) native;
+
+ @DomName('AudioBufferSourceNode.noteOn')
+ @DocsEditable
+ void noteOn(num when) native;
+
}
// 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
@@ -248,10 +260,22 @@
@DocsEditable
DelayNode createDelay([num maxDelayTime]) native;
+ @DomName('AudioContext.createDelayNode')
+ @DocsEditable
+ DelayNode createDelayNode([num maxDelayTime]) native;
+
@DomName('AudioContext.createDynamicsCompressor')
@DocsEditable
DynamicsCompressorNode createDynamicsCompressor() native;
+ @DomName('AudioContext.createGainNode')
+ @DocsEditable
+ GainNode createGainNode() native;
+
+ @DomName('AudioContext.createJavaScriptNode')
+ @DocsEditable
+ ScriptProcessorNode createJavaScriptNode(int bufferSize, [int numberOfInputChannels, int numberOfOutputChannels]) native;
+
@DomName('AudioContext.createMediaElementSource')
@DocsEditable
MediaElementAudioSourceNode createMediaElementSource(MediaElement mediaElement) native;
@@ -451,6 +475,10 @@
@DocsEditable
void setTargetAtTime(num target, num time, num timeConstant) native;
+ @DomName('AudioParam.setTargetValueAtTime')
+ @DocsEditable
+ void setTargetValueAtTime(num targetValue, num time, num timeConstant) native;
+
@DomName('AudioParam.setValueAtTime')
@DocsEditable
void setValueAtTime(num value, num time) native;
@@ -773,6 +801,14 @@
@DocsEditable
String type;
+ @DomName('OscillatorNode.noteOff')
+ @DocsEditable
+ void noteOff(num when) native;
+
+ @DomName('OscillatorNode.noteOn')
+ @DocsEditable
+ void noteOn(num when) native;
+
@DomName('OscillatorNode.setWaveTable')
@DocsEditable
void setWaveTable(WaveTable waveTable) native;
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index d71875c..0556cf3 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -195,6 +195,18 @@
@DocsEditable
int get playbackState native "AudioBufferSourceNode_playbackState_Getter";
+ @DomName('AudioBufferSourceNode.noteGrainOn')
+ @DocsEditable
+ void noteGrainOn(num when, num grainOffset, num grainDuration) native "AudioBufferSourceNode_noteGrainOn_Callback";
+
+ @DomName('AudioBufferSourceNode.noteOff')
+ @DocsEditable
+ void noteOff(num when) native "AudioBufferSourceNode_noteOff_Callback";
+
+ @DomName('AudioBufferSourceNode.noteOn')
+ @DocsEditable
+ void noteOn(num when) native "AudioBufferSourceNode_noteOn_Callback";
+
void start(num when, [num grainOffset, num grainDuration]) {
if ((when is num || when == null) && !?grainOffset && !?grainDuration) {
_start_1(when);
@@ -325,6 +337,17 @@
DelayNode _createDelay_2() native "AudioContext__createDelay_2_Callback";
+ DelayNode createDelayNode([num maxDelayTime]) {
+ if (?maxDelayTime) {
+ return _createDelayNode_1(maxDelayTime);
+ }
+ return _createDelayNode_2();
+ }
+
+ DelayNode _createDelayNode_1(maxDelayTime) native "AudioContext__createDelayNode_1_Callback";
+
+ DelayNode _createDelayNode_2() native "AudioContext__createDelayNode_2_Callback";
+
@DomName('AudioContext.createDynamicsCompressor')
@DocsEditable
DynamicsCompressorNode createDynamicsCompressor() native "AudioContext_createDynamicsCompressor_Callback";
@@ -333,6 +356,26 @@
@DocsEditable
GainNode createGain() native "AudioContext_createGain_Callback";
+ @DomName('AudioContext.createGainNode')
+ @DocsEditable
+ GainNode createGainNode() native "AudioContext_createGainNode_Callback";
+
+ ScriptProcessorNode createJavaScriptNode(int bufferSize, [int numberOfInputChannels, int numberOfOutputChannels]) {
+ if (?numberOfOutputChannels) {
+ return _createJavaScriptNode_1(bufferSize, numberOfInputChannels, numberOfOutputChannels);
+ }
+ if (?numberOfInputChannels) {
+ return _createJavaScriptNode_2(bufferSize, numberOfInputChannels);
+ }
+ return _createJavaScriptNode_3(bufferSize);
+ }
+
+ ScriptProcessorNode _createJavaScriptNode_1(bufferSize, numberOfInputChannels, numberOfOutputChannels) native "AudioContext__createJavaScriptNode_1_Callback";
+
+ ScriptProcessorNode _createJavaScriptNode_2(bufferSize, numberOfInputChannels) native "AudioContext__createJavaScriptNode_2_Callback";
+
+ ScriptProcessorNode _createJavaScriptNode_3(bufferSize) native "AudioContext__createJavaScriptNode_3_Callback";
+
@DomName('AudioContext.createMediaElementSource')
@DocsEditable
MediaElementAudioSourceNode createMediaElementSource(MediaElement mediaElement) native "AudioContext_createMediaElementSource_Callback";
@@ -573,6 +616,10 @@
@DocsEditable
void setTargetAtTime(num target, num time, num timeConstant) native "AudioParam_setTargetAtTime_Callback";
+ @DomName('AudioParam.setTargetValueAtTime')
+ @DocsEditable
+ void setTargetValueAtTime(num targetValue, num time, num timeConstant) native "AudioParam_setTargetValueAtTime_Callback";
+
@DomName('AudioParam.setValueAtTime')
@DocsEditable
void setValueAtTime(num value, num time) native "AudioParam_setValueAtTime_Callback";
@@ -973,6 +1020,14 @@
@DocsEditable
void set type(String value) native "OscillatorNode_type_Setter";
+ @DomName('OscillatorNode.noteOff')
+ @DocsEditable
+ void noteOff(num when) native "OscillatorNode_noteOff_Callback";
+
+ @DomName('OscillatorNode.noteOn')
+ @DocsEditable
+ void noteOn(num when) native "OscillatorNode_noteOn_Callback";
+
@DomName('OscillatorNode.setWaveTable')
@DocsEditable
void setWaveTable(WaveTable waveTable) native "OscillatorNode_setWaveTable_Callback";
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index de46851..1ab1cd79c 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -120,7 +120,7 @@
const int GEQUAL = RenderingContext.GEQUAL;
const int GREATER = RenderingContext.GREATER;
const int GREEN_BITS = RenderingContext.GREEN_BITS;
-const int HALF_FLOAT_OES = RenderingContext.HALF_FLOAT_OES;
+const int HALF_FLOAT_OES = OesTextureHalfFloat.HALF_FLOAT_OES;
const int HIGH_FLOAT = RenderingContext.HIGH_FLOAT;
const int HIGH_INT = RenderingContext.HIGH_INT;
const int INCR = RenderingContext.INCR;
@@ -734,6 +734,10 @@
@DocsEditable
@DomName('OESTextureHalfFloat')
class OesTextureHalfFloat native "OESTextureHalfFloat" {
+
+ @DomName('OESTextureHalfFloat.HALF_FLOAT_OES')
+ @DocsEditable
+ static const int HALF_FLOAT_OES = 0x8D61;
}
// 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
@@ -1197,10 +1201,6 @@
@DocsEditable
static const int GREEN_BITS = 0x0D53;
- @DomName('WebGLRenderingContext.HALF_FLOAT_OES')
- @DocsEditable
- static const int HALF_FLOAT_OES = 0x8D61;
-
@DomName('WebGLRenderingContext.HIGH_FLOAT')
@DocsEditable
static const int HIGH_FLOAT = 0x8DF2;
@@ -2359,10 +2359,6 @@
@DocsEditable
void readPixels(int x, int y, int width, int height, int format, int type, TypedData pixels) native;
- @DomName('WebGLRenderingContext.releaseShaderCompiler')
- @DocsEditable
- void releaseShaderCompiler() native;
-
@DomName('WebGLRenderingContext.renderbufferStorage')
@DocsEditable
void renderbufferStorage(int target, int internalformat, int width, int height) native;
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 31db381..a200ad4 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -118,7 +118,7 @@
const int GEQUAL = RenderingContext.GEQUAL;
const int GREATER = RenderingContext.GREATER;
const int GREEN_BITS = RenderingContext.GREEN_BITS;
-const int HALF_FLOAT_OES = RenderingContext.HALF_FLOAT_OES;
+const int HALF_FLOAT_OES = OesTextureHalfFloat.HALF_FLOAT_OES;
const int HIGH_FLOAT = RenderingContext.HIGH_FLOAT;
const int HIGH_INT = RenderingContext.HIGH_INT;
const int INCR = RenderingContext.INCR;
@@ -828,6 +828,10 @@
class OesTextureHalfFloat extends NativeFieldWrapperClass1 {
OesTextureHalfFloat.internal();
+ @DomName('OESTextureHalfFloat.HALF_FLOAT_OES')
+ @DocsEditable
+ static const int HALF_FLOAT_OES = 0x8D61;
+
}
// 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
@@ -1302,10 +1306,6 @@
@DocsEditable
static const int GREEN_BITS = 0x0D53;
- @DomName('WebGLRenderingContext.HALF_FLOAT_OES')
- @DocsEditable
- static const int HALF_FLOAT_OES = 0x8D61;
-
@DomName('WebGLRenderingContext.HIGH_FLOAT')
@DocsEditable
static const int HIGH_FLOAT = 0x8DF2;
@@ -2492,10 +2492,6 @@
@DocsEditable
void readPixels(int x, int y, int width, int height, int format, int type, TypedData pixels) native "WebGLRenderingContext_readPixels_Callback";
- @DomName('WebGLRenderingContext.releaseShaderCompiler')
- @DocsEditable
- void releaseShaderCompiler() native "WebGLRenderingContext_releaseShaderCompiler_Callback";
-
@DomName('WebGLRenderingContext.renderbufferStorage')
@DocsEditable
void renderbufferStorage(int target, int internalformat, int width, int height) native "WebGLRenderingContext_renderbufferStorage_Callback";
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 2dd3d58..814b54d 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -37,13 +37,8 @@
Language/07_Classes/3_Setters_A03_t04: fail
Language/07_Classes/3_Setters_A03_t06: fail
Language/07_Classes/3_Setters_A03_t08: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A01_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t03: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t05: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t06: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t07: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t08: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t11: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
@@ -52,20 +47,10 @@
Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t07: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t09: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t01: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t02: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t03: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t05: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t06: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t07: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A16_t01: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A16_t02: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A16_t07: fail
-Language/07_Classes/6_Constructors/2_Factories_A01_t05: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: fail
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: fail
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: fail
@@ -78,9 +63,7 @@
Language/11_Expressions/01_Constants_A01_t01: fail
Language/11_Expressions/01_Constants_A08_t02: fail
Language/11_Expressions/01_Constants_A09_t02: fail
-Language/11_Expressions/01_Constants_A10_t03: fail
Language/11_Expressions/01_Constants_A11_t03: fail
-Language/11_Expressions/01_Constants_A11_t04: fail
Language/11_Expressions/01_Constants_A15_t07: fail
Language/11_Expressions/01_Constants_A15_t08: fail
Language/11_Expressions/01_Constants_A16_t01: fail
@@ -205,12 +188,6 @@
Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail
Language/12_Statements/02_Expression_Statements_A01_t06: fail
Language/12_Statements/02_Expression_Statements_A01_t12: fail
-Language/12_Statements/03_Variable_Declaration_A04_t01: fail
-Language/12_Statements/03_Variable_Declaration_A04_t02: fail
-Language/12_Statements/03_Variable_Declaration_A04_t05: fail
-Language/12_Statements/03_Variable_Declaration_A04_t06: fail
-Language/12_Statements/03_Variable_Declaration_A04_t07: fail
-Language/12_Statements/03_Variable_Declaration_A04_t08: fail
Language/12_Statements/04_Local_Function_Declaration_A01_t01: fail
Language/12_Statements/04_Local_Function_Declaration_A02_t02: fail
Language/12_Statements/05_If_A01_t01: fail
@@ -238,6 +215,11 @@
LibTest/core/double/ceil_A01_t05: fail
LibTest/core/double/floor_A01_t05: fail
+# co19 issue #412, using 'null' as operand
+Language/11_Expressions/01_Constants_A11_t01: fail
+Language/11_Expressions/01_Constants_A12_t01: fail
+Language/11_Expressions/01_Constants_A13_t06: fail
+
[ $runtime == drt && $compiler == none ]
*: Skip
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index b2502fa..7567121 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -332,9 +332,6 @@
Language/12_Statements/11_Return_A05_t02: Fail # Inherited from dart2js
Language/12_Statements/11_Return_A05_t03: Fail # Inherited from dart2js
Language/12_Statements/12_Labels_A01_t03: Fail # Inherited from VM (Multiple labels fail).
-Language/12_Statements/12_Labels_A03_t04: Fail # Inherited from dart2js
-Language/12_Statements/14_Continue_A02_t12: Fail # Inherited from dart2js
-Language/12_Statements/14_Continue_A02_t13: Fail # Inherited from dart2js
Language/13_Libraries_and_Scripts/1_Imports_A02_t14: Fail # Inherited from dart2js
Language/13_Libraries_and_Scripts/1_Imports_A02_t28: Fail # Inherited from dart2js
Language/13_Libraries_and_Scripts/1_Imports_A05_t01: Fail # Inherited from dart2js
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 9c16e3d..861ba7a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -5,6 +5,8 @@
[ $compiler == dart2js && $runtime == jsshell ]
LibTest/isolate/isolate_api/spawnUri_A02_t01: Crash # TODO(ahe): Please triage this crash.
+[ $compiler == dart2js && $checked && $runtime == ie9 ]
+LibTest/core/Map/Map_class_A01_t04: Slow, Pass
# Crashes first, please. Then untriaged bugs. There is a section below
# for co19 bugs.
@@ -74,20 +76,13 @@
Language/12_Statements/03_Variable_Declaration_A04_t08: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/04_Local_Function_Declaration_A01_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/04_Local_Function_Declaration_A02_t02: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/09_Switch_A02_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/09_Switch_A02_t02: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/09_Switch_A03_t01: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/09_Switch_A03_t02: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/09_Switch_A04_t01: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/09_Switch_A06_t02: Fail # TODO(ahe): Please triage this failure.
+Language/12_Statements/09_Switch_A06_t02: Fail # co19 issue 413
Language/12_Statements/10_Try_A06_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/10_Try_A07_t03: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/11_Return_A05_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/11_Return_A05_t02: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/11_Return_A05_t03: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/12_Labels_A03_t04: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/14_Continue_A02_t12: Fail # TODO(ahe): Please triage this failure.
-Language/12_Statements/14_Continue_A02_t13: Fail # TODO(ahe): Please triage this failure.
Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t03: Fail # TODO(ahe): Please triage this failure.
Language/13_Libraries_and_Scripts/1_Imports_A02_t12: Fail # TODO(ahe): Please triage this failure.
Language/13_Libraries_and_Scripts/1_Imports_A02_t14: Fail # TODO(ahe): Please triage this failure.
@@ -235,7 +230,6 @@
[ $compiler == dart2js && $checked ]
Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t03: Fail # TODO(ahe): Please triage this failure.
Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t04: Fail # TODO(ahe): Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A03_t07: Fail # TODO(ahe): Please triage this failure.
Language/07_Classes/6_Constructors/2_Factories_A06_t01: Fail # TODO(ahe): Please triage this failure.
Language/07_Classes/6_Constructors/2_Factories_A06_t02: Fail # TODO(ahe): Please triage this failure.
Language/07_Classes/6_Constructors/2_Factories_A06_t03: Fail # TODO(ahe): Please triage this failure.
@@ -246,7 +240,6 @@
Language/11_Expressions/06_Lists_A09_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/06_Lists_A09_t04: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/06_Lists_A09_t05: Fail # TODO(ahe): Please triage this failure.
-Language/11_Expressions/07_Maps_A10_t04: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/07_Maps_A10_t05: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/07_Maps_A11_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/1_New_A07_t01: Fail # TODO(ahe): Please triage this failure.
@@ -269,10 +262,8 @@
LibTest/core/AssertionError/failedAssertion_A01_t01: Fail # TODO(ahe): Please triage this failure.
LibTest/core/AssertionError/line_A01_t02: Fail # TODO(ahe): Please triage this failure.
LibTest/core/AssertionError/url_A01_t01: Fail # TODO(ahe): Please triage this failure.
-LibTest/core/Map/putIfAbsent_A01_t04: Fail # TODO(ahe): Please triage this failure.
LibTest/core/Match/pattern_A01_t01: Fail # TODO(ahe): Please triage this failure.
LibTest/core/Match/str_A01_t01: Fail # TODO(ahe): Please triage this failure.
-LibTest/core/RegExp/RegExp_A01_t02: Fail # TODO(ahe): Please triage this failure.
LibTest/core/RegExp/allMatches_A01_t01: Fail # TODO(ahe): Please triage this failure.
LibTest/core/Set/intersection_A03_t01: Fail # TODO(ahe): Please triage this failure.
LibTest/core/TypeError/column_A01_t01: Fail # TODO(ahe): Please triage this failure.
@@ -289,6 +280,7 @@
LibTest/core/List/operator_subscript_A03_t01: Fail # http://dartbug.com/9228
LibTest/core/List/operator_subscripted_assignment_A03_t01: Fail # http://dartbug.com/9228
+Language/09_Generics/09_Generics_A04_t01: Fail, OK # 1.0 is an int in dart2js; dartbug.com/1533.
Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
@@ -557,6 +549,7 @@
# Issues with co19 test suite in checked mode.
[ $compiler == dart2js && $checked ]
+Language/11_Expressions/30_Identifier_Reference_A07_t01: Fail, OK # test should be marked type-error
LibTest/core/Set/intersection_A01_t01: Fail # issue 390
LibTest/core/Set/intersection_A01_t02: Fail # issue 390
LibTest/core/Set/intersection_A01_t03: Fail # issue 390
@@ -629,6 +622,7 @@
Language/11_Expressions/30_Identifier_Reference_A02_t01: Fail # Pseudo keyword "abstract".
Language/12_Statements/06_For_A01_t11: Fail # http://dartbug.com/9824
+Language/14_Types/6_Type_dynamic_A03_t01: Fail # Renamed Date to DateTime (issue 373, 374)
[ $compiler == dart2js && $jscl ]
@@ -649,9 +643,6 @@
[ $compiler == dart2js && $jscl ]
LibTest/core/Expect/identical_A01_t01: Fail # TODO(floitsch): Is NaN identical to NaN?
-[ $compiler == dart2js && $runtime == d8 ]
-Language/14_Types/6_Type_dynamic_A03_t01: Fail # Renamed Date to DateTime (issue 373, 374)
-
[ $compiler == dart2js && ($runtime == ie10 || $runtime == ff || $runtime == chrome || $runtime == drt || $runtime == safari || $runtime == opera) ]
*: Skip
@@ -729,12 +720,6 @@
Language/07_Classes/3_Setters_A04_t06: Fail # http://dartbug.com/5023
Language/07_Classes/3_Setters_A04_t07: Fail # http://dartbug.com/5023
-Language/14_Types/4_Interface_Types_A05_t04: Fail # http://dartbug.com/5022
-Language/14_Types/4_Interface_Types_A10_t04: Fail # http://dartbug.com/5022
-Language/14_Types/4_Interface_Types_A10_t06: Fail # http://dartbug.com/5022
-Language/14_Types/4_Interface_Types_A10_t07: Fail # http://dartbug.com/5022
-Language/14_Types/4_Interface_Types_A10_t08: Fail # http://dartbug.com/5022
-Language/14_Types/4_Interface_Types_A10_t09: Fail # http://dartbug.com/5022
Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
diff --git a/tests/compiler/dart2js/lookup_member_test.dart b/tests/compiler/dart2js/lookup_member_test.dart
new file mode 100644
index 0000000..ea1d687
--- /dev/null
+++ b/tests/compiler/dart2js/lookup_member_test.dart
@@ -0,0 +1,76 @@
+// 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 subtype_test;
+
+import 'package:expect/expect.dart';
+import 'type_test_helper.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
+import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart"
+ show Element, ClassElement;
+
+void main() {
+ test();
+}
+
+void test() {
+ var env = new TypeEnvironment(r"""
+ class A<T> {
+ T foo;
+ }
+ class B<S> extends A<A<S>> {
+ S bar;
+ }
+ class C<U> extends B<String> with D<B<U>> {
+ U baz;
+ }
+ class D<V> {
+ V boz;
+ }
+ """);
+
+ void expect(DartType receiverType, String memberName, DartType expectedType) {
+ Member member = receiverType.lookupMember(env.sourceString(memberName));
+ Expect.isNotNull(member);
+ DartType memberType = member.computeType(env.compiler);
+ Expect.equals(expectedType, memberType,
+ 'Wrong member type for $receiverType.$memberName.');
+ }
+
+ DartType int_ = env['int'];
+ DartType String_ = env['String'];
+
+ ClassElement A = env.getElement('A');
+ DartType T = A.typeVariables.head;
+ DartType A_T = A.thisType;
+ expect(A_T, 'foo', T);
+
+ DartType A_int = instantiate(A, [int_]);
+ expect(A_int, 'foo', int_);
+
+ ClassElement B = env.getElement('B');
+ DartType S = B.typeVariables.head;
+ DartType B_S = B.thisType;
+ expect(B_S, 'foo', instantiate(A, [S]));
+ expect(B_S, 'bar', S);
+
+ DartType B_int = instantiate(B, [int_]);
+ expect(B_int, 'foo', A_int);
+ expect(B_int, 'bar', int_);
+
+ ClassElement C = env.getElement('C');
+ DartType U = C.typeVariables.head;
+ DartType C_U = C.thisType;
+ expect(C_U, 'foo', instantiate(A, [String_]));
+ expect(C_U, 'bar', String_);
+ expect(C_U, 'baz', U);
+ expect(C_U, 'boz', instantiate(B, [U]));
+
+ DartType C_int = instantiate(C, [int_]);
+ expect(C_int, 'foo', instantiate(A, [String_]));
+ expect(C_int, 'bar', String_);
+ expect(C_int, 'baz', int_);
+ expect(C_int, 'boz', instantiate(B, [int_]));
+}
+
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 07350f9..8e95867 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -97,6 +97,7 @@
var length;
operator[](index) {}
toString() {}
+ operator+(other) => this;
}
class JSNumber extends Interceptor implements num {
// All these methods return a number to please type inferencing.
diff --git a/tests/compiler/dart2js/parser_test.dart b/tests/compiler/dart2js/parser_test.dart
index d70fcb4..5cc7f55 100644
--- a/tests/compiler/dart2js/parser_test.dart
+++ b/tests/compiler/dart2js/parser_test.dart
@@ -306,6 +306,18 @@
Expect.throws(parse, check);
}
+void testUnmatchedAngleBracket() {
+ final String source = 'A<'; // unmatched '<'
+ parse() {
+ fullParseUnit(source, diagnosticHandler: new Collector());
+ }
+ check(Collector c) {
+ Expect.equals(LT_TOKEN, c.token);
+ return true;
+ }
+ Expect.throws(parse, check);
+}
+
void main() {
testGenericTypes();
// TODO(ahe): Enable this test when we handle library prefixes.
@@ -322,4 +334,5 @@
testOperatorParse();
testMissingCloseParen();
testMissingCloseBraceInClass();
+ testUnmatchedAngleBracket();
}
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart
index f2fa92a..1d33715 100644
--- a/tests/compiler/dart2js/patch_test.dart
+++ b/tests/compiler/dart2js/patch_test.dart
@@ -305,6 +305,9 @@
external void method6({String str});
external void method7([String s1]);
external void method8({String s1});
+ external void method9(String str);
+ external void method10([String str]);
+ external void method11({String str});
}
""",
"""
@@ -317,6 +320,9 @@
patch void method6([String str]) {}
patch void method7([String s2]) {}
patch void method8({String s2}) {}
+ patch void method9(int str) {}
+ patch void method10([int str]) {}
+ patch void method11({int str}) {}
}
""");
var container = ensure(compiler, "Class", compiler.coreLibrary.find,
@@ -324,83 +330,41 @@
container.ensureResolved(compiler);
container.parseNode(compiler);
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method1", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method1:${compiler.errors}');
+ void expect(String methodName, List warnings, List errors) {
+ compiler.warnings.clear();
+ compiler.errors.clear();
+ compiler.resolver.resolveMethodElement(
+ ensure(compiler, methodName, container.lookupLocalMember,
+ expectIsPatched: true, checkHasBody: true));
+ Expect.equals(warnings.length, compiler.warnings.length,
+ "Unexpected warnings: ${compiler.warnings} on $methodName");
+ for (int i = 0 ; i < warnings.length ; i++) {
+ Expect.equals(warnings[i], compiler.warnings[i].message.kind);
+ }
+ Expect.equals(errors.length, compiler.errors.length,
+ "Unexpected errors: ${compiler.errors} on $methodName");
+ for (int i = 0 ; i < errors.length ; i++) {
+ Expect.equals(errors[i], compiler.errors[i].message.kind);
+ }
+ }
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method2", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method2:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method3", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method3:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method4", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method4:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method5", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method5:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method6", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method6:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method7", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method7:${compiler.errors}');
-
- compiler.warnings.clear();
- compiler.errors.clear();
- compiler.resolver.resolveMethodElement(
- ensure(compiler, "method8", container.lookupLocalMember,
- expectIsPatched: true, checkHasBody: true));
- Expect.isTrue(compiler.warnings.isEmpty,
- "Unexpected warnings: ${compiler.warnings}");
- Expect.isFalse(compiler.errors.isEmpty);
- print('method8:${compiler.errors}');
+ expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]);
+ expect("method2", [], [MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]);
+ expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method4", [], [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
+ expect("method5", [], [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]);
+ expect("method6", [], [MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]);
+ expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_MISMATCH]);
+ expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
+ expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
+ expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER],
+ [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]);
}
testExternalWithoutImplementationTopLevel() {
diff --git a/tests/compiler/dart2js/resolution_test.dart b/tests/compiler/dart2js/resolution_test.dart
index 9382159..c1a327f 100644
--- a/tests/compiler/dart2js/resolution_test.dart
+++ b/tests/compiler/dart2js/resolution_test.dart
@@ -39,6 +39,7 @@
print(new prefix.DateTime(0));
print(new prefix.DateTime.utc(0));
prefix.DateTime c = new prefix.DateTime(0);
+ A.bar = 0;
}
""";
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index b9f6723..485896c 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -83,16 +83,189 @@
return 42.abs(42);
}
+testIsCheck1(a) {
+ if (a is int) {
+ return a;
+ } else {
+ return 42;
+ }
+}
+
+testIsCheck2(a) {
+ if (a is !int) {
+ return 0;
+ } else {
+ return a;
+ }
+}
+
+testIsCheck3(a) {
+ if (a is !int) {
+ print('hello');
+ } else {
+ return a;
+ }
+}
+
+testIsCheck4(a) {
+ if (a is int) {
+ return a;
+ } else {
+ return 42;
+ }
+}
+
+testIsCheck5(a) {
+ if (a is !int) {
+ return 42;
+ } else {
+ return a;
+ }
+}
+
+testIsCheck6(a) {
+ if (a is !int) {
+ return a;
+ } else {
+ return 42;
+ }
+}
+
+testIsCheck7(a) {
+ if (a == 'foo' && a is int) {
+ return a;
+ } else {
+ return 42;
+ }
+}
+
+testIsCheck8(a) {
+ if (a == 'foo' || a is int) {
+ return a;
+ } else {
+ return 42;
+ }
+}
+
+testIsCheck9(a) {
+ return a is int ? a : 42;
+}
+
+testIsCheck10(a) {
+ return a is !int ? a : 42;
+}
+
+testIsCheck11(a) {
+ return a is !int ? 42 : a;
+}
+
+testIsCheck12(a) {
+ return a is int ? 42 : a;
+}
+
+testIsCheck13(a) {
+ while (a is int) {
+ return a;
+ }
+ return 42;
+}
+
+testIsCheck14(a) {
+ while (a is !int) {
+ return 42;
+ }
+ return a;
+}
+
+testIsCheck15(a) {
+ var c = 42;
+ do {
+ if (a) return c;
+ c = topLevelGetter();
+ } while (c is int);
+ return 42;
+}
+
+testIsCheck16(a) {
+ var c = 42;
+ do {
+ if (a) return c;
+ c = topLevelGetter();
+ } while (c is !int);
+ return 42;
+}
+
+testIsCheck17(a) {
+ var c = 42;
+ for (; c is int;) {
+ if (a) return c;
+ c = topLevelGetter();
+ }
+ return 42;
+}
+
+testIsCheck18(a) {
+ var c = 42;
+ for (; c is int;) {
+ if (a) return c;
+ c = topLevelGetter();
+ }
+ return c;
+}
+
+testIsCheck19(a) {
+ var c = 42;
+ for (; c is !int;) {
+ if (a) return c;
+ c = topLevelGetter();
+ }
+ return 42;
+}
+
returnAsString() {
return topLevelGetter() as String;
}
+returnIntAsNum() {
+ return 0 as num;
+}
+
typedef int Foo();
returnAsTypedef() {
return topLevelGetter() as Foo;
}
+testSwitch1() {
+ var a = null;
+ switch (topLevelGetter) {
+ case 100: a = 42.5; break;
+ case 200: a = 42; break;
+ }
+ return a;
+}
+
+testSwitch2() {
+ var a = null;
+ switch (topLevelGetter) {
+ case 100: a = 42; break;
+ case 200: a = 42; break;
+ default:
+ a = 43;
+ }
+ return a;
+}
+
+testSwitch3() {
+ var a = 42;
+ var b;
+ switch (topLevelGetter) {
+ L1: case 1: b = a + 42; break;
+ case 2: a = 'foo'; continue L1;
+ }
+ return b;
+}
+
get topLevelGetter => 42;
returnDynamic() => topLevelGetter(42);
@@ -142,8 +315,31 @@
returnDynamic();
returnDynamic1();
returnDynamic2();
+ testIsCheck1(topLevelGetter());
+ testIsCheck2(topLevelGetter());
+ testIsCheck3(topLevelGetter());
+ testIsCheck4(topLevelGetter());
+ testIsCheck5(topLevelGetter());
+ testIsCheck6(topLevelGetter());
+ testIsCheck7(topLevelGetter());
+ testIsCheck8(topLevelGetter());
+ testIsCheck9(topLevelGetter());
+ testIsCheck10(topLevelGetter());
+ testIsCheck11(topLevelGetter());
+ testIsCheck12(topLevelGetter());
+ testIsCheck13(topLevelGetter());
+ testIsCheck14(topLevelGetter());
+ testIsCheck15(topLevelGetter());
+ testIsCheck16(topLevelGetter());
+ testIsCheck17(topLevelGetter());
+ testIsCheck18(topLevelGetter());
+ testIsCheck19(topLevelGetter());
returnAsString();
+ returnIntAsNum();
returnAsTypedef();
+ testSwitch1();
+ testSwitch2();
+ testSwitch3();
new A() == null;
new A()..returnInt1()
..returnInt2()
@@ -192,9 +388,34 @@
checkReturn('returnInt8', typesInferrer.intType);
checkReturn('returnDynamic1', typesInferrer.dynamicType);
checkReturn('returnDynamic2', typesInferrer.dynamicType);
+ TypeMask intType = new TypeMask.nonNullSubtype(compiler.intClass.rawType);
+ checkReturn('testIsCheck1', intType);
+ checkReturn('testIsCheck2', intType);
+ checkReturn('testIsCheck3', intType.nullable());
+ checkReturn('testIsCheck4', intType);
+ checkReturn('testIsCheck5', intType);
+ checkReturn('testIsCheck6', typesInferrer.dynamicType);
+ checkReturn('testIsCheck7', intType);
+ checkReturn('testIsCheck8', typesInferrer.dynamicType);
+ checkReturn('testIsCheck9', intType);
+ checkReturn('testIsCheck10', typesInferrer.dynamicType);
+ checkReturn('testIsCheck11', intType);
+ checkReturn('testIsCheck12', typesInferrer.dynamicType);
+ checkReturn('testIsCheck13', intType);
+ checkReturn('testIsCheck14', typesInferrer.dynamicType);
+ checkReturn('testIsCheck15', intType);
+ checkReturn('testIsCheck16', typesInferrer.dynamicType);
+ checkReturn('testIsCheck17', intType);
+ checkReturn('testIsCheck18', typesInferrer.dynamicType);
+ checkReturn('testIsCheck19', typesInferrer.dynamicType);
checkReturn('returnAsString',
new TypeMask.subtype(compiler.stringClass.computeType(compiler)));
+ checkReturn('returnIntAsNum', typesInferrer.intType);
checkReturn('returnAsTypedef', typesInferrer.functionType.nullable());
+ checkReturn('testSwitch1',
+ typesInferrer.intType.union(typesInferrer.doubleType, compiler).nullable());
+ checkReturn('testSwitch2', typesInferrer.intType);
+ checkReturn('testSwitch3', interceptorType.nullable());
checkReturnInClass(String className, String methodName, type) {
var cls = findElement(compiler, className);
diff --git a/tests/compiler/dart2js/source_mapping_test.dart b/tests/compiler/dart2js/source_mapping_test.dart
index 043665f..6b47737 100644
--- a/tests/compiler/dart2js/source_mapping_test.dart
+++ b/tests/compiler/dart2js/source_mapping_test.dart
@@ -67,7 +67,7 @@
String SEND_TEST = '''
void main() {
@staticSend(0);
- NewSend o = new @NewSend();
+ NewSend o = @new NewSend();
@o.dynamicSend(0);
var closureSend = (x) { print(x); };
@closureSend(0);
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index c253aa9..7f1eaa22 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -57,7 +57,7 @@
}
DartType getMemberType(ClassElement element, String name) {
- Element member = element.localLookup(new SourceString(name));
+ Element member = element.localLookup(sourceString(name));
return member.computeType(compiler);
}
@@ -65,6 +65,8 @@
return compiler.types.isSubtype(T, S);
}
+ SourceString sourceString(String name) => new SourceString(name);
+
FunctionType functionType(DartType returnType,
List<DartType> parameters,
{List<DartType> optionalParameter,
@@ -78,7 +80,7 @@
var namedParameterTypes = new LinkBuilder<DartType>();
if (namedParameters != null) {
namedParameters.forEach((String name, DartType type) {
- namedParameterNames.addLast(new SourceString(name));
+ namedParameterNames.addLast(sourceString(name));
namedParameterTypes.addLast(type);
});
}
diff --git a/tests/compiler/dart2js/value_range2_test.dart b/tests/compiler/dart2js/value_range2_test.dart
index 7b8cc8b..3b5bfeb 100644
--- a/tests/compiler/dart2js/value_range2_test.dart
+++ b/tests/compiler/dart2js/value_range2_test.dart
@@ -9,8 +9,8 @@
ValueRangeInfo info = new ValueRangeInfo(const JavaScriptConstantSystem());
-Value instructionValue = info.newInstructionValue(new HReturn(null));
-Value lengthValue = info.newLengthValue(new HReturn(null));
+Value instructionValue = info.newInstructionValue(new HBreak(null));
+Value lengthValue = info.newLengthValue(new HBreak(null));
Range createSingleRange(Value value) => info.newNormalizedRange(value, value);
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 73703bd..dc4effa 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -33,8 +33,8 @@
to_string_test: Fail # Issue 7179.
runtime_type_test: Fail, OK # Tests extected output of Type.toString().
-# Mirrors do not work with minification.
-mirror_test: Fail # Issue 6490.
+mirror_test: Fail # http://dartbug.com/6490
+mirrors_test: Fail # http://dartbug.com/6490
[ $jscl ]
timer_test: Fail # Issue 7728.
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
index 97b18ee..14bb1e6 100644
--- a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
+++ b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
@@ -14,3 +14,10 @@
return (x - 3) ~/ 2;
}
}
+
+class Constant {
+ final value;
+ const Constant(this.value);
+
+ operator==(other) => other is Constant && value == other.value;
+}
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
index f27bf45..87728934 100644
--- a/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
+++ b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
@@ -11,8 +11,9 @@
main() {
var x;
- // TODO(ahe): What are the semantics of this:
- // x = const MyClass();
+ Expect.isNull(const MyClass());
+ Expect.isNull(const Constant(42));
+ Expect.isNull(const [const Constant(42)]);
Expect.isNull(x);
int counter = 0;
lazy.load().then((bool didLoad) {
@@ -21,6 +22,7 @@
print('deferred_class_library was loaded');
x = const MyClass();
Expect.equals(42, x.foo(87));
+ Expect.listEquals(const [const Constant(42)], [new Constant(42)]);
});
Expect.equals(0, counter);
Expect.isNull(x);
@@ -30,10 +32,11 @@
print('deferred_class_library was loaded');
x = const MyClass();
Expect.equals(42, x.foo(87));
+ Expect.listEquals(const [const Constant(42)], [new Constant(42)]);
});
Expect.equals(0, counter);
Expect.isNull(x);
- // TODO(ahe): What are the semantics of this:
- // x = const MyClass();
+ Expect.isNull(const Constant(42));
+ Expect.isNull(const [const Constant(42)]);
Expect.isNull(x);
}
diff --git a/tests/compiler/dart2js_extra/mirror_test.dart b/tests/compiler/dart2js_extra/mirror_test.dart
index 79de2b8..dbc2b46 100644
--- a/tests/compiler/dart2js_extra/mirror_test.dart
+++ b/tests/compiler/dart2js_extra/mirror_test.dart
@@ -14,7 +14,12 @@
print('mirror.type: ${mirror.type}');
print('now.toUtc(): ${now.toUtc()}');
- mirror.invokeAsync("toUtc", []).then((value) {
+ var value = mirror.invoke(const Symbol("toUtc"), []);
+ print('mirror.invoke("toUtc", []): $value');
+ Expect.isTrue(value.hasReflectee);
+ Expect.equals(now.toUtc(), value.reflectee);
+
+ mirror.invokeAsync(const Symbol("toUtc"), []).then((value) {
print('mirror.invokeAsync("toUtc", []): $value');
Expect.isTrue(value.hasReflectee);
Expect.equals(now.toUtc(), value.reflectee);
@@ -23,18 +28,5 @@
}
void main() {
- reflect("""
-
-This program is using an experimental feature called \"mirrors\". As
-currently implemented, mirrors do not work with minification, and will
-cause spurious errors depending on how code was optimized.
-
-The authors of this program are aware of these problems and have
-decided the thrill of using an experimental feature is outweighing the
-risks. Furthermore, the authors of this program understand that
-long-term, to fix the problems mentioned above, mirrors may have
-negative impact on size and performance of Dart programs compiled to
-JavaScript.
-""");
asyncTest(test);
}
diff --git a/tests/compiler/dart2js_extra/mirrors_test.dart b/tests/compiler/dart2js_extra/mirrors_test.dart
new file mode 100644
index 0000000..d9df6c5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/mirrors_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This test should be removed when dart2js can pass all mirror tests.
+// TODO(ahe): Remove this test.
+
+import '../../lib/mirrors/mirrors_test.dart';
+
+main() {
+ mainWithArgument(isDart2js: true);
+}
diff --git a/tests/compiler/dart2js_extra/switch_test.dart b/tests/compiler/dart2js_extra/switch_test.dart
index c6190e4..6c5a798 100644
--- a/tests/compiler/dart2js_extra/switch_test.dart
+++ b/tests/compiler/dart2js_extra/switch_test.dart
@@ -50,7 +50,7 @@
break;
} else {
// Enable when continue to switch-case is implemented.
- continue hest; /// 03: compile-time error
+ continue hest;
}
}
}
diff --git a/tests/compiler/dart2js_native/dart2js_native.status b/tests/compiler/dart2js_native/dart2js_native.status
index 1315cac..9af392c 100644
--- a/tests/compiler/dart2js_native/dart2js_native.status
+++ b/tests/compiler/dart2js_native/dart2js_native.status
@@ -9,6 +9,3 @@
native_null_closure_frog_test: Fail
native_no_such_method_exception4_frog_test: Fail # Issue 9631
native_no_such_method_exception5_frog_test: Fail # Issue 9631
-
-[ $compiler == dart2js && $checked ]
-native_no_such_method_exception3_frog_test: Fail # TODO(ahe): investigate.
diff --git a/tests/compiler/dart2js_native/oddly_named_fields_test.dart b/tests/compiler/dart2js_native/oddly_named_fields_test.dart
new file mode 100644
index 0000000..6ade208
--- /dev/null
+++ b/tests/compiler/dart2js_native/oddly_named_fields_test.dart
@@ -0,0 +1,1387 @@
+// 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 'dart:_js_helper';
+
+// JavaScript reserved words:
+//
+// break
+// case
+// catch
+// class
+// const
+// continue
+// debugger
+// default
+// delete
+// do
+// else
+// enum
+// export
+// extends
+// false
+// finally
+// for
+// function
+// if
+// implements
+// import
+// in
+// instanceof
+// interface
+// let
+// new
+// null
+// package
+// private
+// protected
+// public
+// return
+// static
+// super
+// switch
+// this
+// throw
+// true
+// try
+// typeof
+// var
+// void
+// while
+// with
+// yield
+//
+// Funny thing in JavaScript: there are two syntactic categories:
+// "Identifier" and "IdentifierName". The latter includes reserved
+// words. This is legal JavaScript according to ECMA-262.5:
+//
+// this.default
+//
+// See section 11.2 "Left-Hand-Side Expressions" which states that a
+// "MemberExpression" includes: "MemberExpression . IdentifierName".
+
+class NativeClassWithOddNames native "NativeClassWithOddNames" {
+ @JSName('break') bool breakValue;
+ @JSName('case') bool caseValue;
+ @JSName('catch') bool catchValue;
+ @JSName('class') bool classValue;
+ @JSName('const') bool constValue;
+ @JSName('continue') bool continueValue;
+ @JSName('debugger') bool debuggerValue;
+ @JSName('default') bool defaultValue;
+ @JSName('delete') bool deleteValue;
+ @JSName('do') bool doValue;
+ @JSName('else') bool elseValue;
+ @JSName('enum') bool enumValue;
+ @JSName('export') bool exportValue;
+ @JSName('extends') bool extendsValue;
+ @JSName('false') bool falseValue;
+ @JSName('finally') bool finallyValue;
+ @JSName('for') bool forValue;
+ @JSName('function') bool functionValue;
+ @JSName('if') bool ifValue;
+ @JSName('implements') bool implementsValue;
+ @JSName('import') bool importValue;
+ @JSName('in') bool inValue;
+ @JSName('instanceof') bool instanceofValue;
+ @JSName('interface') bool interfaceValue;
+ @JSName('let') bool letValue;
+ @JSName('new') bool newValue;
+ @JSName('null') bool nullValue;
+ @JSName('package') bool packageValue;
+ @JSName('private') bool privateValue;
+ @JSName('protected') bool protectedValue;
+ @JSName('public') bool publicValue;
+ @JSName('return') bool returnValue;
+ @JSName('static') bool staticValue;
+ @JSName('super') bool superValue;
+ @JSName('switch') bool switchValue;
+ @JSName('this') bool thisValue;
+ @JSName('throw') bool throwValue;
+ @JSName('true') bool trueValue;
+ @JSName('try') bool tryValue;
+ @JSName('typeof') bool typeofValue;
+ @JSName('var') bool varValue;
+ @JSName('void') bool voidValue;
+ @JSName('while') bool whileValue;
+ @JSName('with') bool withValue;
+ @JSName('yield') bool yieldValue;
+
+ void testMyFields() {
+
+ if (breakValue != null) throw 'incorrect initialization of "breakValue"';
+ breakValue = true;
+ if (!breakValue) throw 'incorrect value in "breakValue"';
+ breakValue = false;
+ if (breakValue) throw 'incorrect value in "breakValue"';
+
+ if (caseValue != null) throw 'incorrect initialization of "caseValue"';
+ caseValue = true;
+ if (!caseValue) throw 'incorrect value in "caseValue"';
+ caseValue = false;
+ if (caseValue) throw 'incorrect value in "caseValue"';
+
+ if (catchValue != null) throw 'incorrect initialization of "catchValue"';
+ catchValue = true;
+ if (!catchValue) throw 'incorrect value in "catchValue"';
+ catchValue = false;
+ if (catchValue) throw 'incorrect value in "catchValue"';
+
+ if (classValue != null) throw 'incorrect initialization of "classValue"';
+ classValue = true;
+ if (!classValue) throw 'incorrect value in "classValue"';
+ classValue = false;
+ if (classValue) throw 'incorrect value in "classValue"';
+
+ if (constValue != null) throw 'incorrect initialization of "constValue"';
+ constValue = true;
+ if (!constValue) throw 'incorrect value in "constValue"';
+ constValue = false;
+ if (constValue) throw 'incorrect value in "constValue"';
+
+ if (continueValue != null)
+ throw 'incorrect initialization of "continueValue"';
+ continueValue = true;
+ if (!continueValue) throw 'incorrect value in "continueValue"';
+ continueValue = false;
+ if (continueValue) throw 'incorrect value in "continueValue"';
+
+ if (debuggerValue != null)
+ throw 'incorrect initialization of "debuggerValue"';
+ debuggerValue = true;
+ if (!debuggerValue) throw 'incorrect value in "debuggerValue"';
+ debuggerValue = false;
+ if (debuggerValue) throw 'incorrect value in "debuggerValue"';
+
+ if (defaultValue != null)
+ throw 'incorrect initialization of "defaultValue"';
+ defaultValue = true;
+ if (!defaultValue) throw 'incorrect value in "defaultValue"';
+ defaultValue = false;
+ if (defaultValue) throw 'incorrect value in "defaultValue"';
+
+ if (deleteValue != null) throw 'incorrect initialization of "deleteValue"';
+ deleteValue = true;
+ if (!deleteValue) throw 'incorrect value in "deleteValue"';
+ deleteValue = false;
+ if (deleteValue) throw 'incorrect value in "deleteValue"';
+
+ if (doValue != null) throw 'incorrect initialization of "doValue"';
+ doValue = true;
+ if (!doValue) throw 'incorrect value in "doValue"';
+ doValue = false;
+ if (doValue) throw 'incorrect value in "doValue"';
+
+ if (elseValue != null) throw 'incorrect initialization of "elseValue"';
+ elseValue = true;
+ if (!elseValue) throw 'incorrect value in "elseValue"';
+ elseValue = false;
+ if (elseValue) throw 'incorrect value in "elseValue"';
+
+ if (enumValue != null) throw 'incorrect initialization of "enumValue"';
+ enumValue = true;
+ if (!enumValue) throw 'incorrect value in "enumValue"';
+ enumValue = false;
+ if (enumValue) throw 'incorrect value in "enumValue"';
+
+ if (exportValue != null) throw 'incorrect initialization of "exportValue"';
+ exportValue = true;
+ if (!exportValue) throw 'incorrect value in "exportValue"';
+ exportValue = false;
+ if (exportValue) throw 'incorrect value in "exportValue"';
+
+ if (extendsValue != null)
+ throw 'incorrect initialization of "extendsValue"';
+ extendsValue = true;
+ if (!extendsValue) throw 'incorrect value in "extendsValue"';
+ extendsValue = false;
+ if (extendsValue) throw 'incorrect value in "extendsValue"';
+
+ if (falseValue != null) throw 'incorrect initialization of "falseValue"';
+ falseValue = true;
+ if (!falseValue) throw 'incorrect value in "falseValue"';
+ falseValue = false;
+ if (falseValue) throw 'incorrect value in "falseValue"';
+
+ if (finallyValue != null)
+ throw 'incorrect initialization of "finallyValue"';
+ finallyValue = true;
+ if (!finallyValue) throw 'incorrect value in "finallyValue"';
+ finallyValue = false;
+ if (finallyValue) throw 'incorrect value in "finallyValue"';
+
+ if (forValue != null) throw 'incorrect initialization of "forValue"';
+ forValue = true;
+ if (!forValue) throw 'incorrect value in "forValue"';
+ forValue = false;
+ if (forValue) throw 'incorrect value in "forValue"';
+
+ if (functionValue != null)
+ throw 'incorrect initialization of "functionValue"';
+ functionValue = true;
+ if (!functionValue) throw 'incorrect value in "functionValue"';
+ functionValue = false;
+ if (functionValue) throw 'incorrect value in "functionValue"';
+
+ if (ifValue != null) throw 'incorrect initialization of "ifValue"';
+ ifValue = true;
+ if (!ifValue) throw 'incorrect value in "ifValue"';
+ ifValue = false;
+ if (ifValue) throw 'incorrect value in "ifValue"';
+
+ if (implementsValue != null)
+ throw 'incorrect initialization of "implementsValue"';
+ implementsValue = true;
+ if (!implementsValue) throw 'incorrect value in "implementsValue"';
+ implementsValue = false;
+ if (implementsValue) throw 'incorrect value in "implementsValue"';
+
+ if (importValue != null) throw 'incorrect initialization of "importValue"';
+ importValue = true;
+ if (!importValue) throw 'incorrect value in "importValue"';
+ importValue = false;
+ if (importValue) throw 'incorrect value in "importValue"';
+
+ if (inValue != null) throw 'incorrect initialization of "inValue"';
+ inValue = true;
+ if (!inValue) throw 'incorrect value in "inValue"';
+ inValue = false;
+ if (inValue) throw 'incorrect value in "inValue"';
+
+ if (instanceofValue != null)
+ throw 'incorrect initialization of "instanceofValue"';
+ instanceofValue = true;
+ if (!instanceofValue) throw 'incorrect value in "instanceofValue"';
+ instanceofValue = false;
+ if (instanceofValue) throw 'incorrect value in "instanceofValue"';
+
+ if (interfaceValue != null)
+ throw 'incorrect initialization of "interfaceValue"';
+ interfaceValue = true;
+ if (!interfaceValue) throw 'incorrect value in "interfaceValue"';
+ interfaceValue = false;
+ if (interfaceValue) throw 'incorrect value in "interfaceValue"';
+
+ if (letValue != null) throw 'incorrect initialization of "letValue"';
+ letValue = true;
+ if (!letValue) throw 'incorrect value in "letValue"';
+ letValue = false;
+ if (letValue) throw 'incorrect value in "letValue"';
+
+ if (newValue != null) throw 'incorrect initialization of "newValue"';
+ newValue = true;
+ if (!newValue) throw 'incorrect value in "newValue"';
+ newValue = false;
+ if (newValue) throw 'incorrect value in "newValue"';
+
+ if (nullValue != null) throw 'incorrect initialization of "nullValue"';
+ nullValue = true;
+ if (!nullValue) throw 'incorrect value in "nullValue"';
+ nullValue = false;
+ if (nullValue) throw 'incorrect value in "nullValue"';
+
+ if (packageValue != null)
+ throw 'incorrect initialization of "packageValue"';
+ packageValue = true;
+ if (!packageValue) throw 'incorrect value in "packageValue"';
+ packageValue = false;
+ if (packageValue) throw 'incorrect value in "packageValue"';
+
+ if (privateValue != null)
+ throw 'incorrect initialization of "privateValue"';
+ privateValue = true;
+ if (!privateValue) throw 'incorrect value in "privateValue"';
+ privateValue = false;
+ if (privateValue) throw 'incorrect value in "privateValue"';
+
+ if (protectedValue != null)
+ throw 'incorrect initialization of "protectedValue"';
+ protectedValue = true;
+ if (!protectedValue) throw 'incorrect value in "protectedValue"';
+ protectedValue = false;
+ if (protectedValue) throw 'incorrect value in "protectedValue"';
+
+ if (publicValue != null) throw 'incorrect initialization of "publicValue"';
+ publicValue = true;
+ if (!publicValue) throw 'incorrect value in "publicValue"';
+ publicValue = false;
+ if (publicValue) throw 'incorrect value in "publicValue"';
+
+ if (returnValue != null) throw 'incorrect initialization of "returnValue"';
+ returnValue = true;
+ if (!returnValue) throw 'incorrect value in "returnValue"';
+ returnValue = false;
+ if (returnValue) throw 'incorrect value in "returnValue"';
+
+ if (staticValue != null) throw 'incorrect initialization of "staticValue"';
+ staticValue = true;
+ if (!staticValue) throw 'incorrect value in "staticValue"';
+ staticValue = false;
+ if (staticValue) throw 'incorrect value in "staticValue"';
+
+ if (superValue != null) throw 'incorrect initialization of "superValue"';
+ superValue = true;
+ if (!superValue) throw 'incorrect value in "superValue"';
+ superValue = false;
+ if (superValue) throw 'incorrect value in "superValue"';
+
+ if (switchValue != null) throw 'incorrect initialization of "switchValue"';
+ switchValue = true;
+ if (!switchValue) throw 'incorrect value in "switchValue"';
+ switchValue = false;
+ if (switchValue) throw 'incorrect value in "switchValue"';
+
+ if (thisValue != null) throw 'incorrect initialization of "thisValue"';
+ thisValue = true;
+ if (!thisValue) throw 'incorrect value in "thisValue"';
+ thisValue = false;
+ if (thisValue) throw 'incorrect value in "thisValue"';
+
+ if (throwValue != null) throw 'incorrect initialization of "throwValue"';
+ throwValue = true;
+ if (!throwValue) throw 'incorrect value in "throwValue"';
+ throwValue = false;
+ if (throwValue) throw 'incorrect value in "throwValue"';
+
+ if (trueValue != null) throw 'incorrect initialization of "trueValue"';
+ trueValue = true;
+ if (!trueValue) throw 'incorrect value in "trueValue"';
+ trueValue = false;
+ if (trueValue) throw 'incorrect value in "trueValue"';
+
+ if (tryValue != null) throw 'incorrect initialization of "tryValue"';
+ tryValue = true;
+ if (!tryValue) throw 'incorrect value in "tryValue"';
+ tryValue = false;
+ if (tryValue) throw 'incorrect value in "tryValue"';
+
+ if (typeofValue != null) throw 'incorrect initialization of "typeofValue"';
+ typeofValue = true;
+ if (!typeofValue) throw 'incorrect value in "typeofValue"';
+ typeofValue = false;
+ if (typeofValue) throw 'incorrect value in "typeofValue"';
+
+ if (varValue != null) throw 'incorrect initialization of "varValue"';
+ varValue = true;
+ if (!varValue) throw 'incorrect value in "varValue"';
+ varValue = false;
+ if (varValue) throw 'incorrect value in "varValue"';
+
+ if (voidValue != null) throw 'incorrect initialization of "voidValue"';
+ voidValue = true;
+ if (!voidValue) throw 'incorrect value in "voidValue"';
+ voidValue = false;
+ if (voidValue) throw 'incorrect value in "voidValue"';
+
+ if (whileValue != null) throw 'incorrect initialization of "whileValue"';
+ whileValue = true;
+ if (!whileValue) throw 'incorrect value in "whileValue"';
+ whileValue = false;
+ if (whileValue) throw 'incorrect value in "whileValue"';
+
+ if (withValue != null) throw 'incorrect initialization of "withValue"';
+ withValue = true;
+ if (!withValue) throw 'incorrect value in "withValue"';
+ withValue = false;
+ if (withValue) throw 'incorrect value in "withValue"';
+
+ if (yieldValue != null) throw 'incorrect initialization of "yieldValue"';
+ yieldValue = true;
+ if (!yieldValue) throw 'incorrect value in "yieldValue"';
+ yieldValue = false;
+ if (yieldValue) throw 'incorrect value in "yieldValue"';
+
+ }
+}
+
+class ClassWithOddNames {
+ bool breakValue;
+ bool caseValue;
+ bool catchValue;
+ bool classValue;
+ bool constValue;
+ bool continueValue;
+ bool debuggerValue;
+ bool defaultValue;
+ bool deleteValue;
+ bool doValue;
+ bool elseValue;
+ bool enumValue;
+ bool exportValue;
+ bool extendsValue;
+ bool falseValue;
+ bool finallyValue;
+ bool forValue;
+ bool functionValue;
+ bool ifValue;
+ bool implementsValue;
+ bool importValue;
+ bool inValue;
+ bool instanceofValue;
+ bool interfaceValue;
+ bool letValue;
+ bool newValue;
+ bool nullValue;
+ bool packageValue;
+ bool privateValue;
+ bool protectedValue;
+ bool publicValue;
+ bool returnValue;
+ bool staticValue;
+ bool superValue;
+ bool switchValue;
+ bool thisValue;
+ bool throwValue;
+ bool trueValue;
+ bool tryValue;
+ bool typeofValue;
+ bool varValue;
+ bool voidValue;
+ bool whileValue;
+ bool withValue;
+ bool yieldValue;
+
+ void testMyFields() {
+
+ if (breakValue != null) throw 'incorrect initialization of "breakValue"';
+ breakValue = true;
+ if (!breakValue) throw 'incorrect value in "breakValue"';
+ breakValue = false;
+ if (breakValue) throw 'incorrect value in "breakValue"';
+
+ if (caseValue != null) throw 'incorrect initialization of "caseValue"';
+ caseValue = true;
+ if (!caseValue) throw 'incorrect value in "caseValue"';
+ caseValue = false;
+ if (caseValue) throw 'incorrect value in "caseValue"';
+
+ if (catchValue != null) throw 'incorrect initialization of "catchValue"';
+ catchValue = true;
+ if (!catchValue) throw 'incorrect value in "catchValue"';
+ catchValue = false;
+ if (catchValue) throw 'incorrect value in "catchValue"';
+
+ if (classValue != null) throw 'incorrect initialization of "classValue"';
+ classValue = true;
+ if (!classValue) throw 'incorrect value in "classValue"';
+ classValue = false;
+ if (classValue) throw 'incorrect value in "classValue"';
+
+ if (constValue != null) throw 'incorrect initialization of "constValue"';
+ constValue = true;
+ if (!constValue) throw 'incorrect value in "constValue"';
+ constValue = false;
+ if (constValue) throw 'incorrect value in "constValue"';
+
+ if (continueValue != null)
+ throw 'incorrect initialization of "continueValue"';
+ continueValue = true;
+ if (!continueValue) throw 'incorrect value in "continueValue"';
+ continueValue = false;
+ if (continueValue) throw 'incorrect value in "continueValue"';
+
+ if (debuggerValue != null)
+ throw 'incorrect initialization of "debuggerValue"';
+ debuggerValue = true;
+ if (!debuggerValue) throw 'incorrect value in "debuggerValue"';
+ debuggerValue = false;
+ if (debuggerValue) throw 'incorrect value in "debuggerValue"';
+
+ if (defaultValue != null)
+ throw 'incorrect initialization of "defaultValue"';
+ defaultValue = true;
+ if (!defaultValue) throw 'incorrect value in "defaultValue"';
+ defaultValue = false;
+ if (defaultValue) throw 'incorrect value in "defaultValue"';
+
+ if (deleteValue != null) throw 'incorrect initialization of "deleteValue"';
+ deleteValue = true;
+ if (!deleteValue) throw 'incorrect value in "deleteValue"';
+ deleteValue = false;
+ if (deleteValue) throw 'incorrect value in "deleteValue"';
+
+ if (doValue != null) throw 'incorrect initialization of "doValue"';
+ doValue = true;
+ if (!doValue) throw 'incorrect value in "doValue"';
+ doValue = false;
+ if (doValue) throw 'incorrect value in "doValue"';
+
+ if (elseValue != null) throw 'incorrect initialization of "elseValue"';
+ elseValue = true;
+ if (!elseValue) throw 'incorrect value in "elseValue"';
+ elseValue = false;
+ if (elseValue) throw 'incorrect value in "elseValue"';
+
+ if (enumValue != null) throw 'incorrect initialization of "enumValue"';
+ enumValue = true;
+ if (!enumValue) throw 'incorrect value in "enumValue"';
+ enumValue = false;
+ if (enumValue) throw 'incorrect value in "enumValue"';
+
+ if (exportValue != null) throw 'incorrect initialization of "exportValue"';
+ exportValue = true;
+ if (!exportValue) throw 'incorrect value in "exportValue"';
+ exportValue = false;
+ if (exportValue) throw 'incorrect value in "exportValue"';
+
+ if (extendsValue != null)
+ throw 'incorrect initialization of "extendsValue"';
+ extendsValue = true;
+ if (!extendsValue) throw 'incorrect value in "extendsValue"';
+ extendsValue = false;
+ if (extendsValue) throw 'incorrect value in "extendsValue"';
+
+ if (falseValue != null) throw 'incorrect initialization of "falseValue"';
+ falseValue = true;
+ if (!falseValue) throw 'incorrect value in "falseValue"';
+ falseValue = false;
+ if (falseValue) throw 'incorrect value in "falseValue"';
+
+ if (finallyValue != null)
+ throw 'incorrect initialization of "finallyValue"';
+ finallyValue = true;
+ if (!finallyValue) throw 'incorrect value in "finallyValue"';
+ finallyValue = false;
+ if (finallyValue) throw 'incorrect value in "finallyValue"';
+
+ if (forValue != null) throw 'incorrect initialization of "forValue"';
+ forValue = true;
+ if (!forValue) throw 'incorrect value in "forValue"';
+ forValue = false;
+ if (forValue) throw 'incorrect value in "forValue"';
+
+ if (functionValue != null)
+ throw 'incorrect initialization of "functionValue"';
+ functionValue = true;
+ if (!functionValue) throw 'incorrect value in "functionValue"';
+ functionValue = false;
+ if (functionValue) throw 'incorrect value in "functionValue"';
+
+ if (ifValue != null) throw 'incorrect initialization of "ifValue"';
+ ifValue = true;
+ if (!ifValue) throw 'incorrect value in "ifValue"';
+ ifValue = false;
+ if (ifValue) throw 'incorrect value in "ifValue"';
+
+ if (implementsValue != null)
+ throw 'incorrect initialization of "implementsValue"';
+ implementsValue = true;
+ if (!implementsValue) throw 'incorrect value in "implementsValue"';
+ implementsValue = false;
+ if (implementsValue) throw 'incorrect value in "implementsValue"';
+
+ if (importValue != null) throw 'incorrect initialization of "importValue"';
+ importValue = true;
+ if (!importValue) throw 'incorrect value in "importValue"';
+ importValue = false;
+ if (importValue) throw 'incorrect value in "importValue"';
+
+ if (inValue != null) throw 'incorrect initialization of "inValue"';
+ inValue = true;
+ if (!inValue) throw 'incorrect value in "inValue"';
+ inValue = false;
+ if (inValue) throw 'incorrect value in "inValue"';
+
+ if (instanceofValue != null)
+ throw 'incorrect initialization of "instanceofValue"';
+ instanceofValue = true;
+ if (!instanceofValue) throw 'incorrect value in "instanceofValue"';
+ instanceofValue = false;
+ if (instanceofValue) throw 'incorrect value in "instanceofValue"';
+
+ if (interfaceValue != null)
+ throw 'incorrect initialization of "interfaceValue"';
+ interfaceValue = true;
+ if (!interfaceValue) throw 'incorrect value in "interfaceValue"';
+ interfaceValue = false;
+ if (interfaceValue) throw 'incorrect value in "interfaceValue"';
+
+ if (letValue != null) throw 'incorrect initialization of "letValue"';
+ letValue = true;
+ if (!letValue) throw 'incorrect value in "letValue"';
+ letValue = false;
+ if (letValue) throw 'incorrect value in "letValue"';
+
+ if (newValue != null) throw 'incorrect initialization of "newValue"';
+ newValue = true;
+ if (!newValue) throw 'incorrect value in "newValue"';
+ newValue = false;
+ if (newValue) throw 'incorrect value in "newValue"';
+
+ if (nullValue != null) throw 'incorrect initialization of "nullValue"';
+ nullValue = true;
+ if (!nullValue) throw 'incorrect value in "nullValue"';
+ nullValue = false;
+ if (nullValue) throw 'incorrect value in "nullValue"';
+
+ if (packageValue != null)
+ throw 'incorrect initialization of "packageValue"';
+ packageValue = true;
+ if (!packageValue) throw 'incorrect value in "packageValue"';
+ packageValue = false;
+ if (packageValue) throw 'incorrect value in "packageValue"';
+
+ if (privateValue != null)
+ throw 'incorrect initialization of "privateValue"';
+ privateValue = true;
+ if (!privateValue) throw 'incorrect value in "privateValue"';
+ privateValue = false;
+ if (privateValue) throw 'incorrect value in "privateValue"';
+
+ if (protectedValue != null)
+ throw 'incorrect initialization of "protectedValue"';
+ protectedValue = true;
+ if (!protectedValue) throw 'incorrect value in "protectedValue"';
+ protectedValue = false;
+ if (protectedValue) throw 'incorrect value in "protectedValue"';
+
+ if (publicValue != null) throw 'incorrect initialization of "publicValue"';
+ publicValue = true;
+ if (!publicValue) throw 'incorrect value in "publicValue"';
+ publicValue = false;
+ if (publicValue) throw 'incorrect value in "publicValue"';
+
+ if (returnValue != null) throw 'incorrect initialization of "returnValue"';
+ returnValue = true;
+ if (!returnValue) throw 'incorrect value in "returnValue"';
+ returnValue = false;
+ if (returnValue) throw 'incorrect value in "returnValue"';
+
+ if (staticValue != null) throw 'incorrect initialization of "staticValue"';
+ staticValue = true;
+ if (!staticValue) throw 'incorrect value in "staticValue"';
+ staticValue = false;
+ if (staticValue) throw 'incorrect value in "staticValue"';
+
+ if (superValue != null) throw 'incorrect initialization of "superValue"';
+ superValue = true;
+ if (!superValue) throw 'incorrect value in "superValue"';
+ superValue = false;
+ if (superValue) throw 'incorrect value in "superValue"';
+
+ if (switchValue != null) throw 'incorrect initialization of "switchValue"';
+ switchValue = true;
+ if (!switchValue) throw 'incorrect value in "switchValue"';
+ switchValue = false;
+ if (switchValue) throw 'incorrect value in "switchValue"';
+
+ if (thisValue != null) throw 'incorrect initialization of "thisValue"';
+ thisValue = true;
+ if (!thisValue) throw 'incorrect value in "thisValue"';
+ thisValue = false;
+ if (thisValue) throw 'incorrect value in "thisValue"';
+
+ if (throwValue != null) throw 'incorrect initialization of "throwValue"';
+ throwValue = true;
+ if (!throwValue) throw 'incorrect value in "throwValue"';
+ throwValue = false;
+ if (throwValue) throw 'incorrect value in "throwValue"';
+
+ if (trueValue != null) throw 'incorrect initialization of "trueValue"';
+ trueValue = true;
+ if (!trueValue) throw 'incorrect value in "trueValue"';
+ trueValue = false;
+ if (trueValue) throw 'incorrect value in "trueValue"';
+
+ if (tryValue != null) throw 'incorrect initialization of "tryValue"';
+ tryValue = true;
+ if (!tryValue) throw 'incorrect value in "tryValue"';
+ tryValue = false;
+ if (tryValue) throw 'incorrect value in "tryValue"';
+
+ if (typeofValue != null) throw 'incorrect initialization of "typeofValue"';
+ typeofValue = true;
+ if (!typeofValue) throw 'incorrect value in "typeofValue"';
+ typeofValue = false;
+ if (typeofValue) throw 'incorrect value in "typeofValue"';
+
+ if (varValue != null) throw 'incorrect initialization of "varValue"';
+ varValue = true;
+ if (!varValue) throw 'incorrect value in "varValue"';
+ varValue = false;
+ if (varValue) throw 'incorrect value in "varValue"';
+
+ if (voidValue != null) throw 'incorrect initialization of "voidValue"';
+ voidValue = true;
+ if (!voidValue) throw 'incorrect value in "voidValue"';
+ voidValue = false;
+ if (voidValue) throw 'incorrect value in "voidValue"';
+
+ if (whileValue != null) throw 'incorrect initialization of "whileValue"';
+ whileValue = true;
+ if (!whileValue) throw 'incorrect value in "whileValue"';
+ whileValue = false;
+ if (whileValue) throw 'incorrect value in "whileValue"';
+
+ if (withValue != null) throw 'incorrect initialization of "withValue"';
+ withValue = true;
+ if (!withValue) throw 'incorrect value in "withValue"';
+ withValue = false;
+ if (withValue) throw 'incorrect value in "withValue"';
+
+ if (yieldValue != null) throw 'incorrect initialization of "yieldValue"';
+ yieldValue = true;
+ if (!yieldValue) throw 'incorrect value in "yieldValue"';
+ yieldValue = false;
+ if (yieldValue) throw 'incorrect value in "yieldValue"';
+
+ }
+}
+
+/// Called once with an instance of NativeClassWithOddNames making it easy
+/// to inline accessors.
+testObjectStronglyTyped(object) {
+ if (object.breakValue == null)
+ throw 'incorrect initialization of "breakValue"';
+ object.breakValue = true;
+ if (!object.breakValue) throw 'incorrect value in "breakValue"';
+ object.breakValue = false;
+ if (object.breakValue) throw 'incorrect value in "breakValue"';
+
+ if (object.caseValue == null)
+ throw 'incorrect initialization of "caseValue"';
+ object.caseValue = true;
+ if (!object.caseValue) throw 'incorrect value in "caseValue"';
+ object.caseValue = false;
+ if (object.caseValue) throw 'incorrect value in "caseValue"';
+
+ if (object.catchValue == null)
+ throw 'incorrect initialization of "catchValue"';
+ object.catchValue = true;
+ if (!object.catchValue) throw 'incorrect value in "catchValue"';
+ object.catchValue = false;
+ if (object.catchValue) throw 'incorrect value in "catchValue"';
+
+ if (object.classValue == null)
+ throw 'incorrect initialization of "classValue"';
+ object.classValue = true;
+ if (!object.classValue) throw 'incorrect value in "classValue"';
+ object.classValue = false;
+ if (object.classValue) throw 'incorrect value in "classValue"';
+
+ if (object.constValue == null)
+ throw 'incorrect initialization of "constValue"';
+ object.constValue = true;
+ if (!object.constValue) throw 'incorrect value in "constValue"';
+ object.constValue = false;
+ if (object.constValue) throw 'incorrect value in "constValue"';
+
+ if (object.continueValue == null)
+ throw 'incorrect initialization of "continueValue"';
+ object.continueValue = true;
+ if (!object.continueValue) throw 'incorrect value in "continueValue"';
+ object.continueValue = false;
+ if (object.continueValue) throw 'incorrect value in "continueValue"';
+
+ if (object.debuggerValue == null)
+ throw 'incorrect initialization of "debuggerValue"';
+ object.debuggerValue = true;
+ if (!object.debuggerValue) throw 'incorrect value in "debuggerValue"';
+ object.debuggerValue = false;
+ if (object.debuggerValue) throw 'incorrect value in "debuggerValue"';
+
+ if (object.defaultValue == null)
+ throw 'incorrect initialization of "defaultValue"';
+ object.defaultValue = true;
+ if (!object.defaultValue) throw 'incorrect value in "defaultValue"';
+ object.defaultValue = false;
+ if (object.defaultValue) throw 'incorrect value in "defaultValue"';
+
+ if (object.deleteValue == null)
+ throw 'incorrect initialization of "deleteValue"';
+ object.deleteValue = true;
+ if (!object.deleteValue) throw 'incorrect value in "deleteValue"';
+ object.deleteValue = false;
+ if (object.deleteValue) throw 'incorrect value in "deleteValue"';
+
+ if (object.doValue == null)
+ throw 'incorrect initialization of "doValue"';
+ object.doValue = true;
+ if (!object.doValue) throw 'incorrect value in "doValue"';
+ object.doValue = false;
+ if (object.doValue) throw 'incorrect value in "doValue"';
+
+ if (object.elseValue == null)
+ throw 'incorrect initialization of "elseValue"';
+ object.elseValue = true;
+ if (!object.elseValue) throw 'incorrect value in "elseValue"';
+ object.elseValue = false;
+ if (object.elseValue) throw 'incorrect value in "elseValue"';
+
+ if (object.enumValue == null)
+ throw 'incorrect initialization of "enumValue"';
+ object.enumValue = true;
+ if (!object.enumValue) throw 'incorrect value in "enumValue"';
+ object.enumValue = false;
+ if (object.enumValue) throw 'incorrect value in "enumValue"';
+
+ if (object.exportValue == null)
+ throw 'incorrect initialization of "exportValue"';
+ object.exportValue = true;
+ if (!object.exportValue) throw 'incorrect value in "exportValue"';
+ object.exportValue = false;
+ if (object.exportValue) throw 'incorrect value in "exportValue"';
+
+ if (object.extendsValue == null)
+ throw 'incorrect initialization of "extendsValue"';
+ object.extendsValue = true;
+ if (!object.extendsValue) throw 'incorrect value in "extendsValue"';
+ object.extendsValue = false;
+ if (object.extendsValue) throw 'incorrect value in "extendsValue"';
+
+ if (object.falseValue == null)
+ throw 'incorrect initialization of "falseValue"';
+ object.falseValue = true;
+ if (!object.falseValue) throw 'incorrect value in "falseValue"';
+ object.falseValue = false;
+ if (object.falseValue) throw 'incorrect value in "falseValue"';
+
+ if (object.finallyValue == null)
+ throw 'incorrect initialization of "finallyValue"';
+ object.finallyValue = true;
+ if (!object.finallyValue) throw 'incorrect value in "finallyValue"';
+ object.finallyValue = false;
+ if (object.finallyValue) throw 'incorrect value in "finallyValue"';
+
+ if (object.forValue == null)
+ throw 'incorrect initialization of "forValue"';
+ object.forValue = true;
+ if (!object.forValue) throw 'incorrect value in "forValue"';
+ object.forValue = false;
+ if (object.forValue) throw 'incorrect value in "forValue"';
+
+ if (object.functionValue == null)
+ throw 'incorrect initialization of "functionValue"';
+ object.functionValue = true;
+ if (!object.functionValue) throw 'incorrect value in "functionValue"';
+ object.functionValue = false;
+ if (object.functionValue) throw 'incorrect value in "functionValue"';
+
+ if (object.ifValue == null)
+ throw 'incorrect initialization of "ifValue"';
+ object.ifValue = true;
+ if (!object.ifValue) throw 'incorrect value in "ifValue"';
+ object.ifValue = false;
+ if (object.ifValue) throw 'incorrect value in "ifValue"';
+
+ if (object.implementsValue == null)
+ throw 'incorrect initialization of "implementsValue"';
+ object.implementsValue = true;
+ if (!object.implementsValue) throw 'incorrect value in "implementsValue"';
+ object.implementsValue = false;
+ if (object.implementsValue) throw 'incorrect value in "implementsValue"';
+
+ if (object.importValue == null)
+ throw 'incorrect initialization of "importValue"';
+ object.importValue = true;
+ if (!object.importValue) throw 'incorrect value in "importValue"';
+ object.importValue = false;
+ if (object.importValue) throw 'incorrect value in "importValue"';
+
+ if (object.inValue == null)
+ throw 'incorrect initialization of "inValue"';
+ object.inValue = true;
+ if (!object.inValue) throw 'incorrect value in "inValue"';
+ object.inValue = false;
+ if (object.inValue) throw 'incorrect value in "inValue"';
+
+ if (object.instanceofValue == null)
+ throw 'incorrect initialization of "instanceofValue"';
+ object.instanceofValue = true;
+ if (!object.instanceofValue) throw 'incorrect value in "instanceofValue"';
+ object.instanceofValue = false;
+ if (object.instanceofValue) throw 'incorrect value in "instanceofValue"';
+
+ if (object.interfaceValue == null)
+ throw 'incorrect initialization of "interfaceValue"';
+ object.interfaceValue = true;
+ if (!object.interfaceValue) throw 'incorrect value in "interfaceValue"';
+ object.interfaceValue = false;
+ if (object.interfaceValue) throw 'incorrect value in "interfaceValue"';
+
+ if (object.letValue == null)
+ throw 'incorrect initialization of "letValue"';
+ object.letValue = true;
+ if (!object.letValue) throw 'incorrect value in "letValue"';
+ object.letValue = false;
+ if (object.letValue) throw 'incorrect value in "letValue"';
+
+ if (object.newValue == null)
+ throw 'incorrect initialization of "newValue"';
+ object.newValue = true;
+ if (!object.newValue) throw 'incorrect value in "newValue"';
+ object.newValue = false;
+ if (object.newValue) throw 'incorrect value in "newValue"';
+
+ if (object.nullValue == null)
+ throw 'incorrect initialization of "nullValue"';
+ object.nullValue = true;
+ if (!object.nullValue) throw 'incorrect value in "nullValue"';
+ object.nullValue = false;
+ if (object.nullValue) throw 'incorrect value in "nullValue"';
+
+ if (object.packageValue == null)
+ throw 'incorrect initialization of "packageValue"';
+ object.packageValue = true;
+ if (!object.packageValue) throw 'incorrect value in "packageValue"';
+ object.packageValue = false;
+ if (object.packageValue) throw 'incorrect value in "packageValue"';
+
+ if (object.privateValue == null)
+ throw 'incorrect initialization of "privateValue"';
+ object.privateValue = true;
+ if (!object.privateValue) throw 'incorrect value in "privateValue"';
+ object.privateValue = false;
+ if (object.privateValue) throw 'incorrect value in "privateValue"';
+
+ if (object.protectedValue == null)
+ throw 'incorrect initialization of "protectedValue"';
+ object.protectedValue = true;
+ if (!object.protectedValue) throw 'incorrect value in "protectedValue"';
+ object.protectedValue = false;
+ if (object.protectedValue) throw 'incorrect value in "protectedValue"';
+
+ if (object.publicValue == null)
+ throw 'incorrect initialization of "publicValue"';
+ object.publicValue = true;
+ if (!object.publicValue) throw 'incorrect value in "publicValue"';
+ object.publicValue = false;
+ if (object.publicValue) throw 'incorrect value in "publicValue"';
+
+ if (object.returnValue == null)
+ throw 'incorrect initialization of "returnValue"';
+ object.returnValue = true;
+ if (!object.returnValue) throw 'incorrect value in "returnValue"';
+ object.returnValue = false;
+ if (object.returnValue) throw 'incorrect value in "returnValue"';
+
+ if (object.staticValue == null)
+ throw 'incorrect initialization of "staticValue"';
+ object.staticValue = true;
+ if (!object.staticValue) throw 'incorrect value in "staticValue"';
+ object.staticValue = false;
+ if (object.staticValue) throw 'incorrect value in "staticValue"';
+
+ if (object.superValue == null)
+ throw 'incorrect initialization of "superValue"';
+ object.superValue = true;
+ if (!object.superValue) throw 'incorrect value in "superValue"';
+ object.superValue = false;
+ if (object.superValue) throw 'incorrect value in "superValue"';
+
+ if (object.switchValue == null)
+ throw 'incorrect initialization of "switchValue"';
+ object.switchValue = true;
+ if (!object.switchValue) throw 'incorrect value in "switchValue"';
+ object.switchValue = false;
+ if (object.switchValue) throw 'incorrect value in "switchValue"';
+
+ if (object.thisValue == null)
+ throw 'incorrect initialization of "thisValue"';
+ object.thisValue = true;
+ if (!object.thisValue) throw 'incorrect value in "thisValue"';
+ object.thisValue = false;
+ if (object.thisValue) throw 'incorrect value in "thisValue"';
+
+ if (object.throwValue == null)
+ throw 'incorrect initialization of "throwValue"';
+ object.throwValue = true;
+ if (!object.throwValue) throw 'incorrect value in "throwValue"';
+ object.throwValue = false;
+ if (object.throwValue) throw 'incorrect value in "throwValue"';
+
+ if (object.trueValue == null)
+ throw 'incorrect initialization of "trueValue"';
+ object.trueValue = true;
+ if (!object.trueValue) throw 'incorrect value in "trueValue"';
+ object.trueValue = false;
+ if (object.trueValue) throw 'incorrect value in "trueValue"';
+
+ if (object.tryValue == null)
+ throw 'incorrect initialization of "tryValue"';
+ object.tryValue = true;
+ if (!object.tryValue) throw 'incorrect value in "tryValue"';
+ object.tryValue = false;
+ if (object.tryValue) throw 'incorrect value in "tryValue"';
+
+ if (object.typeofValue == null)
+ throw 'incorrect initialization of "typeofValue"';
+ object.typeofValue = true;
+ if (!object.typeofValue) throw 'incorrect value in "typeofValue"';
+ object.typeofValue = false;
+ if (object.typeofValue) throw 'incorrect value in "typeofValue"';
+
+ if (object.varValue == null)
+ throw 'incorrect initialization of "varValue"';
+ object.varValue = true;
+ if (!object.varValue) throw 'incorrect value in "varValue"';
+ object.varValue = false;
+ if (object.varValue) throw 'incorrect value in "varValue"';
+
+ if (object.voidValue == null)
+ throw 'incorrect initialization of "voidValue"';
+ object.voidValue = true;
+ if (!object.voidValue) throw 'incorrect value in "voidValue"';
+ object.voidValue = false;
+ if (object.voidValue) throw 'incorrect value in "voidValue"';
+
+ if (object.whileValue == null)
+ throw 'incorrect initialization of "whileValue"';
+ object.whileValue = true;
+ if (!object.whileValue) throw 'incorrect value in "whileValue"';
+ object.whileValue = false;
+ if (object.whileValue) throw 'incorrect value in "whileValue"';
+
+ if (object.withValue == null)
+ throw 'incorrect initialization of "withValue"';
+ object.withValue = true;
+ if (!object.withValue) throw 'incorrect value in "withValue"';
+ object.withValue = false;
+ if (object.withValue) throw 'incorrect value in "withValue"';
+
+ if (object.yieldValue == null)
+ throw 'incorrect initialization of "yieldValue"';
+ object.yieldValue = true;
+ if (!object.yieldValue) throw 'incorrect value in "yieldValue"';
+ object.yieldValue = false;
+ if (object.yieldValue) throw 'incorrect value in "yieldValue"';
+}
+
+/// Called multiple times with arguments that are hard to track in type
+/// inference making it hard to inline accessors.
+testObjectWeaklyTyped(object) {
+ object = object[0];
+ if (object == 'fisk') return;
+ if (object.breakValue == null)
+ throw 'incorrect initialization of "breakValue"';
+ object.breakValue = true;
+ if (!object.breakValue) throw 'incorrect value in "breakValue"';
+ object.breakValue = false;
+ if (object.breakValue) throw 'incorrect value in "breakValue"';
+
+ if (object.caseValue == null)
+ throw 'incorrect initialization of "caseValue"';
+ object.caseValue = true;
+ if (!object.caseValue) throw 'incorrect value in "caseValue"';
+ object.caseValue = false;
+ if (object.caseValue) throw 'incorrect value in "caseValue"';
+
+ if (object.catchValue == null)
+ throw 'incorrect initialization of "catchValue"';
+ object.catchValue = true;
+ if (!object.catchValue) throw 'incorrect value in "catchValue"';
+ object.catchValue = false;
+ if (object.catchValue) throw 'incorrect value in "catchValue"';
+
+ if (object.classValue == null)
+ throw 'incorrect initialization of "classValue"';
+ object.classValue = true;
+ if (!object.classValue) throw 'incorrect value in "classValue"';
+ object.classValue = false;
+ if (object.classValue) throw 'incorrect value in "classValue"';
+
+ if (object.constValue == null)
+ throw 'incorrect initialization of "constValue"';
+ object.constValue = true;
+ if (!object.constValue) throw 'incorrect value in "constValue"';
+ object.constValue = false;
+ if (object.constValue) throw 'incorrect value in "constValue"';
+
+ if (object.continueValue == null)
+ throw 'incorrect initialization of "continueValue"';
+ object.continueValue = true;
+ if (!object.continueValue) throw 'incorrect value in "continueValue"';
+ object.continueValue = false;
+ if (object.continueValue) throw 'incorrect value in "continueValue"';
+
+ if (object.debuggerValue == null)
+ throw 'incorrect initialization of "debuggerValue"';
+ object.debuggerValue = true;
+ if (!object.debuggerValue) throw 'incorrect value in "debuggerValue"';
+ object.debuggerValue = false;
+ if (object.debuggerValue) throw 'incorrect value in "debuggerValue"';
+
+ if (object.defaultValue == null)
+ throw 'incorrect initialization of "defaultValue"';
+ object.defaultValue = true;
+ if (!object.defaultValue) throw 'incorrect value in "defaultValue"';
+ object.defaultValue = false;
+ if (object.defaultValue) throw 'incorrect value in "defaultValue"';
+
+ if (object.deleteValue == null)
+ throw 'incorrect initialization of "deleteValue"';
+ object.deleteValue = true;
+ if (!object.deleteValue) throw 'incorrect value in "deleteValue"';
+ object.deleteValue = false;
+ if (object.deleteValue) throw 'incorrect value in "deleteValue"';
+
+ if (object.doValue == null)
+ throw 'incorrect initialization of "doValue"';
+ object.doValue = true;
+ if (!object.doValue) throw 'incorrect value in "doValue"';
+ object.doValue = false;
+ if (object.doValue) throw 'incorrect value in "doValue"';
+
+ if (object.elseValue == null)
+ throw 'incorrect initialization of "elseValue"';
+ object.elseValue = true;
+ if (!object.elseValue) throw 'incorrect value in "elseValue"';
+ object.elseValue = false;
+ if (object.elseValue) throw 'incorrect value in "elseValue"';
+
+ if (object.enumValue == null)
+ throw 'incorrect initialization of "enumValue"';
+ object.enumValue = true;
+ if (!object.enumValue) throw 'incorrect value in "enumValue"';
+ object.enumValue = false;
+ if (object.enumValue) throw 'incorrect value in "enumValue"';
+
+ if (object.exportValue == null)
+ throw 'incorrect initialization of "exportValue"';
+ object.exportValue = true;
+ if (!object.exportValue) throw 'incorrect value in "exportValue"';
+ object.exportValue = false;
+ if (object.exportValue) throw 'incorrect value in "exportValue"';
+
+ if (object.extendsValue == null)
+ throw 'incorrect initialization of "extendsValue"';
+ object.extendsValue = true;
+ if (!object.extendsValue) throw 'incorrect value in "extendsValue"';
+ object.extendsValue = false;
+ if (object.extendsValue) throw 'incorrect value in "extendsValue"';
+
+ if (object.falseValue == null)
+ throw 'incorrect initialization of "falseValue"';
+ object.falseValue = true;
+ if (!object.falseValue) throw 'incorrect value in "falseValue"';
+ object.falseValue = false;
+ if (object.falseValue) throw 'incorrect value in "falseValue"';
+
+ if (object.finallyValue == null)
+ throw 'incorrect initialization of "finallyValue"';
+ object.finallyValue = true;
+ if (!object.finallyValue) throw 'incorrect value in "finallyValue"';
+ object.finallyValue = false;
+ if (object.finallyValue) throw 'incorrect value in "finallyValue"';
+
+ if (object.forValue == null)
+ throw 'incorrect initialization of "forValue"';
+ object.forValue = true;
+ if (!object.forValue) throw 'incorrect value in "forValue"';
+ object.forValue = false;
+ if (object.forValue) throw 'incorrect value in "forValue"';
+
+ if (object.functionValue == null)
+ throw 'incorrect initialization of "functionValue"';
+ object.functionValue = true;
+ if (!object.functionValue) throw 'incorrect value in "functionValue"';
+ object.functionValue = false;
+ if (object.functionValue) throw 'incorrect value in "functionValue"';
+
+ if (object.ifValue == null)
+ throw 'incorrect initialization of "ifValue"';
+ object.ifValue = true;
+ if (!object.ifValue) throw 'incorrect value in "ifValue"';
+ object.ifValue = false;
+ if (object.ifValue) throw 'incorrect value in "ifValue"';
+
+ if (object.implementsValue == null)
+ throw 'incorrect initialization of "implementsValue"';
+ object.implementsValue = true;
+ if (!object.implementsValue) throw 'incorrect value in "implementsValue"';
+ object.implementsValue = false;
+ if (object.implementsValue) throw 'incorrect value in "implementsValue"';
+
+ if (object.importValue == null)
+ throw 'incorrect initialization of "importValue"';
+ object.importValue = true;
+ if (!object.importValue) throw 'incorrect value in "importValue"';
+ object.importValue = false;
+ if (object.importValue) throw 'incorrect value in "importValue"';
+
+ if (object.inValue == null)
+ throw 'incorrect initialization of "inValue"';
+ object.inValue = true;
+ if (!object.inValue) throw 'incorrect value in "inValue"';
+ object.inValue = false;
+ if (object.inValue) throw 'incorrect value in "inValue"';
+
+ if (object.instanceofValue == null)
+ throw 'incorrect initialization of "instanceofValue"';
+ object.instanceofValue = true;
+ if (!object.instanceofValue) throw 'incorrect value in "instanceofValue"';
+ object.instanceofValue = false;
+ if (object.instanceofValue) throw 'incorrect value in "instanceofValue"';
+
+ if (object.interfaceValue == null)
+ throw 'incorrect initialization of "interfaceValue"';
+ object.interfaceValue = true;
+ if (!object.interfaceValue) throw 'incorrect value in "interfaceValue"';
+ object.interfaceValue = false;
+ if (object.interfaceValue) throw 'incorrect value in "interfaceValue"';
+
+ if (object.letValue == null)
+ throw 'incorrect initialization of "letValue"';
+ object.letValue = true;
+ if (!object.letValue) throw 'incorrect value in "letValue"';
+ object.letValue = false;
+ if (object.letValue) throw 'incorrect value in "letValue"';
+
+ if (object.newValue == null)
+ throw 'incorrect initialization of "newValue"';
+ object.newValue = true;
+ if (!object.newValue) throw 'incorrect value in "newValue"';
+ object.newValue = false;
+ if (object.newValue) throw 'incorrect value in "newValue"';
+
+ if (object.nullValue == null)
+ throw 'incorrect initialization of "nullValue"';
+ object.nullValue = true;
+ if (!object.nullValue) throw 'incorrect value in "nullValue"';
+ object.nullValue = false;
+ if (object.nullValue) throw 'incorrect value in "nullValue"';
+
+ if (object.packageValue == null)
+ throw 'incorrect initialization of "packageValue"';
+ object.packageValue = true;
+ if (!object.packageValue) throw 'incorrect value in "packageValue"';
+ object.packageValue = false;
+ if (object.packageValue) throw 'incorrect value in "packageValue"';
+
+ if (object.privateValue == null)
+ throw 'incorrect initialization of "privateValue"';
+ object.privateValue = true;
+ if (!object.privateValue) throw 'incorrect value in "privateValue"';
+ object.privateValue = false;
+ if (object.privateValue) throw 'incorrect value in "privateValue"';
+
+ if (object.protectedValue == null)
+ throw 'incorrect initialization of "protectedValue"';
+ object.protectedValue = true;
+ if (!object.protectedValue) throw 'incorrect value in "protectedValue"';
+ object.protectedValue = false;
+ if (object.protectedValue) throw 'incorrect value in "protectedValue"';
+
+ if (object.publicValue == null)
+ throw 'incorrect initialization of "publicValue"';
+ object.publicValue = true;
+ if (!object.publicValue) throw 'incorrect value in "publicValue"';
+ object.publicValue = false;
+ if (object.publicValue) throw 'incorrect value in "publicValue"';
+
+ if (object.returnValue == null)
+ throw 'incorrect initialization of "returnValue"';
+ object.returnValue = true;
+ if (!object.returnValue) throw 'incorrect value in "returnValue"';
+ object.returnValue = false;
+ if (object.returnValue) throw 'incorrect value in "returnValue"';
+
+ if (object.staticValue == null)
+ throw 'incorrect initialization of "staticValue"';
+ object.staticValue = true;
+ if (!object.staticValue) throw 'incorrect value in "staticValue"';
+ object.staticValue = false;
+ if (object.staticValue) throw 'incorrect value in "staticValue"';
+
+ if (object.superValue == null)
+ throw 'incorrect initialization of "superValue"';
+ object.superValue = true;
+ if (!object.superValue) throw 'incorrect value in "superValue"';
+ object.superValue = false;
+ if (object.superValue) throw 'incorrect value in "superValue"';
+
+ if (object.switchValue == null)
+ throw 'incorrect initialization of "switchValue"';
+ object.switchValue = true;
+ if (!object.switchValue) throw 'incorrect value in "switchValue"';
+ object.switchValue = false;
+ if (object.switchValue) throw 'incorrect value in "switchValue"';
+
+ if (object.thisValue == null)
+ throw 'incorrect initialization of "thisValue"';
+ object.thisValue = true;
+ if (!object.thisValue) throw 'incorrect value in "thisValue"';
+ object.thisValue = false;
+ if (object.thisValue) throw 'incorrect value in "thisValue"';
+
+ if (object.throwValue == null)
+ throw 'incorrect initialization of "throwValue"';
+ object.throwValue = true;
+ if (!object.throwValue) throw 'incorrect value in "throwValue"';
+ object.throwValue = false;
+ if (object.throwValue) throw 'incorrect value in "throwValue"';
+
+ if (object.trueValue == null)
+ throw 'incorrect initialization of "trueValue"';
+ object.trueValue = true;
+ if (!object.trueValue) throw 'incorrect value in "trueValue"';
+ object.trueValue = false;
+ if (object.trueValue) throw 'incorrect value in "trueValue"';
+
+ if (object.tryValue == null)
+ throw 'incorrect initialization of "tryValue"';
+ object.tryValue = true;
+ if (!object.tryValue) throw 'incorrect value in "tryValue"';
+ object.tryValue = false;
+ if (object.tryValue) throw 'incorrect value in "tryValue"';
+
+ if (object.typeofValue == null)
+ throw 'incorrect initialization of "typeofValue"';
+ object.typeofValue = true;
+ if (!object.typeofValue) throw 'incorrect value in "typeofValue"';
+ object.typeofValue = false;
+ if (object.typeofValue) throw 'incorrect value in "typeofValue"';
+
+ if (object.varValue == null)
+ throw 'incorrect initialization of "varValue"';
+ object.varValue = true;
+ if (!object.varValue) throw 'incorrect value in "varValue"';
+ object.varValue = false;
+ if (object.varValue) throw 'incorrect value in "varValue"';
+
+ if (object.voidValue == null)
+ throw 'incorrect initialization of "voidValue"';
+ object.voidValue = true;
+ if (!object.voidValue) throw 'incorrect value in "voidValue"';
+ object.voidValue = false;
+ if (object.voidValue) throw 'incorrect value in "voidValue"';
+
+ if (object.whileValue == null)
+ throw 'incorrect initialization of "whileValue"';
+ object.whileValue = true;
+ if (!object.whileValue) throw 'incorrect value in "whileValue"';
+ object.whileValue = false;
+ if (object.whileValue) throw 'incorrect value in "whileValue"';
+
+ if (object.withValue == null)
+ throw 'incorrect initialization of "withValue"';
+ object.withValue = true;
+ if (!object.withValue) throw 'incorrect value in "withValue"';
+ object.withValue = false;
+ if (object.withValue) throw 'incorrect value in "withValue"';
+
+ if (object.yieldValue == null)
+ throw 'incorrect initialization of "yieldValue"';
+ object.yieldValue = true;
+ if (!object.yieldValue) throw 'incorrect value in "yieldValue"';
+ object.yieldValue = false;
+ if (object.yieldValue) throw 'incorrect value in "yieldValue"';
+}
+
+makeNativeClassWithOddNames() native;
+
+setup() native """
+function NativeClassWithOddNames() {}
+makeNativeClassWithOddNames = function() { return new NativeClassWithOddNames; }
+""";
+
+main() {
+ setup();
+ var object = new NativeClassWithOddNames();
+ object.testMyFields();
+ testObjectStronglyTyped(object);
+ testObjectWeaklyTyped([object]);
+ testObjectWeaklyTyped(['fisk']);
+ testObjectWeaklyTyped([new ClassWithOddNames()..testMyFields()]);
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 3008f2e..3d21fe2 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -4,6 +4,9 @@
reg_exp_unicode_2_test: Fail # Bug 6592
+[ $compiler == dart2js && $checked ]
+list_test: Fail, OK # dartbug.com/10708
+
[ $compiler == none ]
unicode_test: Fail # Bug 6706
*dartc_test: Skip
diff --git a/tests/html/html.status b/tests/html/html.status
index 3fdbc52..409328c 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -4,6 +4,7 @@
window_open_test: Skip # http://dartbug.com/5151
async_window_test: Skip #TODO(gram): investigating
+svg_test: Skip #TODO(vsm): investigating
event_test: Skip # Issue 1996
custom_elements_test: Skip # Not yet implemented.
@@ -33,7 +34,7 @@
[ $compiler == dart2js && $runtime == safari ]
url_test: Fail # Issue 10096
-[ $compiler == dart2js && $runtime == drt && $checked ]
+[ $compiler == dart2js && $browser && $checked ]
postmessage_structured_test/typed_arrays: Fail # Issue 10097
postmessage_structured_test/primitives: Fail # Issue 10097
diff --git a/tests/html/track_element_constructor_test.dart b/tests/html/track_element_constructor_test.dart
new file mode 100644
index 0000000..883dabd
--- /dev/null
+++ b/tests/html/track_element_constructor_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+// A regression test for dart2js generating illegal JavaScript code
+// dynamically in non-csp mode. The name of the field "defaultValue"
+// in JavaScript is "default". This meant that dart2js would create a
+// constructor function that looked like this:
+//
+// function TrackElement(default) { this.default = default; }
+
+import 'dart:html';
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+void main() {
+ useHtmlConfiguration();
+ test('', () {
+ if (!TrackElement.supported) return;
+ document.body.append(new TrackElement()..defaultValue = true);
+ if (!document.query('track').defaultValue) {
+ throw 'Expected default value to be true';
+ }
+ document.query('track').defaultValue = false;
+ if (document.query('track').defaultValue) {
+ throw 'Expected default value to be false';
+ }
+ });
+}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 398930c..8b8934f 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -50,6 +50,7 @@
[ $compiler == dart2js && ($runtime == d8 || $jscl) ]
illegal_msg_stream_test: Fail # Issue 6750
+typed_data_message_test: Fail, OK # DataView only supported in browsers.
[ $compiler == dart2js && $browser ]
illegal_msg_stream_test: Fail, Pass # Issue 6750
@@ -124,6 +125,9 @@
mandel_isolate_test: Pass, Fail, Timeout # Issue 7952
mandel_isolate_stream_test: Pass, Fail, Timeout # Issue 7952
+[ $compiler == dart2js && ( $runtime == ff || $runtime == safari ) ]
+isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
+
[ $arch == arm ]
*: Skip
diff --git a/tests/isolate/isolate_stress_test.dart b/tests/isolate/isolate_stress_test.dart
new file mode 100644
index 0000000..685ea59
--- /dev/null
+++ b/tests/isolate/isolate_stress_test.dart
@@ -0,0 +1,62 @@
+// 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.
+
+// This test creates a lot of isolates. This is meant to exhaust
+// resources if the isolates aren't closed correctly (which happened
+// in dart2js).
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:isolate';
+
+// TODO(ahe): Remove dependency on unittest when tests are wrapperless.
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+const bool IS_UNITTEST = true;
+
+worker() {
+ port.receive((String uri, SendPort replyTo) {
+ replyTo.send('Hello from Worker');
+ port.close();
+ });
+}
+
+main() {
+ useHtmlConfiguration();
+ try {
+ // Create a Worker to confuse broken isolate implementation in dart2js.
+ new Worker('data:application/javascript,').terminate();
+ } catch (e) {
+ // Ignored.
+ }
+ var doneClosure;
+ int isolateCount = 0;
+ spawnMany(reply) {
+ if (reply != 'Hello from Worker') {
+ throw new Exception('Unexpected reply from worker: $reply');
+ }
+ if (++isolateCount > 200) {
+ if (IS_UNITTEST) {
+ doneClosure();
+ } else {
+ port.close();
+ window.postMessage('unittest-suite-done', '*');
+ }
+ return;
+ }
+ spawnFunction(worker).call('').then(spawnMany);
+ print('isolateCount = $isolateCount');
+ }
+
+ if (IS_UNITTEST) {
+ test('stress test', () {
+ spawnMany('Hello from Worker');
+ doneClosure = expectAsync0(() {});
+ });
+ } else {
+ spawnMany('Hello from Worker');
+ window.postMessage('unittest-suite-wait-for-done', '*');
+ }
+}
diff --git a/tests/language/checked_setter_test.dart b/tests/language/checked_setter_test.dart
new file mode 100644
index 0000000..608a472
--- /dev/null
+++ b/tests/language/checked_setter_test.dart
@@ -0,0 +1,32 @@
+// 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 implicit setters in checked mode do a type check.
+
+import "package:expect/expect.dart";
+
+class A {
+ C c;
+}
+
+class B extends A {
+}
+
+class C {
+}
+
+var array = [new B()];
+
+main() {
+ array[0].c = new C();
+ bool inCheckedMode = false;
+ try {
+ String a = 42;
+ } catch (e) {
+ inCheckedMode = true;
+ }
+ if (inCheckedMode) {
+ Expect.throws(() => array[0].c = new B(), (e) => e is TypeError);
+ }
+}
diff --git a/tests/language/infinite_switch_label_test.dart b/tests/language/infinite_switch_label_test.dart
new file mode 100644
index 0000000..9a89b91
--- /dev/null
+++ b/tests/language/infinite_switch_label_test.dart
@@ -0,0 +1,37 @@
+// 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 nested switch statement using labels.
+
+library nested_switch_label;
+
+import "package:expect/expect.dart";
+
+void main() {
+ Expect.throws(() => doSwitch(0), (list) {
+ Expect.listEquals([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], list);
+ return true;
+ });
+ Expect.throws(() => doSwitch(2), (list) {
+ Expect.listEquals([2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], list);
+ return true;
+ });
+}
+
+void doSwitch(int target) {
+ List list = [];
+ switch (target) {
+ l0: case 0:
+ if (list.length > 10) throw list;
+ list.add(0);
+ continue l1;
+ l1: case 1:
+ if (list.length > 10) throw list;
+ list.add(1);
+ continue l0;
+ default:
+ list.add(2);
+ continue l1;
+ }
+}
\ No newline at end of file
diff --git a/tests/language/issue10581_test.dart b/tests/language/issue10581_test.dart
new file mode 100644
index 0000000..30cdfb2
--- /dev/null
+++ b/tests/language/issue10581_test.dart
@@ -0,0 +1,58 @@
+// 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.
+
+// Regression test for https://code.google.com/p/dart/issues/detail?id=10581.
+
+import 'package:expect/expect.dart';
+
+abstract class AxesObject {
+ Update();
+}
+
+String result = '';
+
+class Point2DObject extends AxesObject {
+ Update() { result += 'P'; }
+}
+
+class BestFitObject extends AxesObject {
+ Update() { result += 'B'; }
+}
+
+class Foo {
+ AddAxesObject(type) {
+ AxesObject a = null;
+ switch (type) {
+ case 100:
+ a = new Point2DObject();
+ break;
+ case 200:
+ a = new BestFitObject();
+ break;
+ }
+ if (a != null) {
+ a.Update();
+ }
+ }
+ AddAxesObject2(type) {
+ AxesObject a = null;
+ if (type == 100) {
+ a = new Point2DObject();
+ } else if (type == 200) {
+ a = new BestFitObject();
+ }
+ if (a != null) {
+ a.Update();
+ }
+ }
+}
+
+main() {
+ var f = new Foo();
+ f.AddAxesObject(100);
+ f.AddAxesObject(200);
+ f.AddAxesObject2(100);
+ f.AddAxesObject2(200);
+ Expect.equals('PBPB', result);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index bfda549..e7a5d61 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -470,8 +470,6 @@
static_top_level_test/07: Fail
# Bug in dart2js parser: it happily parses 1is int; variable declaration.
number_identifier_negative_test: Fail
-# Bug in dart2js frontent: does not support this feature.
-switch_label_test: Fail
# Common with language_dart2js.
factory_redirection_test/0*: Skip # Flaky negative tests, crash, fail, or pass. Not implemented.
factory_redirection_test/1*: Skip # Flaky negative tests, crash, fail, or pass. Not implemented.
@@ -564,7 +562,6 @@
assign_static_type_test/04: fail
assign_static_type_test/05: fail
assign_static_type_test/06: fail
-bad_initializer2_negative_test: fail
bad_named_parameters2_test: fail
bad_named_parameters_test: fail
bad_override_test/01: fail
@@ -646,23 +643,17 @@
compile_time_constant_d_test: fail
compile_time_constant_e_test: fail
compile_time_constant_test/02: fail
-const_counter_negative_test: fail
-const_factory_negative_test: fail
const_optional_args_negative_test: fail
const_syntax_test/06: fail
constructor2_negative_test: fail
constructor3_negative_test: fail
constructor_call_wrong_argument_count_negative_test: fail
constructor_negative_test: fail
-constructor_redirect1_negative_test: fail
-constructor_redirect2_negative_test: fail
constructor_redirect2_test/02: fail
-constructor_redirect2_test/03: fail
constructor_redirect2_test/04: fail
constructor_redirect_test/01: fail
constructor_return_with_arrow_negative_test: fail
constructor_return_with_init_and_arrow_negative_test: fail
-cyclic_constructor_test/01: fail
cyclic_type_variable_test/01: fail
cyclic_type_variable_test/02: fail
cyclic_type_variable_test/03: fail
@@ -681,7 +672,6 @@
factory5_test/00: fail
factory_implementation_test/00: skip
factory_redirection2_test/01: fail
-factory_redirection_test/04: fail
factory_redirection_test/07: fail
factory_redirection_test/08: skip
factory_redirection_test/09: skip
@@ -692,7 +682,6 @@
factory_redirection_test/14: skip
fauxverride_test/03: fail
fauxverride_test/05: fail
-field_decl_missing_var_type_test/01: fail
field_method4_negative_test: fail
field_override_test/01: fail
field_override_test/02: fail
@@ -724,6 +713,7 @@
implicit_this_test/none: fail
import_combinators_negative_test: fail
import_private_test/01: fail
+infinite_switch_label_test: fail
inst_field_initializer1_negative_test: fail
instance_call_wrong_argument_count_negative_test: fail
instance_method2_negative_test: fail
@@ -765,6 +755,7 @@
named_parameters_aggregated_test/04: fail
named_parameters_aggregated_test/05: fail
named_parameters_type_test: fail
+nested_switch_label_test: fail
new_expression_type_args_test/00: fail
new_expression_type_args_test/01: fail
new_expression_type_args_test/02: fail
@@ -780,7 +771,6 @@
override_field_test/03: fail
override_method_with_field_test/01: fail
override_method_with_field_test/02: fail
-parameter_initializer3_negative_test: fail
parameter_initializer5_negative_test: fail
positional_parameters_type_test: fail
prefix10_negative_test: fail
@@ -844,7 +834,6 @@
string_interpolation9_test/8: fail
string_interpolation9_test/9: fail
string_interpolation_test/01: fail
-super_call3_test/02: fail
super_operator_index_test/01: fail
super_operator_index_test/02: fail
super_operator_index_test/03: fail
@@ -852,6 +841,7 @@
super_operator_index_test/05: fail
super_operator_index_test/06: fail
super_operator_index_test/07: fail
+switch_label2_test: fail
syntax_test/28: fail
syntax_test/29: fail
syntax_test/30: fail
@@ -907,6 +897,10 @@
wrong_number_type_arguments_test/00: fail
wrong_number_type_arguments_test/02: fail
+# test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
+block_scope_test: fail
+lazy_static3_test: fail
+
[ $arch == arm ]
*: Skip
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 362ff2b..1dfd21f 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -39,11 +39,7 @@
*vm_negative_test: Skip
[ $compiler == dart2js && $checked ]
-mixin_type_parameters_super_extends_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_super_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
-
+function_type_alias6_test: Crash # dartbug.com/9792
prefix16_test: Fail # dartbug.com/7354
default_factory2_test/01: Pass # For the wrong reasons.
@@ -67,7 +63,6 @@
type_annotation_test/09: Fail # Named constructors interpreted as a type.
prefix15_test: Fail # Issue 5022
local_function2_test: Fail # Issue 5022
-number_identity_test: Fail # Issue 9249
[ $compiler == dart2js && $unchecked ]
default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
@@ -197,7 +192,6 @@
named_parameters_aggregated_test/05: Fail # Absence of positional parameters before named parameters does not trigger static type warning.
pseudo_kw_test: Fail # Unexpected token '('
super_implicit_closure_test: Fail # internal error: super property read not implemented
-switch_label_test: Fail # error: target of continue is not a loop or switch case
on_catch_malformed_type_test: Fail # Malformed types cause compile-time errors.
# Missing compilation error for wrong number of type arguments.
diff --git a/tests/language/nested_switch_label_test.dart b/tests/language/nested_switch_label_test.dart
new file mode 100644
index 0000000..420ed6a
--- /dev/null
+++ b/tests/language/nested_switch_label_test.dart
@@ -0,0 +1,42 @@
+// 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 nested switch statement using labels.
+
+library nested_switch_label;
+
+import "package:expect/expect.dart";
+
+void main() {
+ doSwitch(0, ['0', '2:0', '1', 'default']);
+ doSwitch(2, ['2:2', '2:1', '2', '1', 'default']);
+}
+
+void doSwitch(int target, List expect) {
+ List list = [];
+ switch (target) {
+ outer0: case 0:
+ list.add('0');
+ continue outer2;
+ outer1: case 1:
+ list.add('1');
+ continue outerDefault;
+ outer2: case 2:
+ switch (target) {
+ inner0: case 0:
+ list.add('2:0');
+ continue outer1;
+ inner2: case 2:
+ list.add('2:2');
+ continue inner1;
+ inner1: case 1:
+ list.add('2:1');
+ }
+ list.add('2');
+ continue outer1;
+ outerDefault: default:
+ list.add('default');
+ }
+ Expect.listEquals(expect, list);
+}
\ No newline at end of file
diff --git a/tests/language/null_inline_test.dart b/tests/language/null_inline_test.dart
new file mode 100644
index 0000000..265eff5
--- /dev/null
+++ b/tests/language/null_inline_test.dart
@@ -0,0 +1,19 @@
+// 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 inlining takes null into account.
+
+import "package:expect/expect.dart";
+
+class A {
+ foo() => this;
+}
+
+var global;
+
+main() {
+ Expect.throws(() => global.foo());
+ global = new A();
+ Expect.equals(global, global.foo());
+}
diff --git a/tests/language/super_inferrer_test.dart b/tests/language/super_inferrer_test.dart
new file mode 100644
index 0000000..f1f4545
--- /dev/null
+++ b/tests/language/super_inferrer_test.dart
@@ -0,0 +1,32 @@
+// 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 dart2js's backend type inference handles super calls.
+
+import "package:expect/expect.dart";
+
+class A {
+ foo(a) => a + 42;
+}
+
+class B extends A {
+ bar() {
+ super.foo(null);
+ }
+}
+
+var a = [new A()];
+
+main() {
+ analyzeFirst();
+ analyzeSecond();
+}
+
+analyzeFirst() {
+ Expect.equals(84, a[0].foo(42));
+}
+
+analyzeSecond() {
+ Expect.throws(() => new B().bar(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/switch_label2_test.dart b/tests/language/switch_label2_test.dart
new file mode 100644
index 0000000..e051b6f
--- /dev/null
+++ b/tests/language/switch_label2_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test switch statement using labels.
+
+import 'package:expect/expect.dart';
+
+void main() {
+ doSwitch(0, [0, 2]);
+ doSwitch(1, [1]);
+ doSwitch(2, [2]);
+ doSwitch(3, [3, 1]);
+}
+
+void doSwitch(int target, List expect) {
+ List list = [];
+ switch (target) {
+ case 0:
+ list.add(0);
+ continue case2;
+ case1: case 1:
+ list.add(1);
+ break;
+ case2: case 2:
+ list.add(2);
+ break;
+ case 3:
+ list.add(3);
+ continue case1;
+ }
+ Expect.listEquals(expect, list);
+}
\ No newline at end of file
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index fd7b0c8..24f3607 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -30,13 +30,49 @@
equals({"a": 'A', "b":'B', "c": instance}));
}
+testInstanceFieldAccess(mirrors) {
+ var instance = new Class();
+ var instMirror = reflect(instance);
+
+ instMirror.setFieldAsync(const Symbol('field'), 44);
+ instMirror.getFieldAsync(const Symbol('field')).then(
+ expectAsync1((resultMirror) {
+ expect(resultMirror.reflectee, equals(44));
+ expect(instance.field, equals(44));
+ }));
+}
+
+/// In dart2js, lists, numbers, and other objects are treated special
+/// and their methods are invoked through a techique called interceptors.
+testIntercepted(mirrors) {
+ var instance = 1;
+ var instMirror = reflect(instance);
+
+ expect(instMirror.invoke(const Symbol('toString'), []).reflectee,
+ equals('1'));
+
+ instance = [];
+ instMirror = reflect(instance);
+ instMirror.setField(const Symbol('length'), 44);
+ var resultMirror = instMirror.getField(const Symbol('length'));
+ expect(resultMirror.reflectee, equals(44));
+ expect(instance.length, equals(44));
+
+ expect(instMirror.invoke(const Symbol('toString'), []).reflectee,
+ equals('[null, null, null, null, null, null, null, null, null, null,'
+ ' null, null, null, null, null, null, null, null, null, null,'
+ ' null, null, null, null, null, null, null, null, null, null,'
+ ' null, null, null, null, null, null, null, null, null, null,'
+ ' null, null, null, null]'));
+}
+
testFieldAccess(mirrors) {
var instance = new Class();
var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
var classMirror = libMirror.classes[const Symbol("Class")];
var instMirror = reflect(instance);
- var fieldMirror = classMirror.members[new Symbol('field')];
+ var fieldMirror = classMirror.members[const Symbol('field')];
expect(fieldMirror is VariableMirror, isTrue);
expect(fieldMirror.type, equals(mirrors.dynamicType));
@@ -46,22 +82,22 @@
equals([91]));
expect(topLevelField, equals([91]));
- libMirror.setFieldAsync(new Symbol('topLevelField'), 42);
- var future = libMirror.getFieldAsync(new Symbol('topLevelField'));
+ libMirror.setFieldAsync(const Symbol('topLevelField'), 42);
+ var future = libMirror.getFieldAsync(const Symbol('topLevelField'));
future.then(expectAsync1((resultMirror) {
expect(resultMirror.reflectee, equals(42));
expect(topLevelField, equals(42));
}));
- classMirror.setFieldAsync(new Symbol('staticField'), 43);
- future = classMirror.getFieldAsync(new Symbol('staticField'));
+ classMirror.setFieldAsync(const Symbol('staticField'), 43);
+ future = classMirror.getFieldAsync(const Symbol('staticField'));
future.then(expectAsync1((resultMirror) {
expect(resultMirror.reflectee, equals(43));
expect(Class.staticField, equals(43));
}));
- instMirror.setFieldAsync(new Symbol('field'), 44);
- future = instMirror.getFieldAsync(new Symbol('field'));
+ instMirror.setFieldAsync(const Symbol('field'), 44);
+ future = instMirror.getFieldAsync(const Symbol('field'));
future.then(expectAsync1((resultMirror) {
expect(resultMirror.reflectee, equals(44));
expect(instance.field, equals(44));
@@ -87,8 +123,7 @@
}
testInvokeConstructor(mirrors) {
- var libMirror = mirrors.findLibrary(const Symbol("MirrorsTest")).single;
- var classMirror = libMirror.classes[const Symbol("Class")];
+ var classMirror = reflectClass(Class);
var instanceMirror = classMirror.newInstance(const Symbol(''),[]);
expect(instanceMirror.reflectee is Class, equals(true));
@@ -99,14 +134,14 @@
expect(instanceMirror.reflectee is Class, equals(true));
expect(instanceMirror.reflectee.field, equals(45));
- var future = classMirror.newInstanceAsync(new Symbol(''), []);
+ var future = classMirror.newInstanceAsync(const Symbol(''), []);
future.then(expectAsync1((resultMirror) {
var instance = resultMirror.reflectee;
expect(instance is Class, equals(true));
expect(instance.field, equals("default value"));
}));
- future = classMirror.newInstanceAsync(new Symbol('withInitialValue'), [45]);
+ future = classMirror.newInstanceAsync(const Symbol('withInitialValue'), [45]);
future.then(expectAsync1((resultMirror) {
var instance = resultMirror.reflectee;
expect(instance is Class, equals(true));
@@ -163,9 +198,12 @@
expect(check(valueLibrary.uri), isTrue);
}
-main() {
+mainWithArgument({bool isDart2js}) {
var mirrors = currentMirrorSystem();
test("Test reflective method invocation", () { testInvoke(mirrors); });
+ test("Test instance field access", () { testInstanceFieldAccess(mirrors); });
+ test('Test intercepted objects', () { testIntercepted(mirrors); });
+ if (isDart2js) return;
test("Test field access", () { testFieldAccess(mirrors); });
test("Test closure mirrors", () { testClosureMirrors(mirrors); });
test("Test invoke constructor", () { testInvokeConstructor(mirrors); });
@@ -179,3 +217,7 @@
testLibraryUri("test", (Uri uri) => uri == Uri.parse('dart:core'));
});
}
+
+main() {
+ mainWithArgument(isDart2js: false);
+}
diff --git a/tests/standalone/debugger/basic_debugger_test.dart b/tests/standalone/debugger/basic_debugger_test.dart
index ed415a4..f558460 100644
--- a/tests/standalone/debugger/basic_debugger_test.dart
+++ b/tests/standalone/debugger/basic_debugger_test.dart
@@ -15,6 +15,8 @@
print(x);
}
+bam(a) => bar(a);
+
foo(i) {
bar("baz");
print(i);
@@ -24,6 +26,7 @@
if (RunScript(testScript)) return;
print("Hello from debuggee");
foo(42);
+ bam("bam");
print("Hello again");
}
@@ -37,5 +40,10 @@
Resume(),
MatchFrames(["bar", "foo", "main"]),
MatchFrame(1, "foo"),
+ SetBreakpoint(18), // Set breakpoint a line 18, in function bam.
+ Resume(),
+ MatchFrames(["bam", "main"]),
+ Resume(),
+ MatchFrames(["bar", "bam", "main"]),
Resume(),
];
\ No newline at end of file
diff --git a/tests/standalone/debugger/debug_lib.dart b/tests/standalone/debugger/debug_lib.dart
index ff51f9b..977d824 100644
--- a/tests/standalone/debugger/debug_lib.dart
+++ b/tests/standalone/debugger/debug_lib.dart
@@ -179,7 +179,7 @@
var id = template["id"];
assert(id != null && id >= 0);
if (response["id"] != id) {
- debugger.error("Expected messaged id $id but got ${response["id"]}.");
+ debugger.error("Error: expected messaged id $id but got ${response["id"]}.");
}
}
}
@@ -207,7 +207,7 @@
}
}
if (frames.length < functionNames.length) {
- debugger.error("stack trace not long enough "
+ debugger.error("Error: stack trace not long enough "
"to match ${functionNames.length} frames");
return;
}
@@ -216,7 +216,7 @@
var name = frames[idx]["functionName"];
assert(name != null);
if (name != functionNames[i]) {
- debugger.error("call frame $idx: "
+ debugger.error("Error: call frame $idx: "
"expected function name '${functionNames[i]}' but found '$name'");
return;
}
@@ -305,6 +305,7 @@
int seqNr = 0; // Sequence number of next debugger command message.
Command lastCommand = null; // Most recent command sent to target.
List<String> errors = new List();
+ bool cleanupDone = false;
// Data collected from debug target.
Map currentMessage = null; // Currently handled message sent by target.
@@ -344,7 +345,7 @@
print("Debuggee isolate id ${msg["params"]["id"]} shut down.");
shutdownEventSeen = true;
if (!script.isEmpty) {
- error("Premature isolate shutdown event seen.");
+ error("Error: premature isolate shutdown event seen.");
}
}
} else if (msg["event"] == "breakpointResolved") {
@@ -360,7 +361,7 @@
} else if (msg["event"] == "paused") {
isPaused = true;
} else {
- error("unknown debugger event received");
+ error("Error: unknown debugger event received");
}
}
@@ -409,7 +410,7 @@
if (responses.haveGarbage()) {
error("Error: leftover text after message: '${responses.buffer}'");
error("Previous message may be malformed, was: '$msg'");
- close(killDebugee: true);
+ cleanup();
return;
}
var msgObj = JSON.parse(msg);
@@ -417,11 +418,11 @@
if (errorsDetected) {
error("Error while handling script entry");
error("Message received from debug target: $msg");
- close(killDebugee: true);
+ cleanup();
return;
}
if (shutdownEventSeen) {
- close();
+ cleanup();
return;
}
if (isPaused) sendNextCommand();
@@ -464,18 +465,18 @@
handleMessages();
} catch(e, trace) {
print("Unexpected exception:\n$e\n$trace");
- close(killDebugee: true);
+ cleanup();
}
},
onDone: () {
print("Connection closed by debug target");
- close(killDebugee: true);
+ cleanup();
},
onError: (e) {
print("Error '$e' detected in input stream from debug target");
var trace = getAttachedStackTrace(e);
if (trace != null) print("StackTrace: $trace");
- close(killDebugee: true);
+ cleanup();
});
},
onError: (e) {
@@ -483,21 +484,34 @@
var trace = getAttachedStackTrace(e);
if (trace != null) msg += "\nStackTrace: $trace";
error(msg);
- close(killDebugee: true);
+ cleanup();
});
}
- void close({killDebugee: false}) {
- if (errorsDetected) {
- for (int i = 0; i < errors.length; i++) print(errors[i]);
+ void cleanup() {
+ if (cleanupDone) return;
+ if (socket != null) {
+ socket.close().catchError((error) {
+ // Print this directly in addition to adding it to the
+ // error message queue, in case the error message queue
+ // gets printed before this error handler is called.
+ print("Error occurred while closing socket: $error");
+ error("Error while closing socket: $error");
+ });
}
- if (socket != null) socket.close();
- if (killDebugee) {
- targetProcess.kill();
- print("Target process killed");
- }
- if (errorsDetected) throw "Errors detected";
- exit(errors.length);
+ targetProcess.kill();
+ // If the process was already dead exitCode is already
+ // available and we call exit() in the next event loop cycle.
+ // Otherwise this will wait for the process to exit.
+ targetProcess.exitCode.then((exitCode) {
+ if (errorsDetected) {
+ print("\n===== Errors detected: =====");
+ for (int i = 0; i < errors.length; i++) print(errors[i]);
+ print("============================\n");
+ }
+ exit(errors.length);
+ });
+ cleanupDone = true;
}
}
@@ -508,7 +522,7 @@
return false;
}
verboseWire = options.arguments.contains("--wire");
-
+
// Pick a port in the upper half of the port number range.
var seed = new DateTime.now().millisecondsSinceEpoch;
Random random = new Random(seed);
@@ -536,11 +550,11 @@
});
},
onError: (e) {
- if (++retries >= 3) {
+ if (++retries >= 3) {
print('unable to find unused port: $e');
var trace = getAttachedStackTrace(e);
if (trace != null) print("StackTrace: $trace");
- return -1;
+ return -1;
} else {
// Retry with another random port.
RunScript(script);
diff --git a/tests/standalone/io/http_body_test.dart b/tests/standalone/io/http_body_test.dart
index a6ea742..419e381 100644
--- a/tests/standalone/io/http_body_test.dart
+++ b/tests/standalone/io/http_body_test.dart
@@ -46,7 +46,7 @@
Expect.fail("bad body type");
}
}, onError: (error) {
- if (!shouldFail) Expect.fail("Error unexpected");
+ if (!shouldFail) throw error;
})
.whenComplete(() {
client.close();
@@ -90,9 +90,10 @@
List<int> content,
dynamic expectedBody,
String type,
- {bool shouldFail: false}) {
+ {bool shouldFail: false,
+ Encoding defaultEncoding: Encoding.UTF_8}) {
HttpServer.bind("127.0.0.1", 0).then((server) {
- server.transform(new HttpBodyHandler())
+ server.transform(new HttpBodyHandler(defaultEncoding: defaultEncoding))
.listen((body) {
if (shouldFail) Expect.fail("Error expected");
Expect.equals(type, body.type);
@@ -166,6 +167,7 @@
});
});
}
+
test("text/plain", "body".codeUnits, "body", "text");
test("text/plain; charset=utf-8",
"body".codeUnits,
@@ -245,11 +247,76 @@
"form");
test('application/x-www-form-urlencoded',
- '%E5%B9%B3%3D%E4%BB%AE%E5%90%8D=%26%2324179%3B%26%2320206%3B%26%'
- '2321517%3B&b=%26%2324179%3B%26%2320206%3B%26%2321517%3B'.codeUnits,
+ '%E5%B9%B3%3D%E4%BB%AE%E5%90%8D=%E5%B9%B3%E4%BB%AE%E5%90%8D&b'
+ '=%E5%B9%B3%E4%BB%AE%E5%90%8D'.codeUnits,
{ 'b' : '平仮名',
'平=仮名' : '平仮名'},
"form");
+
+ test('application/x-www-form-urlencoded',
+ 'a=%F8+%26%23548%3B'.codeUnits,
+ { 'a' : '\u{FFFD}Ȥ' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'a=%C3%B8+%C8%A4'.codeUnits,
+ { 'a' : 'ø Ȥ' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'a=%F8+%26%23548%3B'.codeUnits,
+ { 'a' : 'ø Ȥ' },
+ "form",
+ defaultEncoding: Encoding.ISO_8859_1);
+
+ test('application/x-www-form-urlencoded',
+ 'name=%26'.codeUnits,
+ { 'name' : '&' },
+ "form",
+ defaultEncoding: Encoding.ISO_8859_1);
+
+ test('application/x-www-form-urlencoded',
+ 'name=%F8%26'.codeUnits,
+ { 'name' : 'ø&' },
+ "form",
+ defaultEncoding: Encoding.ISO_8859_1);
+
+ test('application/x-www-form-urlencoded',
+ 'name=%26%3B'.codeUnits,
+ { 'name' : '&;' },
+ "form",
+ defaultEncoding: Encoding.ISO_8859_1);
+
+ test('application/x-www-form-urlencoded',
+ 'name=%26%23548%3B%26%23548%3B'.codeUnits,
+ { 'name' : 'ȤȤ' },
+ "form",
+ defaultEncoding: Encoding.ISO_8859_1);
+
+ test('application/x-www-form-urlencoded',
+ 'name=%26'.codeUnits,
+ { 'name' : '&' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'name=%C3%B8%26'.codeUnits,
+ { 'name' : 'ø&' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'name=%26%3B'.codeUnits,
+ { 'name' : '&;' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'name=%C8%A4%26%23548%3B'.codeUnits,
+ { 'name' : 'ȤȤ' },
+ "form");
+
+ test('application/x-www-form-urlencoded',
+ 'name=%C8%A4%C8%A4'.codeUnits,
+ { 'name' : 'ȤȤ' },
+ "form");
}
void main() {
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 0030a7d..c0d4e1e 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -76,6 +76,15 @@
onDone: () {
Expect.isFalse(upgraded);
port2.close();
+ Expect.equals(expectedMethod, method);
+ Expect.stringEquals(expectedUri, uri.toString());
+ Expect.equals(expectedVersion, headers.protocolVersion);
+ if (upgrade) {
+ Expect.equals(0, bytesReceived);
+ // port1 is closed by the listener on the detached data.
+ } else {
+ Expect.equals(expectedBytesReceived, bytesReceived);
+ }
});
if (upgraded) {
@@ -93,15 +102,6 @@
incoming.dataDone.then((_) {
port1.close();
Expect.isFalse(upgraded);
- Expect.equals(expectedMethod, method);
- Expect.stringEquals(expectedUri, uri.toString());
- Expect.equals(expectedVersion, headers.protocolVersion);
- if (upgrade) {
- Expect.equals(0, bytesReceived);
- // port1 is closed by the listener on the detached data.
- } else {
- Expect.equals(expectedBytesReceived, bytesReceived);
- }
});
});
@@ -187,19 +187,19 @@
bool upgrade: false,
int unparsedLength: 0,
String expectedVersion: "1.1"}) {
- _HttpParser httpParser;
- bool headersCompleteCalled;
- bool dataEndCalled;
- bool dataEndClose;
- int statusCode;
- String reasonPhrase;
- HttpHeaders headers;
- int contentLength;
- int bytesReceived;
StreamController controller;
bool upgraded;
void reset() {
+ _HttpParser httpParser;
+ bool headersCompleteCalled;
+ bool dataEndCalled;
+ bool dataEndClose;
+ int statusCode;
+ String reasonPhrase;
+ HttpHeaders headers;
+ int contentLength;
+ int bytesReceived;
httpParser = new _HttpParser.responseParser();
controller = new StreamController();
var port = new ReceivePort();
@@ -338,7 +338,6 @@
_testParseRequest(request, method, "/index.html");
});
-
request = "GET / HTTP/1.0\r\n\r\n";
_testParseRequest(request, "GET", "/",
expectedVersion: "1.0",
@@ -403,6 +402,7 @@
\t b\r
\r
""";
+
headers = new Map();
headers["header-a"] = "AAA";
headers["x-header-b"] = "bbb";
diff --git a/tests/standalone/io/http_proxy_configuration_test.dart b/tests/standalone/io/http_proxy_configuration_test.dart
index 568b47c..829a080 100644
--- a/tests/standalone/io/http_proxy_configuration_test.dart
+++ b/tests/standalone/io/http_proxy_configuration_test.dart
@@ -20,6 +20,7 @@
main() {
expectDirect("http://www.google.com", {});
+
expect("PROXY www.proxy.com:1080",
"http://www.google.com",
{"http_proxy": "www.proxy.com"});
@@ -40,6 +41,36 @@
"https://www.google.com",
{"http_proxy": "www.proxy.com:8080",
"https_proxy": "www.proxys.com:8080"});
+
+ expect("PROXY www.proxy.com:1080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com"});
+ expect("PROXY www.proxy.com:1080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com/"});
+ expect("PROXY www.proxy.com:8080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/"});
+ expect("PROXY www.proxy.com:8080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/index.html"});
+ expect("PROXY www.proxy.com:8080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/",
+ "https_proxy": "http://www.proxy.com:8080/"});
+ expect("PROXY www.proxys.com:8080",
+ "https://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/",
+ "https_proxy": "http://www.proxys.com:8080/"});
+ expect("PROXY www.proxy.com:8080",
+ "http://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/",
+ "https_proxy": "http://www.proxy.com:8080/index.html"});
+ expect("PROXY www.proxys.com:8080",
+ "https://www.google.com",
+ {"http_proxy": "http://www.proxy.com:8080/",
+ "https_proxy": "http://www.proxys.com:8080/index.html"});
+
expectDirect("http://www.google.com",
{"http_proxy": "www.proxy.com:8080",
"no_proxy": "www.google.com"});
diff --git a/tests/standalone/io/url_encoding_test.dart b/tests/standalone/io/url_encoding_test.dart
index c99346a..cbe2130 100644
--- a/tests/standalone/io/url_encoding_test.dart
+++ b/tests/standalone/io/url_encoding_test.dart
@@ -12,6 +12,7 @@
part "../../../sdk/lib/io/http_parser.dart";
part "../../../sdk/lib/io/http_utils.dart";
part "../../../sdk/lib/io/socket.dart";
+part "../../../sdk/lib/io/string_transformer.dart";
void testParseEncodedString() {
String encodedString = 'foo+bar%20foobar%25%26';
@@ -23,19 +24,68 @@
}
void testParseQueryString() {
+ test(String queryString, Map<String, String> expected) {
+ Map<String, String> map = _HttpUtils.splitQueryString(queryString);
+ for (String key in map.keys) {
+ Expect.equals(expected[key], map[key]);
+ }
+ Expect.setEquals(expected.keys.toSet(), map.keys.toSet());
+ }
+
// The query string includes escaped "?"s, "&"s, "%"s and "="s.
// These should not affect the splitting of the string.
- String queryString =
- '%3F=%3D&foo=bar&%26=%25&sqrt2=%E2%88%9A2&name=Franti%C5%A1ek';
- Map<String, String> map = _HttpUtils.splitQueryString(queryString);
- for (String key in map.keys) {
- Expect.equals(map[key], { '&' : '%',
- 'foo' : 'bar',
- '?' : '=',
- 'sqrt2' : '\u221A2',
- 'name' : 'Franti\u0161ek'}[key]);
- }
- Expect.setEquals(map.keys.toSet(), ['&', '?', 'foo', 'sqrt2', 'name']);
+ test('%3F=%3D&foo=bar&%26=%25&sqrt2=%E2%88%9A2&name=Franti%C5%A1ek',
+ { '&' : '%',
+ 'foo' : 'bar',
+ '?' : '=',
+ 'sqrt2' : '\u221A2',
+ 'name' : 'Franti\u0161ek'});
+
+ // Same query string with ; as separator.
+ test('%3F=%3D;foo=bar;%26=%25;sqrt2=%E2%88%9A2;name=Franti%C5%A1ek',
+ { '&' : '%',
+ 'foo' : 'bar',
+ '?' : '=',
+ 'sqrt2' : '\u221A2',
+ 'name' : 'Franti\u0161ek'});
+
+ // Same query string with alternating ; and & separators.
+ test('%3F=%3D&foo=bar;%26=%25&sqrt2=%E2%88%9A2;name=Franti%C5%A1ek',
+ { '&' : '%',
+ 'foo' : 'bar',
+ '?' : '=',
+ 'sqrt2' : '\u221A2',
+ 'name' : 'Franti\u0161ek'});
+ test('%3F=%3D;foo=bar&%26=%25;sqrt2=%E2%88%9A2&name=Franti%C5%A1ek',
+ { '&' : '%',
+ 'foo' : 'bar',
+ '?' : '=',
+ 'sqrt2' : '\u221A2',
+ 'name' : 'Franti\u0161ek'});
+
+ // Corner case tests.
+ test('', { });
+ test('&', { });
+ test(';', { });
+ test('&;', { });
+ test(';&', { });
+ test('&&&&', { });
+ test(';;;;', { });
+ test('a', { 'a' : '' });
+ test('&a&', { 'a' : '' });
+ test(';a;', { 'a' : '' });
+ test('a=', { 'a' : '' });
+ test('a=&', { 'a' : '' });
+ test('a=;', { 'a' : '' });
+ test('a=&b', { 'a' : '', 'b' : '' });
+ test('a=;b', { 'a' : '', 'b' : '' });
+ test('a=&b', { 'a' : '', 'b' : '' });
+ test('a=&b=', { 'a' : '', 'b' : '' });
+
+ // These are not really a legal query string.
+ test('=', { });
+ test('=x', { });
+ test('a==&b===', { 'a' : '=', 'b' : '==' });
}
void main() {
diff --git a/tests/standalone/io/zlib_test.dart b/tests/standalone/io/zlib_test.dart
index 1e83af9..6cfa46f 100644
--- a/tests/standalone/io/zlib_test.dart
+++ b/tests/standalone/io/zlib_test.dart
@@ -24,28 +24,8 @@
controller.add(data);
controller.close();
}
- test(0, [120, 1, 0, 10, 0, 245, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0,
- 255, 255]);
- test(1, [120, 1, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(2, [120, 94, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(3, [120, 94, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(4, [120, 94, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(5, [120, 94, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(6, [120, 156, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(-1, [120, 156, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(7, [120, 218, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(8, [120, 218, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
- test(9, [120, 218, 98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 0,
- 255, 255]);
+ test(6, [120, 156, 99, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0, 175,
+ 0, 46]);
}
@@ -58,8 +38,7 @@
return buffer;
})
.then((data) {
- print(data);
- Expect.listEquals([120, 156, 2, 0, 0, 0, 255, 255], data);
+ Expect.listEquals([120, 156, 3, 0, 0, 0, 0, 1], data);
port.close();
});
controller.close();
@@ -76,9 +55,9 @@
return buffer;
})
.then((data) {
- Expect.equals(26, data.length);
- Expect.listEquals([98, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0, 0,
- 0, 255, 255],
+ Expect.equals(30, data.length);
+ Expect.listEquals([99, 96, 100, 98, 102, 97, 101, 99, 231, 224, 4, 0,
+ 70, 215, 108, 69, 10, 0, 0, 0],
// Skip header, as it can change.
data.sublist(10));
port.close();
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 07c89ac..58dfb16 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -100,6 +100,7 @@
int_array_test: Skip # dart:typed_data support needed.
byte_array_view_optimized_test: Skip # dart:typed_data support needed.
io/web_socket_protocol_processor_test: Skip # Importing code with external keyword
+io/url_encoding_test: Skip # Importing code with external keyword
int_array_load_elimination_test: Skip # This is a VM test
medium_integer_test: Fail, OK # Test fails with JS number semantics: issue 1533.
io/process_exit_negative_test: Fail, OK # relies on a static error that is a warning now.
@@ -114,6 +115,7 @@
deoptimization_test: Fail, OK # Requires bigint.
out_of_memory_test: Fail, OK # d8 handles much larger arrays than Dart VM.
io/options_test: Fail, OK # Cannot pass options to d8.
+io/http_parser_test: Fail, OK # Cancelling a Timer not implemented in d8/jsshell.
[ $compiler == dart2js && $runtime == none ]
io/options_test: Fail
diff --git a/tools/VERSION b/tools/VERSION
index 402316f..e85a212 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 5
-BUILD 8
+BUILD 9
PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 9bccf56..3cfd6e5 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -144,7 +144,8 @@
cmd.extend(['--progress=buildbot', '-v'])
# TODO(ricow): temporary hack to run on fyi with --use_browser_controller
- if os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main":
+ if (os.environ.get('BUILDBOT_SCHEDULER') == "fyi-main" and
+ (runtime == 'chrome' or runtime == 'ff')):
cmd.append('--use_browser_controller')
global IsFirstTestStepCall
diff --git a/tools/bots/cross-vm.py b/tools/bots/cross-vm.py
new file mode 100644
index 0000000..e58c6c0
--- /dev/null
+++ b/tools/bots/cross-vm.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+# 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 os
+import re
+import shutil
+import sys
+import tempfile
+
+import bot
+
+GCS_BUCKET = 'gs://dart-cross-compiled-binaries'
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(os.path.join(SCRIPT_DIR, '..'))
+
+import utils
+
+CROSS_VM = r'cross-(arm)-vm-linux-(release)'
+TARGET_VM = r'target-(arm)-vm-linux-(release)'
+GSUTIL = utils.GetBuildbotGSUtilPath()
+
+def run(args):
+ print 'Running: %s' % (' '.join(args))
+ sys.stdout.flush()
+ bot.RunProcess(args)
+
+def main():
+ name, is_buildbot = bot.GetBotName()
+ build_py = os.path.join('tools', 'build.py')
+ test_py = os.path.join('tools', 'test.py')
+
+ cross_vm_pattern_match = re.match(CROSS_VM, name)
+ target_vm_pattern_match = re.match(TARGET_VM, name)
+ if cross_vm_pattern_match:
+ arch = cross_vm_pattern_match.group(1)
+ mode = cross_vm_pattern_match.group(2)
+
+ bot.Clobber()
+ with bot.BuildStep('Build %s %s' % (arch, mode)):
+ args = [sys.executable, build_py,
+ '-m%s' % mode, '--arch=%s' % arch, 'runtime']
+ run(args)
+
+ tarball = 'cross_build_%s_%s.tar.bz2' % (arch, mode)
+ try:
+ with bot.BuildStep('Create build tarball'):
+ run(['tar', '-cjf', tarball, '--exclude=**/obj',
+ '--exclude=**/obj.host', '--exclude=**/obj.target',
+ '--exclude=**/*analyzer*', 'out/'])
+
+ with bot.BuildStep('Upload build tarball'):
+ uri = "%s/%s" % (GCS_BUCKET, tarball)
+ run([GSUTIL, 'cp', tarball, uri])
+ run([GSUTIL, 'setacl', 'public-read', uri])
+ finally:
+ if os.path.exists(tarball):
+ os.remove(tarball)
+ elif target_vm_pattern_match:
+ arch = target_vm_pattern_match.group(1)
+ mode = target_vm_pattern_match.group(2)
+
+ bot.Clobber()
+ tarball = 'cross_build_%s_%s.tar.bz2' % (arch, mode)
+ try:
+ test_args = [sys.executable, test_py, '--progress=line', '--report',
+ '--time', '--mode=' + mode, '--arch=' + arch, '--compiler=none',
+ '--runtime=vm', '--write-debug-log']
+
+ with bot.BuildStep('Fetch build tarball'):
+ run([GSUTIL, 'cp', "%s/%s" % (GCS_BUCKET, tarball), tarball])
+
+ with bot.BuildStep('Unpack build tarball'):
+ run(['tar', '-xjf', tarball])
+
+ with bot.BuildStep('tests'):
+ run(test_args)
+
+ with bot.BuildStep('checked_tests'):
+ run(test_args + ['--checked'])
+ finally:
+ if os.path.exists(tarball):
+ os.remove(tarball)
+ else:
+ raise Exception("Unknown builder name %s" % name)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 1e9ece5..22f3b28 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -96,6 +96,15 @@
"loop": {},
"loopEnd": {},
"loopStart": {},
+ "noteGrainOn": {
+ "support_level": "untriaged"
+ },
+ "noteOff": {
+ "support_level": "untriaged"
+ },
+ "noteOn": {
+ "support_level": "untriaged"
+ },
"playbackRate": {},
"playbackState": {},
"start": {},
@@ -115,8 +124,17 @@
"createChannelSplitter": {},
"createConvolver": {},
"createDelay": {},
+ "createDelayNode": {
+ "support_level": "untriaged"
+ },
"createDynamicsCompressor": {},
"createGain": {},
+ "createGainNode": {
+ "support_level": "untriaged"
+ },
+ "createJavaScriptNode": {
+ "support_level": "untriaged"
+ },
"createMediaElementSource": {},
"createMediaStreamDestination": {},
"createMediaStreamSource": {},
@@ -178,6 +196,9 @@
"minValue": {},
"name": {},
"setTargetAtTime": {},
+ "setTargetValueAtTime": {
+ "support_level": "untriaged"
+ },
"setValueAtTime": {},
"setValueCurveAtTime": {},
"units": {},
@@ -387,6 +408,9 @@
"MEDIA_RULE": {},
"PAGE_RULE": {},
"STYLE_RULE": {},
+ "SUPPORTS_RULE": {
+ "support_level": "untriaged"
+ },
"UNKNOWN_RULE": {
"comment": "http://dev.w3.org/csswg/cssom/#changes-from-dom2",
"dart_action": "suppress",
@@ -477,6 +501,23 @@
},
"support_level": "stable"
},
+ "CSSSupportsRule": {
+ "members": {
+ "conditionText": {
+ "support_level": "untriaged"
+ },
+ "cssRules": {
+ "support_level": "untriaged"
+ },
+ "deleteRule": {
+ "support_level": "untriaged"
+ },
+ "insertRule": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"CSSUnknownRule": {
"comment": "http://dev.w3.org/csswg/cssom/#the-cssstylesheet-interface",
"dart_action": "suppress",
@@ -505,6 +546,14 @@
},
"support_level": "deprecated"
},
+ "Canvas2DContextAttributes": {
+ "members": {
+ "alpha": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"CanvasGradient": {
"comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasgradient",
"members": {
@@ -557,6 +606,9 @@
"fillStyle": {},
"fillText": {},
"font": {},
+ "getContextAttributes": {
+ "support_level": "untriaged"
+ },
"getImageData": {},
"getLineDash": {},
"globalAlpha": {},
@@ -717,6 +769,17 @@
"members": {},
"support_level": "stable"
},
+ "Composition": {
+ "members": {
+ "caret": {
+ "support_level": "untriaged"
+ },
+ "text": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"CompositionEvent": {
"comment": "http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-CompositionEvent",
"members": {
@@ -1208,6 +1271,9 @@
},
"DOMWindow": {
"members": {
+ "CSS": {
+ "support_level": "untriaged"
+ },
"PERSISTENT": {
"comment": "http://www.w3.org/TR/file-system-api/#idl-def-LocalFileSystem",
"support_level": "experimental"
@@ -1464,6 +1530,9 @@
"setInterval": {},
"setTimeout": {},
"showModalDialog": {},
+ "speechSynthesis": {
+ "support_level": "untriaged"
+ },
"status": {},
"statusbar": {},
"stop": {},
@@ -1519,6 +1588,14 @@
},
"support_level": "stable"
},
+ "DOMWindowCSS": {
+ "members": {
+ "supports": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"DataTransferItem": {
"comment": "http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#the-datatransferitem-interface",
"members": {
@@ -5054,6 +5131,32 @@
},
"support_level": "stable"
},
+ "InputMethodContext": {
+ "members": {
+ "composition": {
+ "support_level": "untriaged"
+ },
+ "confirmComposition": {
+ "support_level": "untriaged"
+ },
+ "enabled": {
+ "support_level": "untriaged"
+ },
+ "locale": {
+ "support_level": "untriaged"
+ },
+ "open": {
+ "support_level": "untriaged"
+ },
+ "setCaretRectangle": {
+ "support_level": "untriaged"
+ },
+ "setExclusionRectangle": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"Int16Array": {
"comment": "http://www.khronos.org/registry/typedarray/specs/latest/",
"members": {
@@ -5184,6 +5287,54 @@
},
"support_level": "stable"
},
+ "MIDIConnectionEvent": {
+ "members": {
+ "port": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
+ "MIDIMessageEvent": {
+ "members": {
+ "data": {
+ "support_level": "untriaged"
+ },
+ "receivedTime": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
+ "MIDIPort": {
+ "members": {
+ "addEventListener": {
+ "support_level": "untriaged"
+ },
+ "dispatchEvent": {
+ "support_level": "untriaged"
+ },
+ "id": {
+ "support_level": "untriaged"
+ },
+ "manufacturer": {
+ "support_level": "untriaged"
+ },
+ "name": {
+ "support_level": "untriaged"
+ },
+ "removeEventListener": {
+ "support_level": "untriaged"
+ },
+ "type": {
+ "support_level": "untriaged"
+ },
+ "version": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"MediaController": {
"comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#mediacontroller",
"members": {
@@ -5327,7 +5478,10 @@
"onended": {},
"onremovetrack": {},
"removeEventListener": {},
- "removeTrack": {}
+ "removeTrack": {},
+ "stop": {
+ "support_level": "untriaged"
+ }
},
"support_level": "experimental"
},
@@ -5938,7 +6092,11 @@
"OESTextureHalfFloat": {
"comment": "http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/",
"dart_action": "experimental",
- "members": {},
+ "members": {
+ "HALF_FLOAT_OES": {
+ "support_level": "untriaged"
+ }
+ },
"support_level": "experimental"
},
"OESVertexArrayObject": {
@@ -6001,6 +6159,12 @@
"UNSCHEDULED_STATE": {},
"detune": {},
"frequency": {},
+ "noteOff": {
+ "support_level": "untriaged"
+ },
+ "noteOn": {
+ "support_level": "untriaged"
+ },
"playbackState": {},
"setWaveTable": {},
"start": {},
@@ -6091,6 +6255,27 @@
"Performance": {
"comment": "http://www.w3.org/TR/navigation-timing/#performance",
"members": {
+ "clearMarks": {
+ "support_level": "untriaged"
+ },
+ "clearMeasures": {
+ "support_level": "untriaged"
+ },
+ "getEntries": {
+ "support_level": "untriaged"
+ },
+ "getEntriesByName": {
+ "support_level": "untriaged"
+ },
+ "getEntriesByType": {
+ "support_level": "untriaged"
+ },
+ "mark": {
+ "support_level": "untriaged"
+ },
+ "measure": {
+ "support_level": "untriaged"
+ },
"memory": {
"dart_action": "experimental",
"support_level": "nonstandard"
@@ -9754,6 +9939,9 @@
"comment": "https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#securitypolicyviolationevent-events",
"members": {
"blockedURI": {},
+ "columnNumber": {
+ "support_level": "untriaged"
+ },
"documentURI": {},
"effectiveDirective": {},
"lineNumber": {},
@@ -9936,6 +10124,99 @@
},
"support_level": "experimental"
},
+ "SpeechSynthesis": {
+ "members": {
+ "cancel": {
+ "support_level": "untriaged"
+ },
+ "getVoices": {
+ "support_level": "untriaged"
+ },
+ "pause": {
+ "support_level": "untriaged"
+ },
+ "paused": {
+ "support_level": "untriaged"
+ },
+ "pending": {
+ "support_level": "untriaged"
+ },
+ "resume": {
+ "support_level": "untriaged"
+ },
+ "speak": {
+ "support_level": "untriaged"
+ },
+ "speaking": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
+ "SpeechSynthesisEvent": {
+ "members": {
+ "charIndex": {
+ "support_level": "untriaged"
+ },
+ "elapsedTime": {
+ "support_level": "untriaged"
+ },
+ "name": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
+ "SpeechSynthesisUtterance": {
+ "members": {
+ "SpeechSynthesisUtterance": {},
+ "lang": {
+ "support_level": "untriaged"
+ },
+ "onerror": {
+ "support_level": "untriaged"
+ },
+ "onpause": {
+ "support_level": "untriaged"
+ },
+ "pitch": {
+ "support_level": "untriaged"
+ },
+ "rate": {
+ "support_level": "untriaged"
+ },
+ "text": {
+ "support_level": "untriaged"
+ },
+ "voice": {
+ "support_level": "untriaged"
+ },
+ "volume": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
+ "SpeechSynthesisVoice": {
+ "members": {
+ "default": {
+ "support_level": "untriaged"
+ },
+ "lang": {
+ "support_level": "untriaged"
+ },
+ "localService": {
+ "support_level": "untriaged"
+ },
+ "name": {
+ "support_level": "untriaged"
+ },
+ "voiceURI": {
+ "support_level": "untriaged"
+ }
+ },
+ "support_level": "untriaged"
+ },
"Storage": {
"comment": "http://www.w3.org/TR/webstorage/#the-storage-interface",
"dart_action": "unstable",
diff --git a/tools/dom/scripts/dartgenerator.py b/tools/dom/scripts/dartgenerator.py
index 4fd476c..4f6de3a 100755
--- a/tools/dom/scripts/dartgenerator.py
+++ b/tools/dom/scripts/dartgenerator.py
@@ -210,5 +210,6 @@
ARG = idlnode.IDLArgument([('Type', ('ScopedName', 'object')), ('Id', 'arg')])
for interface in database.GetInterfaces():
for operation in interface.operations:
- if operation.ext_attrs.get('CallWith') == 'ScriptArguments|ScriptState':
+ call_with = operation.ext_attrs.get('CallWith', '').split('|')
+ if 'ScriptArguments' in call_with:
operation.arguments.append(ARG)
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index bcbe91b..0012b76 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -322,7 +322,6 @@
],
'IDBFactory': _indexed_db_annotations,
'IDBDatabase': _indexed_db_annotations,
- 'LocalMediaStream': _rtc_annotations,
'MediaStream': _rtc_annotations,
'MediaStreamEvent': _rtc_annotations,
'MediaStreamTrack': _rtc_annotations,
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 2a512c9..e28460c 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -319,6 +319,7 @@
'Document.querySelector': 'query',
'DOMURL.createObjectURL': 'createObjectUrl',
'DOMURL.revokeObjectURL': 'revokeObjectUrl',
+ 'DOMWindow.CSS': 'css',
'DOMWindow.clearTimeout': '_clearTimeout',
'DOMWindow.clearInterval': '_clearInterval',
'DOMWindow.setTimeout': '_setTimeout',
@@ -364,6 +365,7 @@
# TODO(jacobr): cleanup and augment this list.
_removed_html_members = monitored.Set('htmlrenamer._removed_html_members', [
'Attr.*',
+ 'AudioBufferSourceNode.looping', # TODO(vsm): Use deprecated IDL annotation
'CSSStyleDeclaration.getPropertyCSSValue',
'CanvasRenderingContext2D.clearShadow',
'CanvasRenderingContext2D.drawImageFromRect',
@@ -614,6 +616,13 @@
'NodeIterator.expandEntityReferences',
'NodeIterator.filter',
'NodeList.item',
+ 'Performance.webkitClearMarks',
+ 'Performance.webkitClearMeasures',
+ 'Performance.webkitGetEntries',
+ 'Performance.webkitGetEntriesByName',
+ 'Performance.webkitGetEntriesByType',
+ 'Performance.webkitMark',
+ 'Performance.webkitMeasure',
'ShadowRoot.getElementsByTagNameNS',
'SVGStyledElement.getPresentationAttribute',
'WheelEvent.wheelDelta',
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index 60a6ef7..ea6d78d 100755
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -409,6 +409,13 @@
javascript_interface_name = self.ext_attrs.get('InterfaceName', self.id)
self.javascript_binding_name = javascript_interface_name
self.doc_js_name = javascript_interface_name
+
+ if not (self._find_first(ast, 'Callback') is None):
+ self.ext_attrs['Callback'] = None
+ if not (self._find_first(ast, 'Partial') is None):
+ self.is_supplemental = True
+ self.ext_attrs['Supplemental'] = None
+
self.operations = self._convert_all(ast, 'Operation',
lambda ast: IDLOperation(ast, self.doc_js_name))
self.attributes = self._convert_all(ast, 'Attribute',
@@ -419,6 +426,7 @@
self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs
self.is_fc_suppressed = 'Suppressed' in self.ext_attrs
+
def reset_id(self, new_id):
"""Reset the id of the Interface and corresponding the JS names."""
if self.id != new_id:
@@ -499,6 +507,9 @@
self.type = self._convert_first(ast, 'Type', IDLType)
self.optional = self._has(ast, 'Optional')
self._convert_ext_attrs(ast)
+ # TODO(vsm): Recover this from the type instead.
+ if 'Callback' in self.type.id:
+ self.ext_attrs['Callback'] = None
def __repr__(self):
return '<IDLArgument(type = %s, id = %s)>' % (self.type, self.id)
diff --git a/tools/dom/scripts/idlparser.py b/tools/dom/scripts/idlparser.py
index 194bf4a..6583444 100755
--- a/tools/dom/scripts/idlparser.py
+++ b/tools/dom/scripts/idlparser.py
@@ -90,13 +90,19 @@
[MAYBE(_Annotations), MAYBE(ExtAttrs), 'module', Id,
'{', _Definitions, '}', MAYBE(';')])
+ def Callback():
+ return ['callback']
+
+ def Partial():
+ return ['partial']
+
def Interface():
return syntax_switch(
# Web IDL:
- [MAYBE(ExtAttrs), 'interface', Id, MAYBE(_ParentInterfaces),
+ [MAYBE(ExtAttrs), MAYBE(Partial), MAYBE(Callback), 'interface', Id, MAYBE(_ParentInterfaces),
MAYBE(['{', MAYBE(MANY(_Member)), '}']), ';'],
# WebKit:
- [MAYBE(ExtAttrs), OR('interface', 'exception'), MAYBE(ExtAttrs), Id, MAYBE(_ParentInterfaces),
+ [MAYBE(ExtAttrs), MAYBE(Partial), MAYBE(Callback), OR('interface', 'exception'), MAYBE(ExtAttrs), Id, MAYBE(_ParentInterfaces),
MAYBE(['{', MAYBE(MANY(_Member)), '}']), MAYBE(';')],
# FremontCut:
[MAYBE(_Annotations), MAYBE(ExtAttrs), 'interface',
@@ -206,7 +212,7 @@
[MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier), MAYBE(_Specials),
ReturnType, MAYBE(Id), '(', _Arguments, ')', ';'],
# WebKit:
- [MAYBE(ExtAttrs), MAYBE(Static),
+ [MAYBE(ExtAttrs), MAYBE(Static), MAYBE(_AttrGetterSetter),
ReturnType, MAYBE(Id), '(', _Arguments, ')', ';'],
# FremontCut:
[MAYBE(_Annotations), MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier),
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 2c955bd..a81e322 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -13,6 +13,52 @@
from idlnode import IDLArgument
from systemhtml import js_support_checks, GetCallbackInfo, HTML_LIBRARY_NAMES
+_cpp_type_map = {
+ ('DataTransferItem', 'webkitGetAsEntry'): 'DataTransferItemFileSystem',
+ ('DOMWindow', 'indexedDB'): 'DOMWindowIndexedDatabase',
+ ('DOMWindow', 'speechSynthesis'): 'DOMWindowSpeechSynthesis',
+ ('DOMWindow', 'webkitNotifications'): 'DOMWindowNotifications',
+ ('DOMWindow', 'storage'): 'DOMWindowQuota',
+ ('DOMWindow', 'webkitStorageInfo'): 'DOMWindowQuota',
+ ('DOMWindow', 'openDatabase'): 'DOMWindowWebDatabase',
+ ('DOMWindow', 'webkitRequestFileSystem'): 'DOMWindowFileSystem',
+ ('DOMWindow', 'webkitResolveLocalFileSystemURL'): 'DOMWindowFileSystem',
+ ('HTMLInputElement', 'webkitEntries'): 'HTMLInputElementFileSystem',
+ ('Navigator', 'doNotTrack'): 'NavigatorDoNotTrack',
+ ('Navigator', 'geolocation'): 'NavigatorGeolocation',
+ ('Navigator', 'webkitPersistentStorage'): 'NavigatorStorageQuota',
+ ('Navigator', 'webkitTemporaryStorage'): 'NavigatorStorageQuota',
+ ('Navigator', 'registerProtocolHandler'): 'NavigatorContentUtils',
+ ('Navigator', 'unregisterProtocolHandler'): 'NavigatorContentUtils',
+ ('Navigator', 'webkitGetUserMedia'): 'NavigatorMediaStream',
+ ('Navigator', 'webkitGetGamepads'): 'NavigatorGamepad',
+ }
+
+_cpp_partial_map = {}
+
+def _GetCPPPartialNames(interface_name):
+ if not _cpp_partial_map:
+ for (type, member) in _cpp_type_map.keys():
+ if type not in _cpp_partial_map:
+ _cpp_partial_map[type] = set([])
+ _cpp_partial_map[type].add(_cpp_type_map[(type, member)])
+
+ if interface_name in _cpp_partial_map:
+ return _cpp_partial_map[interface_name]
+ else:
+ return set([])
+
+def _GetCPPTypeName(interface_name, callback_name):
+ # TODO(vsm): We need to track the original IDL file name in order to recover
+ # the proper CPP name.
+
+ cpp_tuple = (interface_name, callback_name)
+ if cpp_tuple in _cpp_type_map:
+ cpp_type_name = _cpp_type_map[cpp_tuple]
+ else:
+ cpp_type_name = interface_name
+ return cpp_type_name
+
class DartiumBackend(HtmlDartGenerator):
"""Generates Dart implementation for one DOM IDL interface."""
@@ -40,7 +86,8 @@
if IsPureInterface(self._interface.id) or IsCustomType(self._interface.id):
return
- cpp_impl_includes = set()
+ cpp_impl_includes = set(['"' + partial + '.h"'
+ for partial in _GetCPPPartialNames(self._interface.id)])
cpp_header_handlers_emitter = emitter.Emitter()
cpp_impl_handlers_emitter = emitter.Emitter()
class_name = 'Dart%s' % self._interface.id
@@ -129,7 +176,8 @@
self._interface_type_info = self._TypeInfo(self._interface.id)
self._members_emitter = members_emitter
self._cpp_declarations_emitter = emitter.Emitter()
- self._cpp_impl_includes = set()
+ self._cpp_impl_includes = set(['"' + partial + '.h"'
+ for partial in _GetCPPPartialNames(self._interface.id)])
self._cpp_definitions_emitter = emitter.Emitter()
self._cpp_resolver_emitter = emitter.Emitter()
@@ -357,6 +405,8 @@
webcore_function_name = '_operator'
elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString':
webcore_function_name = 'svgTarget'
+ elif attr.id == 'CSS':
+ webcore_function_name = 'css'
else:
webcore_function_name = self._ToWebKitName(attr.id)
if attr.type.id.startswith('SVGAnimated'):
@@ -796,6 +846,17 @@
' goto fail;\n'
' }\n')
+
+ if needs_receiver:
+ interface_name = self._interface_type_info.native_type()
+ cpp_type_name = _GetCPPTypeName(interface_name,
+ node.id)
+ if interface_name != cpp_type_name:
+ if interface_name == 'DOMWindow' or interface_name == 'Navigator':
+ cpp_arguments.insert(0, 'receiver')
+ else:
+ cpp_arguments.append('receiver')
+
function_call = '%s(%s)' % (function_expression, ', '.join(cpp_arguments))
if return_type == 'void':
invocation_emitter.Emit(
@@ -843,6 +904,7 @@
NATIVE_BINDING=native_binding)
cpp_callback_name = '%s%s' % (idl_name, native_suffix)
+
self._cpp_resolver_emitter.Emit(
' if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n'
' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n',
@@ -876,7 +938,12 @@
return '%s::%s' % (idl_node.ext_attrs['ImplementedBy'], function_name)
if idl_node.is_static:
return '%s::%s' % (self._interface_type_info.idl_type(), function_name)
- return '%s%s' % (self._interface_type_info.receiver(), function_name)
+ interface_name = self._interface_type_info.idl_type()
+ cpp_type_name = _GetCPPTypeName(interface_name, function_name)
+ if cpp_type_name == interface_name:
+ return '%s%s' % (self._interface_type_info.receiver(), function_name)
+ else:
+ return '%s::%s' % (cpp_type_name, function_name)
def _IsArgumentOptionalInWebCore(self, operation, argument):
if not IsOptional(argument):
diff --git a/tools/dom/src/WebGLConstants.dart b/tools/dom/src/WebGLConstants.dart
index 85b7551..eac8c11 100644
--- a/tools/dom/src/WebGLConstants.dart
+++ b/tools/dom/src/WebGLConstants.dart
@@ -103,7 +103,7 @@
const int GEQUAL = RenderingContext.GEQUAL;
const int GREATER = RenderingContext.GREATER;
const int GREEN_BITS = RenderingContext.GREEN_BITS;
-const int HALF_FLOAT_OES = RenderingContext.HALF_FLOAT_OES;
+const int HALF_FLOAT_OES = OesTextureHalfFloat.HALF_FLOAT_OES;
const int HIGH_FLOAT = RenderingContext.HIGH_FLOAT;
const int HIGH_INT = RenderingContext.HIGH_INT;
const int INCR = RenderingContext.INCR;
diff --git a/tools/dom/templates/html/dartium/cpp_callback_header.template b/tools/dom/templates/html/dartium/cpp_callback_header.template
index 438d36e7..30f3ec3 100644
--- a/tools/dom/templates/html/dartium/cpp_callback_header.template
+++ b/tools/dom/templates/html/dartium/cpp_callback_header.template
@@ -7,9 +7,9 @@
#ifndef Dart$(INTERFACE)_h
#define Dart$(INTERFACE)_h
-#include "ActiveDOMCallback.h"
-#include "DartCallback.h"
-#include "DartDOMWrapper.h"
+#include "bindings/v8/ActiveDOMCallback.h"
+#include "bindings/dart/DartCallback.h"
+#include "bindings/dart/DartDOMWrapper.h"
#include "$(INTERFACE).h"
namespace WebCore {
diff --git a/tools/dom/templates/html/dartium/cpp_callback_implementation.template b/tools/dom/templates/html/dartium/cpp_callback_implementation.template
index 97cb408..3ddcc2d 100644
--- a/tools/dom/templates/html/dartium/cpp_callback_implementation.template
+++ b/tools/dom/templates/html/dartium/cpp_callback_implementation.template
@@ -7,7 +7,7 @@
#include "config.h"
#include "Dart$(INTERFACE).h"
-#include "DartBindingsCommonIncludes.h"
+#include "bindings/dart/DartBindingsCommonIncludes.h"
$INCLUDES
namespace WebCore {
$HANDLERS
diff --git a/tools/dom/templates/html/dartium/cpp_header.template b/tools/dom/templates/html/dartium/cpp_header.template
index bbe5835..f938afc 100644
--- a/tools/dom/templates/html/dartium/cpp_header.template
+++ b/tools/dom/templates/html/dartium/cpp_header.template
@@ -7,7 +7,7 @@
#ifndef Dart$(INTERFACE)_h
#define Dart$(INTERFACE)_h
-#include "DartDOMWrapper.h"
+#include "bindings/dart/DartDOMWrapper.h"
$WEBCORE_INCLUDES
#include <dart_api.h>
diff --git a/tools/dom/templates/html/impl/impl_Navigator.darttemplate b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
index e6ffe05..574a539 100644
--- a/tools/dom/templates/html/impl/impl_Navigator.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
@@ -30,7 +30,7 @@
*
* The user can also pass in Maps to the audio or video parameters to specify
* mandatory and optional constraints for the media stream. Not passing in a
- * map, but passing in `true` will provide a LocalMediaStream with audio or
+ * map, but passing in `true` will provide a MediaStream with audio or
* video capabilities, but without any additional constraints. The particular
* constraint names for audio and video are still in flux, but as of this
* writing, here is an example providing more constraints.
@@ -50,8 +50,8 @@
@DomName('Navigator.webkitGetUserMedia')
@SupportedBrowser(SupportedBrowser.CHROME)
@Experimental
- Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
- var completer = new Completer<LocalMediaStream>();
+ Future<MediaStream> getUserMedia({audio: false, video: false}) {
+ var completer = new Completer<MediaStream>();
var options = {
'audio': audio,
'video': video
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 0912d23..549508c 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -202,7 +202,7 @@
_cleanup = () { userDir.delete(recursive: true); };
var args = ["--user-data-dir=${userDir.path}", url,
"--disable-extensions", "--disable-popup-blocking",
- "--bwsi"];
+ "--bwsi", "--no-first-run"];
return startBrowser(binary, args);
});
@@ -491,7 +491,7 @@
Browser getInstance() {
if (browserName == "chrome") {
return new Chrome();
- } else if (browserName == "firefox") {
+ } else if (browserName == "ff") {
return new Firefox();
}
throw "Non supported browser for browser controller";
@@ -610,9 +610,10 @@
<head>
<title>Driving page</title>
<script type='text/javascript'>
- var numberOfTests = 0;
- var currentId;
+ var number_of_tests = 0;
+ var current_id;
var testing_window;
+ var last_reported_id;
function newTaskHandler() {
if (this.readyState == this.DONE) {
@@ -628,7 +629,7 @@
// URL#ID
var split = this.responseText.split('#');
var nextTask = split[0];
- id = split[1];
+ current_id = split[1];
run(nextTask);
}
} else {
@@ -645,8 +646,8 @@
}
function run(url) {
- numberOfTests++;
- document.getElementById('number').innerHTML = numberOfTests;
+ number_of_tests++;
+ document.getElementById('number').innerHTML = number_of_tests;
if (testing_window == undefined) {
testing_window = window.open(url);
} else {
@@ -658,11 +659,14 @@
var client = new XMLHttpRequest();
function handleReady() {
if (this.readyState == this.DONE) {
- getNextTask();
+ if (current_id != last_reported_id) {
+ getNextTask();
+ last_reported_id = current_id;
+ }
}
}
client.onreadystatechange = handleReady;
- client.open('POST', '$reportPath/${browserId}?id=' + id);
+ client.open('POST', '$reportPath/${browserId}?id=' + current_id);
client.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
client.send(msg);
diff --git a/tools/testing/webdriver_test_setup.py b/tools/testing/webdriver_test_setup.py
index e7a5e97..b1bfe0f 100755
--- a/tools/testing/webdriver_test_setup.py
+++ b/tools/testing/webdriver_test_setup.py
@@ -5,11 +5,11 @@
# BSD-style license that can be found in the LICENSE file.
# Run to install the necessary components to run webdriver on the buildbots or
-# on your local machine.
-# Note: The setup steps can be done fairly easily by hand. This script is
+# on your local machine.
+# Note: The setup steps can be done fairly easily by hand. This script is
# intended to simply and reduce the time for setup since there are a fair number
# of steps.
-
+
# TODO(efortuna): Rewrite this script in Dart when the Process module has a
# better high level API.
import HTMLParser
@@ -30,7 +30,7 @@
the command.
"""
print cmd
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, shell=True)
output, stderr = p.communicate(input=stdin)
if output:
@@ -49,7 +49,7 @@
parser.add_option('--iedriver', '-i', dest='iedriver',
help="Don't install iedriver (only used on Windows).",
action='store_true', default=False)
- parser.add_option('--seleniumrc', '-s', dest='seleniumrc',
+ parser.add_option('--seleniumrc', '-s', dest='seleniumrc',
help="Don't install the Selenium RC server (used for Safari and Opera "
"tests).", action='store_true', default=False)
parser.add_option('--python', '-p', dest='python',
@@ -109,7 +109,7 @@
def find_latest_version(self):
"""Find the latest version number of some code available for download on a
Google code page. This was unfortunately done in an ad hoc manner because
- Google Code does not seem to have an API for their list of current
+ Google Code does not seem to have an API for their list of current
downloads(!).
"""
google_code_site = self.google_code_downloads_page()
diff --git a/tools/upload_sdk.py b/tools/upload_sdk.py
index 83cb113..67f7131 100644
--- a/tools/upload_sdk.py
+++ b/tools/upload_sdk.py
@@ -16,10 +16,9 @@
import utils
-GSUTIL = '/b/build/scripts/slave/gsutil'
+GSUTIL = utils.GetBuildbotGSUtilPath()
HAS_SHELL = False
if platform.system() == 'Windows':
- GSUTIL = 'e:\\\\b\\build\\scripts\\slave\\gsutil'
HAS_SHELL = True
GS_SITE = 'gs://'
GS_DIR = 'dart-dump-render-tree'
diff --git a/tools/utils.py b/tools/utils.py
index eeee968..9ef6c2f 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -196,6 +196,12 @@
'macos': os.path.join('xcodebuild'),
}
+def GetBuildbotGSUtilPath():
+ gsutil = '/b/build/scripts/slave/gsutil'
+ if platform.system() == 'Windows':
+ gsutil = 'e:\\\\b\\build\\scripts\\slave\\gsutil'
+ return gsutil
+
def GetBuildMode(mode):
global BUILD_MODES
return BUILD_MODES[mode]