Version 0.8.2.3
svn merge -c 28641 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 28650 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 28657 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@28709 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 0cc4351..41a06e6 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -660,13 +660,13 @@
Dart_Handle DartUtils::PrepareForScriptLoading(const char* package_root,
Dart_Handle builtin_lib) {
- Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
- DART_CHECK_VALID(corelib);
-
- // Setup the corelib 'print' function.
+ // Setup the internal library's 'internalPrint' function.
+ Dart_Handle internal_lib =
+ Dart_LookupLibrary(NewString("dart:_collection-dev"));
+ DART_CHECK_VALID(internal_lib);
Dart_Handle print = Dart_Invoke(
builtin_lib, NewString("_getPrintClosure"), 0, NULL);
- Dart_Handle result = Dart_SetField(corelib,
+ Dart_Handle result = Dart_SetField(internal_lib,
NewString("_printClosure"),
print);
DART_CHECK_VALID(result);
@@ -685,6 +685,8 @@
async_lib, NewString("_setTimerFactoryClosure"), 1, args));
// Setup the corelib 'Uri.base' getter.
+ Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
+ DART_CHECK_VALID(corelib);
Dart_Handle uri_base = Dart_Invoke(
builtin_lib, NewString("_getUriBaseClosure"), 0, NULL);
DART_CHECK_VALID(uri_base);
diff --git a/runtime/lib/collection_dev_sources.gypi b/runtime/lib/collection_dev_sources.gypi
index 76121f5..63c909f 100644
--- a/runtime/lib/collection_dev_sources.gypi
+++ b/runtime/lib/collection_dev_sources.gypi
@@ -8,6 +8,7 @@
'sources': [
'collection_dev_patch.dart',
# The above file needs to be first as it imports required libraries.
+ 'print_patch.dart',
'symbol_patch.dart',
],
}
diff --git a/runtime/lib/corelib_sources.gypi b/runtime/lib/corelib_sources.gypi
index 3d50b40..95a846d 100644
--- a/runtime/lib/corelib_sources.gypi
+++ b/runtime/lib/corelib_sources.gypi
@@ -38,7 +38,6 @@
'null_patch.dart',
'object.cc',
'object_patch.dart',
- 'print_patch.dart',
'regexp.cc',
'regexp_jsc.cc',
'regexp_jsc.h',
diff --git a/runtime/lib/print_patch.dart b/runtime/lib/print_patch.dart
index 53d034c..186b4fb 100644
--- a/runtime/lib/print_patch.dart
+++ b/runtime/lib/print_patch.dart
@@ -4,8 +4,8 @@
typedef void _PrintClosure(Object obj);
-patch void print(Object obj) {
- _printClosure(obj.toString());
+patch void printToConsole(String line) {
+ _printClosure(line);
}
void _unsupportedPrint(Object obj) {
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index 30a7c5c..d82d903 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -14,6 +14,6 @@
part 'arrays.dart';
part 'iterable.dart';
part 'list.dart';
+part 'print.dart';
part 'sort.dart';
part 'symbol.dart';
-
diff --git a/sdk/lib/_collection_dev/collection_dev_sources.gypi b/sdk/lib/_collection_dev/collection_dev_sources.gypi
index 9cf5415..c85469d 100644
--- a/sdk/lib/_collection_dev/collection_dev_sources.gypi
+++ b/sdk/lib/_collection_dev/collection_dev_sources.gypi
@@ -10,6 +10,7 @@
'arrays.dart',
'iterable.dart',
'list.dart',
+ 'print.dart',
'sort.dart',
'symbol.dart',
],
diff --git a/sdk/lib/_collection_dev/print.dart b/sdk/lib/_collection_dev/print.dart
new file mode 100644
index 0000000..0c7182e
--- /dev/null
+++ b/sdk/lib/_collection_dev/print.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart._collection.dev;
+
+/**
+ * This function is set by the first allocation of a Zone.
+ *
+ * Once the function is set the core `print` function calls this closure instead
+ * of [printToConsole].
+ *
+ * This decouples the core library from the async library.
+ */
+Function printToZone = null;
+
+external void printToConsole(String line);
diff --git a/sdk/lib/_internal/lib/collection_dev_patch.dart b/sdk/lib/_internal/lib/collection_dev_patch.dart
index f224f24..f7467fd 100644
--- a/sdk/lib/_internal/lib/collection_dev_patch.dart
+++ b/sdk/lib/_internal/lib/collection_dev_patch.dart
@@ -2,7 +2,45 @@
// 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:_foreign_helper' show JS;
+
patch class Symbol implements core.Symbol {
patch const Symbol(String name)
: this._name = name;
}
+
+/**
+ * This is the low-level method that is used to implement
+ * [print]. It is possible to override this function from JavaScript
+ * by defining a function in JavaScript called "dartPrint".
+ */
+patch void printToConsole(String line) {
+ if (JS('bool', r'typeof dartPrint == "function"')) {
+ // Support overriding print from JavaScript.
+ JS('void', r'dartPrint(#)', line);
+ return;
+ }
+
+ // Inside browser or nodejs.
+ if (JS('bool', r'typeof console == "object"') &&
+ JS('bool', r'typeof console.log == "function"')) {
+ JS('void', r'console.log(#)', line);
+ return;
+ }
+
+ // Don't throw inside IE, the console is only defined if dev tools is open.
+ if (JS('bool', r'typeof window == "object"')) {
+ return;
+ }
+
+ // Running in d8, the V8 developer shell, or in Firefox' js-shell.
+ if (JS('bool', r'typeof print == "function"')) {
+ JS('void', r'print(#)', line);
+ return;
+ }
+
+ // This is somewhat nasty, but we don't want to drag in a bunch of
+ // dependencies to handle a situation that cannot happen. So we
+ // avoid using Dart [:throw:] and Dart [toString].
+ JS('void', 'throw "Unable to print message: " + String(#)', line);
+}
diff --git a/sdk/lib/_internal/lib/core_patch.dart b/sdk/lib/_internal/lib/core_patch.dart
index e14786a..cb844e0 100644
--- a/sdk/lib/_internal/lib/core_patch.dart
+++ b/sdk/lib/_internal/lib/core_patch.dart
@@ -24,10 +24,6 @@
return result;
}
-patch void print(Object object) {
- Primitives.printString(object.toString());
-}
-
patch int identityHashCode(Object object) => objectHashCode(object);
// Patch for Object implementation.
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 0219440..8e9c4a3 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -281,42 +281,6 @@
static computeGlobalThis() => JS('', 'function() { return this; }()');
- /**
- * This is the low-level method that is used to implement
- * [print]. It is possible to override this function from JavaScript
- * by defining a function in JavaScript called "dartPrint".
- */
- static void printString(String string) {
- if (JS('bool', r'typeof dartPrint == "function"')) {
- // Support overriding print from JavaScript.
- JS('void', r'dartPrint(#)', string);
- return;
- }
-
- // Inside browser or nodejs.
- if (JS('bool', r'typeof console == "object"') &&
- JS('bool', r'typeof console.log == "function"')) {
- JS('void', r'console.log(#)', string);
- return;
- }
-
- // Don't throw inside IE, the console is only defined if dev tools is open.
- if (JS('bool', r'typeof window == "object"')) {
- return;
- }
-
- // Running in d8, the V8 developer shell, or in Firefox' js-shell.
- if (JS('bool', r'typeof print == "function"')) {
- JS('void', r'print(#)', string);
- return;
- }
-
- // This is somewhat nasty, but we don't want to drag in a bunch of
- // dependencies to handle a situation that cannot happen. So we
- // avoid using Dart [:throw:] and Dart [toString].
- JS('void', 'throw "Unable to print message: " + String(#)', string);
- }
-
static _throwFormatException(String string) {
throw new FormatException(string);
}
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 4d03ccd..f336c60 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -18,7 +18,7 @@
library dart.async;
import "dart:collection";
-import "dart:_collection-dev" show deprecated;
+import "dart:_collection-dev" show deprecated, printToZone, printToConsole;
part 'async_error.dart';
part 'broadcast_stream_controller.dart';
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 80184c2..2306a6e 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -31,6 +31,8 @@
typedef Timer CreatePeriodicTimerHandler(
Zone self, ZoneDelegate parent, Zone zone,
Duration period, void f(Timer timer));
+typedef void PrintHandler(
+ Zone self, ZoneDelegate parent, Zone zone, String line);
typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone,
ZoneSpecification specification,
Map<Symbol, dynamic> zoneValues);
@@ -82,6 +84,7 @@
Duration duration, void f()): null,
Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone,
Duration period, void f(Timer timer)): null,
+ void print(Zone self, ZoneDelegate parent, Zone zone, String line): null,
Zone fork(Zone self, ZoneDelegate parent, Zone zone,
ZoneSpecification specification, Map zoneValues): null
}) = _ZoneSpecification;
@@ -112,6 +115,7 @@
Duration duration, void f()): null,
Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone,
Duration period, void f(Timer timer)): null,
+ void print(Zone self, ZoneDelegate parent, Zone zone, String line): null,
Zone fork(Zone self, ZoneDelegate parent, Zone zone,
ZoneSpecification specification,
Map<Symbol, dynamic> zoneValues): null
@@ -141,6 +145,7 @@
createPeriodicTimer: createPeriodicTimer != null
? createPeriodicTimer
: other.createPeriodicTimer,
+ print : print != null ? print : other.print,
fork: fork != null ? fork : other.fork);
}
@@ -156,6 +161,7 @@
RunAsyncHandler get runAsync;
CreateTimerHandler get createTimer;
CreatePeriodicTimerHandler get createPeriodicTimer;
+ PrintHandler get print;
ForkHandler get fork;
}
@@ -179,6 +185,7 @@
this.runAsync: null,
this.createTimer: null,
this.createPeriodicTimer: null,
+ this.print: null,
this.fork: null
});
@@ -195,6 +202,7 @@
final /*RunAsyncHandler*/ runAsync;
final /*CreateTimerHandler*/ createTimer;
final /*CreatePeriodicTimerHandler*/ createPeriodicTimer;
+ final /*PrintHandler*/ print;
final /*ForkHandler*/ fork;
}
@@ -224,6 +232,7 @@
void scheduleMicrotask(Zone zone, f());
Timer createTimer(Zone zone, Duration duration, void f());
Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
+ void print(Zone zone, String line);
Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues);
}
@@ -386,6 +395,11 @@
Timer createPeriodicTimer(Duration period, void callback(Timer timer));
/**
+ * Prints the given [line].
+ */
+ void print(String line);
+
+ /**
* The error zone is the one that is responsible for dealing with uncaught
* errors. Errors are not allowed to cross zones with different error-zones.
*/
@@ -401,14 +415,14 @@
}
class _ZoneDelegate implements ZoneDelegate {
- final _CustomizedZone _degelationTarget;
+ final _BaseZone _degelationTarget;
Zone get _zone => _degelationTarget;
const _ZoneDelegate(this._degelationTarget);
dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.handleUncaughtError == null) {
parent = parent.parent;
}
@@ -417,7 +431,7 @@
}
dynamic run(Zone zone, f()) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.run == null) {
parent = parent.parent;
}
@@ -426,7 +440,7 @@
}
dynamic runUnary(Zone zone, f(arg), arg) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.runUnary == null) {
parent = parent.parent;
}
@@ -435,7 +449,7 @@
}
dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.runBinary == null) {
parent = parent.parent;
}
@@ -444,7 +458,7 @@
}
ZoneCallback registerCallback(Zone zone, f()) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.registerCallback == null) {
parent = parent.parent;
}
@@ -453,7 +467,7 @@
}
ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg)) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.registerUnaryCallback == null) {
parent = parent.parent;
}
@@ -462,7 +476,7 @@
}
ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2)) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.registerBinaryCallback == null) {
parent = parent.parent;
}
@@ -471,7 +485,7 @@
}
void scheduleMicrotask(Zone zone, f()) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.scheduleMicrotask == null &&
parent._specification.runAsync == null) {
parent = parent.parent;
@@ -490,7 +504,7 @@
}
Timer createTimer(Zone zone, Duration duration, void f()) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.createTimer == null) {
parent = parent.parent;
}
@@ -499,7 +513,7 @@
}
Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.createPeriodicTimer == null) {
parent = parent.parent;
}
@@ -507,9 +521,18 @@
parent, new _ZoneDelegate(parent.parent), zone, period, f);
}
+ void print(Zone zone, String line) {
+ _BaseZone parent = _degelationTarget;
+ while (parent._specification.print == null) {
+ parent = parent.parent;
+ }
+ (parent._specification.print)(
+ parent, new _ZoneDelegate(parent.parent), zone, line);
+ }
+
Zone fork(Zone zone, ZoneSpecification specification,
Map<Symbol, dynamic> zoneValues) {
- _CustomizedZone parent = _degelationTarget;
+ _BaseZone parent = _degelationTarget;
while (parent._specification.fork == null) {
parent = parent.parent;
}
@@ -521,22 +544,22 @@
/**
- * Default implementation of a [Zone].
+ * Base class for Zone implementations.
*/
-class _CustomizedZone implements Zone {
+abstract class _BaseZone implements Zone {
+ const _BaseZone();
+
/// The parent zone.
- final _CustomizedZone parent;
+ _BaseZone get parent;
/// The zone's handlers.
- final ZoneSpecification _specification;
- /// The zone's value map.
- final Map<Symbol, dynamic> _map;
-
- const _CustomizedZone(this.parent, this._specification, this._map);
-
- Zone get _errorZone {
- if (_specification.handleUncaughtError != null) return this;
- return parent._errorZone;
- }
+ ZoneSpecification get _specification;
+ /**
+ * The closest error-handling zone.
+ *
+ * Returns `this` if `this` has an error-handler. Otherwise returns the
+ * parent's error-zone.
+ */
+ Zone get _errorZone;
bool inSameErrorZone(Zone otherZone) => _errorZone == otherZone._errorZone;
@@ -591,6 +614,25 @@
return (arg1, arg2) => this.runBinary(registered, arg1, arg2);
}
}
+}
+
+
+/**
+ * Default implementation of a [Zone].
+ */
+class _CustomizedZone extends _BaseZone {
+ final _BaseZone parent;
+ final ZoneSpecification _specification;
+
+ /// The zone's value map.
+ final Map<Symbol, dynamic> _map;
+
+ const _CustomizedZone(this.parent, this._specification, this._map);
+
+ Zone get _errorZone {
+ if (_specification.handleUncaughtError != null) return this;
+ return parent._errorZone;
+ }
operator [](Symbol key) {
var result = _map[key];
@@ -651,6 +693,10 @@
Timer createPeriodicTimer(Duration duration, void f(Timer timer)) {
return new _ZoneDelegate(this).createPeriodicTimer(this, duration, f);
}
+
+ void print(String line) {
+ new _ZoneDelegate(this).print(this, line);
+ }
}
void _rootHandleUncaughtError(
@@ -735,9 +781,22 @@
return _createPeriodicTimer(duration, callback);
}
+void _rootPrint(Zone self, ZoneDelegate parent, Zone zone, String line) {
+ printToConsole(line);
+}
+
+void _printToZone(String line) {
+ Zone.current.print(line);
+}
+
Zone _rootFork(Zone self, ZoneDelegate parent, Zone zone,
ZoneSpecification specification,
Map<Symbol, dynamic> zoneValues) {
+ // TODO(floitsch): it would be nice if we could get rid of this hack.
+ // Change the static zoneOrDirectPrint function to go through zones
+ // from now on.
+ printToZone = _printToZone;
+
if (specification == null) {
specification = const ZoneSpecification();
} else if (specification is! _ZoneSpecification) {
@@ -756,22 +815,83 @@
return new _CustomizedZone(zone, specification, copiedMap);
}
-const _ROOT_SPECIFICATION = const ZoneSpecification(
- handleUncaughtError: _rootHandleUncaughtError,
- run: _rootRun,
- runUnary: _rootRunUnary,
- runBinary: _rootRunBinary,
- registerCallback: _rootRegisterCallback,
- registerUnaryCallback: _rootRegisterUnaryCallback,
- registerBinaryCallback: _rootRegisterBinaryCallback,
- scheduleMicrotask: _rootScheduleMicrotask,
- createTimer: _rootCreateTimer,
- createPeriodicTimer: _rootCreatePeriodicTimer,
- fork: _rootFork
-);
+class _RootZoneSpecification implements ZoneSpecification {
+ const _RootZoneSpecification();
-const _ROOT_ZONE =
- const _CustomizedZone(null, _ROOT_SPECIFICATION, const <Symbol, dynamic>{});
+ HandleUncaughtErrorHandler get handleUncaughtError =>
+ _rootHandleUncaughtError;
+ RunHandler get run => _rootRun;
+ RunUnaryHandler get runUnary => _rootRunUnary;
+ RunBinaryHandler get runBinary => _rootRunBinary;
+ RegisterCallbackHandler get registerCallback => _rootRegisterCallback;
+ RegisterUnaryCallbackHandler get registerUnaryCallback =>
+ _rootRegisterUnaryCallback;
+ RegisterBinaryCallbackHandler get registerBinaryCallback =>
+ _rootRegisterBinaryCallback;
+ ScheduleMicrotaskHandler get scheduleMicrotask => _rootScheduleMicrotask;
+ @deprecated
+ RunAsyncHandler get runAsync => null;
+ CreateTimerHandler get createTimer => _rootCreateTimer;
+ CreatePeriodicTimerHandler get createPeriodicTimer =>
+ _rootCreatePeriodicTimer;
+ PrintHandler get print => _rootPrint;
+ ForkHandler get fork => _rootFork;
+}
+
+class _RootZone extends _BaseZone {
+ const _RootZone();
+
+ Zone get parent => null;
+ ZoneSpecification get _specification => const _RootZoneSpecification();
+ Zone get _errorZone => this;
+
+ bool inSameErrorZone(Zone otherZone) => otherZone._errorZone == this;
+
+ operator [](Symbol key) => null;
+
+ // Methods that can be customized by the zone specification.
+
+ dynamic handleUncaughtError(error, StackTrace stackTrace) =>
+ _rootHandleUncaughtError(this, null, this, error, stackTrace);
+
+ Zone fork({ZoneSpecification specification, Map zoneValues}) =>
+ _rootFork(this, null, this, specification, zoneValues);
+
+ dynamic run(f()) => _rootRun(this, null, this, f);
+
+ dynamic runUnary(f(arg), arg) => _rootRunUnary(this, null, this, f, arg);
+
+ dynamic runBinary(f(arg1, arg2), arg1, arg2) =>
+ _rootRunBinary(this, null, this, f, arg1, arg2);
+
+ ZoneCallback registerCallback(f()) =>
+ _rootRegisterCallback(this, null, this, f);
+
+ ZoneUnaryCallback registerUnaryCallback(f(arg)) =>
+ _rootRegisterUnaryCallback(this, null, this, f);
+
+ ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) =>
+ _rootRegisterBinaryCallback(this, null, this, f);
+
+ void scheduleMicrotask(void f()) {
+ _rootScheduleMicrotask(this, null, this, f);
+ }
+
+ @deprecated
+ void runAsync(void f()) {
+ scheduleMicrotask(f);
+ }
+
+ Timer createTimer(Duration duration, void f()) =>
+ _rootCreateTimer(this, null, this, duration, f);
+
+ Timer createPeriodicTimer(Duration duration, void f(Timer timer)) =>
+ _rootCreatePeriodicTimer(this, null, this, duration, f);
+
+ void print(String line) => _rootPrint(this, null, this, line);
+}
+
+const _ROOT_ZONE = const _RootZone();
/**
diff --git a/sdk/lib/core/print.dart b/sdk/lib/core/print.dart
index 17ef817..4379ceb 100644
--- a/sdk/lib/core/print.dart
+++ b/sdk/lib/core/print.dart
@@ -4,4 +4,11 @@
part of dart.core;
-external void print(Object object);
+void print(Object object) {
+ String line = object.toString();
+ if (printToZone == null) {
+ printToConsole(line);
+ } else {
+ printToZone(line);
+ }
+}
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
index acc1356..25ac037 100644
--- a/tests/compiler/dart2js/mirrors_used_test.dart
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -59,7 +59,7 @@
// 2. Some code was refactored, and there are more methods.
// Either situation could be problematic, but in situation 2, it is often
// acceptable to increase [expectedMethodCount] a little.
- int expectedMethodCount = 325;
+ int expectedMethodCount = 326;
Expect.isTrue(
generatedCode.length <= expectedMethodCount,
'Too many compiled methods: '
diff --git a/tests/lib/async/intercept_print1_test.dart b/tests/lib/async/intercept_print1_test.dart
new file mode 100644
index 0000000..ad074c0
--- /dev/null
+++ b/tests/lib/async/intercept_print1_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'catch_errors.dart';
+
+var events = [];
+
+void printHandler1(Zone self, ZoneDelegate parent, Zone origin, String line) {
+ events.add("print: $line");
+}
+
+bool shouldIntercept = true;
+
+void printHandler2(Zone self, ZoneDelegate parent, Zone origin, String line) {
+ if (shouldIntercept) {
+ events.add("print **: $line");
+ } else {
+ parent.print(origin, line);
+ }
+}
+
+const TEST_SPEC1 = const ZoneSpecification(print: printHandler1);
+const TEST_SPEC2 = const ZoneSpecification(print: printHandler2);
+
+main() {
+ Zone zone1 = Zone.current.fork(specification: TEST_SPEC1);
+ Zone zone2 = zone1.fork(specification: TEST_SPEC2);
+ zone1.run(() {
+ print("1");
+ print(2);
+ print({3: [4]});
+ });
+ zone2.run(() {
+ print("5");
+ shouldIntercept = false;
+ print(6);
+ });
+ Expect.listEquals(
+ ["print: 1", "print: 2", "print: {3: [4]}", "print **: 5", "print: 6"],
+ events);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 4f047c0..b6fd3d5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 8
BUILD 2
-PATCH 2
+PATCH 3