1+ #include " node_util.h"
12#include " base_object-inl.h"
23#include " node_errors.h"
34#include " node_external_reference.h"
@@ -15,7 +16,7 @@ using v8::Context;
1516using v8::External;
1617using v8::FunctionCallbackInfo;
1718using v8::FunctionTemplate;
18- using v8::Global ;
19+ using v8::HandleScope ;
1920using v8::IndexFilter;
2021using v8::Integer;
2122using v8::Isolate;
@@ -207,52 +208,106 @@ void ArrayBufferViewHasBuffer(const FunctionCallbackInfo<Value>& args) {
207208 args.GetReturnValue ().Set (args[0 ].As <ArrayBufferView>()->HasBuffer ());
208209}
209210
210- class WeakReference : public BaseObject {
211- public:
212- WeakReference (Environment* env, Local<Object> object, Local<Object> target)
213- : BaseObject(env, object) {
214- MakeWeak ();
211+ WeakReference::WeakReference (Environment* env,
212+ Local<Object> object,
213+ Local<Object> target)
214+ : WeakReference(env, object, target, 0 ) {}
215+
216+ WeakReference::WeakReference (Environment* env,
217+ Local<Object> object,
218+ Local<Object> target,
219+ uint64_t reference_count)
220+ : SnapshotableObject(env, object, type_int),
221+ reference_count_ (reference_count) {
222+ MakeWeak ();
223+ if (!target.IsEmpty ()) {
215224 target_.Reset (env->isolate (), target);
216- target_.SetWeak ();
225+ if (reference_count_ == 0 ) {
226+ target_.SetWeak ();
227+ }
217228 }
229+ }
218230
219- static void New ( const FunctionCallbackInfo<Value>& args) {
220- Environment* env = Environment::GetCurrent (args);
221- CHECK (args. IsConstructCall ());
222- CHECK (args[ 0 ]-> IsObject ()) ;
223- new WeakReference (env, args. This (), args[ 0 ]. As <Object>()) ;
231+ bool WeakReference::PrepareForSerialization (Local<Context> context,
232+ v8::SnapshotCreator* creator) {
233+ if (target_. IsEmpty ()) {
234+ target_index_ = 0 ;
235+ return true ;
224236 }
225237
226- static void Get (const FunctionCallbackInfo<Value>& args) {
227- WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
228- Isolate* isolate = args.GetIsolate ();
229- if (!weak_ref->target_ .IsEmpty ())
230- args.GetReturnValue ().Set (weak_ref->target_ .Get (isolate));
231- }
238+ // Users can still hold strong references to target in addition to the
239+ // reference that we manage here, and they could expect that the referenced
240+ // object remains the same as long as that external strong reference
241+ // is alive. Since we have no way to know if there is any other reference
242+ // keeping the target alive, the best we can do to maintain consistency is to
243+ // simply save a reference to the target in the snapshot (effectively making
244+ // it strong) during serialization, and restore it during deserialization.
245+ // If there's no known counted reference from our side, we'll make the
246+ // reference here weak upon deserialization so that it can be GC'ed if users
247+ // do not hold additional references to it.
248+ Local<Object> target = target_.Get (context->GetIsolate ());
249+ target_index_ = creator->AddData (context, target);
250+ DCHECK_NE (target_index_, 0 );
251+ target_.Reset ();
252+ return true ;
253+ }
232254
233- static void IncRef (const FunctionCallbackInfo<Value>& args) {
234- WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
235- weak_ref->reference_count_ ++;
236- if (weak_ref->target_ .IsEmpty ()) return ;
237- if (weak_ref->reference_count_ == 1 ) weak_ref->target_ .ClearWeak ();
238- }
255+ InternalFieldInfoBase* WeakReference::Serialize (int index) {
256+ DCHECK_EQ (index, BaseObject::kEmbedderType );
257+ InternalFieldInfo* info =
258+ InternalFieldInfoBase::New<InternalFieldInfo>(type ());
259+ info->target = target_index_;
260+ info->reference_count = reference_count_;
261+ return info;
262+ }
239263
240- static void DecRef (const FunctionCallbackInfo<Value>& args) {
241- WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
242- CHECK_GE (weak_ref->reference_count_ , 1 );
243- weak_ref->reference_count_ --;
244- if (weak_ref->target_ .IsEmpty ()) return ;
245- if (weak_ref->reference_count_ == 0 ) weak_ref->target_ .SetWeak ();
264+ void WeakReference::Deserialize (Local<Context> context,
265+ Local<Object> holder,
266+ int index,
267+ InternalFieldInfoBase* info) {
268+ DCHECK_EQ (index, BaseObject::kEmbedderType );
269+ HandleScope scope (context->GetIsolate ());
270+
271+ InternalFieldInfo* weak_info = reinterpret_cast <InternalFieldInfo*>(info);
272+ Local<Object> target;
273+ if (weak_info->target != 0 ) {
274+ target = context->GetDataFromSnapshotOnce <Object>(weak_info->target )
275+ .ToLocalChecked ();
246276 }
277+ new WeakReference (Environment::GetCurrent (context),
278+ holder,
279+ target,
280+ weak_info->reference_count );
281+ }
282+
283+ void WeakReference::New (const FunctionCallbackInfo<Value>& args) {
284+ Environment* env = Environment::GetCurrent (args);
285+ CHECK (args.IsConstructCall ());
286+ CHECK (args[0 ]->IsObject ());
287+ new WeakReference (env, args.This (), args[0 ].As <Object>());
288+ }
289+
290+ void WeakReference::Get (const FunctionCallbackInfo<Value>& args) {
291+ WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
292+ Isolate* isolate = args.GetIsolate ();
293+ if (!weak_ref->target_ .IsEmpty ())
294+ args.GetReturnValue ().Set (weak_ref->target_ .Get (isolate));
295+ }
247296
248- SET_MEMORY_INFO_NAME (WeakReference)
249- SET_SELF_SIZE (WeakReference)
250- SET_NO_MEMORY_INFO ()
297+ void WeakReference::IncRef (const FunctionCallbackInfo<Value>& args) {
298+ WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
299+ weak_ref->reference_count_ ++;
300+ if (weak_ref->target_ .IsEmpty ()) return ;
301+ if (weak_ref->reference_count_ == 1 ) weak_ref->target_ .ClearWeak ();
302+ }
251303
252- private:
253- Global<Object> target_;
254- uint64_t reference_count_ = 0 ;
255- };
304+ void WeakReference::DecRef (const FunctionCallbackInfo<Value>& args) {
305+ WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder ());
306+ CHECK_GE (weak_ref->reference_count_ , 1 );
307+ weak_ref->reference_count_ --;
308+ if (weak_ref->target_ .IsEmpty ()) return ;
309+ if (weak_ref->reference_count_ == 0 ) weak_ref->target_ .SetWeak ();
310+ }
256311
257312static void GuessHandleType (const FunctionCallbackInfo<Value>& args) {
258313 Environment* env = Environment::GetCurrent (args);
0 commit comments