Bug Summary

File:out/../src/env-inl.h
Warning:line 441, column 3
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name node_blob.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D NODE_ARCH="x64" -D NODE_PLATFORM="linux" -D NODE_WANT_INTERNALS=1 -D V8_DEPRECATION_WARNINGS=1 -D NODE_OPENSSL_SYSTEM_CERT_PATH="" -D NODE_USE_NODE_CODE_CACHE=1 -D HAVE_INSPECTOR=1 -D NODE_ENABLE_LARGE_CODE_PAGES=1 -D __POSIX__ -D NODE_USE_V8_PLATFORM=1 -D NODE_HAVE_I18N_SUPPORT=1 -D HAVE_OPENSSL=1 -D OPENSSL_API_COMPAT=0x10100000L -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS=64 -D _POSIX_C_SOURCE=200112 -D NGHTTP2_STATICLIB -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D NGTCP2_STATICLIB -D NGHTTP3_STATICLIB -I ../src -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/src -I ../deps/googletest/include -I ../deps/histogram/src -I ../deps/uvwasi/include -I ../deps/v8/include -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/zlib -I ../deps/llhttp/include -I ../deps/cares/include -I ../deps/uv/include -I ../deps/nghttp2/lib/includes -I ../deps/brotli/c/include -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/ngtcp2 -I ../deps/ngtcp2/ngtcp2/lib/includes -I ../deps/ngtcp2/ngtcp2/crypto/includes -I ../deps/ngtcp2/nghttp3/lib/includes -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused-parameter -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../src/node_blob.cc

../src/node_blob.cc

1#include "node_blob.h"
2#include "async_wrap-inl.h"
3#include "base_object-inl.h"
4#include "env-inl.h"
5#include "memory_tracker-inl.h"
6#include "node_errors.h"
7#include "node_external_reference.h"
8#include "threadpoolwork-inl.h"
9#include "v8.h"
10
11#include <algorithm>
12
13namespace node {
14
15using v8::Array;
16using v8::ArrayBuffer;
17using v8::ArrayBufferView;
18using v8::BackingStore;
19using v8::Context;
20using v8::EscapableHandleScope;
21using v8::Function;
22using v8::FunctionCallbackInfo;
23using v8::FunctionTemplate;
24using v8::HandleScope;
25using v8::Local;
26using v8::MaybeLocal;
27using v8::Number;
28using v8::Object;
29using v8::String;
30using v8::Uint32;
31using v8::Undefined;
32using v8::Value;
33
34void Blob::Initialize(
35 Local<Object> target,
36 Local<Value> unused,
37 Local<Context> context,
38 void* priv) {
39 Environment* env = Environment::GetCurrent(context);
40
41 BlobBindingData* const binding_data =
42 env->AddBindingData<BlobBindingData>(context, target);
43 if (binding_data == nullptr) return;
44
45 env->SetMethod(target, "createBlob", New);
46 env->SetMethod(target, "storeDataObject", StoreDataObject);
47 env->SetMethod(target, "getDataObject", GetDataObject);
48 env->SetMethod(target, "revokeDataObject", RevokeDataObject);
49 FixedSizeBlobCopyJob::Initialize(env, target);
50}
51
52Local<FunctionTemplate> Blob::GetConstructorTemplate(Environment* env) {
53 Local<FunctionTemplate> tmpl = env->blob_constructor_template();
54 if (tmpl.IsEmpty()) {
55 tmpl = FunctionTemplate::New(env->isolate());
56 tmpl->InstanceTemplate()->SetInternalFieldCount(
57 BaseObject::kInternalFieldCount);
58 tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
59 tmpl->SetClassName(
60 FIXED_ONE_BYTE_STRING(env->isolate(), "Blob"));
61 env->SetProtoMethod(tmpl, "toArrayBuffer", ToArrayBuffer);
62 env->SetProtoMethod(tmpl, "slice", ToSlice);
63 env->set_blob_constructor_template(tmpl);
64 }
65 return tmpl;
66}
67
68bool Blob::HasInstance(Environment* env, v8::Local<v8::Value> object) {
69 return GetConstructorTemplate(env)->HasInstance(object);
70}
71
72BaseObjectPtr<Blob> Blob::Create(
73 Environment* env,
74 const std::vector<BlobEntry> store,
75 size_t length) {
76
77 HandleScope scope(env->isolate());
78
79 Local<Function> ctor;
80 if (!GetConstructorTemplate(env)->GetFunction(env->context()).ToLocal(&ctor))
81 return BaseObjectPtr<Blob>();
82
83 Local<Object> obj;
84 if (!ctor->NewInstance(env->context()).ToLocal(&obj))
85 return BaseObjectPtr<Blob>();
86
87 return MakeBaseObject<Blob>(env, obj, store, length);
88}
89
90void Blob::New(const FunctionCallbackInfo<Value>& args) {
91 Environment* env = Environment::GetCurrent(args);
92 CHECK(args[0]->IsArray())do { if (__builtin_expect(!!(!(args[0]->IsArray())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "92", "args[0]->IsArray()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // sources
93 CHECK(args[1]->IsUint32())do { if (__builtin_expect(!!(!(args[1]->IsUint32())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "93", "args[1]->IsUint32()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // length
94
95 std::vector<BlobEntry> entries;
96
97 size_t length = args[1].As<Uint32>()->Value();
98 size_t len = 0;
99 Local<Array> ary = args[0].As<Array>();
100 for (size_t n = 0; n < ary->Length(); n++) {
101 Local<Value> entry;
102 if (!ary->Get(env->context(), n).ToLocal(&entry))
103 return;
104 CHECK(entry->IsArrayBufferView() || Blob::HasInstance(env, entry))do { if (__builtin_expect(!!(!(entry->IsArrayBufferView() ||
Blob::HasInstance(env, entry))), 0)) { do { static const node
::AssertionInfo args = { "../src/node_blob.cc" ":" "104", "entry->IsArrayBufferView() || Blob::HasInstance(env, entry)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
105 if (entry->IsArrayBufferView()) {
106 Local<ArrayBufferView> view = entry.As<ArrayBufferView>();
107 CHECK_EQ(view->ByteOffset(), 0)do { if (__builtin_expect(!!(!((view->ByteOffset()) == (0)
)), 0)) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "107", "(view->ByteOffset()) == (0)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
108 std::shared_ptr<BackingStore> store = view->Buffer()->GetBackingStore();
109 size_t byte_length = view->ByteLength();
110 view->Buffer()->Detach(); // The Blob will own the backing store now.
111 entries.emplace_back(BlobEntry{std::move(store), byte_length, 0});
112 len += byte_length;
113 } else {
114 Blob* blob;
115 ASSIGN_OR_RETURN_UNWRAP(&blob, entry)do { *&blob = static_cast<typename std::remove_reference
<decltype(*&blob)>::type>( BaseObject::FromJSObject
(entry)); if (*&blob == nullptr) return ; } while (0)
;
116 auto source = blob->entries();
117 entries.insert(entries.end(), source.begin(), source.end());
118 len += blob->length();
119 }
120 }
121 CHECK_EQ(length, len)do { if (__builtin_expect(!!(!((length) == (len))), 0)) { do {
static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "121", "(length) == (len)", __PRETTY_FUNCTION__ }; node::
Assert(args); } while (0); } } while (0)
;
122
123 BaseObjectPtr<Blob> blob = Create(env, entries, length);
124 if (blob)
125 args.GetReturnValue().Set(blob->object());
126}
127
128void Blob::ToArrayBuffer(const FunctionCallbackInfo<Value>& args) {
129 Environment* env = Environment::GetCurrent(args);
130 Blob* blob;
131 ASSIGN_OR_RETURN_UNWRAP(&blob, args.Holder())do { *&blob = static_cast<typename std::remove_reference
<decltype(*&blob)>::type>( BaseObject::FromJSObject
(args.Holder())); if (*&blob == nullptr) return ; } while
(0)
;
132 Local<Value> ret;
133 if (blob->GetArrayBuffer(env).ToLocal(&ret))
134 args.GetReturnValue().Set(ret);
135}
136
137void Blob::ToSlice(const FunctionCallbackInfo<Value>& args) {
138 Environment* env = Environment::GetCurrent(args);
139 Blob* blob;
140 ASSIGN_OR_RETURN_UNWRAP(&blob, args.Holder())do { *&blob = static_cast<typename std::remove_reference
<decltype(*&blob)>::type>( BaseObject::FromJSObject
(args.Holder())); if (*&blob == nullptr) return ; } while
(0)
;
141 CHECK(args[0]->IsUint32())do { if (__builtin_expect(!!(!(args[0]->IsUint32())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "141", "args[0]->IsUint32()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
142 CHECK(args[1]->IsUint32())do { if (__builtin_expect(!!(!(args[1]->IsUint32())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "142", "args[1]->IsUint32()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
143 size_t start = args[0].As<Uint32>()->Value();
144 size_t end = args[1].As<Uint32>()->Value();
145 BaseObjectPtr<Blob> slice = blob->Slice(env, start, end);
146 if (slice)
147 args.GetReturnValue().Set(slice->object());
148}
149
150void Blob::MemoryInfo(MemoryTracker* tracker) const {
151 tracker->TrackFieldWithSize("store", length_);
152}
153
154MaybeLocal<Value> Blob::GetArrayBuffer(Environment* env) {
155 EscapableHandleScope scope(env->isolate());
156 size_t len = length();
157 std::shared_ptr<BackingStore> store =
158 ArrayBuffer::NewBackingStore(env->isolate(), len);
159 if (len > 0) {
160 unsigned char* dest = static_cast<unsigned char*>(store->Data());
161 size_t total = 0;
162 for (const auto& entry : entries()) {
163 unsigned char* src = static_cast<unsigned char*>(entry.store->Data());
164 src += entry.offset;
165 memcpy(dest, src, entry.length);
166 dest += entry.length;
167 total += entry.length;
168 CHECK_LE(total, len)do { if (__builtin_expect(!!(!((total) <= (len))), 0)) { do
{ static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "168", "(total) <= (len)", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
169 }
170 }
171
172 return scope.Escape(ArrayBuffer::New(env->isolate(), store));
173}
174
175BaseObjectPtr<Blob> Blob::Slice(Environment* env, size_t start, size_t end) {
176 CHECK_LE(start, length())do { if (__builtin_expect(!!(!((start) <= (length()))), 0)
) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "176", "(start) <= (length())", __PRETTY_FUNCTION__ }
; node::Assert(args); } while (0); } } while (0)
;
177 CHECK_LE(end, length())do { if (__builtin_expect(!!(!((end) <= (length()))), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "177", "(end) <= (length())", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
178 CHECK_LE(start, end)do { if (__builtin_expect(!!(!((start) <= (end))), 0)) { do
{ static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "178", "(start) <= (end)", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
179
180 std::vector<BlobEntry> slices;
181 size_t total = end - start;
182 size_t remaining = total;
183
184 if (total == 0) return Create(env, slices, 0);
185
186 for (const auto& entry : entries()) {
187 if (start + entry.offset > entry.store->ByteLength()) {
188 start -= entry.length;
189 continue;
190 }
191
192 size_t offset = entry.offset + start;
193 size_t len = std::min(remaining, entry.store->ByteLength() - offset);
194 slices.emplace_back(BlobEntry{entry.store, len, offset});
195
196 remaining -= len;
197 start = 0;
198
199 if (remaining == 0)
200 break;
201 }
202
203 return Create(env, slices, total);
204}
205
206Blob::Blob(
207 Environment* env,
208 v8::Local<v8::Object> obj,
209 const std::vector<BlobEntry>& store,
210 size_t length)
211 : BaseObject(env, obj),
212 store_(store),
213 length_(length) {
214 MakeWeak();
215}
216
217BaseObjectPtr<BaseObject>
218Blob::BlobTransferData::Deserialize(
219 Environment* env,
220 Local<Context> context,
221 std::unique_ptr<worker::TransferData> self) {
222 if (context != env->context()) {
223 THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
224 return {};
225 }
226 return Blob::Create(env, store_, length_);
227}
228
229BaseObject::TransferMode Blob::GetTransferMode() const {
230 return BaseObject::TransferMode::kCloneable;
231}
232
233std::unique_ptr<worker::TransferData> Blob::CloneForMessaging() const {
234 return std::make_unique<BlobTransferData>(store_, length_);
235}
236
237void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
238 Environment* env = Environment::GetCurrent(args);
239 BlobBindingData* binding_data =
240 Environment::GetBindingData<BlobBindingData>(args);
241
242 CHECK(args[0]->IsString())do { if (__builtin_expect(!!(!(args[0]->IsString())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "242", "args[0]->IsString()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // ID key
243 CHECK(Blob::HasInstance(env, args[1]))do { if (__builtin_expect(!!(!(Blob::HasInstance(env, args[1]
))), 0)) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "243", "Blob::HasInstance(env, args[1])", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
; // Blob
244 CHECK(args[2]->IsUint32())do { if (__builtin_expect(!!(!(args[2]->IsUint32())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "244", "args[2]->IsUint32()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // Length
245 CHECK(args[3]->IsString())do { if (__builtin_expect(!!(!(args[3]->IsString())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "245", "args[3]->IsString()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // Type
246
247 Utf8Value key(env->isolate(), args[0]);
248 Blob* blob;
249 ASSIGN_OR_RETURN_UNWRAP(&blob, args[1])do { *&blob = static_cast<typename std::remove_reference
<decltype(*&blob)>::type>( BaseObject::FromJSObject
(args[1])); if (*&blob == nullptr) return ; } while (0)
;
250
251 size_t length = args[2].As<Uint32>()->Value();
252 Utf8Value type(env->isolate(), args[3]);
253
254 binding_data->store_data_object(
255 std::string(*key, key.length()),
256 BlobBindingData::StoredDataObject(
257 BaseObjectPtr<Blob>(blob),
258 length,
259 std::string(*type, type.length())));
260}
261
262void Blob::RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
263 BlobBindingData* binding_data =
264 Environment::GetBindingData<BlobBindingData>(args);
265
266 Environment* env = Environment::GetCurrent(args);
267 CHECK(args[0]->IsString())do { if (__builtin_expect(!!(!(args[0]->IsString())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "267", "args[0]->IsString()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
; // ID key
268
269 Utf8Value key(env->isolate(), args[0]);
270
271 binding_data->revoke_data_object(std::string(*key, key.length()));
272}
273
274void Blob::GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
275 BlobBindingData* binding_data =
276 Environment::GetBindingData<BlobBindingData>(args);
277
278 Environment* env = Environment::GetCurrent(args);
279 CHECK(args[0]->IsString())do { if (__builtin_expect(!!(!(args[0]->IsString())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "279", "args[0]->IsString()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
280
281 Utf8Value key(env->isolate(), args[0]);
282
283 BlobBindingData::StoredDataObject stored =
284 binding_data->get_data_object(std::string(*key, key.length()));
285 if (stored.blob) {
286 Local<Value> type;
287 if (!String::NewFromUtf8(
288 env->isolate(),
289 stored.type.c_str(),
290 v8::NewStringType::kNormal,
291 static_cast<int>(stored.type.length())).ToLocal(&type)) {
292 return;
293 }
294
295 Local<Value> values[] = {
296 stored.blob->object(),
297 Uint32::NewFromUnsigned(env->isolate(), stored.length),
298 type
299 };
300
301 args.GetReturnValue().Set(
302 Array::New(
303 env->isolate(),
304 values,
305 arraysize(values)));
306 }
307}
308
309FixedSizeBlobCopyJob::FixedSizeBlobCopyJob(
310 Environment* env,
311 Local<Object> object,
312 Blob* blob,
313 FixedSizeBlobCopyJob::Mode mode)
314 : AsyncWrap(env, object, AsyncWrap::PROVIDER_FIXEDSIZEBLOBCOPY),
315 ThreadPoolWork(env),
316 mode_(mode) {
317 if (mode == FixedSizeBlobCopyJob::Mode::SYNC) MakeWeak();
318 source_ = blob->entries();
319 length_ = blob->length();
320}
321
322void FixedSizeBlobCopyJob::AfterThreadPoolWork(int status) {
323 Environment* env = AsyncWrap::env();
324 CHECK_EQ(mode_, Mode::ASYNC)do { if (__builtin_expect(!!(!((mode_) == (Mode::ASYNC))), 0)
) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "324", "(mode_) == (Mode::ASYNC)", __PRETTY_FUNCTION__ }
; node::Assert(args); } while (0); } } while (0)
;
325 CHECK(status == 0 || status == UV_ECANCELED)do { if (__builtin_expect(!!(!(status == 0 || status == UV_ECANCELED
)), 0)) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "325", "status == 0 || status == UV_ECANCELED", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
326 std::unique_ptr<FixedSizeBlobCopyJob> ptr(this);
327 HandleScope handle_scope(env->isolate());
328 Context::Scope context_scope(env->context());
329 Local<Value> args[2];
330
331 if (status == UV_ECANCELED) {
332 args[0] = Number::New(env->isolate(), status),
333 args[1] = Undefined(env->isolate());
334 } else {
335 args[0] = Undefined(env->isolate());
336 args[1] = ArrayBuffer::New(env->isolate(), destination_);
337 }
338
339 ptr->MakeCallback(env->ondone_string(), arraysize(args), args);
340}
341
342void FixedSizeBlobCopyJob::DoThreadPoolWork() {
343 unsigned char* dest = static_cast<unsigned char*>(destination_->Data());
344 if (length_ > 0) {
345 size_t total = 0;
346 for (const auto& entry : source_) {
347 unsigned char* src = static_cast<unsigned char*>(entry.store->Data());
348 src += entry.offset;
349 memcpy(dest, src, entry.length);
350 dest += entry.length;
351 total += entry.length;
352 CHECK_LE(total, length_)do { if (__builtin_expect(!!(!((total) <= (length_))), 0))
{ do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "352", "(total) <= (length_)", __PRETTY_FUNCTION__ };
node::Assert(args); } while (0); } } while (0)
;
353 }
354 }
355}
356
357void FixedSizeBlobCopyJob::MemoryInfo(MemoryTracker* tracker) const {
358 tracker->TrackFieldWithSize("source", length_);
359 tracker->TrackFieldWithSize(
360 "destination",
361 destination_ ? destination_->ByteLength() : 0);
362}
363
364void FixedSizeBlobCopyJob::Initialize(Environment* env, Local<Object> target) {
365 v8::Local<v8::FunctionTemplate> job = env->NewFunctionTemplate(New);
366 job->Inherit(AsyncWrap::GetConstructorTemplate(env));
367 job->InstanceTemplate()->SetInternalFieldCount(
368 AsyncWrap::kInternalFieldCount);
369 env->SetProtoMethod(job, "run", Run);
370 env->SetConstructorFunction(target, "FixedSizeBlobCopyJob", job);
371}
372
373void FixedSizeBlobCopyJob::New(const FunctionCallbackInfo<Value>& args) {
374 static constexpr size_t kMaxSyncLength = 4096;
375 static constexpr size_t kMaxEntryCount = 4;
376
377 Environment* env = Environment::GetCurrent(args);
378 CHECK(args.IsConstructCall())do { if (__builtin_expect(!!(!(args.IsConstructCall())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "378", "args.IsConstructCall()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
379 CHECK(args[0]->IsObject())do { if (__builtin_expect(!!(!(args[0]->IsObject())), 0)) {
do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "379", "args[0]->IsObject()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
380 CHECK(Blob::HasInstance(env, args[0]))do { if (__builtin_expect(!!(!(Blob::HasInstance(env, args[0]
))), 0)) { do { static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "380", "Blob::HasInstance(env, args[0])", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
381
382 Blob* blob;
383 ASSIGN_OR_RETURN_UNWRAP(&blob, args[0])do { *&blob = static_cast<typename std::remove_reference
<decltype(*&blob)>::type>( BaseObject::FromJSObject
(args[0])); if (*&blob == nullptr) return ; } while (0)
;
384
385 // This is a fairly arbitrary heuristic. We want to avoid deferring to
386 // the threadpool if the amount of data being copied is small and there
387 // aren't that many entries to copy.
388 FixedSizeBlobCopyJob::Mode mode =
389 (blob->length() < kMaxSyncLength &&
390 blob->entries().size() < kMaxEntryCount) ?
391 FixedSizeBlobCopyJob::Mode::SYNC :
392 FixedSizeBlobCopyJob::Mode::ASYNC;
393
394 new FixedSizeBlobCopyJob(env, args.This(), blob, mode);
395}
396
397void FixedSizeBlobCopyJob::Run(const FunctionCallbackInfo<Value>& args) {
398 Environment* env = Environment::GetCurrent(args);
399 FixedSizeBlobCopyJob* job;
400 ASSIGN_OR_RETURN_UNWRAP(&job, args.Holder())do { *&job = static_cast<typename std::remove_reference
<decltype(*&job)>::type>( BaseObject::FromJSObject
(args.Holder())); if (*&job == nullptr) return ; } while (
0)
;
401 job->destination_ =
402 ArrayBuffer::NewBackingStore(env->isolate(), job->length_);
403 if (job->mode() == FixedSizeBlobCopyJob::Mode::ASYNC)
404 return job->ScheduleWork();
405
406 job->DoThreadPoolWork();
407 args.GetReturnValue().Set(
408 ArrayBuffer::New(env->isolate(), job->destination_));
409}
410
411void FixedSizeBlobCopyJob::RegisterExternalReferences(
412 ExternalReferenceRegistry* registry) {
413 registry->Register(New);
414 registry->Register(Run);
415}
416
417void BlobBindingData::StoredDataObject::MemoryInfo(
418 MemoryTracker* tracker) const {
419 tracker->TrackField("blob", blob);
420 tracker->TrackFieldWithSize("type", type.length());
421}
422
423BlobBindingData::StoredDataObject::StoredDataObject(
424 const BaseObjectPtr<Blob>& blob_,
425 size_t length_,
426 const std::string& type_)
427 : blob(blob_),
428 length(length_),
429 type(type_) {}
430
431BlobBindingData::BlobBindingData(Environment* env, Local<Object> wrap)
432 : SnapshotableObject(env, wrap, type_int) {
433 MakeWeak();
434}
435
436void BlobBindingData::MemoryInfo(MemoryTracker* tracker) const {
437 tracker->TrackField("data_objects", data_objects_);
438}
439
440void BlobBindingData::store_data_object(
441 const std::string& uuid,
442 const BlobBindingData::StoredDataObject& object) {
443 data_objects_[uuid] = object;
444}
445
446void BlobBindingData::revoke_data_object(const std::string& uuid) {
447 if (data_objects_.find(uuid) == data_objects_.end()) {
448 return;
449 }
450 data_objects_.erase(uuid);
451 CHECK_EQ(data_objects_.find(uuid), data_objects_.end())do { if (__builtin_expect(!!(!((data_objects_.find(uuid)) == (
data_objects_.end()))), 0)) { do { static const node::AssertionInfo
args = { "../src/node_blob.cc" ":" "451", "(data_objects_.find(uuid)) == (data_objects_.end())"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
452}
453
454BlobBindingData::StoredDataObject BlobBindingData::get_data_object(
455 const std::string& uuid) {
456 auto entry = data_objects_.find(uuid);
457 if (entry == data_objects_.end())
458 return BlobBindingData::StoredDataObject {};
459 return entry->second;
460}
461
462void BlobBindingData::Deserialize(
463 Local<Context> context,
464 Local<Object> holder,
465 int index,
466 InternalFieldInfo* info) {
467 DCHECK_EQ(index, BaseObject::kSlot);
468 HandleScope scope(context->GetIsolate());
469 Environment* env = Environment::GetCurrent(context);
470 BlobBindingData* binding =
471 env->AddBindingData<BlobBindingData>(context, holder);
1
Calling 'Environment::AddBindingData'
472 CHECK_NOT_NULL(binding)do { if (__builtin_expect(!!(!((binding) != nullptr)), 0)) { do
{ static const node::AssertionInfo args = { "../src/node_blob.cc"
":" "472", "(binding) != nullptr", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
473}
474
475void BlobBindingData::PrepareForSerialization(
476 Local<Context> context,
477 v8::SnapshotCreator* creator) {
478 // Stored blob objects are not actually persisted.
479}
480
481InternalFieldInfo* BlobBindingData::Serialize(int index) {
482 DCHECK_EQ(index, BaseObject::kSlot);
483 InternalFieldInfo* info = InternalFieldInfo::New(type());
484 return info;
485}
486
487void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
488 registry->Register(Blob::New);
489 registry->Register(Blob::ToArrayBuffer);
490 registry->Register(Blob::ToSlice);
491 registry->Register(Blob::StoreDataObject);
492 registry->Register(Blob::GetDataObject);
493 registry->Register(Blob::RevokeDataObject);
494
495 FixedSizeBlobCopyJob::RegisterExternalReferences(registry);
496}
497
498} // namespace node
499
500NODE_MODULE_CONTEXT_AWARE_INTERNAL(blob, node::Blob::Initialize)static node::node_module _module = { 108, NM_F_INTERNAL, nullptr
, "../src/node_blob.cc", nullptr, (node::addon_context_register_func
)(node::Blob::Initialize), "blob", nullptr, nullptr}; void _register_blob
() { node_module_register(&_module); }
501NODE_MODULE_EXTERNAL_REFERENCE(blob, node::Blob::RegisterExternalReferences)void _register_external_reference_blob( node::ExternalReferenceRegistry
* registry) { node::Blob::RegisterExternalReferences(registry
); }

../src/env-inl.h

1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22#ifndef SRC_ENV_INL_H_
23#define SRC_ENV_INL_H_
24
25#if defined(NODE_WANT_INTERNALS1) && NODE_WANT_INTERNALS1
26
27#include "aliased_buffer.h"
28#include "callback_queue-inl.h"
29#include "env.h"
30#include "node.h"
31#include "node_context_data.h"
32#include "node_internals.h"
33#include "node_perf_common.h"
34#include "util-inl.h"
35#include "uv.h"
36#include "v8-fast-api-calls.h"
37#include "v8.h"
38
39#include <cstddef>
40#include <cstdint>
41
42#include <utility>
43
44namespace node {
45
46NoArrayBufferZeroFillScope::NoArrayBufferZeroFillScope(
47 IsolateData* isolate_data)
48 : node_allocator_(isolate_data->node_allocator()) {
49 if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 0;
50}
51
52NoArrayBufferZeroFillScope::~NoArrayBufferZeroFillScope() {
53 if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 1;
54}
55
56inline v8::Isolate* IsolateData::isolate() const {
57 return isolate_;
58}
59
60inline uv_loop_t* IsolateData::event_loop() const {
61 return event_loop_;
62}
63
64inline NodeArrayBufferAllocator* IsolateData::node_allocator() const {
65 return node_allocator_;
66}
67
68inline MultiIsolatePlatform* IsolateData::platform() const {
69 return platform_;
70}
71
72inline void IsolateData::set_worker_context(worker::Worker* context) {
73 CHECK_NULL(worker_context_)do { if (__builtin_expect(!!(!((worker_context_) == nullptr))
, 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "73", "(worker_context_) == nullptr", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
; // Should be set only once.
74 worker_context_ = context;
75}
76
77inline worker::Worker* IsolateData::worker_context() const {
78 return worker_context_;
79}
80
81inline v8::Local<v8::String> IsolateData::async_wrap_provider(int index) const {
82 return async_wrap_providers_[index].Get(isolate_);
83}
84
85inline AliasedUint32Array& AsyncHooks::fields() {
86 return fields_;
87}
88
89inline AliasedFloat64Array& AsyncHooks::async_id_fields() {
90 return async_id_fields_;
91}
92
93inline AliasedFloat64Array& AsyncHooks::async_ids_stack() {
94 return async_ids_stack_;
95}
96
97v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() {
98 if (UNLIKELY(js_execution_async_resources_.IsEmpty())__builtin_expect(!!(js_execution_async_resources_.IsEmpty()),
0)
) {
99 js_execution_async_resources_.Reset(
100 env()->isolate(), v8::Array::New(env()->isolate()));
101 }
102 return PersistentToLocal::Strong(js_execution_async_resources_);
103}
104
105v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) {
106 if (i >= native_execution_async_resources_.size()) return {};
107 return native_execution_async_resources_[i];
108}
109
110inline void AsyncHooks::SetJSPromiseHooks(v8::Local<v8::Function> init,
111 v8::Local<v8::Function> before,
112 v8::Local<v8::Function> after,
113 v8::Local<v8::Function> resolve) {
114 js_promise_hooks_[0].Reset(env()->isolate(), init);
115 js_promise_hooks_[1].Reset(env()->isolate(), before);
116 js_promise_hooks_[2].Reset(env()->isolate(), after);
117 js_promise_hooks_[3].Reset(env()->isolate(), resolve);
118 for (auto it = contexts_.begin(); it != contexts_.end(); it++) {
119 if (it->IsEmpty()) {
120 contexts_.erase(it--);
121 continue;
122 }
123 PersistentToLocal::Weak(env()->isolate(), *it)
124 ->SetPromiseHooks(init, before, after, resolve);
125 }
126}
127
128inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) {
129 return env()->isolate_data()->async_wrap_provider(idx);
130}
131
132inline void AsyncHooks::no_force_checks() {
133 fields_[kCheck] -= 1;
134}
135
136inline Environment* AsyncHooks::env() {
137 return Environment::ForAsyncHooks(this);
138}
139
140// Remember to keep this code aligned with pushAsyncContext() in JS.
141inline void AsyncHooks::push_async_context(double async_id,
142 double trigger_async_id,
143 v8::Local<v8::Object> resource) {
144 // Since async_hooks is experimental, do only perform the check
145 // when async_hooks is enabled.
146 if (fields_[kCheck] > 0) {
147 CHECK_GE(async_id, -1)do { if (__builtin_expect(!!(!((async_id) >= (-1))), 0)) {
do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "147", "(async_id) >= (-1)", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
148 CHECK_GE(trigger_async_id, -1)do { if (__builtin_expect(!!(!((trigger_async_id) >= (-1))
), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "148", "(trigger_async_id) >= (-1)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
149 }
150
151 uint32_t offset = fields_[kStackLength];
152 if (offset * 2 >= async_ids_stack_.Length())
153 grow_async_ids_stack();
154 async_ids_stack_[2 * offset] = async_id_fields_[kExecutionAsyncId];
155 async_ids_stack_[2 * offset + 1] = async_id_fields_[kTriggerAsyncId];
156 fields_[kStackLength] += 1;
157 async_id_fields_[kExecutionAsyncId] = async_id;
158 async_id_fields_[kTriggerAsyncId] = trigger_async_id;
159
160#ifdef DEBUG
161 for (uint32_t i = offset; i < native_execution_async_resources_.size(); i++)
162 CHECK(native_execution_async_resources_[i].IsEmpty())do { if (__builtin_expect(!!(!(native_execution_async_resources_
[i].IsEmpty())), 0)) { do { static const node::AssertionInfo args
= { "../src/env-inl.h" ":" "162", "native_execution_async_resources_[i].IsEmpty()"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
163#endif
164
165 // When this call comes from JS (as a way of increasing the stack size),
166 // `resource` will be empty, because JS caches these values anyway.
167 if (!resource.IsEmpty()) {
168 native_execution_async_resources_.resize(offset + 1);
169 // Caveat: This is a v8::Local<> assignment, we do not keep a v8::Global<>!
170 native_execution_async_resources_[offset] = resource;
171 }
172}
173
174// Remember to keep this code aligned with popAsyncContext() in JS.
175inline bool AsyncHooks::pop_async_context(double async_id) {
176 // In case of an exception then this may have already been reset, if the
177 // stack was multiple MakeCallback()'s deep.
178 if (UNLIKELY(fields_[kStackLength] == 0)__builtin_expect(!!(fields_[kStackLength] == 0), 0)) return false;
179
180 // Ask for the async_id to be restored as a check that the stack
181 // hasn't been corrupted.
182 if (UNLIKELY(fields_[kCheck] > 0 &&__builtin_expect(!!(fields_[kCheck] > 0 && async_id_fields_
[kExecutionAsyncId] != async_id), 0)
183 async_id_fields_[kExecutionAsyncId] != async_id)__builtin_expect(!!(fields_[kCheck] > 0 && async_id_fields_
[kExecutionAsyncId] != async_id), 0)
) {
184 FailWithCorruptedAsyncStack(async_id);
185 }
186
187 uint32_t offset = fields_[kStackLength] - 1;
188 async_id_fields_[kExecutionAsyncId] = async_ids_stack_[2 * offset];
189 async_id_fields_[kTriggerAsyncId] = async_ids_stack_[2 * offset + 1];
190 fields_[kStackLength] = offset;
191
192 if (LIKELY(offset < native_execution_async_resources_.size() &&__builtin_expect(!!(offset < native_execution_async_resources_
.size() && !native_execution_async_resources_[offset]
.IsEmpty()), 1)
193 !native_execution_async_resources_[offset].IsEmpty())__builtin_expect(!!(offset < native_execution_async_resources_
.size() && !native_execution_async_resources_[offset]
.IsEmpty()), 1)
) {
194#ifdef DEBUG
195 for (uint32_t i = offset + 1;
196 i < native_execution_async_resources_.size();
197 i++) {
198 CHECK(native_execution_async_resources_[i].IsEmpty())do { if (__builtin_expect(!!(!(native_execution_async_resources_
[i].IsEmpty())), 0)) { do { static const node::AssertionInfo args
= { "../src/env-inl.h" ":" "198", "native_execution_async_resources_[i].IsEmpty()"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
199 }
200#endif
201 native_execution_async_resources_.resize(offset);
202 if (native_execution_async_resources_.size() <
203 native_execution_async_resources_.capacity() / 2 &&
204 native_execution_async_resources_.size() > 16) {
205 native_execution_async_resources_.shrink_to_fit();
206 }
207 }
208
209 if (UNLIKELY(js_execution_async_resources()->Length() > offset)__builtin_expect(!!(js_execution_async_resources()->Length
() > offset), 0)
) {
210 v8::HandleScope handle_scope(env()->isolate());
211 USE(js_execution_async_resources()->Set(
212 env()->context(),
213 env()->length_string(),
214 v8::Integer::NewFromUnsigned(env()->isolate(), offset)));
215 }
216
217 return fields_[kStackLength] > 0;
218}
219
220void AsyncHooks::clear_async_id_stack() {
221 v8::Isolate* isolate = env()->isolate();
222 v8::HandleScope handle_scope(isolate);
223 if (!js_execution_async_resources_.IsEmpty()) {
224 USE(PersistentToLocal::Strong(js_execution_async_resources_)->Set(
225 env()->context(),
226 env()->length_string(),
227 v8::Integer::NewFromUnsigned(isolate, 0)));
228 }
229 native_execution_async_resources_.clear();
230 native_execution_async_resources_.shrink_to_fit();
231
232 async_id_fields_[kExecutionAsyncId] = 0;
233 async_id_fields_[kTriggerAsyncId] = 0;
234 fields_[kStackLength] = 0;
235}
236
237inline void AsyncHooks::AddContext(v8::Local<v8::Context> ctx) {
238 ctx->SetPromiseHooks(
239 js_promise_hooks_[0].IsEmpty() ?
240 v8::Local<v8::Function>() :
241 PersistentToLocal::Strong(js_promise_hooks_[0]),
242 js_promise_hooks_[1].IsEmpty() ?
243 v8::Local<v8::Function>() :
244 PersistentToLocal::Strong(js_promise_hooks_[1]),
245 js_promise_hooks_[2].IsEmpty() ?
246 v8::Local<v8::Function>() :
247 PersistentToLocal::Strong(js_promise_hooks_[2]),
248 js_promise_hooks_[3].IsEmpty() ?
249 v8::Local<v8::Function>() :
250 PersistentToLocal::Strong(js_promise_hooks_[3]));
251
252 size_t id = contexts_.size();
253 contexts_.resize(id + 1);
254 contexts_[id].Reset(env()->isolate(), ctx);
255 contexts_[id].SetWeak();
256}
257
258inline void AsyncHooks::RemoveContext(v8::Local<v8::Context> ctx) {
259 v8::Isolate* isolate = env()->isolate();
260 v8::HandleScope handle_scope(isolate);
261 contexts_.erase(std::remove_if(contexts_.begin(),
262 contexts_.end(),
263 [&](auto&& el) { return el.IsEmpty(); }),
264 contexts_.end());
265 for (auto it = contexts_.begin(); it != contexts_.end(); it++) {
266 v8::Local<v8::Context> saved_context =
267 PersistentToLocal::Weak(isolate, *it);
268 if (saved_context == ctx) {
269 it->Reset();
270 contexts_.erase(it);
271 break;
272 }
273 }
274}
275
276// The DefaultTriggerAsyncIdScope(AsyncWrap*) constructor is defined in
277// async_wrap-inl.h to avoid a circular dependency.
278
279inline AsyncHooks::DefaultTriggerAsyncIdScope ::DefaultTriggerAsyncIdScope(
280 Environment* env, double default_trigger_async_id)
281 : async_hooks_(env->async_hooks()) {
282 if (env->async_hooks()->fields()[AsyncHooks::kCheck] > 0) {
283 CHECK_GE(default_trigger_async_id, 0)do { if (__builtin_expect(!!(!((default_trigger_async_id) >=
(0))), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "283", "(default_trigger_async_id) >= (0)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
284 }
285
286 old_default_trigger_async_id_ =
287 async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
288 async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] =
289 default_trigger_async_id;
290}
291
292inline AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() {
293 async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] =
294 old_default_trigger_async_id_;
295}
296
297Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) {
298 return ContainerOf(&Environment::async_hooks_, hooks);
299}
300
301inline size_t Environment::async_callback_scope_depth() const {
302 return async_callback_scope_depth_;
303}
304
305inline void Environment::PushAsyncCallbackScope() {
306 async_callback_scope_depth_++;
307}
308
309inline void Environment::PopAsyncCallbackScope() {
310 async_callback_scope_depth_--;
311}
312
313inline AliasedUint32Array& ImmediateInfo::fields() {
314 return fields_;
315}
316
317inline uint32_t ImmediateInfo::count() const {
318 return fields_[kCount];
319}
320
321inline uint32_t ImmediateInfo::ref_count() const {
322 return fields_[kRefCount];
323}
324
325inline bool ImmediateInfo::has_outstanding() const {
326 return fields_[kHasOutstanding] == 1;
327}
328
329inline void ImmediateInfo::ref_count_inc(uint32_t increment) {
330 fields_[kRefCount] += increment;
331}
332
333inline void ImmediateInfo::ref_count_dec(uint32_t decrement) {
334 fields_[kRefCount] -= decrement;
335}
336
337inline AliasedUint8Array& TickInfo::fields() {
338 return fields_;
339}
340
341inline bool TickInfo::has_tick_scheduled() const {
342 return fields_[kHasTickScheduled] == 1;
343}
344
345inline bool TickInfo::has_rejection_to_warn() const {
346 return fields_[kHasRejectionToWarn] == 1;
347}
348
349inline void Environment::AssignToContext(v8::Local<v8::Context> context,
350 const ContextInfo& info) {
351 context->SetAlignedPointerInEmbedderData(
352 ContextEmbedderIndex::kEnvironment, this);
353 // Used by Environment::GetCurrent to know that we are on a node context.
354 context->SetAlignedPointerInEmbedderData(
355 ContextEmbedderIndex::kContextTag, Environment::kNodeContextTagPtr);
356 // Used to retrieve bindings
357 context->SetAlignedPointerInEmbedderData(
358 ContextEmbedderIndex::kBindingListIndex, &(this->bindings_));
359
360#if HAVE_INSPECTOR1
361 inspector_agent()->ContextCreated(context, info);
362#endif // HAVE_INSPECTOR
363
364 this->async_hooks()->AddContext(context);
365}
366
367inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
368 if (UNLIKELY(!isolate->InContext())__builtin_expect(!!(!isolate->InContext()), 0)) return nullptr;
369 v8::HandleScope handle_scope(isolate);
370 return GetCurrent(isolate->GetCurrentContext());
371}
372
373inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
374 if (UNLIKELY(context.IsEmpty())__builtin_expect(!!(context.IsEmpty()), 0)) {
375 return nullptr;
376 }
377 if (UNLIKELY(context->GetNumberOfEmbedderDataFields() <=__builtin_expect(!!(context->GetNumberOfEmbedderDataFields
() <= ContextEmbedderIndex::kContextTag), 0)
378 ContextEmbedderIndex::kContextTag)__builtin_expect(!!(context->GetNumberOfEmbedderDataFields
() <= ContextEmbedderIndex::kContextTag), 0)
) {
379 return nullptr;
380 }
381 if (UNLIKELY(context->GetAlignedPointerFromEmbedderData(__builtin_expect(!!(context->GetAlignedPointerFromEmbedderData
( ContextEmbedderIndex::kContextTag) != Environment::kNodeContextTagPtr
), 0)
382 ContextEmbedderIndex::kContextTag) !=__builtin_expect(!!(context->GetAlignedPointerFromEmbedderData
( ContextEmbedderIndex::kContextTag) != Environment::kNodeContextTagPtr
), 0)
383 Environment::kNodeContextTagPtr)__builtin_expect(!!(context->GetAlignedPointerFromEmbedderData
( ContextEmbedderIndex::kContextTag) != Environment::kNodeContextTagPtr
), 0)
) {
384 return nullptr;
385 }
386 return static_cast<Environment*>(
387 context->GetAlignedPointerFromEmbedderData(
388 ContextEmbedderIndex::kEnvironment));
389}
390
391inline Environment* Environment::GetCurrent(
392 const v8::FunctionCallbackInfo<v8::Value>& info) {
393 return GetCurrent(info.GetIsolate()->GetCurrentContext());
394}
395
396template <typename T>
397inline Environment* Environment::GetCurrent(
398 const v8::PropertyCallbackInfo<T>& info) {
399 return GetCurrent(info.GetIsolate()->GetCurrentContext());
400}
401
402template <typename T, typename U>
403inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo<U>& info) {
404 return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
405}
406
407template <typename T>
408inline T* Environment::GetBindingData(
409 const v8::FunctionCallbackInfo<v8::Value>& info) {
410 return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
411}
412
413template <typename T>
414inline T* Environment::GetBindingData(v8::Local<v8::Context> context) {
415 BindingDataStore* map = static_cast<BindingDataStore*>(
416 context->GetAlignedPointerFromEmbedderData(
417 ContextEmbedderIndex::kBindingListIndex));
418 DCHECK_NOT_NULL(map);
419 auto it = map->find(T::type_name);
420 if (UNLIKELY(it == map->end())__builtin_expect(!!(it == map->end()), 0)) return nullptr;
421 T* result = static_cast<T*>(it->second.get());
422 DCHECK_NOT_NULL(result);
423 DCHECK_EQ(result->env(), GetCurrent(context));
424 return result;
425}
426
427template <typename T>
428inline T* Environment::AddBindingData(
429 v8::Local<v8::Context> context,
430 v8::Local<v8::Object> target) {
431 DCHECK_EQ(GetCurrent(context), this);
432 // This won't compile if T is not a BaseObject subclass.
433 BaseObjectPtr<T> item = MakeDetachedBaseObject<T>(this, target);
434 BindingDataStore* map = static_cast<BindingDataStore*>(
435 context->GetAlignedPointerFromEmbedderData(
436 ContextEmbedderIndex::kBindingListIndex));
437 DCHECK_NOT_NULL(map);
438 auto result = map->emplace(T::type_name, item);
439 CHECK(result.second)do { if (__builtin_expect(!!(!(result.second)), 0)) { do { static
const node::AssertionInfo args = { "../src/env-inl.h" ":" "439"
, "result.second", __PRETTY_FUNCTION__ }; node::Assert(args);
} while (0); } } while (0)
;
2
Assuming field 'second' is true
3
Taking false branch
4
Loop condition is false. Exiting loop
440 DCHECK_EQ(GetBindingData<T>(context), item.get());
441 return item.get();
5
Calling '~BaseObjectPtrImpl'
23
Returning from '~BaseObjectPtrImpl'
24
Use of memory after it is freed
442}
443
444inline v8::Isolate* Environment::isolate() const {
445 return isolate_;
446}
447
448inline Environment* Environment::from_timer_handle(uv_timer_t* handle) {
449 return ContainerOf(&Environment::timer_handle_, handle);
450}
451
452inline uv_timer_t* Environment::timer_handle() {
453 return &timer_handle_;
454}
455
456inline Environment* Environment::from_immediate_check_handle(
457 uv_check_t* handle) {
458 return ContainerOf(&Environment::immediate_check_handle_, handle);
459}
460
461inline uv_check_t* Environment::immediate_check_handle() {
462 return &immediate_check_handle_;
463}
464
465inline uv_idle_t* Environment::immediate_idle_handle() {
466 return &immediate_idle_handle_;
467}
468
469inline void Environment::RegisterHandleCleanup(uv_handle_t* handle,
470 HandleCleanupCb cb,
471 void* arg) {
472 handle_cleanup_queue_.push_back(HandleCleanup{handle, cb, arg});
473}
474
475template <typename T, typename OnCloseCallback>
476inline void Environment::CloseHandle(T* handle, OnCloseCallback callback) {
477 handle_cleanup_waiting_++;
478 static_assert(sizeof(T) >= sizeof(uv_handle_t), "T is a libuv handle");
479 static_assert(offsetof(T, data)__builtin_offsetof(T, data) == offsetof(uv_handle_t, data)__builtin_offsetof(uv_handle_t, data),
480 "T is a libuv handle");
481 static_assert(offsetof(T, close_cb)__builtin_offsetof(T, close_cb) == offsetof(uv_handle_t, close_cb)__builtin_offsetof(uv_handle_t, close_cb),
482 "T is a libuv handle");
483 struct CloseData {
484 Environment* env;
485 OnCloseCallback callback;
486 void* original_data;
487 };
488 handle->data = new CloseData { this, callback, handle->data };
489 uv_close(reinterpret_cast<uv_handle_t*>(handle), [](uv_handle_t* handle) {
490 std::unique_ptr<CloseData> data { static_cast<CloseData*>(handle->data) };
491 data->env->handle_cleanup_waiting_--;
492 handle->data = data->original_data;
493 data->callback(reinterpret_cast<T*>(handle));
494 });
495}
496
497void Environment::IncreaseWaitingRequestCounter() {
498 request_waiting_++;
499}
500
501void Environment::DecreaseWaitingRequestCounter() {
502 request_waiting_--;
503 CHECK_GE(request_waiting_, 0)do { if (__builtin_expect(!!(!((request_waiting_) >= (0)))
, 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "503", "(request_waiting_) >= (0)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
504}
505
506inline uv_loop_t* Environment::event_loop() const {
507 return isolate_data()->event_loop();
508}
509
510inline void Environment::TryLoadAddon(
511 const char* filename,
512 int flags,
513 const std::function<bool(binding::DLib*)>& was_loaded) {
514 loaded_addons_.emplace_back(filename, flags);
515 if (!was_loaded(&loaded_addons_.back())) {
516 loaded_addons_.pop_back();
517 }
518}
519
520#if HAVE_INSPECTOR1
521inline bool Environment::is_in_inspector_console_call() const {
522 return is_in_inspector_console_call_;
523}
524
525inline void Environment::set_is_in_inspector_console_call(bool value) {
526 is_in_inspector_console_call_ = value;
527}
528#endif
529
530inline AsyncHooks* Environment::async_hooks() {
531 return &async_hooks_;
532}
533
534inline ImmediateInfo* Environment::immediate_info() {
535 return &immediate_info_;
536}
537
538inline TickInfo* Environment::tick_info() {
539 return &tick_info_;
540}
541
542inline uint64_t Environment::timer_base() const {
543 return timer_base_;
544}
545
546inline std::shared_ptr<KVStore> Environment::env_vars() {
547 return env_vars_;
548}
549
550inline void Environment::set_env_vars(std::shared_ptr<KVStore> env_vars) {
551 env_vars_ = env_vars;
552}
553
554inline bool Environment::printed_error() const {
555 return printed_error_;
556}
557
558inline void Environment::set_printed_error(bool value) {
559 printed_error_ = value;
560}
561
562inline void Environment::set_trace_sync_io(bool value) {
563 trace_sync_io_ = value;
564}
565
566inline bool Environment::abort_on_uncaught_exception() const {
567 return options_->abort_on_uncaught_exception;
568}
569
570inline void Environment::set_force_context_aware(bool value) {
571 options_->force_context_aware = value;
572}
573
574inline bool Environment::force_context_aware() const {
575 return options_->force_context_aware;
576}
577
578inline void Environment::set_abort_on_uncaught_exception(bool value) {
579 options_->abort_on_uncaught_exception = value;
580}
581
582inline AliasedUint32Array& Environment::should_abort_on_uncaught_toggle() {
583 return should_abort_on_uncaught_toggle_;
584}
585
586inline AliasedInt32Array& Environment::stream_base_state() {
587 return stream_base_state_;
588}
589
590inline uint32_t Environment::get_next_module_id() {
591 return module_id_counter_++;
592}
593inline uint32_t Environment::get_next_script_id() {
594 return script_id_counter_++;
595}
596inline uint32_t Environment::get_next_function_id() {
597 return function_id_counter_++;
598}
599
600ShouldNotAbortOnUncaughtScope::ShouldNotAbortOnUncaughtScope(
601 Environment* env)
602 : env_(env) {
603 env_->PushShouldNotAbortOnUncaughtScope();
604}
605
606ShouldNotAbortOnUncaughtScope::~ShouldNotAbortOnUncaughtScope() {
607 Close();
608}
609
610void ShouldNotAbortOnUncaughtScope::Close() {
611 if (env_ != nullptr) {
612 env_->PopShouldNotAbortOnUncaughtScope();
613 env_ = nullptr;
614 }
615}
616
617inline void Environment::PushShouldNotAbortOnUncaughtScope() {
618 should_not_abort_scope_counter_++;
619}
620
621inline void Environment::PopShouldNotAbortOnUncaughtScope() {
622 should_not_abort_scope_counter_--;
623}
624
625inline bool Environment::inside_should_not_abort_on_uncaught_scope() const {
626 return should_not_abort_scope_counter_ > 0;
627}
628
629inline std::vector<double>* Environment::destroy_async_id_list() {
630 return &destroy_async_id_list_;
631}
632
633inline double Environment::new_async_id() {
634 async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1;
635 return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];
636}
637
638inline double Environment::execution_async_id() {
639 return async_hooks()->async_id_fields()[AsyncHooks::kExecutionAsyncId];
640}
641
642inline double Environment::trigger_async_id() {
643 return async_hooks()->async_id_fields()[AsyncHooks::kTriggerAsyncId];
644}
645
646inline double Environment::get_default_trigger_async_id() {
647 double default_trigger_async_id =
648 async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
649 // If defaultTriggerAsyncId isn't set, use the executionAsyncId
650 if (default_trigger_async_id < 0)
651 default_trigger_async_id = execution_async_id();
652 return default_trigger_async_id;
653}
654
655inline std::shared_ptr<EnvironmentOptions> Environment::options() {
656 return options_;
657}
658
659inline const std::vector<std::string>& Environment::argv() {
660 return argv_;
661}
662
663inline const std::vector<std::string>& Environment::exec_argv() {
664 return exec_argv_;
665}
666
667inline const std::string& Environment::exec_path() const {
668 return exec_path_;
669}
670
671inline std::string Environment::GetCwd() {
672 char cwd[PATH_MAX_BYTES(4096)];
673 size_t size = PATH_MAX_BYTES(4096);
674 const int err = uv_cwd(cwd, &size);
675
676 if (err == 0) {
677 CHECK_GT(size, 0)do { if (__builtin_expect(!!(!((size) > (0))), 0)) { do { static
const node::AssertionInfo args = { "../src/env-inl.h" ":" "677"
, "(size) > (0)", __PRETTY_FUNCTION__ }; node::Assert(args
); } while (0); } } while (0)
;
678 return cwd;
679 }
680
681 // This can fail if the cwd is deleted. In that case, fall back to
682 // exec_path.
683 const std::string& exec_path = exec_path_;
684 return exec_path.substr(0, exec_path.find_last_of(kPathSeparator));
685}
686
687#if HAVE_INSPECTOR1
688inline void Environment::set_coverage_directory(const char* dir) {
689 coverage_directory_ = std::string(dir);
690}
691
692inline void Environment::set_coverage_connection(
693 std::unique_ptr<profiler::V8CoverageConnection> connection) {
694 CHECK_NULL(coverage_connection_)do { if (__builtin_expect(!!(!((coverage_connection_) == nullptr
)), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "694", "(coverage_connection_) == nullptr", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
695 std::swap(coverage_connection_, connection);
696}
697
698inline profiler::V8CoverageConnection* Environment::coverage_connection() {
699 return coverage_connection_.get();
700}
701
702inline const std::string& Environment::coverage_directory() const {
703 return coverage_directory_;
704}
705
706inline void Environment::set_cpu_profiler_connection(
707 std::unique_ptr<profiler::V8CpuProfilerConnection> connection) {
708 CHECK_NULL(cpu_profiler_connection_)do { if (__builtin_expect(!!(!((cpu_profiler_connection_) == nullptr
)), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "708", "(cpu_profiler_connection_) == nullptr", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
709 std::swap(cpu_profiler_connection_, connection);
710}
711
712inline profiler::V8CpuProfilerConnection*
713Environment::cpu_profiler_connection() {
714 return cpu_profiler_connection_.get();
715}
716
717inline void Environment::set_cpu_prof_interval(uint64_t interval) {
718 cpu_prof_interval_ = interval;
719}
720
721inline uint64_t Environment::cpu_prof_interval() const {
722 return cpu_prof_interval_;
723}
724
725inline void Environment::set_cpu_prof_name(const std::string& name) {
726 cpu_prof_name_ = name;
727}
728
729inline const std::string& Environment::cpu_prof_name() const {
730 return cpu_prof_name_;
731}
732
733inline void Environment::set_cpu_prof_dir(const std::string& dir) {
734 cpu_prof_dir_ = dir;
735}
736
737inline const std::string& Environment::cpu_prof_dir() const {
738 return cpu_prof_dir_;
739}
740
741inline void Environment::set_heap_profiler_connection(
742 std::unique_ptr<profiler::V8HeapProfilerConnection> connection) {
743 CHECK_NULL(heap_profiler_connection_)do { if (__builtin_expect(!!(!((heap_profiler_connection_) ==
nullptr)), 0)) { do { static const node::AssertionInfo args =
{ "../src/env-inl.h" ":" "743", "(heap_profiler_connection_) == nullptr"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
744 std::swap(heap_profiler_connection_, connection);
745}
746
747inline profiler::V8HeapProfilerConnection*
748Environment::heap_profiler_connection() {
749 return heap_profiler_connection_.get();
750}
751
752inline void Environment::set_heap_prof_name(const std::string& name) {
753 heap_prof_name_ = name;
754}
755
756inline const std::string& Environment::heap_prof_name() const {
757 return heap_prof_name_;
758}
759
760inline void Environment::set_heap_prof_dir(const std::string& dir) {
761 heap_prof_dir_ = dir;
762}
763
764inline const std::string& Environment::heap_prof_dir() const {
765 return heap_prof_dir_;
766}
767
768inline void Environment::set_heap_prof_interval(uint64_t interval) {
769 heap_prof_interval_ = interval;
770}
771
772inline uint64_t Environment::heap_prof_interval() const {
773 return heap_prof_interval_;
774}
775
776#endif // HAVE_INSPECTOR
777
778inline
779std::shared_ptr<ExclusiveAccess<HostPort>> Environment::inspector_host_port() {
780 return inspector_host_port_;
781}
782
783inline std::shared_ptr<PerIsolateOptions> IsolateData::options() {
784 return options_;
785}
786
787inline void IsolateData::set_options(
788 std::shared_ptr<PerIsolateOptions> options) {
789 options_ = std::move(options);
790}
791
792template <typename Fn>
793void Environment::SetImmediate(Fn&& cb, CallbackFlags::Flags flags) {
794 auto callback = native_immediates_.CreateCallback(std::move(cb), flags);
795 native_immediates_.Push(std::move(callback));
796
797 if (flags & CallbackFlags::kRefed) {
798 if (immediate_info()->ref_count() == 0)
799 ToggleImmediateRef(true);
800 immediate_info()->ref_count_inc(1);
801 }
802}
803
804template <typename Fn>
805void Environment::SetImmediateThreadsafe(Fn&& cb, CallbackFlags::Flags flags) {
806 auto callback = native_immediates_threadsafe_.CreateCallback(
807 std::move(cb), flags);
808 {
809 Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
810 native_immediates_threadsafe_.Push(std::move(callback));
811 if (task_queues_async_initialized_)
812 uv_async_send(&task_queues_async_);
813 }
814}
815
816template <typename Fn>
817void Environment::RequestInterrupt(Fn&& cb) {
818 auto callback = native_immediates_interrupts_.CreateCallback(
819 std::move(cb), CallbackFlags::kRefed);
820 {
821 Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
822 native_immediates_interrupts_.Push(std::move(callback));
823 if (task_queues_async_initialized_)
824 uv_async_send(&task_queues_async_);
825 }
826 RequestInterruptFromV8();
827}
828
829inline bool Environment::can_call_into_js() const {
830 return can_call_into_js_ && !is_stopping();
831}
832
833inline void Environment::set_can_call_into_js(bool can_call_into_js) {
834 can_call_into_js_ = can_call_into_js;
835}
836
837inline bool Environment::has_run_bootstrapping_code() const {
838 return has_run_bootstrapping_code_;
839}
840
841inline void Environment::DoneBootstrapping() {
842 has_run_bootstrapping_code_ = true;
843 // This adjusts the return value of base_object_created_after_bootstrap() so
844 // that tests that check the count do not have to account for internally
845 // created BaseObjects.
846 base_object_created_by_bootstrap_ = base_object_count_;
847}
848
849inline bool Environment::has_serialized_options() const {
850 return has_serialized_options_;
851}
852
853inline void Environment::set_has_serialized_options(bool value) {
854 has_serialized_options_ = value;
855}
856
857inline bool Environment::is_main_thread() const {
858 return worker_context() == nullptr;
859}
860
861inline bool Environment::no_native_addons() const {
862 return (flags_ & EnvironmentFlags::kNoNativeAddons) ||
863 !options_->allow_native_addons;
864}
865
866inline bool Environment::should_not_register_esm_loader() const {
867 return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
868}
869
870inline bool Environment::owns_process_state() const {
871 return flags_ & EnvironmentFlags::kOwnsProcessState;
872}
873
874inline bool Environment::owns_inspector() const {
875 return flags_ & EnvironmentFlags::kOwnsInspector;
876}
877
878inline bool Environment::should_create_inspector() const {
879 return (flags_ & EnvironmentFlags::kNoCreateInspector) == 0;
880}
881
882inline bool Environment::tracks_unmanaged_fds() const {
883 return flags_ & EnvironmentFlags::kTrackUnmanagedFds;
884}
885
886inline bool Environment::hide_console_windows() const {
887 return flags_ & EnvironmentFlags::kHideConsoleWindows;
888}
889
890inline bool Environment::no_global_search_paths() const {
891 return (flags_ & EnvironmentFlags::kNoGlobalSearchPaths) ||
892 !options_->global_search_paths;
893}
894
895inline bool Environment::no_browser_globals() const {
896 // configure --no-browser-globals
897#ifdef NODE_NO_BROWSER_GLOBALS
898 return true;
899#else
900 return flags_ & EnvironmentFlags::kNoBrowserGlobals;
901#endif
902}
903
904bool Environment::filehandle_close_warning() const {
905 return emit_filehandle_warning_;
906}
907
908void Environment::set_filehandle_close_warning(bool on) {
909 emit_filehandle_warning_ = on;
910}
911
912void Environment::set_source_maps_enabled(bool on) {
913 source_maps_enabled_ = on;
914}
915
916bool Environment::source_maps_enabled() const {
917 return source_maps_enabled_;
918}
919
920inline uint64_t Environment::thread_id() const {
921 return thread_id_;
922}
923
924inline worker::Worker* Environment::worker_context() const {
925 return isolate_data()->worker_context();
926}
927
928inline void Environment::add_sub_worker_context(worker::Worker* context) {
929 sub_worker_contexts_.insert(context);
930}
931
932inline void Environment::remove_sub_worker_context(worker::Worker* context) {
933 sub_worker_contexts_.erase(context);
934}
935
936template <typename Fn>
937inline void Environment::ForEachWorker(Fn&& iterator) {
938 for (worker::Worker* w : sub_worker_contexts_) iterator(w);
939}
940
941inline void Environment::add_refs(int64_t diff) {
942 task_queues_async_refs_ += diff;
943 CHECK_GE(task_queues_async_refs_, 0)do { if (__builtin_expect(!!(!((task_queues_async_refs_) >=
(0))), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "943", "(task_queues_async_refs_) >= (0)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
944 if (task_queues_async_refs_ == 0)
945 uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
946 else
947 uv_ref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
948}
949
950inline bool Environment::is_stopping() const {
951 return is_stopping_.load();
952}
953
954inline void Environment::set_stopping(bool value) {
955 is_stopping_.store(value);
956}
957
958inline std::list<node_module>* Environment::extra_linked_bindings() {
959 return &extra_linked_bindings_;
960}
961
962inline node_module* Environment::extra_linked_bindings_head() {
963 return extra_linked_bindings_.size() > 0 ?
964 &extra_linked_bindings_.front() : nullptr;
965}
966
967inline node_module* Environment::extra_linked_bindings_tail() {
968 return extra_linked_bindings_.size() > 0 ?
969 &extra_linked_bindings_.back() : nullptr;
970}
971
972inline const Mutex& Environment::extra_linked_bindings_mutex() const {
973 return extra_linked_bindings_mutex_;
974}
975
976inline performance::PerformanceState* Environment::performance_state() {
977 return performance_state_.get();
978}
979
980inline IsolateData* Environment::isolate_data() const {
981 return isolate_data_;
982}
983
984inline uv_buf_t Environment::allocate_managed_buffer(
985 const size_t suggested_size) {
986 NoArrayBufferZeroFillScope no_zero_fill_scope(isolate_data());
987 std::unique_ptr<v8::BackingStore> bs =
988 v8::ArrayBuffer::NewBackingStore(isolate(), suggested_size);
989 uv_buf_t buf = uv_buf_init(static_cast<char*>(bs->Data()), bs->ByteLength());
990 released_allocated_buffers_.emplace(buf.base, std::move(bs));
991 return buf;
992}
993
994inline std::unique_ptr<v8::BackingStore> Environment::release_managed_buffer(
995 const uv_buf_t& buf) {
996 std::unique_ptr<v8::BackingStore> bs;
997 if (buf.base != nullptr) {
998 auto it = released_allocated_buffers_.find(buf.base);
999 CHECK_NE(it, released_allocated_buffers_.end())do { if (__builtin_expect(!!(!((it) != (released_allocated_buffers_
.end()))), 0)) { do { static const node::AssertionInfo args =
{ "../src/env-inl.h" ":" "999", "(it) != (released_allocated_buffers_.end())"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
1000 bs = std::move(it->second);
1001 released_allocated_buffers_.erase(it);
1002 }
1003 return bs;
1004}
1005
1006inline void Environment::ThrowError(const char* errmsg) {
1007 ThrowError(v8::Exception::Error, errmsg);
1008}
1009
1010inline void Environment::ThrowTypeError(const char* errmsg) {
1011 ThrowError(v8::Exception::TypeError, errmsg);
1012}
1013
1014inline void Environment::ThrowRangeError(const char* errmsg) {
1015 ThrowError(v8::Exception::RangeError, errmsg);
1016}
1017
1018inline void Environment::ThrowError(
1019 v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
1020 const char* errmsg) {
1021 v8::HandleScope handle_scope(isolate());
1022 isolate()->ThrowException(fun(OneByteString(isolate(), errmsg)));
1023}
1024
1025inline void Environment::ThrowErrnoException(int errorno,
1026 const char* syscall,
1027 const char* message,
1028 const char* path) {
1029 isolate()->ThrowException(
1030 ErrnoException(isolate(), errorno, syscall, message, path));
1031}
1032
1033inline void Environment::ThrowUVException(int errorno,
1034 const char* syscall,
1035 const char* message,
1036 const char* path,
1037 const char* dest) {
1038 isolate()->ThrowException(
1039 UVException(isolate(), errorno, syscall, message, path, dest));
1040}
1041
1042inline v8::Local<v8::FunctionTemplate> Environment::NewFunctionTemplate(
1043 v8::FunctionCallback callback,
1044 v8::Local<v8::Signature> signature,
1045 v8::ConstructorBehavior behavior,
1046 v8::SideEffectType side_effect_type,
1047 const v8::CFunction* c_function) {
1048 return v8::FunctionTemplate::New(isolate(),
1049 callback,
1050 v8::Local<v8::Value>(),
1051 signature,
1052 0,
1053 behavior,
1054 side_effect_type,
1055 c_function);
1056}
1057
1058inline void Environment::SetMethod(v8::Local<v8::Object> that,
1059 const char* name,
1060 v8::FunctionCallback callback) {
1061 v8::Local<v8::Context> context = isolate()->GetCurrentContext();
1062 v8::Local<v8::Function> function =
1063 NewFunctionTemplate(callback, v8::Local<v8::Signature>(),
1064 v8::ConstructorBehavior::kThrow,
1065 v8::SideEffectType::kHasSideEffect)
1066 ->GetFunction(context)
1067 .ToLocalChecked();
1068 // kInternalized strings are created in the old space.
1069 const v8::NewStringType type = v8::NewStringType::kInternalized;
1070 v8::Local<v8::String> name_string =
1071 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1072 that->Set(context, name_string, function).Check();
1073 function->SetName(name_string); // NODE_SET_METHOD() compatibility.
1074}
1075
1076inline void Environment::SetFastMethod(v8::Local<v8::Object> that,
1077 const char* name,
1078 v8::FunctionCallback slow_callback,
1079 const v8::CFunction* c_function) {
1080 v8::Local<v8::Context> context = isolate()->GetCurrentContext();
1081 v8::Local<v8::Function> function =
1082 NewFunctionTemplate(slow_callback,
1083 v8::Local<v8::Signature>(),
1084 v8::ConstructorBehavior::kThrow,
1085 v8::SideEffectType::kHasNoSideEffect,
1086 c_function)
1087 ->GetFunction(context)
1088 .ToLocalChecked();
1089 const v8::NewStringType type = v8::NewStringType::kInternalized;
1090 v8::Local<v8::String> name_string =
1091 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1092 that->Set(context, name_string, function).Check();
1093}
1094
1095inline void Environment::SetMethodNoSideEffect(v8::Local<v8::Object> that,
1096 const char* name,
1097 v8::FunctionCallback callback) {
1098 v8::Local<v8::Context> context = isolate()->GetCurrentContext();
1099 v8::Local<v8::Function> function =
1100 NewFunctionTemplate(callback, v8::Local<v8::Signature>(),
1101 v8::ConstructorBehavior::kThrow,
1102 v8::SideEffectType::kHasNoSideEffect)
1103 ->GetFunction(context)
1104 .ToLocalChecked();
1105 // kInternalized strings are created in the old space.
1106 const v8::NewStringType type = v8::NewStringType::kInternalized;
1107 v8::Local<v8::String> name_string =
1108 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1109 that->Set(context, name_string, function).Check();
1110 function->SetName(name_string); // NODE_SET_METHOD() compatibility.
1111}
1112
1113inline void Environment::SetProtoMethod(v8::Local<v8::FunctionTemplate> that,
1114 const char* name,
1115 v8::FunctionCallback callback) {
1116 v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1117 v8::Local<v8::FunctionTemplate> t =
1118 NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1119 v8::SideEffectType::kHasSideEffect);
1120 // kInternalized strings are created in the old space.
1121 const v8::NewStringType type = v8::NewStringType::kInternalized;
1122 v8::Local<v8::String> name_string =
1123 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1124 that->PrototypeTemplate()->Set(name_string, t);
1125 t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility.
1126}
1127
1128inline void Environment::SetProtoMethodNoSideEffect(
1129 v8::Local<v8::FunctionTemplate> that,
1130 const char* name,
1131 v8::FunctionCallback callback) {
1132 v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1133 v8::Local<v8::FunctionTemplate> t =
1134 NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1135 v8::SideEffectType::kHasNoSideEffect);
1136 // kInternalized strings are created in the old space.
1137 const v8::NewStringType type = v8::NewStringType::kInternalized;
1138 v8::Local<v8::String> name_string =
1139 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1140 that->PrototypeTemplate()->Set(name_string, t);
1141 t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility.
1142}
1143
1144inline void Environment::SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
1145 const char* name,
1146 v8::FunctionCallback callback) {
1147 v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1148 v8::Local<v8::FunctionTemplate> t =
1149 NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1150 v8::SideEffectType::kHasSideEffect);
1151 // kInternalized strings are created in the old space.
1152 const v8::NewStringType type = v8::NewStringType::kInternalized;
1153 v8::Local<v8::String> name_string =
1154 v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1155 that->InstanceTemplate()->Set(name_string, t);
1156 t->SetClassName(name_string);
1157}
1158
1159inline void Environment::SetConstructorFunction(
1160 v8::Local<v8::Object> that,
1161 const char* name,
1162 v8::Local<v8::FunctionTemplate> tmpl,
1163 SetConstructorFunctionFlag flag) {
1164 SetConstructorFunction(that, OneByteString(isolate(), name), tmpl, flag);
1165}
1166
1167inline void Environment::SetConstructorFunction(
1168 v8::Local<v8::Object> that,
1169 v8::Local<v8::String> name,
1170 v8::Local<v8::FunctionTemplate> tmpl,
1171 SetConstructorFunctionFlag flag) {
1172 if (LIKELY(flag == SetConstructorFunctionFlag::SET_CLASS_NAME)__builtin_expect(!!(flag == SetConstructorFunctionFlag::SET_CLASS_NAME
), 1)
)
1173 tmpl->SetClassName(name);
1174 that->Set(
1175 context(),
1176 name,
1177 tmpl->GetFunction(context()).ToLocalChecked()).Check();
1178}
1179
1180void Environment::AddCleanupHook(CleanupCallback fn, void* arg) {
1181 auto insertion_info = cleanup_hooks_.emplace(CleanupHookCallback {
1182 fn, arg, cleanup_hook_counter_++
1183 });
1184 // Make sure there was no existing element with these values.
1185 CHECK_EQ(insertion_info.second, true)do { if (__builtin_expect(!!(!((insertion_info.second) == (true
))), 0)) { do { static const node::AssertionInfo args = { "../src/env-inl.h"
":" "1185", "(insertion_info.second) == (true)", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
1186}
1187
1188void Environment::RemoveCleanupHook(CleanupCallback fn, void* arg) {
1189 CleanupHookCallback search { fn, arg, 0 };
1190 cleanup_hooks_.erase(search);
1191}
1192
1193size_t CleanupHookCallback::Hash::operator()(
1194 const CleanupHookCallback& cb) const {
1195 return std::hash<void*>()(cb.arg_);
1196}
1197
1198bool CleanupHookCallback::Equal::operator()(
1199 const CleanupHookCallback& a, const CleanupHookCallback& b) const {
1200 return a.fn_ == b.fn_ && a.arg_ == b.arg_;
1201}
1202
1203BaseObject* CleanupHookCallback::GetBaseObject() const {
1204 if (fn_ == BaseObject::DeleteMe)
1205 return static_cast<BaseObject*>(arg_);
1206 else
1207 return nullptr;
1208}
1209
1210template <typename T>
1211void Environment::ForEachBaseObject(T&& iterator) {
1212 for (const auto& hook : cleanup_hooks_) {
1213 BaseObject* obj = hook.GetBaseObject();
1214 if (obj != nullptr)
1215 iterator(obj);
1216 }
1217}
1218
1219template <typename T>
1220void Environment::ForEachBindingData(T&& iterator) {
1221 BindingDataStore* map = static_cast<BindingDataStore*>(
1222 context()->GetAlignedPointerFromEmbedderData(
1223 ContextEmbedderIndex::kBindingListIndex));
1224 DCHECK_NOT_NULL(map);
1225 for (auto& it : *map) {
1226 iterator(it.first, it.second);
1227 }
1228}
1229
1230void Environment::modify_base_object_count(int64_t delta) {
1231 base_object_count_ += delta;
1232}
1233
1234int64_t Environment::base_object_created_after_bootstrap() const {
1235 return base_object_count_ - base_object_created_by_bootstrap_;
1236}
1237
1238int64_t Environment::base_object_count() const {
1239 return base_object_count_;
1240}
1241
1242void Environment::set_main_utf16(std::unique_ptr<v8::String::Value> str) {
1243 CHECK(!main_utf16_)do { if (__builtin_expect(!!(!(!main_utf16_)), 0)) { do { static
const node::AssertionInfo args = { "../src/env-inl.h" ":" "1243"
, "!main_utf16_", __PRETTY_FUNCTION__ }; node::Assert(args); }
while (0); } } while (0)
;
1244 main_utf16_ = std::move(str);
1245}
1246
1247void Environment::set_process_exit_handler(
1248 std::function<void(Environment*, int)>&& handler) {
1249 process_exit_handler_ = std::move(handler);
1250}
1251
1252#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
1253#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
1254#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
1255#define V(TypeName, PropertyName) \
1256 inline \
1257 v8::Local<TypeName> IsolateData::PropertyName() const { \
1258 return PropertyName ## _ .Get(isolate_); \
1259 }
1260 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)VP(alpn_buffer_private_symbol, "node:alpnBuffer") VP(arrow_message_private_symbol
, "node:arrowMessage") VP(contextify_context_private_symbol, "node:contextify:context"
) VP(contextify_global_private_symbol, "node:contextify:global"
) VP(decorated_private_symbol, "node:decorated") VP(napi_type_tag
, "node:napi:type_tag") VP(napi_wrapper, "node:napi:wrapper")
VP(untransferable_object_private_symbol, "node:untransferableObject"
)
1261 PER_ISOLATE_SYMBOL_PROPERTIES(VY)VY(async_id_symbol, "async_id_symbol") VY(handle_onclose_symbol
, "handle_onclose") VY(no_message_symbol, "no_message_symbol"
) VY(messaging_deserialize_symbol, "messaging_deserialize_symbol"
) VY(messaging_transfer_symbol, "messaging_transfer_symbol") VY
(messaging_clone_symbol, "messaging_clone_symbol") VY(messaging_transfer_list_symbol
, "messaging_transfer_list_symbol") VY(oninit_symbol, "oninit"
) VY(owner_symbol, "owner_symbol") VY(onpskexchange_symbol, "onpskexchange"
) VY(resource_symbol, "resource_symbol") VY(trigger_async_id_symbol
, "trigger_async_id_symbol")
1262 PER_ISOLATE_STRING_PROPERTIES(VS)VS(ack_string, "ack") VS(address_string, "address") VS(aliases_string
, "aliases") VS(args_string, "args") VS(asn1curve_string, "asn1Curve"
) VS(async_ids_stack_string, "async_ids_stack") VS(bits_string
, "bits") VS(block_list_string, "blockList") VS(buffer_string
, "buffer") VS(bytes_parsed_string, "bytesParsed") VS(bytes_read_string
, "bytesRead") VS(bytes_written_string, "bytesWritten") VS(cached_data_produced_string
, "cachedDataProduced") VS(cached_data_rejected_string, "cachedDataRejected"
) VS(cached_data_string, "cachedData") VS(cache_key_string, "cacheKey"
) VS(change_string, "change") VS(channel_string, "channel") VS
(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite"
) VS(clone_unsupported_type_str, "Cannot transfer object of unsupported type."
) VS(code_string, "code") VS(commonjs_string, "commonjs") VS(
config_string, "config") VS(constants_string, "constants") VS
(crypto_dh_string, "dh") VS(crypto_dsa_string, "dsa") VS(crypto_ec_string
, "ec") VS(crypto_ed25519_string, "ed25519") VS(crypto_ed448_string
, "ed448") VS(crypto_x25519_string, "x25519") VS(crypto_x448_string
, "x448") VS(crypto_rsa_string, "rsa") VS(crypto_rsa_pss_string
, "rsa-pss") VS(cwd_string, "cwd") VS(data_string, "data") VS
(default_is_true_string, "defaultIsTrue") VS(deserialize_info_string
, "deserializeInfo") VS(dest_string, "dest") VS(destroyed_string
, "destroyed") VS(detached_string, "detached") VS(dh_string, "DH"
) VS(divisor_length_string, "divisorLength") VS(dns_a_string,
"A") VS(dns_aaaa_string, "AAAA") VS(dns_caa_string, "CAA") VS
(dns_critical_string, "critical") VS(dns_cname_string, "CNAME"
) VS(dns_mx_string, "MX") VS(dns_naptr_string, "NAPTR") VS(dns_ns_string
, "NS") VS(dns_ptr_string, "PTR") VS(dns_soa_string, "SOA") VS
(dns_srv_string, "SRV") VS(dns_txt_string, "TXT") VS(done_string
, "done") VS(duration_string, "duration") VS(ecdh_string, "ECDH"
) VS(emit_string, "emit") VS(emit_warning_string, "emitWarning"
) VS(empty_object_string, "{}") VS(encoding_string, "encoding"
) VS(entries_string, "entries") VS(entry_type_string, "entryType"
) VS(env_pairs_string, "envPairs") VS(env_var_settings_string
, "envVarSettings") VS(errno_string, "errno") VS(error_string
, "error") VS(exchange_string, "exchange") VS(exit_code_string
, "exitCode") VS(expire_string, "expire") VS(exponent_string,
"exponent") VS(exports_string, "exports") VS(ext_key_usage_string
, "ext_key_usage") VS(external_stream_string, "_externalStream"
) VS(family_string, "family") VS(fatal_exception_string, "_fatalException"
) VS(fd_string, "fd") VS(fields_string, "fields") VS(file_string
, "file") VS(filename_string, "filename") VS(fingerprint256_string
, "fingerprint256") VS(fingerprint512_string, "fingerprint512"
) VS(fingerprint_string, "fingerprint") VS(flags_string, "flags"
) VS(flowlabel_string, "flowlabel") VS(fragment_string, "fragment"
) VS(frames_received_string, "framesReceived") VS(frames_sent_string
, "framesSent") VS(function_string, "function") VS(get_data_clone_error_string
, "_getDataCloneError") VS(get_shared_array_buffer_id_string,
"_getSharedArrayBufferId") VS(gid_string, "gid") VS(h2_string
, "h2") VS(handle_string, "handle") VS(hash_algorithm_string,
"hashAlgorithm") VS(help_text_string, "helpText") VS(homedir_string
, "homedir") VS(host_string, "host") VS(hostmaster_string, "hostmaster"
) VS(http_1_1_string, "http/1.1") VS(id_string, "id") VS(identity_string
, "identity") VS(ignore_string, "ignore") VS(infoaccess_string
, "infoAccess") VS(inherit_string, "inherit") VS(input_string
, "input") VS(internal_binding_string, "internalBinding") VS(
internal_string, "internal") VS(ipv4_string, "IPv4") VS(ipv6_string
, "IPv6") VS(isclosing_string, "isClosing") VS(issuer_string,
"issuer") VS(issuercert_string, "issuerCertificate") VS(jwk_crv_string
, "crv") VS(jwk_d_string, "d") VS(jwk_dp_string, "dp") VS(jwk_dq_string
, "dq") VS(jwk_dsa_string, "DSA") VS(jwk_e_string, "e") VS(jwk_ec_string
, "EC") VS(jwk_g_string, "g") VS(jwk_k_string, "k") VS(jwk_p_string
, "p") VS(jwk_q_string, "q") VS(jwk_qi_string, "qi") VS(jwk_kty_string
, "kty") VS(jwk_n_string, "n") VS(jwk_oct_string, "oct") VS(jwk_okp_string
, "OKP") VS(jwk_rsa_string, "RSA") VS(jwk_x_string, "x") VS(jwk_y_string
, "y") VS(kill_signal_string, "killSignal") VS(kind_string, "kind"
) VS(length_string, "length") VS(library_string, "library") VS
(mac_string, "mac") VS(max_buffer_string, "maxBuffer") VS(max_concurrent_streams_string
, "maxConcurrentStreams") VS(message_port_constructor_string,
"MessagePort") VS(message_port_string, "messagePort") VS(message_string
, "message") VS(messageerror_string, "messageerror") VS(mgf1_hash_algorithm_string
, "mgf1HashAlgorithm") VS(minttl_string, "minttl") VS(module_string
, "module") VS(modulus_string, "modulus") VS(modulus_length_string
, "modulusLength") VS(name_string, "name") VS(named_curve_string
, "namedCurve") VS(netmask_string, "netmask") VS(next_string,
"next") VS(nistcurve_string, "nistCurve") VS(node_string, "node"
) VS(nsname_string, "nsname") VS(ocsp_request_string, "OCSPRequest"
) VS(oncertcb_string, "oncertcb") VS(onchange_string, "onchange"
) VS(onclienthello_string, "onclienthello") VS(oncomplete_string
, "oncomplete") VS(onconnection_string, "onconnection") VS(ondone_string
, "ondone") VS(onerror_string, "onerror") VS(onexit_string, "onexit"
) VS(onhandshakedone_string, "onhandshakedone") VS(onhandshakestart_string
, "onhandshakestart") VS(onkeylog_string, "onkeylog") VS(onmessage_string
, "onmessage") VS(onnewsession_string, "onnewsession") VS(onocspresponse_string
, "onocspresponse") VS(onreadstart_string, "onreadstart") VS(
onreadstop_string, "onreadstop") VS(onshutdown_string, "onshutdown"
) VS(onsignal_string, "onsignal") VS(onunpipe_string, "onunpipe"
) VS(onwrite_string, "onwrite") VS(openssl_error_stack, "opensslErrorStack"
) VS(options_string, "options") VS(order_string, "order") VS(
output_string, "output") VS(overlapped_string, "overlapped") VS
(parse_error_string, "Parse Error") VS(password_string, "password"
) VS(path_string, "path") VS(pending_handle_string, "pendingHandle"
) VS(pid_string, "pid") VS(ping_rtt_string, "pingRTT") VS(pipe_source_string
, "pipeSource") VS(pipe_string, "pipe") VS(pipe_target_string
, "pipeTarget") VS(port1_string, "port1") VS(port2_string, "port2"
) VS(port_string, "port") VS(preference_string, "preference")
VS(primordials_string, "primordials") VS(priority_string, "priority"
) VS(process_string, "process") VS(promise_string, "promise")
VS(psk_string, "psk") VS(pubkey_string, "pubkey") VS(public_exponent_string
, "publicExponent") VS(query_string, "query") VS(rate_string,
"rate") VS(raw_string, "raw") VS(read_host_object_string, "_readHostObject"
) VS(readable_string, "readable") VS(reason_string, "reason")
VS(refresh_string, "refresh") VS(regexp_string, "regexp") VS
(rename_string, "rename") VS(replacement_string, "replacement"
) VS(require_string, "require") VS(retry_string, "retry") VS(
salt_length_string, "saltLength") VS(scheme_string, "scheme")
VS(scopeid_string, "scopeid") VS(serial_number_string, "serialNumber"
) VS(serial_string, "serial") VS(servername_string, "servername"
) VS(service_string, "service") VS(session_id_string, "sessionId"
) VS(shell_string, "shell") VS(signal_string, "signal") VS(sink_string
, "sink") VS(size_string, "size") VS(sni_context_err_string, "Invalid SNI context"
) VS(sni_context_string, "sni_context") VS(source_string, "source"
) VS(stack_string, "stack") VS(standard_name_string, "standardName"
) VS(start_time_string, "startTime") VS(state_string, "state"
) VS(stats_string, "stats") VS(status_string, "status") VS(stdio_string
, "stdio") VS(stream_average_duration_string, "streamAverageDuration"
) VS(stream_count_string, "streamCount") VS(subject_string, "subject"
) VS(subjectaltname_string, "subjectaltname") VS(syscall_string
, "syscall") VS(target_string, "target") VS(thread_id_string,
"threadId") VS(ticketkeycallback_string, "onticketkeycallback"
) VS(timeout_string, "timeout") VS(time_to_first_byte_string,
"timeToFirstByte") VS(time_to_first_byte_sent_string, "timeToFirstByteSent"
) VS(time_to_first_header_string, "timeToFirstHeader") VS(tls_ticket_string
, "tlsTicket") VS(transfer_string, "transfer") VS(ttl_string,
"ttl") VS(type_string, "type") VS(uid_string, "uid") VS(unknown_string
, "<unknown>") VS(url_special_ftp_string, "ftp:") VS(url_special_file_string
, "file:") VS(url_special_http_string, "http:") VS(url_special_https_string
, "https:") VS(url_special_ws_string, "ws:") VS(url_special_wss_string
, "wss:") VS(url_string, "url") VS(username_string, "username"
) VS(valid_from_string, "valid_from") VS(valid_to_string, "valid_to"
) VS(value_string, "value") VS(verify_error_string, "verifyError"
) VS(version_string, "version") VS(weight_string, "weight") VS
(windows_hide_string, "windowsHide") VS(windows_verbatim_arguments_string
, "windowsVerbatimArguments") VS(wrap_string, "wrap") VS(writable_string
, "writable") VS(write_host_object_string, "_writeHostObject"
) VS(write_queue_size_string, "writeQueueSize") VS(x_forwarded_string
, "x-forwarded-for") VS(zero_return_string, "ZERO_RETURN")
1263#undef V
1264#undef VS
1265#undef VY
1266#undef VP
1267
1268#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
1269#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
1270#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
1271#define V(TypeName, PropertyName) \
1272 inline v8::Local<TypeName> Environment::PropertyName() const { \
1273 return isolate_data()->PropertyName(); \
1274 }
1275 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)VP(alpn_buffer_private_symbol, "node:alpnBuffer") VP(arrow_message_private_symbol
, "node:arrowMessage") VP(contextify_context_private_symbol, "node:contextify:context"
) VP(contextify_global_private_symbol, "node:contextify:global"
) VP(decorated_private_symbol, "node:decorated") VP(napi_type_tag
, "node:napi:type_tag") VP(napi_wrapper, "node:napi:wrapper")
VP(untransferable_object_private_symbol, "node:untransferableObject"
)
1276 PER_ISOLATE_SYMBOL_PROPERTIES(VY)VY(async_id_symbol, "async_id_symbol") VY(handle_onclose_symbol
, "handle_onclose") VY(no_message_symbol, "no_message_symbol"
) VY(messaging_deserialize_symbol, "messaging_deserialize_symbol"
) VY(messaging_transfer_symbol, "messaging_transfer_symbol") VY
(messaging_clone_symbol, "messaging_clone_symbol") VY(messaging_transfer_list_symbol
, "messaging_transfer_list_symbol") VY(oninit_symbol, "oninit"
) VY(owner_symbol, "owner_symbol") VY(onpskexchange_symbol, "onpskexchange"
) VY(resource_symbol, "resource_symbol") VY(trigger_async_id_symbol
, "trigger_async_id_symbol")
1277 PER_ISOLATE_STRING_PROPERTIES(VS)VS(ack_string, "ack") VS(address_string, "address") VS(aliases_string
, "aliases") VS(args_string, "args") VS(asn1curve_string, "asn1Curve"
) VS(async_ids_stack_string, "async_ids_stack") VS(bits_string
, "bits") VS(block_list_string, "blockList") VS(buffer_string
, "buffer") VS(bytes_parsed_string, "bytesParsed") VS(bytes_read_string
, "bytesRead") VS(bytes_written_string, "bytesWritten") VS(cached_data_produced_string
, "cachedDataProduced") VS(cached_data_rejected_string, "cachedDataRejected"
) VS(cached_data_string, "cachedData") VS(cache_key_string, "cacheKey"
) VS(change_string, "change") VS(channel_string, "channel") VS
(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite"
) VS(clone_unsupported_type_str, "Cannot transfer object of unsupported type."
) VS(code_string, "code") VS(commonjs_string, "commonjs") VS(
config_string, "config") VS(constants_string, "constants") VS
(crypto_dh_string, "dh") VS(crypto_dsa_string, "dsa") VS(crypto_ec_string
, "ec") VS(crypto_ed25519_string, "ed25519") VS(crypto_ed448_string
, "ed448") VS(crypto_x25519_string, "x25519") VS(crypto_x448_string
, "x448") VS(crypto_rsa_string, "rsa") VS(crypto_rsa_pss_string
, "rsa-pss") VS(cwd_string, "cwd") VS(data_string, "data") VS
(default_is_true_string, "defaultIsTrue") VS(deserialize_info_string
, "deserializeInfo") VS(dest_string, "dest") VS(destroyed_string
, "destroyed") VS(detached_string, "detached") VS(dh_string, "DH"
) VS(divisor_length_string, "divisorLength") VS(dns_a_string,
"A") VS(dns_aaaa_string, "AAAA") VS(dns_caa_string, "CAA") VS
(dns_critical_string, "critical") VS(dns_cname_string, "CNAME"
) VS(dns_mx_string, "MX") VS(dns_naptr_string, "NAPTR") VS(dns_ns_string
, "NS") VS(dns_ptr_string, "PTR") VS(dns_soa_string, "SOA") VS
(dns_srv_string, "SRV") VS(dns_txt_string, "TXT") VS(done_string
, "done") VS(duration_string, "duration") VS(ecdh_string, "ECDH"
) VS(emit_string, "emit") VS(emit_warning_string, "emitWarning"
) VS(empty_object_string, "{}") VS(encoding_string, "encoding"
) VS(entries_string, "entries") VS(entry_type_string, "entryType"
) VS(env_pairs_string, "envPairs") VS(env_var_settings_string
, "envVarSettings") VS(errno_string, "errno") VS(error_string
, "error") VS(exchange_string, "exchange") VS(exit_code_string
, "exitCode") VS(expire_string, "expire") VS(exponent_string,
"exponent") VS(exports_string, "exports") VS(ext_key_usage_string
, "ext_key_usage") VS(external_stream_string, "_externalStream"
) VS(family_string, "family") VS(fatal_exception_string, "_fatalException"
) VS(fd_string, "fd") VS(fields_string, "fields") VS(file_string
, "file") VS(filename_string, "filename") VS(fingerprint256_string
, "fingerprint256") VS(fingerprint512_string, "fingerprint512"
) VS(fingerprint_string, "fingerprint") VS(flags_string, "flags"
) VS(flowlabel_string, "flowlabel") VS(fragment_string, "fragment"
) VS(frames_received_string, "framesReceived") VS(frames_sent_string
, "framesSent") VS(function_string, "function") VS(get_data_clone_error_string
, "_getDataCloneError") VS(get_shared_array_buffer_id_string,
"_getSharedArrayBufferId") VS(gid_string, "gid") VS(h2_string
, "h2") VS(handle_string, "handle") VS(hash_algorithm_string,
"hashAlgorithm") VS(help_text_string, "helpText") VS(homedir_string
, "homedir") VS(host_string, "host") VS(hostmaster_string, "hostmaster"
) VS(http_1_1_string, "http/1.1") VS(id_string, "id") VS(identity_string
, "identity") VS(ignore_string, "ignore") VS(infoaccess_string
, "infoAccess") VS(inherit_string, "inherit") VS(input_string
, "input") VS(internal_binding_string, "internalBinding") VS(
internal_string, "internal") VS(ipv4_string, "IPv4") VS(ipv6_string
, "IPv6") VS(isclosing_string, "isClosing") VS(issuer_string,
"issuer") VS(issuercert_string, "issuerCertificate") VS(jwk_crv_string
, "crv") VS(jwk_d_string, "d") VS(jwk_dp_string, "dp") VS(jwk_dq_string
, "dq") VS(jwk_dsa_string, "DSA") VS(jwk_e_string, "e") VS(jwk_ec_string
, "EC") VS(jwk_g_string, "g") VS(jwk_k_string, "k") VS(jwk_p_string
, "p") VS(jwk_q_string, "q") VS(jwk_qi_string, "qi") VS(jwk_kty_string
, "kty") VS(jwk_n_string, "n") VS(jwk_oct_string, "oct") VS(jwk_okp_string
, "OKP") VS(jwk_rsa_string, "RSA") VS(jwk_x_string, "x") VS(jwk_y_string
, "y") VS(kill_signal_string, "killSignal") VS(kind_string, "kind"
) VS(length_string, "length") VS(library_string, "library") VS
(mac_string, "mac") VS(max_buffer_string, "maxBuffer") VS(max_concurrent_streams_string
, "maxConcurrentStreams") VS(message_port_constructor_string,
"MessagePort") VS(message_port_string, "messagePort") VS(message_string
, "message") VS(messageerror_string, "messageerror") VS(mgf1_hash_algorithm_string
, "mgf1HashAlgorithm") VS(minttl_string, "minttl") VS(module_string
, "module") VS(modulus_string, "modulus") VS(modulus_length_string
, "modulusLength") VS(name_string, "name") VS(named_curve_string
, "namedCurve") VS(netmask_string, "netmask") VS(next_string,
"next") VS(nistcurve_string, "nistCurve") VS(node_string, "node"
) VS(nsname_string, "nsname") VS(ocsp_request_string, "OCSPRequest"
) VS(oncertcb_string, "oncertcb") VS(onchange_string, "onchange"
) VS(onclienthello_string, "onclienthello") VS(oncomplete_string
, "oncomplete") VS(onconnection_string, "onconnection") VS(ondone_string
, "ondone") VS(onerror_string, "onerror") VS(onexit_string, "onexit"
) VS(onhandshakedone_string, "onhandshakedone") VS(onhandshakestart_string
, "onhandshakestart") VS(onkeylog_string, "onkeylog") VS(onmessage_string
, "onmessage") VS(onnewsession_string, "onnewsession") VS(onocspresponse_string
, "onocspresponse") VS(onreadstart_string, "onreadstart") VS(
onreadstop_string, "onreadstop") VS(onshutdown_string, "onshutdown"
) VS(onsignal_string, "onsignal") VS(onunpipe_string, "onunpipe"
) VS(onwrite_string, "onwrite") VS(openssl_error_stack, "opensslErrorStack"
) VS(options_string, "options") VS(order_string, "order") VS(
output_string, "output") VS(overlapped_string, "overlapped") VS
(parse_error_string, "Parse Error") VS(password_string, "password"
) VS(path_string, "path") VS(pending_handle_string, "pendingHandle"
) VS(pid_string, "pid") VS(ping_rtt_string, "pingRTT") VS(pipe_source_string
, "pipeSource") VS(pipe_string, "pipe") VS(pipe_target_string
, "pipeTarget") VS(port1_string, "port1") VS(port2_string, "port2"
) VS(port_string, "port") VS(preference_string, "preference")
VS(primordials_string, "primordials") VS(priority_string, "priority"
) VS(process_string, "process") VS(promise_string, "promise")
VS(psk_string, "psk") VS(pubkey_string, "pubkey") VS(public_exponent_string
, "publicExponent") VS(query_string, "query") VS(rate_string,
"rate") VS(raw_string, "raw") VS(read_host_object_string, "_readHostObject"
) VS(readable_string, "readable") VS(reason_string, "reason")
VS(refresh_string, "refresh") VS(regexp_string, "regexp") VS
(rename_string, "rename") VS(replacement_string, "replacement"
) VS(require_string, "require") VS(retry_string, "retry") VS(
salt_length_string, "saltLength") VS(scheme_string, "scheme")
VS(scopeid_string, "scopeid") VS(serial_number_string, "serialNumber"
) VS(serial_string, "serial") VS(servername_string, "servername"
) VS(service_string, "service") VS(session_id_string, "sessionId"
) VS(shell_string, "shell") VS(signal_string, "signal") VS(sink_string
, "sink") VS(size_string, "size") VS(sni_context_err_string, "Invalid SNI context"
) VS(sni_context_string, "sni_context") VS(source_string, "source"
) VS(stack_string, "stack") VS(standard_name_string, "standardName"
) VS(start_time_string, "startTime") VS(state_string, "state"
) VS(stats_string, "stats") VS(status_string, "status") VS(stdio_string
, "stdio") VS(stream_average_duration_string, "streamAverageDuration"
) VS(stream_count_string, "streamCount") VS(subject_string, "subject"
) VS(subjectaltname_string, "subjectaltname") VS(syscall_string
, "syscall") VS(target_string, "target") VS(thread_id_string,
"threadId") VS(ticketkeycallback_string, "onticketkeycallback"
) VS(timeout_string, "timeout") VS(time_to_first_byte_string,
"timeToFirstByte") VS(time_to_first_byte_sent_string, "timeToFirstByteSent"
) VS(time_to_first_header_string, "timeToFirstHeader") VS(tls_ticket_string
, "tlsTicket") VS(transfer_string, "transfer") VS(ttl_string,
"ttl") VS(type_string, "type") VS(uid_string, "uid") VS(unknown_string
, "<unknown>") VS(url_special_ftp_string, "ftp:") VS(url_special_file_string
, "file:") VS(url_special_http_string, "http:") VS(url_special_https_string
, "https:") VS(url_special_ws_string, "ws:") VS(url_special_wss_string
, "wss:") VS(url_string, "url") VS(username_string, "username"
) VS(valid_from_string, "valid_from") VS(valid_to_string, "valid_to"
) VS(value_string, "value") VS(verify_error_string, "verifyError"
) VS(version_string, "version") VS(weight_string, "weight") VS
(windows_hide_string, "windowsHide") VS(windows_verbatim_arguments_string
, "windowsVerbatimArguments") VS(wrap_string, "wrap") VS(writable_string
, "writable") VS(write_host_object_string, "_writeHostObject"
) VS(write_queue_size_string, "writeQueueSize") VS(x_forwarded_string
, "x-forwarded-for") VS(zero_return_string, "ZERO_RETURN")
1278#undef V
1279#undef VS
1280#undef VY
1281#undef VP
1282
1283#define V(PropertyName, TypeName) \
1284 inline v8::Local<TypeName> Environment::PropertyName() const { \
1285 return PersistentToLocal::Strong(PropertyName ## _); \
1286 } \
1287 inline void Environment::set_ ## PropertyName(v8::Local<TypeName> value) { \
1288 PropertyName ## _.Reset(isolate(), value); \
1289 }
1290 ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)V(async_wrap_ctor_template, v8::FunctionTemplate) V(async_wrap_object_ctor_template
, v8::FunctionTemplate) V(base_object_ctor_template, v8::FunctionTemplate
) V(binding_data_ctor_template, v8::FunctionTemplate) V(blob_constructor_template
, v8::FunctionTemplate) V(blocklist_constructor_template, v8::
FunctionTemplate) V(compiled_fn_entry_template, v8::ObjectTemplate
) V(dir_instance_template, v8::ObjectTemplate) V(fd_constructor_template
, v8::ObjectTemplate) V(fdclose_constructor_template, v8::ObjectTemplate
) V(filehandlereadwrap_template, v8::ObjectTemplate) V(fsreqpromise_constructor_template
, v8::ObjectTemplate) V(handle_wrap_ctor_template, v8::FunctionTemplate
) V(histogram_ctor_template, v8::FunctionTemplate) V(http2settings_constructor_template
, v8::ObjectTemplate) V(http2stream_constructor_template, v8::
ObjectTemplate) V(http2ping_constructor_template, v8::ObjectTemplate
) V(i18n_converter_template, v8::ObjectTemplate) V(intervalhistogram_constructor_template
, v8::FunctionTemplate) V(libuv_stream_wrap_ctor_template, v8
::FunctionTemplate) V(message_port_constructor_template, v8::
FunctionTemplate) V(microtask_queue_ctor_template, v8::FunctionTemplate
) V(pipe_constructor_template, v8::FunctionTemplate) V(promise_wrap_template
, v8::ObjectTemplate) V(sab_lifetimepartner_constructor_template
, v8::FunctionTemplate) V(script_context_constructor_template
, v8::FunctionTemplate) V(secure_context_constructor_template
, v8::FunctionTemplate) V(shutdown_wrap_template, v8::ObjectTemplate
) V(socketaddress_constructor_template, v8::FunctionTemplate)
V(streambaseoutputstream_constructor_template, v8::ObjectTemplate
) V(qlogoutputstream_constructor_template, v8::ObjectTemplate
) V(tcp_constructor_template, v8::FunctionTemplate) V(tty_constructor_template
, v8::FunctionTemplate) V(write_wrap_template, v8::ObjectTemplate
) V(worker_heap_snapshot_taker_template, v8::ObjectTemplate) V
(x509_constructor_template, v8::FunctionTemplate)
1291 ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)V(async_hooks_after_function, v8::Function) V(async_hooks_before_function
, v8::Function) V(async_hooks_callback_trampoline, v8::Function
) V(async_hooks_binding, v8::Object) V(async_hooks_destroy_function
, v8::Function) V(async_hooks_init_function, v8::Function) V(
async_hooks_promise_resolve_function, v8::Function) V(buffer_prototype_object
, v8::Object) V(crypto_key_object_constructor, v8::Function) V
(crypto_key_object_handle_constructor, v8::Function) V(crypto_key_object_private_constructor
, v8::Function) V(crypto_key_object_public_constructor, v8::Function
) V(crypto_key_object_secret_constructor, v8::Function) V(domexception_function
, v8::Function) V(enhance_fatal_stack_after_inspector, v8::Function
) V(enhance_fatal_stack_before_inspector, v8::Function) V(fs_use_promises_symbol
, v8::Symbol) V(host_import_module_dynamically_callback, v8::
Function) V(host_initialize_import_meta_object_callback, v8::
Function) V(http2session_on_altsvc_function, v8::Function) V(
http2session_on_error_function, v8::Function) V(http2session_on_frame_error_function
, v8::Function) V(http2session_on_goaway_data_function, v8::Function
) V(http2session_on_headers_function, v8::Function) V(http2session_on_origin_function
, v8::Function) V(http2session_on_ping_function, v8::Function
) V(http2session_on_priority_function, v8::Function) V(http2session_on_settings_function
, v8::Function) V(http2session_on_stream_close_function, v8::
Function) V(http2session_on_stream_trailers_function, v8::Function
) V(internal_binding_loader, v8::Function) V(immediate_callback_function
, v8::Function) V(inspector_console_extension_installer, v8::
Function) V(inspector_disable_async_hooks, v8::Function) V(inspector_enable_async_hooks
, v8::Function) V(maybe_cache_generated_source_map, v8::Function
) V(messaging_deserialize_create_object, v8::Function) V(message_port
, v8::Object) V(native_module_require, v8::Function) V(performance_entry_callback
, v8::Function) V(performance_entry_template, v8::Function) V
(prepare_stack_trace_callback, v8::Function) V(process_object
, v8::Object) V(primordials, v8::Object) V(primordials_safe_map_prototype_object
, v8::Object) V(primordials_safe_set_prototype_object, v8::Object
) V(primordials_safe_weak_map_prototype_object, v8::Object) V
(primordials_safe_weak_set_prototype_object, v8::Object) V(promise_hook_handler
, v8::Function) V(promise_reject_callback, v8::Function) V(script_data_constructor_function
, v8::Function) V(snapshot_serialize_callback, v8::Function) V
(snapshot_deserialize_callback, v8::Function) V(snapshot_deserialize_main
, v8::Function) V(source_map_cache_getter, v8::Function) V(tick_callback_function
, v8::Function) V(timers_callback_function, v8::Function) V(tls_wrap_constructor_function
, v8::Function) V(trace_category_state_function, v8::Function
) V(udp_constructor_function, v8::Function) V(url_constructor_function
, v8::Function) V(wasm_streaming_compilation_impl, v8::Function
) V(wasm_streaming_object_constructor, v8::Function)
1292#undef V
1293
1294v8::Local<v8::Context> Environment::context() const {
1295 return PersistentToLocal::Strong(context_);
1296}
1297
1298} // namespace node
1299
1300// These two files depend on each other. Including base_object-inl.h after this
1301// file is the easiest way to avoid issues with that circular dependency.
1302#include "base_object-inl.h"
1303
1304#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1305
1306#endif // SRC_ENV_INL_H_

../src/base_object-inl.h

1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22#ifndef SRC_BASE_OBJECT_INL_H_
23#define SRC_BASE_OBJECT_INL_H_
24
25#if defined(NODE_WANT_INTERNALS1) && NODE_WANT_INTERNALS1
26
27#include "base_object.h"
28#include "env-inl.h"
29#include "util.h"
30
31#include "v8.h"
32
33namespace node {
34
35BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
36 : persistent_handle_(env->isolate(), object), env_(env) {
37 CHECK_EQ(false, object.IsEmpty())do { if (__builtin_expect(!!(!((false) == (object.IsEmpty()))
), 0)) { do { static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "37", "(false) == (object.IsEmpty())", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
38 CHECK_GT(object->InternalFieldCount(), 0)do { if (__builtin_expect(!!(!((object->InternalFieldCount
()) > (0))), 0)) { do { static const node::AssertionInfo args
= { "../src/base_object-inl.h" ":" "38", "(object->InternalFieldCount()) > (0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
39 object->SetAlignedPointerInInternalField(
40 BaseObject::kSlot,
41 static_cast<void*>(this));
42 env->AddCleanupHook(DeleteMe, static_cast<void*>(this));
43 env->modify_base_object_count(1);
44}
45
46BaseObject::~BaseObject() {
47 env()->modify_base_object_count(-1);
48 env()->RemoveCleanupHook(DeleteMe, static_cast<void*>(this));
49
50 if (UNLIKELY(has_pointer_data())__builtin_expect(!!(has_pointer_data()), 0)) {
51 PointerData* metadata = pointer_data();
52 CHECK_EQ(metadata->strong_ptr_count, 0)do { if (__builtin_expect(!!(!((metadata->strong_ptr_count
) == (0))), 0)) { do { static const node::AssertionInfo args =
{ "../src/base_object-inl.h" ":" "52", "(metadata->strong_ptr_count) == (0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
53 metadata->self = nullptr;
54 if (metadata->weak_ptr_count == 0)
55 delete metadata;
56 }
57
58 if (persistent_handle_.IsEmpty()) {
59 // This most likely happened because the weak callback below cleared it.
60 return;
61 }
62
63 {
64 v8::HandleScope handle_scope(env()->isolate());
65 object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
66 }
67}
68
69void BaseObject::Detach() {
70 CHECK_GT(pointer_data()->strong_ptr_count, 0)do { if (__builtin_expect(!!(!((pointer_data()->strong_ptr_count
) > (0))), 0)) { do { static const node::AssertionInfo args
= { "../src/base_object-inl.h" ":" "70", "(pointer_data()->strong_ptr_count) > (0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
71 pointer_data()->is_detached = true;
72}
73
74v8::Global<v8::Object>& BaseObject::persistent() {
75 return persistent_handle_;
76}
77
78
79v8::Local<v8::Object> BaseObject::object() const {
80 return PersistentToLocal::Default(env()->isolate(), persistent_handle_);
81}
82
83v8::Local<v8::Object> BaseObject::object(v8::Isolate* isolate) const {
84 v8::Local<v8::Object> handle = object();
85
86 DCHECK_EQ(handle->GetCreationContext().ToLocalChecked()->GetIsolate(),
87 isolate);
88 DCHECK_EQ(env()->isolate(), isolate);
89
90 return handle;
91}
92
93Environment* BaseObject::env() const {
94 return env_;
95}
96
97BaseObject* BaseObject::FromJSObject(v8::Local<v8::Value> value) {
98 v8::Local<v8::Object> obj = value.As<v8::Object>();
99 DCHECK_GE(obj->InternalFieldCount(), BaseObject::kSlot);
100 return static_cast<BaseObject*>(
101 obj->GetAlignedPointerFromInternalField(BaseObject::kSlot));
102}
103
104
105template <typename T>
106T* BaseObject::FromJSObject(v8::Local<v8::Value> object) {
107 return static_cast<T*>(FromJSObject(object));
108}
109
110
111void BaseObject::MakeWeak() {
112 if (has_pointer_data()) {
113 pointer_data()->wants_weak_jsobj = true;
114 if (pointer_data()->strong_ptr_count > 0) return;
115 }
116
117 persistent_handle_.SetWeak(
118 this,
119 [](const v8::WeakCallbackInfo<BaseObject>& data) {
120 BaseObject* obj = data.GetParameter();
121 // Clear the persistent handle so that ~BaseObject() doesn't attempt
122 // to mess with internal fields, since the JS object may have
123 // transitioned into an invalid state.
124 // Refs: https://github.com/nodejs/node/issues/18897
125 obj->persistent_handle_.Reset();
126 CHECK_IMPLIES(obj->has_pointer_data(),do { if (__builtin_expect(!!(!(!(obj->has_pointer_data()) ||
(obj->pointer_data()->strong_ptr_count == 0))), 0)) { do
{ static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "127", "!(obj->has_pointer_data()) || (obj->pointer_data()->strong_ptr_count == 0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
127 obj->pointer_data()->strong_ptr_count == 0)do { if (__builtin_expect(!!(!(!(obj->has_pointer_data()) ||
(obj->pointer_data()->strong_ptr_count == 0))), 0)) { do
{ static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "127", "!(obj->has_pointer_data()) || (obj->pointer_data()->strong_ptr_count == 0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
128 obj->OnGCCollect();
129 }, v8::WeakCallbackType::kParameter);
130}
131
132void BaseObject::OnGCCollect() {
133 delete this;
20
Memory is released
134}
135
136void BaseObject::ClearWeak() {
137 if (has_pointer_data())
138 pointer_data()->wants_weak_jsobj = false;
139
140 persistent_handle_.ClearWeak();
141}
142
143bool BaseObject::IsWeakOrDetached() const {
144 if (persistent_handle_.IsWeak()) return true;
145
146 if (!has_pointer_data()) return false;
147 const PointerData* pd = const_cast<BaseObject*>(this)->pointer_data();
148 return pd->wants_weak_jsobj || pd->is_detached;
149}
150
151void BaseObject::LazilyInitializedJSTemplateConstructor(
152 const v8::FunctionCallbackInfo<v8::Value>& args) {
153 DCHECK(args.IsConstructCall());
154 DCHECK_GT(args.This()->InternalFieldCount(), 0);
155 args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
156}
157
158v8::Local<v8::FunctionTemplate>
159BaseObject::MakeLazilyInitializedJSTemplate(Environment* env) {
160 v8::Local<v8::FunctionTemplate> t =
161 env->NewFunctionTemplate(LazilyInitializedJSTemplateConstructor);
162 t->Inherit(BaseObject::GetConstructorTemplate(env));
163 t->InstanceTemplate()->SetInternalFieldCount(
164 BaseObject::kInternalFieldCount);
165 return t;
166}
167
168template <int Field>
169void BaseObject::InternalFieldGet(
170 v8::Local<v8::String> property,
171 const v8::PropertyCallbackInfo<v8::Value>& info) {
172 info.GetReturnValue().Set(info.This()->GetInternalField(Field));
173}
174
175template <int Field, bool (v8::Value::* typecheck)() const>
176void BaseObject::InternalFieldSet(v8::Local<v8::String> property,
177 v8::Local<v8::Value> value,
178 const v8::PropertyCallbackInfo<void>& info) {
179 // This could be e.g. value->IsFunction().
180 CHECK(((*value)->*typecheck)())do { if (__builtin_expect(!!(!(((*value)->*typecheck)())),
0)) { do { static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "180", "((*value)->*typecheck)()", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
181 info.This()->SetInternalField(Field, value);
182}
183
184bool BaseObject::has_pointer_data() const {
185 return pointer_data_ != nullptr;
186}
187
188BaseObject::PointerData* BaseObject::pointer_data() {
189 if (!has_pointer_data()) {
190 PointerData* metadata = new PointerData();
191 metadata->wants_weak_jsobj = persistent_handle_.IsWeak();
192 metadata->self = this;
193 pointer_data_ = metadata;
194 }
195 CHECK(has_pointer_data())do { if (__builtin_expect(!!(!(has_pointer_data())), 0)) { do
{ static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "195", "has_pointer_data()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
196 return pointer_data_;
197}
198
199void BaseObject::decrease_refcount() {
200 CHECK(has_pointer_data())do { if (__builtin_expect(!!(!(has_pointer_data())), 0)) { do
{ static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "200", "has_pointer_data()", __PRETTY_FUNCTION__ }; node
::Assert(args); } while (0); } } while (0)
;
10
Taking false branch
11
Loop condition is false. Exiting loop
201 PointerData* metadata = pointer_data();
202 CHECK_GT(metadata->strong_ptr_count, 0)do { if (__builtin_expect(!!(!((metadata->strong_ptr_count
) > (0))), 0)) { do { static const node::AssertionInfo args
= { "../src/base_object-inl.h" ":" "202", "(metadata->strong_ptr_count) > (0)"
, __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } }
while (0)
;
12
Assuming field 'strong_ptr_count' is > 0
13
Taking false branch
14
Loop condition is false. Exiting loop
203 unsigned int new_refcount = --metadata->strong_ptr_count;
204 if (new_refcount == 0) {
15
Assuming 'new_refcount' is equal to 0
16
Taking true branch
205 if (metadata->is_detached) {
17
Assuming field 'is_detached' is true
18
Taking true branch
206 OnGCCollect();
19
Calling 'BaseObject::OnGCCollect'
21
Returning; memory was released
207 } else if (metadata->wants_weak_jsobj && !persistent_handle_.IsEmpty()) {
208 MakeWeak();
209 }
210 }
211}
212
213void BaseObject::increase_refcount() {
214 unsigned int prev_refcount = pointer_data()->strong_ptr_count++;
215 if (prev_refcount == 0 && !persistent_handle_.IsEmpty())
216 persistent_handle_.ClearWeak();
217}
218
219template <typename T, bool kIsWeak>
220BaseObject::PointerData*
221BaseObjectPtrImpl<T, kIsWeak>::pointer_data() const {
222 if (kIsWeak) {
223 return data_.pointer_data;
224 }
225 if (get_base_object() == nullptr) {
226 return nullptr;
227 }
228 return get_base_object()->pointer_data();
229}
230
231template <typename T, bool kIsWeak>
232BaseObject* BaseObjectPtrImpl<T, kIsWeak>::get_base_object() const {
233 if (kIsWeak) {
234 if (pointer_data() == nullptr) {
235 return nullptr;
236 }
237 return pointer_data()->self;
238 }
239 return data_.target;
240}
241
242template <typename T, bool kIsWeak>
243BaseObjectPtrImpl<T, kIsWeak>::~BaseObjectPtrImpl() {
244 if (kIsWeak) {
6
Taking false branch
245 if (pointer_data() != nullptr &&
246 --pointer_data()->weak_ptr_count == 0 &&
247 pointer_data()->self == nullptr) {
248 delete pointer_data();
249 }
250 } else if (get() != nullptr) {
7
Assuming the condition is true
8
Taking true branch
251 get()->decrease_refcount();
9
Calling 'BaseObject::decrease_refcount'
22
Returning; memory was released
252 }
253}
254
255template <typename T, bool kIsWeak>
256BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl() {
257 data_.target = nullptr;
258}
259
260template <typename T, bool kIsWeak>
261BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(T* target)
262 : BaseObjectPtrImpl() {
263 if (target == nullptr) return;
264 if (kIsWeak) {
265 data_.pointer_data = target->pointer_data();
266 CHECK_NOT_NULL(pointer_data())do { if (__builtin_expect(!!(!((pointer_data()) != nullptr)),
0)) { do { static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "266", "(pointer_data()) != nullptr", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
267 pointer_data()->weak_ptr_count++;
268 } else {
269 data_.target = target;
270 CHECK_NOT_NULL(pointer_data())do { if (__builtin_expect(!!(!((pointer_data()) != nullptr)),
0)) { do { static const node::AssertionInfo args = { "../src/base_object-inl.h"
":" "270", "(pointer_data()) != nullptr", __PRETTY_FUNCTION__
}; node::Assert(args); } while (0); } } while (0)
;
271 get()->increase_refcount();
272 }
273}
274
275template <typename T, bool kIsWeak>
276template <typename U, bool kW>
277BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(
278 const BaseObjectPtrImpl<U, kW>& other)
279 : BaseObjectPtrImpl(other.get()) {}
280
281template <typename T, bool kIsWeak>
282BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(const BaseObjectPtrImpl& other)
283 : BaseObjectPtrImpl(other.get()) {}
284
285template <typename T, bool kIsWeak>
286template <typename U, bool kW>
287BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
288 const BaseObjectPtrImpl<U, kW>& other) {
289 if (other.get() == get()) return *this;
290 this->~BaseObjectPtrImpl();
291 return *new (this) BaseObjectPtrImpl(other);
292}
293
294template <typename T, bool kIsWeak>
295BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
296 const BaseObjectPtrImpl& other) {
297 if (other.get() == get()) return *this;
298 this->~BaseObjectPtrImpl();
299 return *new (this) BaseObjectPtrImpl(other);
300}
301
302template <typename T, bool kIsWeak>
303BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(BaseObjectPtrImpl&& other)
304 : data_(other.data_) {
305 if (kIsWeak)
306 other.data_.target = nullptr;
307 else
308 other.data_.pointer_data = nullptr;
309}
310
311template <typename T, bool kIsWeak>
312BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
313 BaseObjectPtrImpl&& other) {
314 if (&other == this) return *this;
315 this->~BaseObjectPtrImpl();
316 return *new (this) BaseObjectPtrImpl(std::move(other));
317}
318
319template <typename T, bool kIsWeak>
320void BaseObjectPtrImpl<T, kIsWeak>::reset(T* ptr) {
321 *this = BaseObjectPtrImpl(ptr);
322}
323
324template <typename T, bool kIsWeak>
325T* BaseObjectPtrImpl<T, kIsWeak>::get() const {
326 return static_cast<T*>(get_base_object());
327}
328
329template <typename T, bool kIsWeak>
330T& BaseObjectPtrImpl<T, kIsWeak>::operator*() const {
331 return *get();
332}
333
334template <typename T, bool kIsWeak>
335T* BaseObjectPtrImpl<T, kIsWeak>::operator->() const {
336 return get();
337}
338
339template <typename T, bool kIsWeak>
340BaseObjectPtrImpl<T, kIsWeak>::operator bool() const {
341 return get() != nullptr;
342}
343
344template <typename T, bool kIsWeak>
345template <typename U, bool kW>
346bool BaseObjectPtrImpl<T, kIsWeak>::operator ==(
347 const BaseObjectPtrImpl<U, kW>& other) const {
348 return get() == other.get();
349}
350
351template <typename T, bool kIsWeak>
352template <typename U, bool kW>
353bool BaseObjectPtrImpl<T, kIsWeak>::operator !=(
354 const BaseObjectPtrImpl<U, kW>& other) const {
355 return get() != other.get();
356}
357
358template <typename T, typename... Args>
359BaseObjectPtr<T> MakeBaseObject(Args&&... args) {
360 return BaseObjectPtr<T>(new T(std::forward<Args>(args)...));
361}
362
363template <typename T, typename... Args>
364BaseObjectPtr<T> MakeDetachedBaseObject(Args&&... args) {
365 BaseObjectPtr<T> target = MakeBaseObject<T>(std::forward<Args>(args)...);
366 target->Detach();
367 return target;
368}
369
370} // namespace node
371
372#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
373
374#endif // SRC_BASE_OBJECT_INL_H_