[serializer] avoid deferring objects with embedder fields

JS objects with embedder fields cannot be deferred because the
serialize/deserialize callbacks need the back reference immediately
to identify the object.

Refs: https://github.com/nodejs/node-v8/issues/175
Bug: v8:11146
Change-Id: I4292f2ab0041f7b0779620437ed26905c194cd9b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2531195
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Cr-Commit-Position: refs/heads/master@{#71134}
diff --git a/src/snapshot/serializer-deserializer.cc b/src/snapshot/serializer-deserializer.cc
index afa41e7..0deaaa8 100644
--- a/src/snapshot/serializer-deserializer.cc
+++ b/src/snapshot/serializer-deserializer.cc
@@ -30,13 +30,18 @@
 }
 
 bool SerializerDeserializer::CanBeDeferred(HeapObject o) {
-  // Maps cannot be deferred as objects are expected to have a valid map
-  // immediately. Internalized strings cannot be deferred as they might be
+  // 1. Maps cannot be deferred as objects are expected to have a valid map
+  // immediately.
+  // 2. Internalized strings cannot be deferred as they might be
   // converted to thin strings during post processing, at which point forward
   // references to the now-thin string will already have been written.
+  // 3. JS objects with embedder fields cannot be deferred because the
+  // serialize/deserialize callbacks need the back reference immediately to
+  // identify the object.
   // TODO(leszeks): Could we defer string serialization if forward references
   // were resolved after object post processing?
-  return !o.IsMap() && !o.IsInternalizedString();
+  return !o.IsMap() && !o.IsInternalizedString() &&
+         !(o.IsJSObject() && JSObject::cast(o).GetEmbedderFieldCount() > 0);
 }
 
 void SerializerDeserializer::RestoreExternalReferenceRedirector(