From 4386d67082a558fba2d12db072aa8d7366a68f7a Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 9 May 2018 18:32:59 +0200 Subject: [PATCH] src: make `AsyncResource` destructor virtual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `AsyncResource` is intended to be a base class, and since we don’t know what API consumers will do with it in their own code, it’s good practice to make its destructor virtual. This should not be ABI-breaking since all class methods are inline. --- src/node.h | 2 +- test/addons/async-resource/binding.cc | 22 ++++++++++++++++++++++ test/addons/async-resource/test.js | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/node.h b/src/node.h index 5a491c1abf54..0fea0d849587 100644 --- a/src/node.h +++ b/src/node.h @@ -699,7 +699,7 @@ class AsyncResource { trigger_async_id); } - ~AsyncResource() { + virtual ~AsyncResource() { EmitAsyncDestroy(isolate_, async_context_); } diff --git a/test/addons/async-resource/binding.cc b/test/addons/async-resource/binding.cc index 857d74c2e622..ab33858c233d 100644 --- a/test/addons/async-resource/binding.cc +++ b/test/addons/async-resource/binding.cc @@ -17,6 +17,17 @@ using v8::Object; using v8::String; using v8::Value; +int custom_async_resource_destructor_calls = 0; + +class CustomAsyncResource : public AsyncResource { + public: + CustomAsyncResource(Isolate* isolate, Local resource) + : AsyncResource(isolate, resource, "CustomAsyncResource") {} + ~CustomAsyncResource() { + custom_async_resource_destructor_calls++; + } +}; + void CreateAsyncResource(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(args[0]->IsObject()); @@ -98,6 +109,16 @@ void GetResource(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(r->get_resource()); } +void RunSubclassTest(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + Local obj = Object::New(isolate); + + assert(custom_async_resource_destructor_calls == 0); + CustomAsyncResource* resource = new CustomAsyncResource(isolate, obj); + delete static_cast(resource); + assert(custom_async_resource_destructor_calls == 1); +} + void Initialize(Local exports) { NODE_SET_METHOD(exports, "createAsyncResource", CreateAsyncResource); NODE_SET_METHOD(exports, "destroyAsyncResource", DestroyAsyncResource); @@ -107,6 +128,7 @@ void Initialize(Local exports) { NODE_SET_METHOD(exports, "getAsyncId", GetAsyncId); NODE_SET_METHOD(exports, "getTriggerAsyncId", GetTriggerAsyncId); NODE_SET_METHOD(exports, "getResource", GetResource); + NODE_SET_METHOD(exports, "runSubclassTest", RunSubclassTest); } } // anonymous namespace diff --git a/test/addons/async-resource/test.js b/test/addons/async-resource/test.js index f19ad58637f1..c37d4df83d01 100644 --- a/test/addons/async-resource/test.js +++ b/test/addons/async-resource/test.js @@ -5,6 +5,8 @@ const assert = require('assert'); const binding = require(`./build/${common.buildType}/binding`); const async_hooks = require('async_hooks'); +binding.runSubclassTest(); + const kObjectTag = Symbol('kObjectTag'); const rootAsyncId = async_hooks.executionAsyncId();