Version 2.14.0-96.0.dev

Merge commit '90127334ea4aab5267135b959e361229dfac6bc9' into 'dev'
diff --git a/DEPS b/DEPS
index f96eb25..c955d7e 100644
--- a/DEPS
+++ b/DEPS
@@ -146,10 +146,10 @@
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
-  "shelf_static_rev": "fa30419055279a00c9e428439b1abe362d18f25d",
+  "shelf_static_rev": "b8e51372332a27a4939466d94a22f15be53ac3e4",
   "shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
   "shelf_proxy_tag": "v1.0.0",
-  "shelf_rev": "4b9294e29eb308709444a5c0b890fa8ccd69fae4",
+  "shelf_rev": "c511f06e6d2d28ffe905a45eea1da761b95ea0ca",
   "shelf_web_socket_rev": "24fb8a04befa75a94ac63a27047b231d1a22aab4",
   "source_map_stack_trace_rev": "1c3026f69d9771acf2f8c176a1ab750463309cce",
   "source_maps-0.9.4_rev": "38524",
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 498c686..60a464a 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -6130,7 +6130,6 @@
     }
 
     ir.Member memberContextNode = _elementMap.getMemberContextNode(function);
-    bool hasBox = false;
     KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(function);
     forEachOrderedParameter(_elementMap, function,
         (ir.VariableDeclaration variable, {bool isElided}) {
@@ -6144,14 +6143,13 @@
           scopeData.isBoxedVariable(_localsMap, local)) {
         // The parameter will be a field in the box passed as the last
         // parameter. So no need to have it.
-        hasBox = true;
         return;
       }
       HInstruction argument = compiledArguments[argumentIndex++];
       localsHandler.updateLocal(local, argument);
     });
 
-    if (hasBox) {
+    if (forGenerativeConstructorBody && scopeData.requiresContextBox) {
       HInstruction box = compiledArguments[argumentIndex++];
       assert(box is HCreateBox);
       // TODO(sra): Make inlining of closures work. We should always call
diff --git a/pkg/compiler/test/analyses/api_allowed.json b/pkg/compiler/test/analyses/api_allowed.json
index cbee4e6..060fb45 100644
--- a/pkg/compiler/test/analyses/api_allowed.json
+++ b/pkg/compiler/test/analyses/api_allowed.json
@@ -1,76 +1,14 @@
 {
   "org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_number.dart": {
-    "Dynamic invocation of '[]'.": 5,
-    "Dynamic invocation of '<'.": 4,
-    "Dynamic invocation of '>='.": 1,
-    "Dynamic invocation of '<='.": 1,
-    "Dynamic invocation of '>'.": 2
+    "Dynamic invocation of '[]'.": 5
   },
   "org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_helper.dart": {
-    "Dynamic invocation of '[]'.": 3,
-    "Dynamic access of 'isNaN'.": 3,
-    "Dynamic invocation of '<='.": 2,
-    "Dynamic invocation of '-'.": 3,
-    "Dynamic invocation of '&'.": 1,
-    "Dynamic invocation of '>>'.": 1,
-    "Dynamic invocation of '<'.": 2,
-    "Dynamic invocation of '+'.": 1,
-    "Dynamic invocation of '>'.": 1,
     "Dynamic access of 'length'.": 1
   },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/string_helper.dart": {
-    "Dynamic invocation of '<'.": 1,
-    "Dynamic invocation of '+'.": 1,
-    "Dynamic invocation of '>='.": 1,
-    "Dynamic invocation of 'substring'.": 7,
-    "Dynamic invocation of 'allMatches'.": 3,
-    "Dynamic access of 'isNotEmpty'.": 1,
-    "Dynamic invocation of '_js_helper::_execGlobal'.": 1,
-    "Dynamic access of 'start'.": 1,
-    "Dynamic access of 'end'.": 1,
-    "Dynamic invocation of 'call'.": 13,
-    "Dynamic access of 'length'.": 3,
-    "Dynamic invocation of 'codeUnitAt'.": 2,
-    "Dynamic invocation of '[]'.": 1,
-    "Dynamic access of 'iterator'.": 2,
-    "Dynamic invocation of 'replaceRange'.": 2
-  },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/linked_hash_map.dart": {
-    "Dynamic access of '_js_helper::_length'.": 2,
-    "Dynamic access of '_js_helper::_modifications'.": 4,
-    "Dynamic invocation of 'containsKey'.": 1,
-    "Dynamic access of '_js_helper::_first'.": 2
-  },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/native_helper.dart": {
-    "Dynamic access of 'length'.": 2,
-    "Dynamic invocation of '[]'.": 1
-  },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/regexp_helper.dart": {
-    "Dynamic access of 'length'.": 1,
-    "Dynamic invocation of '-'.": 1
-  },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/native_typed_data.dart": {
-    "Dynamic invocation of '>'.": 1,
-    "Dynamic invocation of '>='.": 1
-  },
   "org-dartlang-sdk:///lib/_internal/js_runtime/lib/async_patch.dart": {
-    "Dynamic invocation of '-'.": 1,
     "Dynamic access of 'iterator'.": 1,
-    "Dynamic invocation of 'call'.": 1,
     "Dynamic invocation of 'then'.": 1
   },
-  "org-dartlang-sdk:///lib/_internal/js_runtime/lib/collection_patch.dart": {
-    "Dynamic access of 'dart.collection::_length'.": 2,
-    "Dynamic invocation of 'dart.collection::_computeKeys'.": 2,
-    "Dynamic invocation of 'containsKey'.": 2,
-    "Dynamic access of 'dart.collection::_keys'.": 2,
-    "Dynamic access of 'length'.": 1,
-    "Dynamic access of 'isEmpty'.": 1,
-    "Dynamic access of 'dart.collection::_modifications'.": 5,
-    "Dynamic access of 'dart.collection::_map'.": 4,
-    "Dynamic access of 'dart.collection::_elements'.": 1,
-    "Dynamic access of 'dart.collection::_first'.": 1
-  },
   "org-dartlang-sdk:///lib/html/dart2js/html_dart2js.dart": {
     "Dynamic access of 'style'.": 1,
     "Dynamic invocation of 'remove'.": 2,
diff --git a/pkg/compiler/test/rti/data/map_literal.dart b/pkg/compiler/test/rti/data/map_literal.dart
index 5776790..1d91a1b 100644
--- a/pkg/compiler/test/rti/data/map_literal.dart
+++ b/pkg/compiler/test/rti/data/map_literal.dart
@@ -11,7 +11,7 @@
 /*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/data/map_to_set.dart b/pkg/compiler/test/rti/data/map_to_set.dart
index 0555c1e..79f0f2a 100644
--- a/pkg/compiler/test/rti/data/map_to_set.dart
+++ b/pkg/compiler/test/rti/data/map_to_set.dart
@@ -11,7 +11,7 @@
 /*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/emission/local_function_map_literal.dart b/pkg/compiler/test/rti/emission/local_function_map_literal.dart
index 0468a3e..8c54820 100644
--- a/pkg/compiler/test/rti/emission/local_function_map_literal.dart
+++ b/pkg/compiler/test/rti/emission/local_function_map_literal.dart
@@ -6,7 +6,9 @@
 
 import 'package:expect/expect.dart';
 
-/*class: global#JsLinkedHashMap:checks=[],instance*/
+/*spec.class: global#JsLinkedHashMap:checkedInstance,checks=[],instance*/
+
+/*prod.class: global#JsLinkedHashMap:checks=[],instance*/
 
 @pragma('dart2js:noInline')
 method<T>() {
diff --git a/pkg/compiler/test/rti/emission/map_literal.dart b/pkg/compiler/test/rti/emission/map_literal.dart
index 884ba8a..7803471 100644
--- a/pkg/compiler/test/rti/emission/map_literal.dart
+++ b/pkg/compiler/test/rti/emission/map_literal.dart
@@ -7,7 +7,8 @@
 /*spec.class: global#Map:instance*/
 
 /*class: global#LinkedHashMap:*/
-/*class: global#JsLinkedHashMap:checks=[],instance*/
+/*spec.class: global#JsLinkedHashMap:checkedInstance,checks=[],instance*/
+/*prod.class: global#JsLinkedHashMap:checks=[],instance*/
 
 /*spec.class: global#double:checkedInstance,instance,typeArgument*/
 
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 3f1f0ad..293a271 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -41,12 +41,12 @@
       // Use mutationObservers.
       var div = JS('', 'self.document.createElement("div")');
       var span = JS('', 'self.document.createElement("span")');
-      var storedCallback;
+      void Function()? storedCallback;
 
       internalCallback(_) {
         var f = storedCallback;
         storedCallback = null;
-        f();
+        f!();
       }
 
       var observer = JS('', 'new self.MutationObserver(#)',
@@ -148,7 +148,8 @@
           convertDartClosureToJS(() {
             int tick = this._tick + 1;
             if (milliseconds > 0) {
-              int duration = JS('int', 'Date.now()') - start;
+              int end = JS('int', 'Date.now()');
+              int duration = end - start;
               if (duration > (tick + 1) * milliseconds) {
                 tick = duration ~/ milliseconds;
               }
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index 4d4076c..6ff4a1f 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -448,7 +448,7 @@
 }
 
 class _HashMapKeyIterable<E> extends EfficientLengthIterable<E> {
-  final _map;
+  final _HashMap _map;
   _HashMapKeyIterable(this._map);
 
   int get length => _map._length;
@@ -474,7 +474,7 @@
 }
 
 class _HashMapKeyIterator<E> implements Iterator<E> {
-  final _map;
+  final _HashMap _map;
   final List _keys;
   int _offset = 0;
   E? _current;
@@ -682,7 +682,7 @@
 }
 
 class _Es6MapIterable<E> extends EfficientLengthIterable<E> {
-  final _map;
+  final _Es6LinkedIdentityHashMap _map;
   final bool _isKeys;
 
   _Es6MapIterable(this._map, this._isKeys);
@@ -717,7 +717,7 @@
 }
 
 class _Es6MapIterator<E> implements Iterator<E> {
-  final _map;
+  final _Es6LinkedIdentityHashMap _map;
   final int _modifications;
   final bool _isKeys;
   var _jsIterator;
@@ -1187,7 +1187,7 @@
 
 // TODO(kasperl): Share this code with _HashMapKeyIterator<E>?
 class _HashSetIterator<E> implements Iterator<E> {
-  final _set;
+  final _HashSet<E> _set;
   final List _elements;
   int _offset = 0;
   E? _current;
@@ -1689,7 +1689,7 @@
 
 // TODO(kasperl): Share this code with LinkedHashMapKeyIterator<E>?
 class _LinkedHashSetIterator<E> implements Iterator<E> {
-  final _set;
+  final _LinkedHashSet<E> _set;
   final int _modifications;
   _LinkedHashSetCell? _cell;
   E? _current;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 8143db0..b8ec87b 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -22,7 +22,6 @@
         patch,
         Primitives,
         quoteStringForRegExp,
-        stringJoinUnchecked,
         getTraceFromException,
         RuntimeError;
 
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 3f2302d..890fd9a 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -270,7 +270,7 @@
   static int? parseInt(String source, int? radix) {
     checkString(source);
     var re = JS('', r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i');
-    var match = JS('JSExtendableArray|Null', '#.exec(#)', re, source);
+    List? match = JS('JSExtendableArray|Null', '#.exec(#)', re, source);
     int digitsIndex = 1;
     int hexIndex = 2;
     int decimalIndex = 3;
@@ -353,7 +353,7 @@
         source)) {
       return null;
     }
-    var result = JS('num', r'parseFloat(#)', source);
+    double result = JS('double', r'parseFloat(#)', source);
     if (result.isNaN) {
       var trimmed = source.trim();
       if (trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN') {
@@ -531,7 +531,7 @@
     return result;
   }
 
-  static String stringFromCharCode(charCode) {
+  static String stringFromCharCode(int charCode) {
     if (0 <= charCode) {
       if (charCode <= 0xffff) {
         return JS('returns:String;effects:none;depends:none',
@@ -599,8 +599,8 @@
         as int;
   }
 
-  static int? valueFromDecomposedDate(
-      years, month, day, hours, minutes, seconds, milliseconds, isUtc) {
+  static int? valueFromDecomposedDate(int years, int month, int day, int hours,
+      int minutes, int seconds, int milliseconds, bool isUtc) {
     final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
     checkInt(years);
     checkInt(month);
@@ -619,7 +619,7 @@
       years += 400;
       jsMonth -= 400 * 12;
     }
-    var value;
+    num value;
     if (isUtc) {
       value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
           hours, minutes, seconds, milliseconds);
@@ -733,9 +733,9 @@
     return (weekday + 6) % 7 + 1;
   }
 
-  static valueFromDateString(str) {
+  static num valueFromDateString(str) {
     if (str is! String) throw argumentErrorValue(str);
-    var value = JS('num', r'Date.parse(#)', str);
+    num value = JS('num', r'Date.parse(#)', str);
     if (value.isNaN) throw argumentErrorValue(str);
     return value;
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_number.dart b/sdk/lib/_internal/js_runtime/lib/js_number.dart
index d0f0c71..678a61b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_number.dart
@@ -329,7 +329,7 @@
     JSNumber result = JS<JSNumber>('JSNumber', r'# % #', this, other);
     if (result == 0) return JS('num', '0'); // Make sure we don't return -0.0.
     if (result > 0) return result;
-    if (JS('num', '#', other) < 0) {
+    if (other < 0) {
       return JS<JSNumber>('JSNumber', '# - #', result, other);
     } else {
       return JS<JSNumber>('JSNumber', '# + #', result, other);
@@ -357,7 +357,7 @@
   }
 
   int _tdivSlow(num other) {
-    var quotient = JS('num', r'# / #', this, other);
+    num quotient = JS('num', r'# / #', this, other);
     if (quotient >= _MIN_INT32 && quotient <= _MAX_INT32) {
       // This path includes -0.0 and +0.0.
       return JS('int', '# | 0', quotient);
@@ -385,7 +385,7 @@
 
   num operator <<(num other) {
     if (other is! num) throw argumentErrorValue(other);
-    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
+    if (other < 0) throw argumentErrorValue(other);
     return _shlPositive(other);
   }
 
@@ -398,14 +398,14 @@
   }
 
   num operator >>(num other) {
-    if (false) _shrReceiverPositive(other);
     if (other is! num) throw argumentErrorValue(other);
-    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
+    if (other < 0) throw argumentErrorValue(other);
+    if (false) _shrReceiverPositive(other);
     return _shrOtherPositive(other);
   }
 
   num _shrOtherPositive(num other) {
-    return JS('num', '#', this) > 0
+    return this > 0
         ? _shrBothPositive(other)
         // For negative numbers we just clamp the shift-by amount.
         // `this` could be negative but not have its 31st bit set.
@@ -415,7 +415,7 @@
   }
 
   num _shrReceiverPositive(num other) {
-    if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
+    if (0 > other) throw argumentErrorValue(other);
     return _shrBothPositive(other);
   }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
index 70882d8..fdf9d23 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -204,7 +204,7 @@
       V value = JS('', '#', cell.hashMapCellValue);
       action(key, value);
       if (modifications != _modifications) {
-        throw new ConcurrentModificationError(this);
+        throw ConcurrentModificationError(this);
       }
       cell = cell._next;
     }
@@ -385,7 +385,7 @@
 }
 
 class LinkedHashMapKeyIterable<E> extends EfficientLengthIterable<E> {
-  final dynamic _map;
+  final JsLinkedHashMap _map;
   LinkedHashMapKeyIterable(this._map);
 
   int get length => _map._length;
@@ -405,7 +405,7 @@
     while (cell != null) {
       f(JS('', '#', cell.hashMapCellKey));
       if (modifications != _map._modifications) {
-        throw new ConcurrentModificationError(_map);
+        throw ConcurrentModificationError(_map);
       }
       cell = cell._next;
     }
@@ -413,7 +413,7 @@
 }
 
 class LinkedHashMapKeyIterator<E> implements Iterator<E> {
-  final dynamic _map;
+  final JsLinkedHashMap _map;
   final int _modifications;
   LinkedHashMapCell? _cell;
   E? _current;
@@ -422,11 +422,12 @@
     _cell = _map._first;
   }
 
+  @pragma('dart2js:as:trust')
   E get current => _current as E;
 
   bool moveNext() {
     if (_modifications != _map._modifications) {
-      throw new ConcurrentModificationError(_map);
+      throw ConcurrentModificationError(_map);
     }
     var cell = _cell;
     if (cell == null) {
diff --git a/sdk/lib/_internal/js_runtime/lib/native_helper.dart b/sdk/lib/_internal/js_runtime/lib/native_helper.dart
index f5f40b7..4c404e0 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_helper.dart
@@ -283,7 +283,7 @@
   // tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch
   // property if the function's prototype to a dispatch record.
   var map = interceptorsByTag;
-  var tags = JS('JSMutableArray', 'Object.getOwnPropertyNames(#)', map);
+  JSArray tags = JS('JSMutableArray', 'Object.getOwnPropertyNames(#)', map);
 
   if (JS('bool', 'typeof window != "undefined"')) {
     var context = JS('=Object', 'window');
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index 060a643..bc83d41 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -338,7 +338,7 @@
 
   void _checkPosition(int position, int length, String name) {
     if (JS('bool', '(# >>> 0) !== #', position, position) ||
-        JS('int', '#', position) > length) {
+        JS<int>('int', '#', position) > length) {
       // 'int' guaranteed by above test.
       _invalidPosition(position, length, name);
     }
@@ -1825,7 +1825,7 @@
 ///
 /// That is, [index] is an integer in the range `0..length - 1`.
 void _checkValidIndex(int index, List list, int length) {
-  if (_isInvalidArrayIndex(index) || JS('int', '#', index) >= length) {
+  if (_isInvalidArrayIndex(index) || JS<int>('int', '#', index) >= length) {
     throw diagnoseIndexError(list, index);
   }
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index c6adb12..6ffc76e 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -30,7 +30,7 @@
 /// it finds a match.
 int regExpCaptureCount(JSSyntaxRegExp regexp) {
   var nativeAnchoredRegExp = regexp._nativeAnchoredVersion;
-  var match = JS('JSExtendableArray', '#.exec("")', nativeAnchoredRegExp);
+  JSArray match = JS('JSExtendableArray', '#.exec("")', nativeAnchoredRegExp);
   // The native-anchored regexp always have one capture more than the original,
   // and always matches the empty string.
   return match.length - 2;
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index 3e07cdd..5e6c50d 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -4,23 +4,28 @@
 
 part of _js_helper;
 
-stringIndexOfStringUnchecked(receiver, other, startIndex) {
+int stringIndexOfStringUnchecked(
+    String receiver, String other, int startIndex) {
   return JS('int', '#.indexOf(#, #)', receiver, other, startIndex);
 }
 
-substring1Unchecked(receiver, startIndex) {
+String substring1Unchecked(String receiver, int startIndex) {
   return JS('String', '#.substring(#)', receiver, startIndex);
 }
 
-substring2Unchecked(receiver, startIndex, endIndex) {
+String substring2Unchecked(String receiver, int startIndex, int endIndex) {
   return JS('String', '#.substring(#, #)', receiver, startIndex, endIndex);
 }
 
-stringContainsStringUnchecked(receiver, other, startIndex) {
+bool stringContainsStringUnchecked(
+    String receiver, String other, int startIndex) {
   return stringIndexOfStringUnchecked(receiver, other, startIndex) >= 0;
 }
 
-List<String> stringSplitUnchecked(String receiver, pattern) {
+List<String> stringSplitUnchecked(
+    String receiver,
+    /* String | JavaScript RegExp */
+    pattern) {
   return new JSArray<String>.markGrowable(JS(
       'returns:JSExtendableArray;new:true', '#.split(#)', receiver, pattern));
 }
@@ -89,7 +94,7 @@
       _current = null;
       return false;
     }
-    var index = stringIndexOfStringUnchecked(_input, _pattern, _index);
+    int index = stringIndexOfStringUnchecked(_input, _pattern, _index);
     if (index < 0) {
       _index = _input.length + 1;
       _current = null;
@@ -106,7 +111,7 @@
   Match get current => _current!;
 }
 
-stringContainsUnchecked(receiver, other, startIndex) {
+bool stringContainsUnchecked(String receiver, Pattern other, int startIndex) {
   if (other is String) {
     return stringContainsStringUnchecked(receiver, other, startIndex);
   } else if (other is JSSyntaxRegExp) {
@@ -136,7 +141,8 @@
   return replacement;
 }
 
-stringReplaceFirstRE(receiver, regexp, replacement, startIndex) {
+String stringReplaceFirstRE(String receiver, JSSyntaxRegExp regexp,
+    String replacement, int startIndex) {
   var match = regexp._execGlobal(receiver, startIndex);
   if (match == null) return receiver;
   var start = match.start;
@@ -155,7 +161,8 @@
   return string;
 }
 
-stringReplaceAllUnchecked(receiver, pattern, replacement) {
+String stringReplaceAllUnchecked(
+    String receiver, Pattern pattern, String replacement) {
   checkString(replacement);
   if (pattern is String) {
     return stringReplaceAllUncheckedString(receiver, pattern, replacement);
@@ -212,16 +219,18 @@
   return stringReplaceJS(receiver, replacer, replacement);
 }
 
-String stringReplaceAllUsingSplitJoin(receiver, pattern, replacement) {
+String stringReplaceAllUsingSplitJoin(
+    String receiver, String pattern, String replacement) {
   return JS('String', '#.split(#).join(#)', receiver, pattern, replacement);
 }
 
-String? _matchString(Match match) => match[0];
+String _matchString(Match match) => match[0]!;
 String _stringIdentity(String string) => string;
 
-stringReplaceAllFuncUnchecked(receiver, pattern, onMatch, onNonMatch) {
-  if (onMatch == null) onMatch = _matchString;
-  if (onNonMatch == null) onNonMatch = _stringIdentity;
+String stringReplaceAllFuncUnchecked(String receiver, Pattern pattern,
+    String Function(Match)? onMatch, String Function(String)? onNonMatch) {
+  onMatch ??= _matchString;
+  onNonMatch ??= _stringIdentity;
   if (pattern is String) {
     return stringReplaceAllStringFuncUnchecked(
         receiver, pattern, onMatch, onNonMatch);
@@ -243,9 +252,10 @@
   return buffer.toString();
 }
 
-stringReplaceAllEmptyFuncUnchecked(receiver, onMatch, onNonMatch) {
+String stringReplaceAllEmptyFuncUnchecked(String receiver,
+    String Function(Match) onMatch, String Function(String) onNonMatch) {
   // Pattern is the empty string.
-  StringBuffer buffer = new StringBuffer('');
+  StringBuffer buffer = StringBuffer();
   int length = receiver.length;
   int i = 0;
   buffer.write(onNonMatch(""));
@@ -271,7 +281,8 @@
   return buffer.toString();
 }
 
-stringReplaceAllStringFuncUnchecked(receiver, pattern, onMatch, onNonMatch) {
+String stringReplaceAllStringFuncUnchecked(String receiver, String pattern,
+    String Function(Match) onMatch, String Function(String) onNonMatch) {
   int patternLength = pattern.length;
   if (patternLength == 0) {
     return stringReplaceAllEmptyFuncUnchecked(receiver, onMatch, onNonMatch);
@@ -292,7 +303,8 @@
   return buffer.toString();
 }
 
-stringReplaceFirstUnchecked(receiver, pattern, replacement, int startIndex) {
+String stringReplaceFirstUnchecked(
+    String receiver, Pattern pattern, String replacement, int startIndex) {
   if (pattern is String) {
     int index = stringIndexOfStringUnchecked(receiver, pattern, startIndex);
     if (index < 0) return receiver;
@@ -311,7 +323,8 @@
   return receiver.replaceRange(match.start, match.end, replacement);
 }
 
-stringReplaceFirstMappedUnchecked(receiver, pattern, replace, int startIndex) {
+String stringReplaceFirstMappedUnchecked(String receiver, Pattern pattern,
+    String Function(Match) replace, int startIndex) {
   Iterator<Match> matches = pattern.allMatches(receiver, startIndex).iterator;
   if (!matches.moveNext()) return receiver;
   Match match = matches.current;
@@ -319,10 +332,6 @@
   return receiver.replaceRange(match.start, match.end, replacement);
 }
 
-stringJoinUnchecked(array, separator) {
-  return JS('String', r'#.join(#)', array, separator);
-}
-
 String stringReplaceRangeUnchecked(
     String receiver, int start, int end, String replacement) {
   var prefix = JS('String', '#.substring(0, #)', receiver, start);
diff --git a/tests/web/regress/45943_test.dart b/tests/web/regress/45943_test.dart
index 52315f5..4b40c44a 100644
--- a/tests/web/regress/45943_test.dart
+++ b/tests/web/regress/45943_test.dart
@@ -12,7 +12,7 @@
       return true;
     }());
     if (inDebugMode == false) {
-      throw Error();
+      print('Error');
     }
   }
 }
diff --git a/tests/web_2/regress/45943_test.dart b/tests/web_2/regress/45943_test.dart
index 52315f5..4b40c44a 100644
--- a/tests/web_2/regress/45943_test.dart
+++ b/tests/web_2/regress/45943_test.dart
@@ -12,7 +12,7 @@
       return true;
     }());
     if (inDebugMode == false) {
-      throw Error();
+      print('Error');
     }
   }
 }
diff --git a/tools/VERSION b/tools/VERSION
index 71779f9..b7c0fa0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 95
+PRERELEASE 96
 PRERELEASE_PATCH 0
\ No newline at end of file