[dart2wasm] Fix two TODOs in JS utils

This copies some of the TODO fixes from
https://dart-review.googlesource.com/c/sdk/+/288381.

Change-Id: I6a887414052f73be3714098e153a7644280de188
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/329103
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/sdk/lib/_internal/wasm/lib/js_helper.dart b/sdk/lib/_internal/wasm/lib/js_helper.dart
index 83467a0..5cfddbb 100644
--- a/sdk/lib/_internal/wasm/lib/js_helper.dart
+++ b/sdk/lib/_internal/wasm/lib/js_helper.dart
@@ -552,11 +552,6 @@
 WasmExternRef? getConstructorRaw(String name) =>
     getPropertyRaw(globalThisRaw(), name.toExternRef);
 
-/// Equivalent to `Object.keys(object)`.
-// TODO(joshualitt): Make this a static helper on 'JSObject'.
-@js.JS('Object.keys')
-external JSArray objectKeys(JSObject object);
-
 /// Takes a [codeTemplate] string which must represent a valid JS function, and
 /// a list of optional arguments. The [codeTemplate] will be inserted into the
 /// JS runtime, and the call to [JS] will be replaced by a call to an external
diff --git a/sdk/lib/_internal/wasm/lib/js_types.dart b/sdk/lib/_internal/wasm/lib/js_types.dart
index 59fe38c..54bed49 100644
--- a/sdk/lib/_internal/wasm/lib/js_types.dart
+++ b/sdk/lib/_internal/wasm/lib/js_types.dart
@@ -82,11 +82,14 @@
   external factory JSAny._();
 }
 
-@JS()
+@JS('Object')
 @staticInterop
 class JSObject implements JSAny {
   /// Returns a new object literal.
   factory JSObject() => js.JSValue(js.newObjectRaw()) as JSObject;
+
+  /// Equivalent to `Object.keys(object)`.
+  external static JSArray keys(JSObject o);
 }
 
 @JS()
diff --git a/sdk/lib/_internal/wasm/lib/regexp_helper.dart b/sdk/lib/_internal/wasm/lib/regexp_helper.dart
index 5a2f797..23b546a 100644
--- a/sdk/lib/_internal/wasm/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/wasm/lib/regexp_helper.dart
@@ -214,7 +214,7 @@
   Iterable<String> get groupNames {
     JSObject? groups = _match.groups;
     if (groups.isDefinedAndNotNull) {
-      return JSArrayIterableAdapter<String>(objectKeys(groups!));
+      return JSArrayIterableAdapter<String>(JSObject.keys(groups!));
     }
     return Iterable.empty();
   }
diff --git a/tests/web/wasm/js_util_test.dart b/tests/web/wasm/js_util_test.dart
index 29382e8..b16de39 100644
--- a/tests/web/wasm/js_util_test.dart
+++ b/tests/web/wasm/js_util_test.dart
@@ -131,8 +131,7 @@
 
 void deepConversionsTest() {
   // Dart to JS.
-  // TODO(joshualitt): Consider supporting `null` in jsify.
-  // Expect.isNull(dartify(jsify(null)));
+  Expect.isNull(dartify(jsify(null)));
   Expect.equals(true, dartify(jsify(true)));
   Expect.equals(2.0, dartify(jsify(2.0)));
   Expect.equals('foo', dartify(jsify('foo')));