[ddc] Refactor typeName

Move the method body out of one giant JS foreign function and into
Dart code with small JS foreign function calls inside.

Issue: https://github.com/dart-lang/sdk/issues/46002
Change-Id: I978f752c8bb6f09ed3c2ca7d149561f488034509
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251851
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 3c7ccc7..0d8ebd4 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -1156,35 +1156,40 @@
 }
 
 @notNull
-String typeName(type) => JS('', '''(() => {
-  if ($type === void 0) return "undefined type";
-  if ($type === null) return "null type";
+String typeName(type) {
+  if (JS<bool>('!', '# === void 0', type)) return 'undefined type';
+  if (JS<bool>('!', '# === null', type)) return 'null type';
   // Non-instance types
-  if (${_jsInstanceOf(type, DartType)}) {
-    return $type.toString();
+  if (_jsInstanceOf(type, DartType)) {
+    return JS<String>('!', '#.toString()', type);
   }
 
   // Instance types
-  let tag = $type[$_runtimeType];
-  if (tag === $Type) {
-    let name = $type.name;
-    let args = ${getGenericArgs(type)};
+  var tag = JS('', '#[#]', type, _runtimeType);
+  if (JS<bool>('!', '# === #', tag, Type)) {
+    var name = JS<String>('!', '#.name', type);
+    var args = getGenericArgs(type);
     if (args == null) return name;
 
-    if (${getGenericClass(type)} == ${getGenericClassStatic<JSArray>()}) name = 'List';
+    if (JS<bool>('!', '# == #', getGenericClass(type),
+        getGenericClassStatic<JSArray>())) {
+      name = 'List';
+    }
 
-    let result = name;
-    result += '<';
-    for (let i = 0; i < args.length; ++i) {
+    var result = name + '<';
+    for (var i = 0; i < JS<int>('!', '#.length', args); ++i) {
       if (i > 0) result += ', ';
-      result += $typeName(args[i]);
+      result += typeName(JS('', '#[#]', args, i));
     }
     result += '>';
     return result;
   }
-  if (tag) return "Not a type: " + tag.name;
-  return "JSObject<" + $type.name + ">";
-})()''');
+  // Test the JavaScript "truthiness" of `tag`.
+  if (JS<bool>('!', '!!#', tag)) {
+    return 'Not a type: ' + JS<String>('!', '#.name', tag);
+  }
+  return 'JSObject<' + JS<String>('!', '#.name', type) + '>';
+}
 
 /// Returns true if [ft1] <: [ft2].
 @notNull