Version 0.4.7.4 .

svn merge -c 21605 https://dart.googlecode.com/svn/branches/bleeding_edge/dart dart
svn merge -c 21608 https://dart.googlecode.com/svn/branches/bleeding_edge/dart dart
svn merge -c 21623 https://dart.googlecode.com/svn/branches/bleeding_edge/dart dart

Review URL: https://codereview.chromium.org//14188009

git-svn-id: http://dart.googlecode.com/svn/trunk@21638 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 97c585c..57b3aca 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -1188,8 +1188,8 @@
                              Map<Element, HInstruction> fieldValues,
                              FunctionElement inlinedFromElement,
                              Node callNode) {
+    constructor = constructor.implementation;
     compiler.withCurrentElement(constructor, () {
-      assert(invariant(constructor, constructor.isImplementation));
       constructors.add(constructor);
 
       List<HInstruction> compiledArguments = new List<HInstruction>();
@@ -1312,8 +1312,13 @@
           FunctionElement target = elements[call];
           Selector selector = elements.getSelector(call);
           Link<Node> arguments = call.arguments;
-          inlineSuperOrRedirect(target, selector, arguments, constructors,
-                                fieldValues, constructor, call);
+          inlineSuperOrRedirect(target,
+                                selector,
+                                arguments,
+                                constructors,
+                                fieldValues,
+                                constructor,
+                                call);
           foundSuperOrRedirect = true;
         } else {
           // A field initializer.
@@ -1343,7 +1348,7 @@
         if (target == null) {
           compiler.internalError("no default constructor available");
         }
-        inlineSuperOrRedirect(target.implementation,
+        inlineSuperOrRedirect(target,
                               selector,
                               const Link<Node>(),
                               constructors,
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 62174c8..3416265 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -339,6 +339,34 @@
   }
 
   /**
+   * Executes [action] on each data event of the stream.
+   *
+   * Completes the returned [Future] when all events of the stream
+   * have been processed. Completes the future with an error if the
+   * stream has an error event, or if [action] throws.
+   */
+  Future forEach(void action(T element)) {
+    _FutureImpl future = new _FutureImpl();
+    StreamSubscription subscription;
+    subscription = this.listen(
+        // TODO(ahe): Restore type when feature is implemented in dart2js
+        // checked mode. http://dartbug.com/7733
+        (/*T*/ element) {
+          _runUserCode(
+            () => action(element),
+            (_) {},
+            _cancelAndError(subscription, future)
+          );
+        },
+        onError: future._setError,
+        onDone: () {
+          future._setValue(null);
+        },
+        cancelOnError: true);
+    return future;
+  }
+
+  /**
    * Checks whether [test] accepts all elements provided by this stream.
    *
    * Completes the [Future] when the answer is known.
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index 4e40a61..3bc32c5 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -414,6 +414,7 @@
   void _handleData(T inputEvent, _EventOutputSink<T> sink) {
     if (_hasFailed) {
       sink._sendData(inputEvent);
+      return;
     }
     bool satisfies;
     try {
diff --git a/tests/language/issue9949_test.dart b/tests/language/issue9949_test.dart
new file mode 100644
index 0000000..cec8102
--- /dev/null
+++ b/tests/language/issue9949_test.dart
@@ -0,0 +1,18 @@
+// 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 dart2js that used to crash in the presence of a
+// super constructor declared external.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+class Crash extends HashMap<String,String> {
+  Crash(): super();
+}
+
+void main() {
+  Crash map = new Crash();
+  Expect.isTrue(map is HashMap);
+}
diff --git a/tests/lib/async/stream_controller_async_test.dart b/tests/lib/async/stream_controller_async_test.dart
index 6949900..9d88104 100644
--- a/tests/lib/async/stream_controller_async_test.dart
+++ b/tests/lib/async/stream_controller_async_test.dart
@@ -125,6 +125,44 @@
 testExtraMethods() {
   Events sentEvents = new Events()..add(7)..add(9)..add(13)..add(87)..close();
 
+  test("forEach", () {
+    StreamController c = new StreamController();
+    Events actualEvents = new Events();
+    Future f = c.stream.forEach(actualEvents.add);
+    f.then(expectAsync1((_) {
+      actualEvents.close();
+      Expect.listEquals(sentEvents.events, actualEvents.events);
+    }));
+    sentEvents.replay(c);
+  });
+
+  test("forEachError", () {
+    Events sentEvents = new Events()..add(7)..error("bad")..add(87)..close();
+    StreamController c = new StreamController();
+    Events actualEvents = new Events();
+    Future f = c.stream.forEach(actualEvents.add);
+    f.catchError(expectAsync1((error) {
+      Expect.equals("bad", error);
+      Expect.listEquals((new Events()..add(7)).events, actualEvents.events);
+    }));
+    sentEvents.replay(c);
+  });
+
+  test("forEachError2", () {
+    Events sentEvents = new Events()..add(7)..add(9)..add(87)..close();
+    StreamController c = new StreamController();
+    Events actualEvents = new Events();
+    Future f = c.stream.forEach((x) {
+      if (x == 9) throw "bad";
+      actualEvents.add(x);
+    });
+    f.catchError(expectAsync1((error) {
+      Expect.equals("bad", error);
+      Expect.listEquals((new Events()..add(7)).events, actualEvents.events);
+    }));
+    sentEvents.replay(c);
+  });
+
   test("firstWhere", () {
     StreamController c = new StreamController();
     Future f = c.stream.firstWhere((x) => (x % 3) == 0);
@@ -373,7 +411,7 @@
 
 testRethrow() {
   TestError error = const TestError();
-  
+
 
   testStream(name, streamValueTransform) {
     test("rethrow-$name-value", () {
@@ -416,6 +454,7 @@
   testStream("where", (s, act) => s.where(act));
   testStreamError("handleError", (s, act) => s.handleError(act));
   testStreamError("handleTest", (s, act) => s.handleError((v) {}, test: act));
+  testFuture("forEach", (s, act) => s.forEach(act));
   testFuture("every", (s, act) => s.every(act));
   testFuture("any", (s, act) => s.any(act));
   testFuture("reduce", (s, act) => s.reduce((a,b) => act(b)));
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index e3a6da2..9990f44 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -360,6 +360,20 @@
 
 
   c = new StreamController();
+  expectedEvents = new Events()..add(2)..add(3)..close();
+  actualEvents = new Events.capture(c.stream.skipWhile((x) => x <= 1));
+  sentEvents.replay(c);
+  Expect.listEquals(expectedEvents.events, actualEvents.events);
+
+
+  c = new StreamController();
+  expectedEvents = new Events()..add(1)..add(2)..add(3)..close();
+  actualEvents = new Events.capture(c.stream.skipWhile((x) => false));
+  sentEvents.replay(c);
+  Expect.listEquals(expectedEvents.events, actualEvents.events);
+
+
+  c = new StreamController();
   expectedEvents = new Events()..add(1)..add(2)..close();
   actualEvents = new Events.capture(c.stream.take(2));
   sentEvents.replay(c);
diff --git a/tools/VERSION b/tools/VERSION
index f7dcd55..eecf41e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 4
 BUILD 7
-PATCH 3
+PATCH 4