diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-11-19 21:36:41 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-11-30 02:02:51 +0100 |
commit | fa5937b1e75ab04c1a1aaf396b36fbfaf4fff155 (patch) | |
tree | 16f3081cfc8235cc40efcc966fc867afe5adec16 /src | |
parent | b7ef5937444c2693809f149acbb57457d75fe1bb (diff) | |
download | android-node-v8-fa5937b1e75ab04c1a1aaf396b36fbfaf4fff155.tar.gz android-node-v8-fa5937b1e75ab04c1a1aaf396b36fbfaf4fff155.tar.bz2 android-node-v8-fa5937b1e75ab04c1a1aaf396b36fbfaf4fff155.zip |
n-api: detach external ArrayBuffers on env exit
Make sure that `ArrayBuffer`s created using
`napi_create_external_arraybuffer` are rendered unusable
after its memory has been released.
PR-URL: https://github.com/nodejs/node/pull/30551
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/js_native_api_v8.cc | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 05712afde0..5506b2b4c6 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -186,8 +186,8 @@ inline static napi_status ConcludeDeferred(napi_env env, } // Wrapper around v8impl::Persistent that implements reference counting. -class Reference : private Finalizer, RefTracker { - private: +class Reference : protected Finalizer, RefTracker { + protected: Reference(napi_env env, v8::Local<v8::Value> value, uint32_t initial_refcount, @@ -289,7 +289,7 @@ class Reference : private Finalizer, RefTracker { } } - private: + protected: void Finalize(bool is_env_teardown = false) override { if (_finalize_callback != nullptr) { _env->CallIntoModuleThrow([&](napi_env env) { @@ -310,6 +310,7 @@ class Reference : private Finalizer, RefTracker { } } + private: // The N-API finalizer callback may make calls into the engine. V8's heap is // not in a consistent state during the weak callback, and therefore it does // not support calls back into it. However, it provides a mechanism for adding @@ -335,6 +336,37 @@ class Reference : private Finalizer, RefTracker { bool _delete_self; }; +class ArrayBufferReference final : public Reference { + public: + // Same signatures for ctor and New() as Reference, except this only works + // with ArrayBuffers: + template <typename... Args> + explicit ArrayBufferReference(napi_env env, + v8::Local<v8::ArrayBuffer> value, + Args&&... args) + : Reference(env, value, std::forward<Args>(args)...) {} + + template <typename... Args> + static ArrayBufferReference* New(napi_env env, + v8::Local<v8::ArrayBuffer> value, + Args&&... args) { + return new ArrayBufferReference(env, value, std::forward<Args>(args)...); + } + + private: + void Finalize(bool is_env_teardown) override { + if (is_env_teardown) { + v8::HandleScope handle_scope(_env->isolate); + v8::Local<v8::Value> ab = Get(); + CHECK(!ab.IsEmpty()); + CHECK(ab->IsArrayBuffer()); + ab.As<v8::ArrayBuffer>()->Detach(); + } + + Reference::Finalize(is_env_teardown); + } +}; + enum UnwrapAction { KeepWrap, RemoveWrap @@ -2587,8 +2619,9 @@ napi_status napi_create_external_arraybuffer(napi_env env, if (finalize_cb != nullptr) { // Create a self-deleting weak reference that invokes the finalizer - // callback. - v8impl::Reference::New(env, + // callback and detaches the ArrayBuffer if it still exists on Environment + // teardown. + v8impl::ArrayBufferReference::New(env, buffer, 0, true, |