Version 2.15.0-15.0.dev

Merge commit '7760548a4b7a6fd68fd3e77592073ae6be67571e' into 'dev'
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index d7acc90..49c2ff5 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -310,13 +310,16 @@
       id ??= js_ast.TemporaryId(idName);
       addSymbol(
           id,
-          js.call('#.privateName(#, #)',
-              [runtimeModule, emitLibraryName(library), js.string(name)]));
+          runtimeCall('privateName(#, #)',
+              [emitLibraryName(library), js.string(name)]));
       if (!containerizeSymbols) {
         // TODO(vsm): Change back to `const`.
         // See https://github.com/dart-lang/sdk/issues/40380.
-        moduleItems.add(js.statement('var # = #.privateName(#, #)',
-            [id, runtimeModule, emitLibraryName(library), js.string(name)]));
+        moduleItems.add(js.statement('var # = #', [
+          id,
+          runtimeCall(
+              'privateName(#, #)', [emitLibraryName(library), js.string(name)])
+        ]));
       }
       return id;
     }
@@ -492,15 +495,15 @@
       // To bootstrap the SDK, this needs to be emitted before other code.
       var symbol = js_ast.TemporaryId('_privateNames');
       items.add(js.statement('const # = Symbol("_privateNames")', symbol));
-      items.add(js.statement(r'''
-        #.privateName = function(library, name) {
+      items.add(runtimeStatement(r'''
+        privateName = function(library, name) {
           let names = library[#];
           if (names == null) names = library[#] = new Map();
           let symbol = names.get(name);
           if (symbol == null) names.set(name, symbol = Symbol(name));
           return symbol;
         }
-      ''', [runtimeModule, symbol, symbol]));
+      ''', [symbol, symbol]));
     }
 
     return items;
@@ -689,9 +692,9 @@
 
     // Track the module name for each library in the module.
     // This data is only required for debugging.
-    moduleItems.add(js.statement(
-        '#.trackLibraries(#, #, #, $sourceMapLocationID);',
-        [runtimeModule, js.string(name), module, partMap]));
+    moduleItems.add(runtimeStatement(
+        'trackLibraries(#, #, #, $sourceMapLocationID)',
+        [js.string(name), module, partMap]));
   }
 
   /// Returns an accessor for [id] via the symbol container.
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index bb8e920..57a1c38a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -392,7 +392,7 @@
 
     var items = startModule(libraries);
     _nullableInference.allowNotNullDeclarations = isBuildingSdk;
-    _typeTable = TypeTable(runtimeModule);
+    _typeTable = TypeTable(runtimeCall);
 
     // Collect all class/type Element -> Node mappings
     // in case we need to forward declare any classes.
@@ -712,8 +712,10 @@
     var jsPeerNames = _extensionTypes.getNativePeers(c);
     if (jsPeerNames.length == 1 && c.typeParameters.isNotEmpty) {
       // Special handling for JSArray<E>
-      body.add(runtimeStatement('setExtensionBaseClass(#, #.global.#)',
-          [className, runtimeModule, jsPeerNames[0]]));
+      body.add(runtimeStatement('setExtensionBaseClass(#, #)', [
+        className,
+        runtimeCall('global.#', [jsPeerNames[0]])
+      ]));
     }
 
     var finishGenericTypeTest = _emitClassTypeTests(c, className, body);
@@ -876,9 +878,9 @@
       arrowFnBody = js_ast.Block(extensionInit);
     }
 
-    body.add(js.statement('#[#.mixinOn] = #', [
+    body.add(js.statement('#[#] = #', [
       className,
-      runtimeModule,
+      runtimeCall('mixinOn'),
       js_ast.ArrowFun([superclassId], arrowFnBody)
     ]));
   }
@@ -1339,8 +1341,7 @@
       var names = extensions
           .map((e) => propertyName(js_ast.memberNameForDartMember(e)))
           .toList();
-      body.add(js.statement('#.#(#, #);', [
-        runtimeModule,
+      body.add(runtimeStatement('#(#, #)', [
         helperName,
         className,
         js_ast.ArrayInitializer(names, multiline: names.length > 4)
@@ -1361,9 +1362,9 @@
     var interfaces = c.implementedTypes.toList()
       ..addAll(c.superclassConstraints());
     if (interfaces.isNotEmpty) {
-      body.add(js.statement('#[#.implements] = () => [#];', [
+      body.add(js.statement('#[#] = () => [#];', [
         className,
-        runtimeModule,
+        runtimeCall('implements'),
         interfaces.map((i) =>
             _emitInterfaceType(i.asInterfaceType, emitNullability: false))
       ]));
@@ -1786,11 +1787,14 @@
     if (c == _coreTypes.objectClass) {
       // Dart does not use ES6 constructors.
       // Add an error to catch any invalid usage.
-      jsMethods.add(
-          js_ast.Method(propertyName('constructor'), js.fun(r'''function() {
-                  throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
-                      ".new(...)` to create a Dart object");
-              }''', [runtimeModule, runtimeModule])));
+      jsMethods.add(js_ast.Method(
+          propertyName('constructor'),
+          js.fun(r'''function() {
+                throw Error("use `new " + # +
+                    ".new(...)` to create a Dart object");
+              }''', [
+            runtimeCall('typeName(#)', [runtimeCall('getReifiedType(this)')])
+          ])));
     } else if (c == _jsArrayClass) {
       // Provide access to the Array constructor property, so it works like
       // other native types (rather than calling the Dart Object "constructor"
@@ -2191,6 +2195,8 @@
     // an ES6 iterator.
     return js_ast.Method(
         js.call('Symbol.iterator'),
+        // TODO(nshahan) Don't access values in `runtimeModule` outside of
+        // `runtimeCall`.
         js.call('function() { return new #.JsIterator(this.#); }', [
           runtimeModule,
           _emitMemberName('iterator', memberClass: _coreTypes.iterableClass)
@@ -3593,13 +3599,14 @@
         // Get the best available location even if the offset is missing.
         // https://github.com/dart-lang/sdk/issues/34942
         var location = p.location;
-        var check = js.statement(' if (#) #.nullFailed(#, #, #, #);', [
+        var check = js.statement(' if (#) #;', [
           condition,
-          runtimeModule,
-          _cacheUri(location?.file?.toString()),
-          js.number(location?.line ?? -1),
-          js.number(location?.column ?? -1),
-          js.escapedString('${p.name}'),
+          runtimeCall('nullFailed(#, #, #, #)', [
+            _cacheUri(location?.file?.toString()),
+            js.number(location?.line ?? -1),
+            js.number(location?.column ?? -1),
+            js.escapedString('${p.name}')
+          ])
         ]);
         body.add(check);
       }
@@ -3928,18 +3935,19 @@
     var conditionSource =
         source.substring(node.conditionStartOffset, node.conditionEndOffset);
     var location = _toSourceLocation(node.conditionStartOffset);
-    return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
+    return js.statement(' if (!#) #;', [
       jsCondition,
-      runtimeModule,
-      if (node.message == null)
-        js_ast.LiteralNull()
-      else
-        _visitExpression(node.message),
-      _cacheUri(location.sourceUrl.toString()),
-      // Lines and columns are typically printed with 1 based indexing.
-      js.number(location.line + 1),
-      js.number(location.column + 1),
-      js.escapedString(conditionSource),
+      runtimeCall('assertFailed(#, #, #, #, #)', [
+        if (node.message == null)
+          js_ast.LiteralNull()
+        else
+          _visitExpression(node.message),
+        _cacheUri(location.sourceUrl.toString()),
+        // Lines and columns are typically printed with 1 based indexing.
+        js.number(location.line + 1),
+        js.number(location.column + 1),
+        js.escapedString(conditionSource),
+      ])
     ]);
   }
 
@@ -4352,16 +4360,14 @@
           clause, catchBody, exceptionParameter, stackTraceParameter);
     }
     var catchStatements = [
-      js.statement('let # = #.getThrown(#)', [
+      js.statement('let # = #', [
         _emitVariableDef(exceptionParameter),
-        runtimeModule,
-        _emitVariableRef(caughtError)
+        runtimeCall('getThrown(#)', [_emitVariableRef(caughtError)])
       ]),
       if (stackTraceParameter != null)
-        js.statement('let # = #.stackTrace(#)', [
+        js.statement('let # = #', [
           _emitVariableDef(stackTraceParameter),
-          runtimeModule,
-          _emitVariableRef(caughtError)
+          runtimeCall('stackTrace(#)', [_emitVariableRef(caughtError)])
         ]),
       catchBody,
     ];
@@ -5218,8 +5224,10 @@
     // a measurable performance effect (possibly the helper is simple enough to
     // be inlined).
     if (isNullable(left)) {
-      return js.call(negated ? '!#.equals(#, #)' : '#.equals(#, #)',
-          [runtimeModule, _visitExpression(left), _visitExpression(right)]);
+      return js.call(negated ? '!#' : '#', [
+        runtimeCall(
+            'equals(#, #)', [_visitExpression(left), _visitExpression(right)])
+      ]);
     }
 
     // Otherwise we emit a call to the == method.
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index b9833db..54a7d17 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -112,9 +112,9 @@
   final typeContainer = ModuleItemContainer<DartType>.asObject('T',
       keyToString: (DartType t) => escapeIdentifier(_typeString(t)));
 
-  final js_ast.Identifier _runtimeModule;
+  final js_ast.Expression Function(String, [List<Object>]) _runtimeCall;
 
-  TypeTable(this._runtimeModule);
+  TypeTable(this._runtimeCall);
 
   /// Returns true if [type] is already recorded in the table.
   bool _isNamed(DartType type) =>
@@ -135,8 +135,10 @@
   List<js_ast.Statement> dischargeBoundTypes() {
     js_ast.Expression emitValue(DartType t, ModuleItemData data) {
       var access = js.call('#.#', [data.id, data.jsKey]);
-      return js.call('() => ((# = #.constFn(#))())',
-          [access, _runtimeModule, data.jsValue]);
+      return js.call('() => ((# = #)())', [
+        access,
+        _runtimeCall('constFn(#)', [data.jsValue])
+      ]);
     }
 
     var boundTypes = typeContainer.emit(emitValue: emitValue);
@@ -153,8 +155,11 @@
     var id = _unboundTypeIds[type];
     // TODO(vsm): Change back to `let`.
     // See https://github.com/dart-lang/sdk/issues/40380.
-    return js.statement('var # = () => ((# = #.constFn(#))());',
-        [id, id, _runtimeModule, init]);
+    return js.statement('var # = () => ((# = #)());', [
+      id,
+      id,
+      _runtimeCall('constFn(#)', [init])
+    ]);
   }
 
   /// Emit a list of statements declaring the cache variables and generator
diff --git a/tools/VERSION b/tools/VERSION
index cd176dc..61d8e8a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 14
+PRERELEASE 15
 PRERELEASE_PATCH 0
\ No newline at end of file