Version 1.9.0-dev.8.4

svn merge -c 43788 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 43887 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 43892 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 43893 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@43903 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index fe7de66..dc915b3 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -43,7 +43,7 @@
 </style></head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version 1.2.0</h1>
+    <h1 style="color:#999999">Version 1.3.0</h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -147,6 +147,12 @@
       kind of notification being sent. The structure of this field is
       described with each notification.
     </p>
+    <p>
+      In order to be backward compatible, clients should ignore fields that were
+      not specified in the version of the API on which they were based. Clients
+      should also use the server.getVersion request to test that the version of
+      the server supports an API before using it.
+    </p>
     <h3>Eventual Consistency</h3>
     <p>
       TBD
@@ -266,6 +272,9 @@
             <p>A list of the services being subscribed to.</p>
           </dd></dl></dd></dl><h3>Notifications</h3><dl><dt class="notification">server.connected</dt><dd><div class="box"><pre>notification: {
   "event": "server.connected"
+  "params": {
+    "<b>version</b>": String
+  }
 }</pre></div>
         <p>
           Reports that the server is running. This notification is
@@ -277,7 +286,11 @@
           It is not possible to subscribe to or unsubscribe from this
           notification.
         </p>
-      </dd><dt class="notification">server.error</dt><dd><div class="box"><pre>notification: {
+       
+      <h4>Parameters</h4><dl><dt class="field"><b><i>version ( String )</i></b></dt><dd>
+            
+            <p>The version number of the analysis server.</p>
+          </dd></dl></dd><dt class="notification">server.error</dt><dd><div class="box"><pre>notification: {
   "event": "server.error"
   "params": {
     "<b>isFatal</b>": bool
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 0e50099..ab012fe 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -67,7 +67,7 @@
    * The version of the analysis server. The value should be replaced
    * automatically during the build.
    */
-  static final String VERSION = '1.1.0';
+  static final String VERSION = '1.3.0';
 
   /**
    * The number of milliseconds to perform operations before inserting
@@ -267,7 +267,8 @@
         _performance = performanceAfterStartup;
       });
     });
-    Notification notification = new ServerConnectedParams().toNotification();
+    Notification notification =
+        new ServerConnectedParams(VERSION).toNotification();
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
   }
@@ -1293,3 +1294,38 @@
     }
   }
 }
+
+
+/**
+ * Container with global [AnalysisServer] performance statistics.
+ */
+class ServerPerformanceStatistics {
+  /**
+   * The [PerformanceTag] for time spent in
+   * PerformAnalysisOperation._updateIndex.
+   */
+  static PerformanceTag index = new PerformanceTag('index');
+
+  /**
+   * The [PerformanceTag] for time spent in
+   * PerformAnalysisOperation._sendNotices.
+   */
+  static PerformanceTag notices = new PerformanceTag('notices');
+
+  /**
+   * The [PerformanceTag] for time spent performing a _DartIndexOperation.
+   */
+  static PerformanceTag indexOperation = new PerformanceTag('indexOperation');
+
+  /**
+   * The [PerformanceTag] for time spent between calls to
+   * AnalysisServer.performOperation when the server is not idle.
+   */
+  static PerformanceTag intertask = new PerformanceTag('intertask');
+
+  /**
+   * The [PerformanceTag] for time spent between calls to
+   * AnalysisServer.performOperation when the server is idle.
+   */
+  static PerformanceTag idle = new PerformanceTag('idle');
+}
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index f4292bb..5674427 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -223,25 +223,70 @@
     return 748820900;
   }
 }
+
 /**
  * server.connected params
+ *
+ * {
+ *   "version": String
+ * }
  */
-class ServerConnectedParams {
-  Notification toNotification() {
-    return new Notification("server.connected", null);
+class ServerConnectedParams implements HasToJson {
+  /**
+   * The version number of the analysis server.
+   */
+  String version;
+
+  ServerConnectedParams(this.version);
+
+  factory ServerConnectedParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String version;
+      if (json.containsKey("version")) {
+        version = jsonDecoder._decodeString(jsonPath + ".version", json["version"]);
+      } else {
+        throw jsonDecoder.missingKey(jsonPath, "version");
+      }
+      return new ServerConnectedParams(version);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "server.connected params");
+    }
   }
 
+  factory ServerConnectedParams.fromNotification(Notification notification) {
+    return new ServerConnectedParams.fromJson(
+        new ResponseDecoder(null), "params", notification._params);
+  }
+
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["version"] = version;
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("server.connected", toJson());
+  }
+
+  @override
+  String toString() => JSON.encode(toJson());
+
   @override
   bool operator==(other) {
     if (other is ServerConnectedParams) {
-      return true;
+      return version == other.version;
     }
     return false;
   }
 
   @override
   int get hashCode {
-    return 509239412;
+    int hash = 0;
+    hash = _JenkinsSmiHash.combine(hash, version.hashCode);
+    return _JenkinsSmiHash.finish(hash);
   }
 }
 
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index f49ae4a..86879e6 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -87,6 +87,12 @@
    * let the client know that it started correctly.
    *
    * It is not possible to subscribe to or unsubscribe from this notification.
+   *
+   * Parameters
+   *
+   * version ( String )
+   *
+   *   The version number of the analysis server.
    */
   Stream<ServerConnectedParams> onServerConnected;
 
@@ -1531,7 +1537,7 @@
     switch (event) {
       case "server.connected":
         expect(params, isServerConnectedParams);
-        _onServerConnected.add(new ServerConnectedParams());
+        _onServerConnected.add(new ServerConnectedParams.fromJson(decoder, 'params', params));
         break;
       case "server.error":
         expect(params, isServerErrorParams);
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 6072aec..3afd352 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -62,8 +62,15 @@
 
 /**
  * server.connected params
+ *
+ * {
+ *   "version": String
+ * }
  */
-final Matcher isServerConnectedParams = isNull;
+final Matcher isServerConnectedParams = new LazyMatcher(() => new MatchesJsonObject(
+  "server.connected params", {
+    "version": isString
+  }));
 
 /**
  * server.error params
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index b34defb..65854bb 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -6,7 +6,7 @@
   </head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version <version>1.2.0</version></h1>
+    <h1 style="color:#999999">Version <version>1.3.0</version></h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -110,6 +110,12 @@
       kind of notification being sent. The structure of this field is
       described with each notification.
     </p>
+    <p>
+      In order to be backward compatible, clients should ignore fields that were
+      not specified in the version of the API on which they were based. Clients
+      should also use the server.getVersion request to test that the version of
+      the server supports an API before using it.
+    </p>
     <h3>Eventual Consistency</h3>
     <p>
       TBD
@@ -215,6 +221,12 @@
           It is not possible to subscribe to or unsubscribe from this
           notification.
         </p>
+       <params>
+          <field name="version">
+            <ref>String</ref>
+            <p>The version number of the analysis server.</p>
+          </field>
+        </params>
       </notification>
       <notification event="error">
         <p>
diff --git a/pkg/analyzer/lib/options.dart b/pkg/analyzer/lib/options.dart
index 33a9a1e..50519dc 100644
--- a/pkg/analyzer/lib/options.dart
+++ b/pkg/analyzer/lib/options.dart
@@ -65,11 +65,16 @@
   /** Whether to treat warnings as fatal */
   final bool warningsAreFatal;
 
+  /** A table mapping library URIs to the file system path where the library
+   *  source is located.
+   */
+  final Map<String, String> customUrlMappings;
+
   /**
    * Initialize options from the given parsed [args].
    */
   CommandLineOptions._fromArgs(ArgResults args, Map<String,
-      String> definedVariables)
+      String> definedVariables, Map<String, String> customUrlMappings)
       : dartSdkPath = args['dart-sdk'],
         this.definedVariables = definedVariables,
         disableHints = args['no-hints'],
@@ -86,7 +91,8 @@
         showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
         sourceFiles = args.rest,
         warmPerf = args['warm-perf'],
-        warningsAreFatal = args['fatal-warnings'];
+        warningsAreFatal = args['fatal-warnings'],
+        this.customUrlMappings = customUrlMappings;
 
   /**
    * Parse [args] into [CommandLineOptions] describing the specified
@@ -199,6 +205,12 @@
             help: 'Display this help message',
             defaultsTo: false,
             negatable: false)
+        ..addOption(
+            'url-mapping',
+            help: '--url-mapping=libraryUri,/path/to/library.dart directs the '
+                  'analyzer to use "library.dart" as the source for an import '
+                  'of "libraryUri"',
+            allowMultiple: true)
         //
         // Hidden flags.
         //
@@ -260,7 +272,17 @@
           exit(15);
         }
       }
-      return new CommandLineOptions._fromArgs(results, definedVariables);
+      Map<String, String> customUrlMappings = <String, String>{};
+      for (String mapping in results['url-mapping']) {
+        List<String> splitMapping = mapping.split(',');
+        if (splitMapping.length != 2) {
+          _showUsage(parser);
+          exit(15);
+        }
+        customUrlMappings[splitMapping[0]] = splitMapping[1];
+      }
+      return new CommandLineOptions._fromArgs(
+          results, definedVariables, customUrlMappings);
     } on FormatException catch (e) {
       print(e.message);
       _showUsage(parser);
diff --git a/pkg/analyzer/lib/src/analyzer_impl.dart b/pkg/analyzer/lib/src/analyzer_impl.dart
index df17a70..09de9d7 100644
--- a/pkg/analyzer/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer/lib/src/analyzer_impl.dart
@@ -139,6 +139,7 @@
 
   void prepareAnalysisContext(JavaFile sourceFile, Source source) {
     List<UriResolver> resolvers = [
+        new CustomUriResolver(options.customUrlMappings),
         new DartUriResolver(sdk),
         new FileUriResolver()];
     // may be add package resolver
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 7c48e3c..2c01d6d 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -17,7 +17,9 @@
 import 'engine.dart';
 import 'java_core.dart';
 import 'java_engine.dart';
+import 'java_io.dart' show JavaFile;
 import 'sdk.dart' show DartSdk;
+import 'source_io.dart' show FileBasedSource;
 
 /**
  * A function that is used to handle [ContentCache] entries.
@@ -165,6 +167,24 @@
   static bool isDartUri(Uri uri) => DART_SCHEME == uri.scheme;
 }
 
+class CustomUriResolver extends UriResolver {
+  final Map<String, String> _urlMappings;
+
+  CustomUriResolver(this._urlMappings);
+
+  @override
+  Source resolveAbsolute(Uri uri) {
+    String mapping = _urlMappings[uri.toString()];
+    if (mapping == null) return null;
+
+    Uri fileUri = new Uri.file(mapping);
+    if (!fileUri.isAbsolute) return null;
+
+    JavaFile javaFile = new JavaFile.fromUri(fileUri);
+    return new FileBasedSource.con1(javaFile);
+  }
+}
+
 /**
  * Instances of the class `LineInfo` encapsulate information about line and column information
  * within a source file.
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index c1c294b..8f190b8 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -51,6 +51,7 @@
   runReflectiveTests(ConstantValueComputerTest);
   runReflectiveTests(ConstantVisitorTest);
   runReflectiveTests(ContentCacheTest);
+  runReflectiveTests(CustomUriResolverTest);
   runReflectiveTests(DartObjectImplTest);
   runReflectiveTests(DartUriResolverTest);
   runReflectiveTests(DeclaredVariablesTest);
@@ -7733,6 +7734,35 @@
 
 
 @reflectiveTest
+class CustomUriResolverTest {
+  void test_creation() {
+    expect(new CustomUriResolver({}), isNotNull);
+  }
+
+  void test_resolve_unknown_uri() {
+    UriResolver resolver = new CustomUriResolver({
+      'custom:library': '/path/to/library.dart',
+    });
+    Source result = resolver.resolveAbsolute(
+        parseUriWithException("custom:non_library"));
+    expect(result, isNull);
+  }
+
+  void test_resolve_uri() {
+    String path =
+        FileUtilities2.createFile("/path/to/library.dart").getAbsolutePath();
+    UriResolver resolver = new CustomUriResolver({
+      'custom:library': path,
+    });
+    Source result = resolver.resolveAbsolute(
+        parseUriWithException("custom:library"));
+    expect(result, isNotNull);
+    expect(result.fullName, path);
+  }
+}
+
+
+@reflectiveTest
 class HtmlParserTest extends EngineTestCase {
   /**
    * The name of the 'script' tag in an HTML file.
diff --git a/pkg/analyzer/test/options_test.dart b/pkg/analyzer/test/options_test.dart
index 3d16370..dd65283 100644
--- a/pkg/analyzer/test/options_test.dart
+++ b/pkg/analyzer/test/options_test.dart
@@ -30,6 +30,8 @@
       expect(options.sourceFiles, equals(['foo.dart']));
       expect(options.warmPerf, isFalse);
       expect(options.warningsAreFatal, isFalse);
+      expect(options.customUrlMappings, isNotNull);
+      expect(options.customUrlMappings.isEmpty, isTrue);
     });
 
     test('batch', () {
@@ -107,6 +109,17 @@
       expect(options.warningsAreFatal, isTrue);
     });
 
+    test('customUrlMappings', () {
+      CommandLineOptions options = CommandLineOptions.parse([
+          '--dart-sdk', '.',
+          '--url-mapping', 'dart:dummy,/path/to/dummy.dart',
+          'foo.dart']);
+      expect(options.customUrlMappings, isNotNull);
+      expect(options.customUrlMappings.isEmpty, isFalse);
+      expect(options.customUrlMappings['dart:dummy'],
+             equals('/path/to/dummy.dart'));
+    });
+
 //    test('notice unrecognized flags', () {
 //      CommandLineOptions options = new CommandLineOptions.parse(['--bar', '--baz',
 //        'foo.dart']);
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 4f3e7ee..e16641c 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -127,6 +127,11 @@
     return checkPositiveInteger(instruction);
   }
 
+  TypeMask visitDivide(HDivide instruction) {
+    // Always double, as initialized.
+    return instruction.instructionType;
+  }
+
   TypeMask visitNegate(HNegate instruction) {
     HInstruction operand = instruction.operand;
     // We have integer subclasses that represent ranges, so widen any int
diff --git a/runtime/tools/create_snapshot_bin.py b/runtime/tools/create_snapshot_bin.py
index 24095c6..71b72e1 100755
--- a/runtime/tools/create_snapshot_bin.py
+++ b/runtime/tools/create_snapshot_bin.py
@@ -36,7 +36,8 @@
   result.add_option("--url_mapping",
       default=[],
       action="append",
-      help="mapping from url to file name, used when generating snapshots")
+      help=("mapping from url to file name, used when generating snapshots " +
+            "E.g.: --url_mapping=fileUri,/path/to/file.dart"))
   result.add_option("-v", "--verbose",
       help='Verbose output.',
       default=False, action="store_true")
diff --git a/tests/compiler/dart2js_extra/22487_test.dart b/tests/compiler/dart2js_extra/22487_test.dart
new file mode 100644
index 0000000..4bf5426
--- /dev/null
+++ b/tests/compiler/dart2js_extra/22487_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2015, 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 http://dartbug.com/22487
+
+import 'package:expect/expect.dart';
+
+divIsInt(a, b) => (a / b) is int;
+
+main() {
+  Expect.isFalse((divIsInt)(10, 3));
+}
diff --git a/tools/VERSION b/tools/VERSION
index d7305aa..8185edc 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
 MINOR 9
 PATCH 0
 PRERELEASE 8
-PRERELEASE_PATCH 3
+PRERELEASE_PATCH 4