File tree Expand file tree Collapse file tree 11 files changed +94
-0
lines changed Open diff view settings
Expand file tree Collapse file tree 11 files changed +94
-0
lines changed Open diff view settings
Original file line number Diff line number Diff line change @@ -324,5 +324,6 @@ module.exports = {
324324 TextEncoder : 'readable' ,
325325 TextDecoder : 'readable' ,
326326 queueMicrotask : 'readable' ,
327+ globalThis : 'readable' ,
327328 } ,
328329} ;
Original file line number Diff line number Diff line change @@ -100,6 +100,9 @@ void InternalCallbackScope::Close() {
100100 TickInfo* tick_info = env_->tick_info ();
101101
102102 if (!env_->can_call_into_js ()) return ;
103+
104+ OnScopeLeave weakref_cleanup ([&]() { env_->RunWeakRefCleanup (); });
105+
103106 if (!tick_info->has_tick_scheduled ()) {
104107 MicrotasksScope::PerformCheckpoint (env_->isolate ());
105108 }
Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ using errors::TryCatchScope;
1212using v8::Array;
1313using v8::Context;
1414using v8::EscapableHandleScope;
15+ using v8::FinalizationGroup;
1516using v8::Function;
1617using v8::HandleScope;
1718using v8::Isolate;
@@ -76,6 +77,15 @@ static MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
7677 return result;
7778}
7879
80+ static void HostCleanupFinalizationGroupCallback (
81+ Local<Context> context, Local<FinalizationGroup> group) {
82+ Environment* env = Environment::GetCurrent (context);
83+ if (env == nullptr ) {
84+ return ;
85+ }
86+ env->RegisterFinalizationGroupForCleanup (group);
87+ }
88+
7989void * NodeArrayBufferAllocator::Allocate (size_t size) {
8090 if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers )
8191 return UncheckedCalloc (size);
@@ -203,6 +213,8 @@ void SetIsolateUpForNode(v8::Isolate* isolate, IsolateSettingCategories cat) {
203213 isolate->SetAllowWasmCodeGenerationCallback (
204214 AllowWasmCodeGenerationCallback);
205215 isolate->SetPromiseRejectCallback (task_queue::PromiseRejectCallback);
216+ isolate->SetHostCleanupFinalizationGroupCallback (
217+ HostCleanupFinalizationGroupCallback);
206218 v8::CpuProfiler::UseDetailedSourcePositionsForProfiling (isolate);
207219 break ;
208220 default :
Original file line number Diff line number Diff line change @@ -1115,6 +1115,11 @@ void Environment::RemoveCleanupHook(void (*fn)(void*), void* arg) {
11151115 cleanup_hooks_.erase (search);
11161116}
11171117
1118+ inline void Environment::RegisterFinalizationGroupForCleanup (
1119+ v8::Local<v8::FinalizationGroup> group) {
1120+ cleanup_finalization_groups_.emplace_back (isolate (), group);
1121+ }
1122+
11181123size_t CleanupHookCallback::Hash::operator ()(
11191124 const CleanupHookCallback& cb) const {
11201125 return std::hash<void *>()(cb.arg_ );
Original file line number Diff line number Diff line change @@ -28,6 +28,7 @@ using v8::ArrayBuffer;
2828using v8::Boolean;
2929using v8::Context;
3030using v8::EmbedderGraph;
31+ using v8::FinalizationGroup;
3132using v8::Function;
3233using v8::FunctionTemplate;
3334using v8::HandleScope;
@@ -1050,6 +1051,21 @@ void Environment::AddArrayBufferAllocatorToKeepAliveUntilIsolateDispose(
10501051 keep_alive_allocators_->insert (allocator);
10511052}
10521053
1054+ bool Environment::RunWeakRefCleanup () {
1055+ isolate ()->ClearKeptObjects ();
1056+
1057+ while (!cleanup_finalization_groups_.empty ()) {
1058+ Local<FinalizationGroup> fg =
1059+ cleanup_finalization_groups_.front ().Get (isolate ());
1060+ cleanup_finalization_groups_.pop_front ();
1061+ if (!FinalizationGroup::Cleanup (fg).FromMaybe (false )) {
1062+ return false ;
1063+ }
1064+ }
1065+
1066+ return true ;
1067+ }
1068+
10531069void AsyncRequest::Install (Environment* env, void * data, uv_async_cb target) {
10541070 CHECK_NULL (async_);
10551071 env_ = env;
Original file line number Diff line number Diff line change @@ -1132,6 +1132,9 @@ class Environment : public MemoryRetainer {
11321132 void AtExit (void (*cb)(void * arg), void* arg);
11331133 void RunAtExitCallbacks ();
11341134
1135+ void RegisterFinalizationGroupForCleanup (v8::Local<v8::FinalizationGroup> fg);
1136+ bool RunWeakRefCleanup ();
1137+
11351138 // Strings and private symbols are shared across shared contexts
11361139 // The getters simply proxy to the per-isolate primitive.
11371140#define VP (PropertyName, StringValue ) V(v8::Private, PropertyName)
@@ -1338,6 +1341,8 @@ class Environment : public MemoryRetainer {
13381341 uint64_t thread_id_;
13391342 std::unordered_set<worker::Worker*> sub_worker_contexts_;
13401343
1344+ std::deque<v8::Global<v8::FinalizationGroup>> cleanup_finalization_groups_;
1345+
13411346 static void * const kNodeContextTagPtr ;
13421347 static int const kNodeContextTag ;
13431348
Original file line number Diff line number Diff line change @@ -43,6 +43,8 @@ static void EnqueueMicrotask(const FunctionCallbackInfo<Value>& args) {
4343
4444// Should be in sync with runNextTicks in internal/process/task_queues.js
4545bool RunNextTicksNative (Environment* env) {
46+ OnScopeLeave weakref_cleanup ([&]() { env->RunWeakRefCleanup (); });
47+
4648 TickInfo* tick_info = env->tick_info ();
4749 if (!tick_info->has_tick_scheduled () && !tick_info->has_rejection_to_warn ())
4850 MicrotasksScope::PerformCheckpoint (env->isolate ());
Original file line number Diff line number Diff line change @@ -34,3 +34,4 @@ globals:
3434 BigInt64Array : false
3535 BigUint64Array : false
3636 SharedArrayBuffer : false
37+ globalThis : false
Original file line number Diff line number Diff line change 1+ 'use strict' ;
2+
3+ // Flags: --expose-gc --harmony-weak-refs
4+
5+ const common = require ( '../common' ) ;
6+ const assert = require ( 'assert' ) ;
7+
8+ const g = new globalThis . FinalizationGroup ( common . mustCallAtLeast ( ( ) => {
9+ throw new Error ( 'test' ) ;
10+ } , 1 ) ) ;
11+ g . register ( { } , 42 ) ;
12+
13+ setTimeout ( ( ) => {
14+ globalThis . gc ( ) ;
15+ assert . throws ( ( ) => {
16+ g . cleanupSome ( ) ;
17+ } , {
18+ name : 'Error' ,
19+ message : 'test' ,
20+ } ) ;
21+ } , 200 ) ;
22+
23+ process . on ( 'uncaughtException' , common . mustCall ( ) ) ;
Original file line number Diff line number Diff line change 1+ 'use strict' ;
2+
3+ // Flags: --expose-gc --harmony-weak-refs
4+
5+ const common = require ( '../common' ) ;
6+
7+ const g = new globalThis . FinalizationGroup ( common . mustCallAtLeast ( 1 ) ) ;
8+ g . register ( { } , 42 ) ;
9+
10+ setTimeout ( ( ) => {
11+ globalThis . gc ( ) ;
12+ g . cleanupSome ( ) ;
13+ } , 200 ) ;
You can’t perform that action at this time.
0 commit comments