Version 2.14.0-263.0.dev

Merge commit '63ac437e9934c6422c96e5195201e8968bc8dfc6' into 'dev'
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
index 4b41e12..b29d418 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -12,6 +12,8 @@
 /// emits the code as a JavaScript code fragment.
 class JsUtilOptimizer extends Transformer {
   final Procedure _jsTarget;
+  final Procedure _callMethodTarget;
+  final List<Procedure> _callMethodUncheckedTargets;
   final Procedure _getPropertyTarget;
   final Procedure _setPropertyTarget;
   final Procedure _setPropertyUncheckedTarget;
@@ -27,6 +29,7 @@
   ];
   final Iterable<Procedure> _allowedInteropJsUtilTargets;
   final Procedure _allowInteropTarget;
+  final Procedure _listEmptyFactory;
 
   final CoreTypes _coreTypes;
   final StatefulStaticTypeContext _staticTypeContext;
@@ -34,6 +37,12 @@
   JsUtilOptimizer(this._coreTypes, ClassHierarchy hierarchy)
       : _jsTarget =
             _coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
+        _callMethodTarget =
+            _coreTypes.index.getTopLevelMember('dart:js_util', 'callMethod'),
+        _callMethodUncheckedTargets = List<Procedure>.generate(
+            5,
+            (i) => _coreTypes.index
+                .getTopLevelMember('dart:js_util', '_callMethodUnchecked$i')),
         _getPropertyTarget =
             _coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty'),
         _setPropertyTarget =
@@ -45,6 +54,8 @@
         _allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
             (member) =>
                 _coreTypes.index.getTopLevelMember('dart:js_util', member)),
+        _listEmptyFactory =
+            _coreTypes.index.getMember('dart:core', 'List', 'empty'),
         _staticTypeContext = StatefulStaticTypeContext.stacked(
             TypeEnvironment(_coreTypes, hierarchy)) {}
 
@@ -69,12 +80,16 @@
   /// Lowers `getProperty` for any argument type straight to JS fragment call.
   /// Lowers `setProperty` to `_setPropertyUnchecked` for values that are
   /// not Function type and guaranteed to be interop allowed.
+  /// Lowers `callMethod` to `_callMethodUncheckedN` when the number of given
+  /// arguments is 0-4 and all arguments are guaranteed to be interop allowed.
   @override
   visitStaticInvocation(StaticInvocation node) {
     if (node.target == _getPropertyTarget) {
       node = _lowerGetProperty(node);
     } else if (node.target == _setPropertyTarget) {
       node = _lowerSetProperty(node);
+    } else if (node.target == _callMethodTarget) {
+      node = _lowerCallMethod(node);
     }
     node.transformChildren(this);
     return node;
@@ -104,6 +119,7 @@
 
   /// Lowers the given js_util `setProperty` call to `_setPropertyUnchecked`
   /// when the additional validation checks in `setProperty` can be elided.
+  ///
   /// Removing the checks allows further inlining by the compilers.
   StaticInvocation _lowerSetProperty(StaticInvocation node) {
     Arguments arguments = node.arguments;
@@ -119,6 +135,85 @@
       ..fileOffset = node.fileOffset;
   }
 
+  /// Lowers the given js_util `callMethod` call to `_callMethodUncheckedN`
+  /// when the additional validation checks on the arguments can be elided.
+  ///
+  /// Calls will be lowered when using a List literal or constant list with 0-4
+  /// elements for the `callMethod` arguments, or the `List.empty()` factory.
+  /// Removing the checks allows further inlining by the compilers.
+  StaticInvocation _lowerCallMethod(StaticInvocation node) {
+    Arguments arguments = node.arguments;
+    assert(arguments.types.isEmpty);
+    assert(arguments.positional.length == 3);
+    assert(arguments.named.isEmpty);
+
+    // Lower List.empty factory call.
+    var argumentsList = arguments.positional.last;
+    if (argumentsList is StaticInvocation &&
+        argumentsList.target == _listEmptyFactory) {
+      return _createNewCallMethodNode([], arguments, node.fileOffset);
+    }
+
+    // Lower other kinds of Lists.
+    var callMethodArguments;
+    var entryType;
+    if (argumentsList is ListLiteral) {
+      if (argumentsList.expressions.length >=
+          _callMethodUncheckedTargets.length) {
+        return node;
+      }
+      callMethodArguments = argumentsList.expressions;
+      entryType = argumentsList.typeArgument;
+    } else if (argumentsList is ConstantExpression &&
+        argumentsList.constant is ListConstant) {
+      var argumentsListConstant = argumentsList.constant as ListConstant;
+      if (argumentsListConstant.entries.length >=
+          _callMethodUncheckedTargets.length) {
+        return node;
+      }
+      callMethodArguments = argumentsListConstant.entries
+          .map((constant) => ConstantExpression(
+              constant, constant.getType(_staticTypeContext)))
+          .toList();
+      entryType = argumentsListConstant.typeArgument;
+    } else {
+      // Skip lowering any other type of List.
+      return node;
+    }
+
+    // Check the overall List entry type, then verify each argument if needed.
+    if (!_allowedInteropType(entryType)) {
+      for (var argument in callMethodArguments) {
+        if (!_allowedInterop(argument)) {
+          return node;
+        }
+      }
+    }
+
+    return _createNewCallMethodNode(
+        callMethodArguments, arguments, node.fileOffset);
+  }
+
+  /// Creates a new StaticInvocation node for `_callMethodUncheckedN` with the
+  /// given 0-4 arguments.
+  StaticInvocation _createNewCallMethodNode(
+      List<Expression> callMethodArguments,
+      Arguments arguments,
+      int nodeFileOffset) {
+    assert(callMethodArguments.length <= 4);
+    return StaticInvocation(
+        _callMethodUncheckedTargets[callMethodArguments.length],
+        Arguments(
+          [
+            arguments.positional[0],
+            arguments.positional[1],
+            ...callMethodArguments
+          ],
+          types: [],
+        )..fileOffset = arguments.fileOffset)
+      ..fileOffset = nodeFileOffset;
+  }
+
   /// Returns whether the given Expression is guaranteed to be allowed to
   /// interop with JS.
   ///
@@ -138,7 +233,12 @@
       if (_allowedInteropJsUtilTargets.contains(node.target)) return true;
     }
 
-    var type = node.getStaticType(_staticTypeContext);
+    return _allowedInteropType(node.getStaticType(_staticTypeContext));
+  }
+
+  /// Returns whether the given DartType is guaranteed to be not a function
+  /// and therefore allowed to interop with JS.
+  bool _allowedInteropType(DartType type) {
     if (type is InterfaceType) {
       return type.classNode != _coreTypes.functionClass &&
           type.classNode != _coreTypes.objectClass;
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index 867fd7f..ee3dd0f 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -68,13 +68,12 @@
 
 bool hasProperty(Object o, Object name) => JS('bool', '# in #', name, o);
 
-// All usage optimized away in a CFE transformation. Changes here will not
-// affect the generated JS.
+// A CFE transformation will optimize all calls to `getProperty`.
 dynamic getProperty(Object o, Object name) =>
     JS('Object|Null', '#[#]', o, name);
 
-// Some usage optimized away in a CFE transformation. If given value is a
-// function, changes here will not affect the generated JS.
+// A CFE transformation may optimize calls to `setProperty`, when [value] is
+// statically known to be a non-function.
 dynamic setProperty(Object o, Object name, Object? value) {
   assertInterop(value);
   return JS('', '#[#]=#', o, name, value);
@@ -86,11 +85,48 @@
   return JS('', '#[#]=#', o, name, value);
 }
 
+// A CFE transformation may optimize calls to `callMethod` when [args] is a
+// a list literal or const list containing at most 4 values, all of which are
+// statically known to be non-functions.
 dynamic callMethod(Object o, String method, List<Object?> args) {
   assertInteropArgs(args);
   return JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
 }
 
+/// Unchecked version for 0 arguments, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _callMethodUnchecked0(Object o, String method) {
+  return JS('Object|Null', '#[#]()', o, method);
+}
+
+/// Unchecked version for 1 argument, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _callMethodUnchecked1(Object o, String method, Object? arg1) {
+  return JS('Object|Null', '#[#](#)', o, method, arg1);
+}
+
+/// Unchecked version for 2 arguments, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _callMethodUnchecked2(
+    Object o, String method, Object? arg1, Object? arg2) {
+  return JS('Object|Null', '#[#](#, #)', o, method, arg1, arg2);
+}
+
+/// Unchecked version for 3 arguments, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _callMethodUnchecked3(
+    Object o, String method, Object? arg1, Object? arg2, Object? arg3) {
+  return JS('Object|Null', '#[#](#, #, #)', o, method, arg1, arg2, arg3);
+}
+
+/// Unchecked version for 4 arguments, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _callMethodUnchecked4(Object o, String method, Object? arg1,
+    Object? arg2, Object? arg3, Object? arg4) {
+  return JS(
+      'Object|Null', '#[#](#, #, #, #)', o, method, arg1, arg2, arg3, arg4);
+}
+
 /// Check whether [o] is an instance of [type].
 ///
 /// The value in [type] is expected to be a JS-interop object that
diff --git a/tests/lib/js/js_util/properties_implicit_checks_test.dart b/tests/lib/js/js_util/properties_implicit_checks_test.dart
new file mode 100644
index 0000000..90a8349
--- /dev/null
+++ b/tests/lib/js/js_util/properties_implicit_checks_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, 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.
+
+// Tests the functionality of object properties with the js_util library that
+// involve implicit type checks.
+
+@JS()
+library js_util_properties_implicit_checks_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class CallMethodTest {
+  external CallMethodTest();
+
+  external one(a);
+}
+
+main() {
+  eval(r"""
+    function CallMethodTest() {}
+
+    CallMethodTest.prototype.one = function(a) {
+      return 'one';
+    }
+    """);
+
+  var o = CallMethodTest();
+  expect(() => js_util.callMethod(o, 'one', <String>[5 as dynamic]), throws);
+  expect(() => js_util.callMethod(o, 'one', <int>['foo' as dynamic]), throws);
+}
diff --git a/tests/lib/js/js_util/properties_test.dart b/tests/lib/js/js_util/properties_test.dart
index a9db3d2..326de20 100644
--- a/tests/lib/js/js_util/properties_test.dart
+++ b/tests/lib/js/js_util/properties_test.dart
@@ -53,6 +53,9 @@
 class DartClass {
   int x = 3;
   int getX() => x;
+
+  static staticFunction() => 'static';
+  static const staticConstList = [1];
 }
 
 class GenericDartClass<T> {
@@ -70,6 +73,18 @@
   return 'bar';
 }
 
+@JS()
+class CallMethodTest {
+  external CallMethodTest();
+
+  external zero();
+  external one(a);
+  external two(a, b);
+  external three(a, b, c);
+  external four(a, b, c, d);
+  external five(a, b, c, d, e);
+}
+
 main() {
   eval(r"""
     function Foo(a) {
@@ -121,6 +136,27 @@
     Foo.prototype.callFn = function(fn) {
       return fn();
     }
+
+    function CallMethodTest() {}
+
+    CallMethodTest.prototype.zero = function() {
+      return 'zero';
+    }
+    CallMethodTest.prototype.one = function(a) {
+      return 'one';
+    }
+    CallMethodTest.prototype.two = function(a, b) {
+      return 'two';
+    }
+    CallMethodTest.prototype.three = function(a, b, c) {
+      return 'three';
+    }
+    CallMethodTest.prototype.four = function(a, b, c, d) {
+      return 'four';
+    }
+    CallMethodTest.prototype.five = function(a, b, c, d, e) {
+      return 'five';
+    }
     """);
 
   group('newObject', () {
@@ -324,6 +360,8 @@
         return 'Inline';
       }));
       expect(js_util.callMethod(f, 'bar', []), equals('Inline'));
+      js_util.setProperty(f, 'bar', allowInterop(DartClass.staticFunction));
+      expect(js_util.callMethod(f, 'bar', []), equals('static'));
 
       // Set property to a JS function.
       js_util.setProperty(f, 'bar', allowInterop(jsFunction));
@@ -403,16 +441,20 @@
       expect(js_util.callMethod(f, 'sumFn', [2, 3]), equals(5));
       expect(js_util.callMethod(f, 'getA', [f]), equals(42));
       expect(js_util.callMethod(f, 'callFn', [allowInterop(jsFunction)]),
-          equals("JS Function"));
+          equals('JS Function'));
       expect(js_util.callMethod(f, 'callFn', [allowInterop(dartFunction)]),
-          equals("Dart Function"));
+          equals('Dart Function'));
       expect(
           js_util.callMethod(f, 'callFn', [
             allowInterop(() {
-              return "inline";
+              return 'inline';
             })
           ]),
-          equals("inline"));
+          equals('inline'));
+      expect(
+          js_util.callMethod(
+              f, 'callFn', [allowInterop(DartClass.staticFunction)]),
+          equals('static'));
 
       // Using a variable for the method name.
       String methodName = 'bar';
@@ -420,6 +462,70 @@
       String bar = _getBarWithSideEffect();
       expect(js_util.callMethod(f, bar, []), equals(42));
     });
+
+    test('callMethod with List edge cases', () {
+      var o = CallMethodTest();
+
+      expect(js_util.callMethod(o, 'zero', List.empty()), equals('zero'));
+      expect(js_util.callMethod(o, 'zero', List<int>.empty()), equals('zero'));
+
+      expect(
+          js_util.callMethod(o, 'two', List<int>.filled(2, 0)), equals('two'));
+      expect(js_util.callMethod(o, 'three', List<int>.generate(3, (i) => i)),
+          equals('three'));
+
+      Iterable<String> iterableStrings = <String>['foo', 'bar'];
+      expect(js_util.callMethod(o, 'two', List.of(iterableStrings)),
+          equals('two'));
+
+      const l1 = [1, 2];
+      const l2 = [3, 4];
+      expect(js_util.callMethod(o, 'four', List.from(l1)..addAll(l2)),
+          equals('four'));
+      expect(js_util.callMethod(o, 'four', l1 + l2), equals('four'));
+      expect(js_util.callMethod(o, 'four', List.unmodifiable([1, 2, 3, 4])),
+          equals('four'));
+
+      var setElements = {1, 2};
+      expect(js_util.callMethod(o, 'two', setElements.toList()), equals('two'));
+
+      var spreadList = [1, 2, 3];
+      expect(js_util.callMethod(o, 'four', [1, ...spreadList]), equals('four'));
+    });
+
+    test('edge cases for lowering to _callMethodUncheckedN', () {
+      var o = CallMethodTest();
+
+      expect(js_util.callMethod(o, 'zero', []), equals('zero'));
+      expect(js_util.callMethod(o, 'one', [1]), equals('one'));
+      expect(js_util.callMethod(o, 'four', [1, 2, 3, 4]), equals('four'));
+      expect(js_util.callMethod(o, 'five', [1, 2, 3, 4, 5]), equals('five'));
+
+      // List with a type declaration, short circuits element checking
+      expect(js_util.callMethod(o, 'two', <int>[1, 2]), equals('two'));
+
+      // List as a variable instead of a List Literal or constant
+      var list = [1, 2];
+      expect(js_util.callMethod(o, 'two', list), equals('two'));
+
+      // Mixed types of elements to check in the given list.
+      var x = 4;
+      var str = 'cat';
+      var b = false;
+      var evens = [2, 4, 6];
+      expect(js_util.callMethod(o, 'four', [x, str, b, evens]), equals('four'));
+      var obj = Object();
+      expect(js_util.callMethod(o, 'one', [obj]), equals('one'));
+      var nullElement = null;
+      expect(js_util.callMethod(o, 'one', [nullElement]), equals('one'));
+
+      // const lists.
+      expect(js_util.callMethod(o, 'one', const [3]), equals('one'));
+      const constList = [10, 20, 30];
+      expect(js_util.callMethod(o, 'three', constList), equals('three'));
+      expect(js_util.callMethod(o, 'one', DartClass.staticConstList),
+          equals('one'));
+    });
   });
 
   group('instanceof', () {
diff --git a/tests/lib/lib_dart2js.status b/tests/lib/lib_dart2js.status
index 7478db8..b1d2d3b 100644
--- a/tests/lib/lib_dart2js.status
+++ b/tests/lib/lib_dart2js.status
@@ -26,6 +26,9 @@
 [ $compiler != dart2js ]
 async/dart2js_uncaught_error_test: Skip # JS-integration only test
 
+[ $builder_tag == dart2js_production && $compiler == dart2js ]
+js/js_util/properties_implicit_checks_test: SkipByDesign # No implicit checks in production mode
+
 [ $compiler == dart2js && $runtime == chrome ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
diff --git a/tests/lib_2/js/js_util/properties_implicit_checks_test.dart b/tests/lib_2/js/js_util/properties_implicit_checks_test.dart
new file mode 100644
index 0000000..c3e141e
--- /dev/null
+++ b/tests/lib_2/js/js_util/properties_implicit_checks_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.9
+
+// Tests the functionality of object properties with the js_util library that
+// involve implicit type checks.
+
+@JS()
+library js_util_properties_implicit_checks_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class CallMethodTest {
+  external CallMethodTest();
+
+  external one(a);
+}
+
+main() {
+  eval(r"""
+    function CallMethodTest() {}
+
+    CallMethodTest.prototype.one = function(a) {
+      return 'one';
+    }
+    """);
+
+  var o = CallMethodTest();
+  expect(() => js_util.callMethod(o, 'one', <String>[5 as dynamic]), throws);
+  expect(() => js_util.callMethod(o, 'one', <int>['foo' as dynamic]), throws);
+}
diff --git a/tests/lib_2/js/js_util/properties_test.dart b/tests/lib_2/js/js_util/properties_test.dart
index 511780f..8479414 100644
--- a/tests/lib_2/js/js_util/properties_test.dart
+++ b/tests/lib_2/js/js_util/properties_test.dart
@@ -55,6 +55,9 @@
 class DartClass {
   int x = 3;
   int getX() => x;
+
+  static staticFunction() => 'static';
+  static const staticConstList = [1];
 }
 
 class GenericDartClass<T> {
@@ -72,6 +75,18 @@
   return 'bar';
 }
 
+@JS()
+class CallMethodTest {
+  external CallMethodTest();
+
+  external zero();
+  external one(a);
+  external two(a, b);
+  external three(a, b, c);
+  external four(a, b, c, d);
+  external five(a, b, c, d, e);
+}
+
 main() {
   eval(r"""
     function Foo(a) {
@@ -123,6 +138,27 @@
     Foo.prototype.callFn = function(fn) {
       return fn();
     }
+
+    function CallMethodTest() {}
+
+    CallMethodTest.prototype.zero = function() {
+      return 'zero';
+    }
+    CallMethodTest.prototype.one = function(a) {
+      return 'one';
+    }
+    CallMethodTest.prototype.two = function(a, b) {
+      return 'two';
+    }
+    CallMethodTest.prototype.three = function(a, b, c) {
+      return 'three';
+    }
+    CallMethodTest.prototype.four = function(a, b, c, d) {
+      return 'four';
+    }
+    CallMethodTest.prototype.five = function(a, b, c, d, e) {
+      return 'five';
+    }
     """);
 
   group('newObject', () {
@@ -326,6 +362,8 @@
         return 'Inline';
       }));
       expect(js_util.callMethod(f, 'bar', []), equals('Inline'));
+      js_util.setProperty(f, 'bar', allowInterop(DartClass.staticFunction));
+      expect(js_util.callMethod(f, 'bar', []), equals('static'));
 
       // Set property to a JS function.
       js_util.setProperty(f, 'bar', allowInterop(jsFunction));
@@ -405,16 +443,20 @@
       expect(js_util.callMethod(f, 'sumFn', [2, 3]), equals(5));
       expect(js_util.callMethod(f, 'getA', [f]), equals(42));
       expect(js_util.callMethod(f, 'callFn', [allowInterop(jsFunction)]),
-          equals("JS Function"));
+          equals('JS Function'));
       expect(js_util.callMethod(f, 'callFn', [allowInterop(dartFunction)]),
-          equals("Dart Function"));
+          equals('Dart Function'));
       expect(
           js_util.callMethod(f, 'callFn', [
             allowInterop(() {
-              return "inline";
+              return 'inline';
             })
           ]),
-          equals("inline"));
+          equals('inline'));
+      expect(
+          js_util.callMethod(
+              f, 'callFn', [allowInterop(DartClass.staticFunction)]),
+          equals('static'));
 
       // Using a variable for the method name.
       String methodName = 'bar';
@@ -422,6 +464,72 @@
       String bar = _getBarWithSideEffect();
       expect(js_util.callMethod(f, bar, []), equals(42));
     });
+
+    test('callMethod with List edge cases', () {
+      var o = CallMethodTest();
+
+      expect(js_util.callMethod(o, 'zero', List()), equals('zero'));
+      expect(js_util.callMethod(o, 'zero', List<int>()), equals('zero'));
+      expect(js_util.callMethod(o, 'zero', List.empty()), equals('zero'));
+      expect(js_util.callMethod(o, 'zero', List<int>.empty()), equals('zero'));
+
+      expect(
+          js_util.callMethod(o, 'two', List<int>.filled(2, 0)), equals('two'));
+      expect(js_util.callMethod(o, 'three', List<int>.generate(3, (i) => i)),
+          equals('three'));
+
+      Iterable<String> iterableStrings = <String>['foo', 'bar'];
+      expect(js_util.callMethod(o, 'two', List.of(iterableStrings)),
+          equals('two'));
+
+      const l1 = [1, 2];
+      const l2 = [3, 4];
+      expect(js_util.callMethod(o, 'four', List.from(l1)..addAll(l2)),
+          equals('four'));
+      expect(js_util.callMethod(o, 'four', l1 + l2), equals('four'));
+      expect(js_util.callMethod(o, 'four', List.unmodifiable([1, 2, 3, 4])),
+          equals('four'));
+
+      var setElements = {1, 2};
+      expect(js_util.callMethod(o, 'two', setElements.toList()), equals('two'));
+
+      var spreadList = [1, 2, 3];
+      expect(js_util.callMethod(o, 'four', [1, ...spreadList]), equals('four'));
+    });
+
+    test('edge cases for lowering to _callMethodUncheckedN', () {
+      var o = CallMethodTest();
+
+      expect(js_util.callMethod(o, 'zero', []), equals('zero'));
+      expect(js_util.callMethod(o, 'one', [1]), equals('one'));
+      expect(js_util.callMethod(o, 'four', [1, 2, 3, 4]), equals('four'));
+      expect(js_util.callMethod(o, 'five', [1, 2, 3, 4, 5]), equals('five'));
+
+      // List with a type declaration, short circuits element checking
+      expect(js_util.callMethod(o, 'two', <int>[1, 2]), equals('two'));
+
+      // List as a variable instead of a List Literal or constant
+      var list = [1, 2];
+      expect(js_util.callMethod(o, 'two', list), equals('two'));
+
+      // Mixed types of elements to check in the given list.
+      var x = 4;
+      var str = 'cat';
+      var b = false;
+      var evens = [2, 4, 6];
+      expect(js_util.callMethod(o, 'four', [x, str, b, evens]), equals('four'));
+      var obj = Object();
+      expect(js_util.callMethod(o, 'one', [obj]), equals('one'));
+      var nullElement = null;
+      expect(js_util.callMethod(o, 'one', [nullElement]), equals('one'));
+
+      // const lists.
+      expect(js_util.callMethod(o, 'one', const [3]), equals('one'));
+      const constList = [10, 20, 30];
+      expect(js_util.callMethod(o, 'three', constList), equals('three'));
+      expect(js_util.callMethod(o, 'one', DartClass.staticConstList),
+          equals('one'));
+    });
   });
 
   group('instanceof', () {
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 2db76f5..1f09063 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -24,6 +24,9 @@
 [ $compiler != dart2js ]
 async/dart2js_uncaught_error_test: Skip # JS-integration only test
 
+[ $builder_tag == dart2js_production && $compiler == dart2js ]
+js/js_util/properties_implicit_checks_test: SkipByDesign # No implicit checks in production mode
+
 [ $compiler == dart2js && $runtime == chrome ]
 async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
 convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
diff --git a/tools/VERSION b/tools/VERSION
index e796ecf..dcd145e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 262
+PRERELEASE 263
 PRERELEASE_PATCH 0
\ No newline at end of file