@@ -118,8 +118,9 @@ Local<Name> Uint32ToName(Local<Context> context, uint32_t index) {
118
118
119
119
} // anonymous namespace
120
120
121
- BaseObjectPtr<ContextifyContext> ContextifyContext::New (
122
- Environment* env, Local<Object> sandbox_obj, ContextOptions* options) {
121
+ ContextifyContext* ContextifyContext::New (Environment* env,
122
+ Local<Object> sandbox_obj,
123
+ ContextOptions* options) {
123
124
Local<ObjectTemplate> object_template;
124
125
HandleScope scope (env->isolate ());
125
126
CHECK_IMPLIES (sandbox_obj.IsEmpty (), options->vanilla );
@@ -140,43 +141,56 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
140
141
if (!(CreateV8Context (env->isolate (), object_template, snapshot_data, queue)
141
142
.ToLocal (&v8_context))) {
142
143
// Allocation failure, maximum call stack size reached, termination, etc.
143
- return BaseObjectPtr<ContextifyContext>() ;
144
+ return nullptr ;
144
145
}
145
146
return New (v8_context, env, sandbox_obj, options);
146
147
}
147
148
148
- void ContextifyContext::MemoryInfo (MemoryTracker* tracker) const {}
149
+ void ContextifyContext::Trace (cppgc::Visitor* visitor) const {
150
+ CppgcMixin::Trace (visitor);
151
+ visitor->Trace (context_);
152
+ }
149
153
150
154
ContextifyContext::ContextifyContext (Environment* env,
151
155
Local<Object> wrapper,
152
156
Local<Context> v8_context,
153
157
ContextOptions* options)
154
- : BaseObject(env, wrapper),
155
- microtask_queue_ (options->own_microtask_queue
158
+ : microtask_queue_(options->own_microtask_queue
156
159
? options->own_microtask_queue.release()
157
160
: nullptr ) {
161
+ CppgcMixin::Wrap (this , env, wrapper);
162
+
158
163
context_.Reset (env->isolate (), v8_context);
159
164
// This should only be done after the initial initializations of the context
160
165
// global object is finished.
161
166
DCHECK_NULL (v8_context->GetAlignedPointerFromEmbedderData (
162
167
ContextEmbedderIndex::kContextifyContext ));
163
168
v8_context->SetAlignedPointerInEmbedderData (
164
169
ContextEmbedderIndex::kContextifyContext , this );
165
- // It's okay to make this reference weak - V8 would create an internal
166
- // reference to this context via the constructor of the wrapper.
167
- // As long as the wrapper is alive, it's constructor is alive, and so
168
- // is the context.
169
- context_.SetWeak ();
170
170
}
171
171
172
- ContextifyContext::~ContextifyContext ( ) {
173
- Isolate* isolate = env () ->isolate ();
172
+ void ContextifyContext::CleanEnvResource (Environment* env ) {
173
+ Isolate* isolate = env->isolate ();
174
174
HandleScope scope (isolate);
175
175
176
- env ()->UnassignFromContext (PersistentToLocal::Weak (isolate, context_));
176
+ // PurgeTrackedEmptyContexts() is all we need because when the
177
+ // wrapper is unreachable, the v8::Context is also already going
178
+ // away and there's no point to reset its internal pointers.
179
+ // In the context list, the global handle to the original
180
+ // context should have already been empty and will be removed
181
+ // in PurgeTrackedEmptyContexts().
182
+ // TODO(joyeecheung): consider just using a default destructor.
183
+ // We don't even need to purge the empty contexts in the
184
+ // destructors if TrackContext() purges them, restricting the
185
+ // amount of empty contexts in the list.
186
+ env->PurgeTrackedEmptyContexts ();
177
187
context_.Reset ();
178
188
}
179
189
190
+ ContextifyContext::~ContextifyContext () {
191
+ Clean ();
192
+ }
193
+
180
194
void ContextifyContext::InitializeGlobalTemplates (IsolateData* isolate_data) {
181
195
DCHECK (isolate_data->contextify_wrapper_template ().IsEmpty ());
182
196
Local<FunctionTemplate> global_func_template =
@@ -251,19 +265,18 @@ MaybeLocal<Context> ContextifyContext::CreateV8Context(
251
265
return scope.Escape (ctx);
252
266
}
253
267
254
- BaseObjectPtr<ContextifyContext> ContextifyContext::New (
255
- Local<Context> v8_context,
256
- Environment* env,
257
- Local<Object> sandbox_obj,
258
- ContextOptions* options) {
268
+ ContextifyContext* ContextifyContext::New (Local<Context> v8_context,
269
+ Environment* env,
270
+ Local<Object> sandbox_obj,
271
+ ContextOptions* options) {
259
272
HandleScope scope (env->isolate ());
260
273
CHECK_IMPLIES (sandbox_obj.IsEmpty (), options->vanilla );
261
274
// This only initializes part of the context. The primordials are
262
275
// only initialized when needed because even deserializing them slows
263
276
// things down significantly and they are only needed in rare occasions
264
277
// in the vm contexts.
265
278
if (InitializeContextRuntime (v8_context).IsNothing ()) {
266
- return BaseObjectPtr<ContextifyContext>() ;
279
+ return nullptr ;
267
280
}
268
281
269
282
Local<Context> main_context = env->context ();
@@ -300,7 +313,7 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
300
313
info.origin = *origin_val;
301
314
}
302
315
303
- BaseObjectPtr< ContextifyContext> result;
316
+ ContextifyContext* result;
304
317
Local<Object> wrapper;
305
318
{
306
319
Context::Scope context_scope (v8_context);
@@ -315,7 +328,7 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
315
328
ctor_name,
316
329
static_cast <v8::PropertyAttribute>(v8::DontEnum))
317
330
.IsNothing ()) {
318
- return BaseObjectPtr<ContextifyContext>() ;
331
+ return nullptr ;
319
332
}
320
333
}
321
334
@@ -328,21 +341,23 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
328
341
env->host_defined_option_symbol (),
329
342
options->host_defined_options_id )
330
343
.IsNothing ()) {
331
- return BaseObjectPtr<ContextifyContext>() ;
344
+ return nullptr ;
332
345
}
333
346
334
347
env->AssignToContext (v8_context, nullptr , info);
335
348
336
349
if (!env->contextify_wrapper_template ()
337
350
->NewInstance (v8_context)
338
351
.ToLocal (&wrapper)) {
339
- return BaseObjectPtr<ContextifyContext>() ;
352
+ return nullptr ;
340
353
}
341
354
342
- result =
343
- MakeBaseObject<ContextifyContext>(env, wrapper, v8_context, options);
344
- // The only strong reference to the wrapper will come from the sandbox.
345
- result->MakeWeak ();
355
+ result = cppgc::MakeGarbageCollected<ContextifyContext>(
356
+ env->isolate ()->GetCppHeap ()->GetAllocationHandle (),
357
+ env,
358
+ wrapper,
359
+ v8_context,
360
+ options);
346
361
}
347
362
348
363
Local<Object> wrapper_holder =
@@ -352,7 +367,7 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
352
367
->SetPrivate (
353
368
v8_context, env->contextify_context_private_symbol (), wrapper)
354
369
.IsNothing ()) {
355
- return BaseObjectPtr<ContextifyContext>() ;
370
+ return nullptr ;
356
371
}
357
372
358
373
// Assign host_defined_options_id to the sandbox object or the global object
@@ -364,7 +379,7 @@ BaseObjectPtr<ContextifyContext> ContextifyContext::New(
364
379
env->host_defined_option_symbol (),
365
380
options->host_defined_options_id )
366
381
.IsNothing ()) {
367
- return BaseObjectPtr<ContextifyContext>() ;
382
+ return nullptr ;
368
383
}
369
384
return result;
370
385
}
@@ -438,7 +453,7 @@ void ContextifyContext::MakeContext(const FunctionCallbackInfo<Value>& args) {
438
453
options.host_defined_options_id = args[6 ].As <Symbol>();
439
454
440
455
TryCatchScope try_catch (env);
441
- BaseObjectPtr< ContextifyContext> context_ptr =
456
+ ContextifyContext* context_ptr =
442
457
ContextifyContext::New (env, sandbox, &options);
443
458
444
459
if (try_catch.HasCaught ()) {
@@ -469,6 +484,10 @@ ContextifyContext* ContextifyContext::ContextFromContextifiedSandbox(
469
484
470
485
template <typename T>
471
486
ContextifyContext* ContextifyContext::Get (const PropertyCallbackInfo<T>& args) {
487
+ // TODO(joyeecheung): it should be fine to simply use
488
+ // args.GetIsolate()->GetCurrentContext() and take the pointer at
489
+ // ContextEmbedderIndex::kContextifyContext, as V8 is supposed to
490
+ // push the creation context before invoking these callbacks.
472
491
return Get (args.This ());
473
492
}
474
493
0 commit comments