[beta][dart2js] Bailout tracing of record fields when record is bailed out

Bug: #52968
Fixes: #53001
Cherry-Pick: https://dart-review.googlesource.com/c/sdk/+/315020
Change-Id: Iad450fa342f33d38a23367bbac280b464a4d618d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/315240
Commit-Queue: Mayank Patke <fishythefish@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 058042c..6e2106f 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -353,21 +353,24 @@
 
   void analyzeStoredIntoRecord(RecordTypeInformation record) {
     inferrer.analyzeRecordAndEnqueue(record);
-
-    record.flowsInto.forEach((TypeInformation flow) {
-      flow.users.forEach((TypeInformation user) {
-        if (user is RecordFieldAccessTypeInformation) {
-          final getterIndex =
-              record.recordShape.indexOfGetterName(user.getterName);
-          if (user.receiver == flow &&
-              getterIndex >= 0 &&
-              getterIndex < record.fieldTypes.length &&
-              record.fieldTypes[getterIndex] == currentUser) {
-            addNewEscapeInformation(user);
+    if (record.bailedOut) {
+      bailout('Stored in a record that bailed out');
+    } else {
+      record.flowsInto.forEach((TypeInformation flow) {
+        flow.users.forEach((TypeInformation user) {
+          if (user is RecordFieldAccessTypeInformation) {
+            final getterIndex =
+                record.recordShape.indexOfGetterName(user.getterName);
+            if (user.receiver == flow &&
+                getterIndex >= 0 &&
+                getterIndex < record.fieldTypes.length &&
+                record.fieldTypes[getterIndex] == currentUser) {
+              addNewEscapeInformation(user);
+            }
           }
-        }
+        });
       });
-    });
+    }
   }
 
   /// Checks whether this is a call to a list adding method. The definition of
diff --git a/tests/web/regress/issue/52968_test.dart b/tests/web/regress/issue/52968_test.dart
new file mode 100644
index 0000000..5c436ea
--- /dev/null
+++ b/tests/web/regress/issue/52968_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2023, 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.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  final validator = createValidator([
+    (validate: isNotEmpty, message: 'Value is required'),
+  ]);
+  Expect.isEmpty(validator('foo'));
+  Expect.isNotEmpty(validator(null));
+}
+
+typedef FieldValidator<T> = List<String> Function(T? value);
+typedef Validator<T> = bool Function(T? value);
+FieldValidator<T> createValidator<T>(
+        List<({Validator<T> validate, String message})> validators) =>
+    (T? value) {
+      return validators
+          .where((validator) => !validator.validate(value))
+          .map((validator) => validator.message)
+          .toList();
+    };
+
+bool isNotEmpty(String? value) => value != null && value.isNotEmpty;