1
+ #include " node_util.h"
1
2
#include " base_object-inl.h"
2
3
#include " node_errors.h"
3
4
#include " node_external_reference.h"
@@ -15,7 +16,7 @@ using v8::Context;
15
16
using v8::External;
16
17
using v8::FunctionCallbackInfo;
17
18
using v8::FunctionTemplate;
18
- using v8::Global ;
19
+ using v8::HandleScope ;
19
20
using v8::IndexFilter;
20
21
using v8::Integer;
21
22
using v8::Isolate;
@@ -207,52 +208,106 @@ void ArrayBufferViewHasBuffer(const FunctionCallbackInfo<Value>& args) {
207
208
args.GetReturnValue ().Set (args[0 ].As <ArrayBufferView>()->HasBuffer ());
208
209
}
209
210
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 ()) {
215
224
target_.Reset (env->isolate (), target);
216
- target_.SetWeak ();
225
+ if (reference_count_ == 0 ) {
226
+ target_.SetWeak ();
227
+ }
217
228
}
229
+ }
218
230
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 ;
224
236
}
225
237
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
+ }
232
254
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
+ }
239
263
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 ();
246
276
}
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
+ }
247
296
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
+ }
251
303
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
+ }
256
311
257
312
static void GuessHandleType (const FunctionCallbackInfo<Value>& args) {
258
313
Environment* env = Environment::GetCurrent (args);
0 commit comments