Version 0.2.9.2

Cherry pick 16069 and 16079 from bleeding_edge into trunk.

git-svn-id: http://dart.googlecode.com/svn/trunk@16081 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 934490f..5277d97 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2025,6 +2025,11 @@
 }
 
 
+bool Class::IsFunctionClass() const {
+  return raw() == Type::Handle(Type::Function()).type_class();
+}
+
+
 bool Class::IsListClass() const {
   return raw() == Isolate::Current()->object_store()->list_class();
 }
@@ -2098,16 +2103,42 @@
                                    len,
                                    malformed_error);
   }
-  // TODO(regis): Check if type S has a call() method of function type T.
-  // Check for two function types.
-  if (IsSignatureClass() && other.IsSignatureClass()) {
-    const Function& fun = Function::Handle(signature_function());
+  const bool other_is_function_class = other.IsFunctionClass();
+  if (other.IsSignatureClass() || other_is_function_class) {
     const Function& other_fun = Function::Handle(other.signature_function());
-    return fun.TypeTest(test_kind,
-                        type_arguments,
-                        other_fun,
-                        other_type_arguments,
-                        malformed_error);
+    if (IsSignatureClass()) {
+      if (other_is_function_class) {
+        return true;
+      }
+      // Check for two function types.
+      const Function& fun = Function::Handle(signature_function());
+      return fun.TypeTest(test_kind,
+                          type_arguments,
+                          other_fun,
+                          other_type_arguments,
+                          malformed_error);
+    }
+    // Check if type S has a call() method of function type T.
+    const String& function_name = String::Handle(Symbols::Call());
+    Function& function = Function::Handle(LookupDynamicFunction(function_name));
+    if (function.IsNull()) {
+      // Walk up the super_class chain.
+      Class& cls = Class::Handle(SuperClass());
+      while (!cls.IsNull() && function.IsNull()) {
+        function = cls.LookupDynamicFunction(function_name);
+        cls = cls.SuperClass();
+      }
+    }
+    if (!function.IsNull()) {
+      if (other_is_function_class ||
+          function.TypeTest(test_kind,
+                            type_arguments,
+                            other_fun,
+                            other_type_arguments,
+                            malformed_error)) {
+        return true;
+      }
+    }
   }
   // Check for 'direct super type' specified in the implements clause
   // and check for transitivity at the same time.
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 367f64c..5864410 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -611,6 +611,9 @@
   // Check if this class represents the 'Object' class.
   bool IsObjectClass() const { return id() == kInstanceCid; }
 
+  // Check if this class represents the 'Function' class.
+  bool IsFunctionClass() const;
+
   // Check if this class represents the 'List' class.
   bool IsListClass() const;
 
diff --git a/tests/language/callable_test.dart b/tests/language/callable_test.dart
new file mode 100644
index 0000000..be43bfb
--- /dev/null
+++ b/tests/language/callable_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class X {
+  call() => 42;
+}
+
+class Y {
+  call(int x) => 87;
+}
+
+typedef F(int x);
+typedef G(String y);
+
+main() {
+  X x = new X();
+  Function f = x;  // Should pass checked mode test
+  Y y = new Y();
+  Function g = y;  // Should pass checked mode test
+  F f0 = y;  // Should pass checked mode test
+  F f1 = x;  /// 00: dynamic type error, static type warning
+  G g0 = y;  /// 01: dynamic type error, static type warning
+}
+
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 0c88a52..be05302 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -53,6 +53,7 @@
 factory1_test/00: Fail
 factory1_test/01: Fail
 type_annotation_test/09: Fail # Named constructors interpreted as a type.
+callable_test/0*: Fail # Issue 7354
 
 [ $compiler == dart2js && $unchecked ]
 default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
diff --git a/tools/VERSION b/tools/VERSION
index f2f2502..5e43b49 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 2
 BUILD 9
-PATCH 1
+PATCH 2
diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart
index 420952c..01c03bc 100644
--- a/utils/pub/command_lish.dart
+++ b/utils/pub/command_lish.dart
@@ -15,6 +15,7 @@
 import 'io.dart';
 import 'log.dart' as log;
 import 'oauth2.dart' as oauth2;
+import 'path.dart' as path;
 import 'pub.dart';
 import 'validator.dart';
 
@@ -164,7 +165,20 @@
             // Should instead only make these relative right before generating
             // the tree display (which is what really needs them to be).
             // Make it relative to the package root.
-            return relativeTo(entry, rootDir);
+            entry = relativeTo(entry, rootDir);
+
+            // TODO(rnystrom): dir.list() will include paths with resolved
+            // symlinks. In particular, we'll get paths to symlinked files from
+            // "packages" that reach outside of this package. Since the path
+            // has already been resolved, we don't even see "packages" in that
+            // path anymore.
+            // These should not be included in the archive. As a hack, ignore
+            // any file whose relative path is backing out of the root
+            // directory. Should do something cleaner.
+            var parts = path.split(entry);
+            if (!parts.isEmpty && parts[0] == '..') return null;
+
+            return entry;
           });
         }));
       });