Fix JsLinkedHashMap memory leak

Change-Id: I768de1f8e52c890dfbf8ca214e9e82051b4070fa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99885
Auto-Submit: Stephen Adams <sra@google.com>
Reviewed-by: Vijay Menon <vsm@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
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 81fd124..42ad0c4 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -173,15 +173,18 @@
   V internalRemove(Object key) {
     var rest = _rest;
     if (rest == null) return null;
-    var bucket = _getBucket(rest, key);
+    var hash = internalComputeHashCode(key);
+    var bucket = _getTableBucket(rest, hash);
     int index = internalFindBucketIndex(bucket, key);
     if (index < 0) return null;
     // Use splice to remove the [cell] element at the index and
     // unlink the cell before returning its value.
     LinkedHashMapCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index);
     _unlinkCell(cell);
-    // TODO(kasperl): Consider getting rid of the bucket list when
-    // the length reaches zero.
+    // Remove empty bucket list to avoid memory leak.
+    if (JS('int', '#.length', bucket) == 0) {
+      _deleteTableEntry(rest, hash);
+    }
     return JS('', '#', cell.hashMapCellValue);
   }