Skip to content

Commit f750205

Browse files
authored
Merge pull request #546 from Bartel-C8/runtimeElectronCheck
2 parents 31a6de4 + 2aeeb35 commit f750205

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ test/typings-compatibility/
2121
/script/*/*.js.map
2222
tsconfig.tsbuildinfo
2323
/docs-raw
24+
.DS_Store

src/incoming_msg.cc

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Copyright (c) 2017-2019 Rolf Timmermans */
22
#include "incoming_msg.h"
33

4+
#include "util/electron_helper.h"
45
#include "util/error.h"
56

67
namespace zmq {
@@ -14,39 +15,38 @@ IncomingMsg::~IncomingMsg() {
1415
}
1516

1617
Napi::Value IncomingMsg::IntoBuffer(const Napi::Env& env) {
17-
#if !(NODE_RUNTIME_ELECTRON && NODE_MODULE_VERSION >= 109) // 109 is Electron v21 and up
18-
if (moved) {
19-
/* If ownership has been transferred, do not attempt to read the buffer
20-
again in any case. This should not happen of course. */
21-
ErrnoException(env, EINVAL).ThrowAsJavaScriptException();
22-
return env.Undefined();
18+
static auto const noElectronMemoryCage = !hasElectronMemoryCage(env);
19+
if (noElectronMemoryCage) {
20+
if (moved) {
21+
/* If ownership has been transferred, do not attempt to read the buffer
22+
again in any case. This should not happen of course. */
23+
ErrnoException(env, EINVAL).ThrowAsJavaScriptException();
24+
return env.Undefined();
25+
}
2326
}
24-
25-
static auto constexpr zero_copy_threshold = 1 << 7;
26-
#endif
27-
2827
auto data = reinterpret_cast<uint8_t*>(zmq_msg_data(*ref));
2928
auto length = zmq_msg_size(*ref);
3029

31-
#if !(NODE_RUNTIME_ELECTRON && NODE_MODULE_VERSION >= 109) // 109 is Electron v21 and up
32-
if (length > zero_copy_threshold) {
33-
/* Reuse existing buffer for external storage. This avoids copying but
34-
does include an overhead in having to call a finalizer when the
35-
buffer is GC'ed. For very small messages it is faster to copy. */
36-
moved = true;
30+
if (noElectronMemoryCage) {
31+
static auto constexpr zero_copy_threshold = 1 << 7;
32+
if (length > zero_copy_threshold) {
33+
/* Reuse existing buffer for external storage. This avoids copying but
34+
does include an overhead in having to call a finalizer when the
35+
buffer is GC'ed. For very small messages it is faster to copy. */
36+
moved = true;
3737

38-
/* Put appropriate GC pressure according to the size of the buffer. */
39-
Napi::MemoryManagement::AdjustExternalMemory(env, length);
38+
/* Put appropriate GC pressure according to the size of the buffer. */
39+
Napi::MemoryManagement::AdjustExternalMemory(env, length);
4040

41-
auto release = [](const Napi::Env& env, uint8_t*, Reference* ref) {
42-
ptrdiff_t length = zmq_msg_size(*ref);
43-
Napi::MemoryManagement::AdjustExternalMemory(env, -length);
44-
delete ref;
45-
};
41+
auto release = [](const Napi::Env& env, uint8_t*, Reference* ref) {
42+
ptrdiff_t length = zmq_msg_size(*ref);
43+
Napi::MemoryManagement::AdjustExternalMemory(env, -length);
44+
delete ref;
45+
};
4646

47-
return Napi::Buffer<uint8_t>::New(env, data, length, release, ref);
47+
return Napi::Buffer<uint8_t>::New(env, data, length, release, ref);
48+
}
4849
}
49-
#endif
5050

5151
if (length > 0) {
5252
return Napi::Buffer<uint8_t>::Copy(env, data, length);

src/util/electron_helper.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include <napi.h>
4+
#include <string>
5+
6+
namespace zmq {
7+
bool hasRun = false;
8+
bool hasElectronMemoryCageCache = false;
9+
10+
static inline std::string first_component(std::string const& value) {
11+
std::string::size_type pos = value.find('.');
12+
return pos == value.npos ? value : value.substr(0, pos);
13+
}
14+
15+
/* Check if runtime is Electron. */
16+
static inline bool IsElectron(const Napi::Env& env) {
17+
auto global = env.Global();
18+
auto isElectron = global.Get("process")
19+
.As<Napi::Object>()
20+
.Get("versions")
21+
.As<Napi::Object>()
22+
.Has("electron");
23+
return isElectron;
24+
}
25+
26+
static inline bool hasElectronMemoryCage(const Napi::Env& env) {
27+
if (!hasRun) {
28+
if (IsElectron(env)) {
29+
auto electronVers = env.Global()
30+
.Get("process")
31+
.ToObject()
32+
.Get("versions")
33+
.ToObject()
34+
.Get("electron")
35+
.ToString()
36+
.Utf8Value();
37+
int majorVer = stoi(first_component(electronVers));
38+
if (majorVer >= 21) {
39+
hasElectronMemoryCageCache = true;
40+
}
41+
}
42+
hasRun = true;
43+
}
44+
return hasElectronMemoryCageCache;
45+
}
46+
}

0 commit comments

Comments
 (0)