diff --git a/src/base_object-inl.h b/src/base_object-inl.h index bb1e8d4b46bce3..f39b1b211bb830 100644 --- a/src/base_object-inl.h +++ b/src/base_object-inl.h @@ -32,10 +32,21 @@ namespace node { +namespace { +// This just has to be different from the Chromium ones: +// https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=18-23;drc=5a758a97032f0b656c3c36a3497560762495501a +// Otherwise, when Node is loaded in an isolate which uses cppgc, cppgc will +// misinterpret the data stored in the embedder fields and try to garbage +// collect them. +static uint16_t kNodeEmbedderId = 0x90de; +} + BaseObject::BaseObject(Environment* env, v8::Local object) : persistent_handle_(env->isolate(), object), env_(env) { CHECK_EQ(false, object.IsEmpty()); - CHECK_GT(object->InternalFieldCount(), 0); + CHECK_GT(object->InternalFieldCount(), BaseObject::kSlot); + object->SetAlignedPointerInInternalField(BaseObject::kEmbedderType, + &kNodeEmbedderId); object->SetAlignedPointerInInternalField( BaseObject::kSlot, static_cast(this)); @@ -151,7 +162,8 @@ bool BaseObject::IsWeakOrDetached() const { void BaseObject::LazilyInitializedJSTemplateConstructor( const v8::FunctionCallbackInfo& args) { DCHECK(args.IsConstructCall()); - DCHECK_GT(args.This()->InternalFieldCount(), 0); + DCHECK_GT(args.This()->InternalFieldCount(), BaseObject::kSlot); + args.This()->SetAlignedPointerInInternalField(BaseObject::kEmbedderType, &kNodeEmbedderId); args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr); } diff --git a/src/base_object.h b/src/base_object.h index 1c63da92fd80c0..d6a4b0438d88e3 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -40,7 +40,7 @@ class TransferData; class BaseObject : public MemoryRetainer { public: - enum InternalFields { kSlot, kInternalFieldCount }; + enum InternalFields { kEmbedderType, kSlot, kInternalFieldCount }; // Associates this object with `object`. It uses the 0th internal field for // that, and in particular aborts if there is no such field.