File: | out/../src/env-inl.h |
Warning: | line 441, column 3 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
13 | namespace node { | |||
14 | ||||
15 | using v8::Array; | |||
16 | using v8::ArrayBuffer; | |||
17 | using v8::ArrayBufferView; | |||
18 | using v8::BackingStore; | |||
19 | using v8::Context; | |||
20 | using v8::EscapableHandleScope; | |||
21 | using v8::Function; | |||
22 | using v8::FunctionCallbackInfo; | |||
23 | using v8::FunctionTemplate; | |||
24 | using v8::HandleScope; | |||
25 | using v8::Local; | |||
26 | using v8::MaybeLocal; | |||
27 | using v8::Number; | |||
28 | using v8::Object; | |||
29 | using v8::String; | |||
30 | using v8::Uint32; | |||
31 | using v8::Undefined; | |||
32 | using v8::Value; | |||
33 | ||||
34 | void 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 | ||||
52 | Local<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 | ||||
68 | bool Blob::HasInstance(Environment* env, v8::Local<v8::Value> object) { | |||
69 | return GetConstructorTemplate(env)->HasInstance(object); | |||
70 | } | |||
71 | ||||
72 | BaseObjectPtr<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 | ||||
90 | void 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 | ||||
128 | void 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 | ||||
137 | void 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 | ||||
150 | void Blob::MemoryInfo(MemoryTracker* tracker) const { | |||
151 | tracker->TrackFieldWithSize("store", length_); | |||
152 | } | |||
153 | ||||
154 | MaybeLocal<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 | ||||
175 | BaseObjectPtr<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 | ||||
206 | Blob::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 | ||||
217 | BaseObjectPtr<BaseObject> | |||
218 | Blob::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 | ||||
229 | BaseObject::TransferMode Blob::GetTransferMode() const { | |||
230 | return BaseObject::TransferMode::kCloneable; | |||
231 | } | |||
232 | ||||
233 | std::unique_ptr<worker::TransferData> Blob::CloneForMessaging() const { | |||
234 | return std::make_unique<BlobTransferData>(store_, length_); | |||
235 | } | |||
236 | ||||
237 | void 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 | ||||
262 | void 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 | ||||
274 | void 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 | ||||
309 | FixedSizeBlobCopyJob::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 | ||||
322 | void 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 | ||||
342 | void 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 | ||||
357 | void FixedSizeBlobCopyJob::MemoryInfo(MemoryTracker* tracker) const { | |||
358 | tracker->TrackFieldWithSize("source", length_); | |||
359 | tracker->TrackFieldWithSize( | |||
360 | "destination", | |||
361 | destination_ ? destination_->ByteLength() : 0); | |||
362 | } | |||
363 | ||||
364 | void 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 | ||||
373 | void 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 | ||||
397 | void 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 | ||||
411 | void FixedSizeBlobCopyJob::RegisterExternalReferences( | |||
412 | ExternalReferenceRegistry* registry) { | |||
413 | registry->Register(New); | |||
414 | registry->Register(Run); | |||
415 | } | |||
416 | ||||
417 | void BlobBindingData::StoredDataObject::MemoryInfo( | |||
418 | MemoryTracker* tracker) const { | |||
419 | tracker->TrackField("blob", blob); | |||
420 | tracker->TrackFieldWithSize("type", type.length()); | |||
421 | } | |||
422 | ||||
423 | BlobBindingData::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 | ||||
431 | BlobBindingData::BlobBindingData(Environment* env, Local<Object> wrap) | |||
432 | : SnapshotableObject(env, wrap, type_int) { | |||
433 | MakeWeak(); | |||
434 | } | |||
435 | ||||
436 | void BlobBindingData::MemoryInfo(MemoryTracker* tracker) const { | |||
437 | tracker->TrackField("data_objects", data_objects_); | |||
438 | } | |||
439 | ||||
440 | void BlobBindingData::store_data_object( | |||
441 | const std::string& uuid, | |||
442 | const BlobBindingData::StoredDataObject& object) { | |||
443 | data_objects_[uuid] = object; | |||
444 | } | |||
445 | ||||
446 | void 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 | ||||
454 | BlobBindingData::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 | ||||
462 | void 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); | |||
| ||||
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 | ||||
475 | void BlobBindingData::PrepareForSerialization( | |||
476 | Local<Context> context, | |||
477 | v8::SnapshotCreator* creator) { | |||
478 | // Stored blob objects are not actually persisted. | |||
479 | } | |||
480 | ||||
481 | InternalFieldInfo* BlobBindingData::Serialize(int index) { | |||
482 | DCHECK_EQ(index, BaseObject::kSlot); | |||
483 | InternalFieldInfo* info = InternalFieldInfo::New(type()); | |||
484 | return info; | |||
485 | } | |||
486 | ||||
487 | void 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 | ||||
500 | NODE_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); } | |||
501 | NODE_MODULE_EXTERNAL_REFERENCE(blob, node::Blob::RegisterExternalReferences)void _register_external_reference_blob( node::ExternalReferenceRegistry * registry) { node::Blob::RegisterExternalReferences(registry ); } |
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 | ||||
44 | namespace node { | |||
45 | ||||
46 | NoArrayBufferZeroFillScope::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 | ||||
52 | NoArrayBufferZeroFillScope::~NoArrayBufferZeroFillScope() { | |||
53 | if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 1; | |||
54 | } | |||
55 | ||||
56 | inline v8::Isolate* IsolateData::isolate() const { | |||
57 | return isolate_; | |||
58 | } | |||
59 | ||||
60 | inline uv_loop_t* IsolateData::event_loop() const { | |||
61 | return event_loop_; | |||
62 | } | |||
63 | ||||
64 | inline NodeArrayBufferAllocator* IsolateData::node_allocator() const { | |||
65 | return node_allocator_; | |||
66 | } | |||
67 | ||||
68 | inline MultiIsolatePlatform* IsolateData::platform() const { | |||
69 | return platform_; | |||
70 | } | |||
71 | ||||
72 | inline 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 | ||||
77 | inline worker::Worker* IsolateData::worker_context() const { | |||
78 | return worker_context_; | |||
79 | } | |||
80 | ||||
81 | inline v8::Local<v8::String> IsolateData::async_wrap_provider(int index) const { | |||
82 | return async_wrap_providers_[index].Get(isolate_); | |||
83 | } | |||
84 | ||||
85 | inline AliasedUint32Array& AsyncHooks::fields() { | |||
86 | return fields_; | |||
87 | } | |||
88 | ||||
89 | inline AliasedFloat64Array& AsyncHooks::async_id_fields() { | |||
90 | return async_id_fields_; | |||
91 | } | |||
92 | ||||
93 | inline AliasedFloat64Array& AsyncHooks::async_ids_stack() { | |||
94 | return async_ids_stack_; | |||
95 | } | |||
96 | ||||
97 | v8::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 | ||||
105 | v8::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 | ||||
110 | inline 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 | ||||
128 | inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) { | |||
129 | return env()->isolate_data()->async_wrap_provider(idx); | |||
130 | } | |||
131 | ||||
132 | inline void AsyncHooks::no_force_checks() { | |||
133 | fields_[kCheck] -= 1; | |||
134 | } | |||
135 | ||||
136 | inline Environment* AsyncHooks::env() { | |||
137 | return Environment::ForAsyncHooks(this); | |||
138 | } | |||
139 | ||||
140 | // Remember to keep this code aligned with pushAsyncContext() in JS. | |||
141 | inline 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. | |||
175 | inline 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 | ||||
220 | void 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 | ||||
237 | inline 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 | ||||
258 | inline 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 | ||||
279 | inline 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 | ||||
292 | inline AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() { | |||
293 | async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = | |||
294 | old_default_trigger_async_id_; | |||
295 | } | |||
296 | ||||
297 | Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) { | |||
298 | return ContainerOf(&Environment::async_hooks_, hooks); | |||
299 | } | |||
300 | ||||
301 | inline size_t Environment::async_callback_scope_depth() const { | |||
302 | return async_callback_scope_depth_; | |||
303 | } | |||
304 | ||||
305 | inline void Environment::PushAsyncCallbackScope() { | |||
306 | async_callback_scope_depth_++; | |||
307 | } | |||
308 | ||||
309 | inline void Environment::PopAsyncCallbackScope() { | |||
310 | async_callback_scope_depth_--; | |||
311 | } | |||
312 | ||||
313 | inline AliasedUint32Array& ImmediateInfo::fields() { | |||
314 | return fields_; | |||
315 | } | |||
316 | ||||
317 | inline uint32_t ImmediateInfo::count() const { | |||
318 | return fields_[kCount]; | |||
319 | } | |||
320 | ||||
321 | inline uint32_t ImmediateInfo::ref_count() const { | |||
322 | return fields_[kRefCount]; | |||
323 | } | |||
324 | ||||
325 | inline bool ImmediateInfo::has_outstanding() const { | |||
326 | return fields_[kHasOutstanding] == 1; | |||
327 | } | |||
328 | ||||
329 | inline void ImmediateInfo::ref_count_inc(uint32_t increment) { | |||
330 | fields_[kRefCount] += increment; | |||
331 | } | |||
332 | ||||
333 | inline void ImmediateInfo::ref_count_dec(uint32_t decrement) { | |||
334 | fields_[kRefCount] -= decrement; | |||
335 | } | |||
336 | ||||
337 | inline AliasedUint8Array& TickInfo::fields() { | |||
338 | return fields_; | |||
339 | } | |||
340 | ||||
341 | inline bool TickInfo::has_tick_scheduled() const { | |||
342 | return fields_[kHasTickScheduled] == 1; | |||
343 | } | |||
344 | ||||
345 | inline bool TickInfo::has_rejection_to_warn() const { | |||
346 | return fields_[kHasRejectionToWarn] == 1; | |||
347 | } | |||
348 | ||||
349 | inline 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 | ||||
367 | inline 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 | ||||
373 | inline 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 | ||||
391 | inline Environment* Environment::GetCurrent( | |||
392 | const v8::FunctionCallbackInfo<v8::Value>& info) { | |||
393 | return GetCurrent(info.GetIsolate()->GetCurrentContext()); | |||
394 | } | |||
395 | ||||
396 | template <typename T> | |||
397 | inline Environment* Environment::GetCurrent( | |||
398 | const v8::PropertyCallbackInfo<T>& info) { | |||
399 | return GetCurrent(info.GetIsolate()->GetCurrentContext()); | |||
400 | } | |||
401 | ||||
402 | template <typename T, typename U> | |||
403 | inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo<U>& info) { | |||
404 | return GetBindingData<T>(info.GetIsolate()->GetCurrentContext()); | |||
405 | } | |||
406 | ||||
407 | template <typename T> | |||
408 | inline T* Environment::GetBindingData( | |||
409 | const v8::FunctionCallbackInfo<v8::Value>& info) { | |||
410 | return GetBindingData<T>(info.GetIsolate()->GetCurrentContext()); | |||
411 | } | |||
412 | ||||
413 | template <typename T> | |||
414 | inline 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 | ||||
427 | template <typename T> | |||
428 | inline 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); | |||
440 | DCHECK_EQ(GetBindingData<T>(context), item.get()); | |||
441 | return item.get(); | |||
| ||||
442 | } | |||
443 | ||||
444 | inline v8::Isolate* Environment::isolate() const { | |||
445 | return isolate_; | |||
446 | } | |||
447 | ||||
448 | inline Environment* Environment::from_timer_handle(uv_timer_t* handle) { | |||
449 | return ContainerOf(&Environment::timer_handle_, handle); | |||
450 | } | |||
451 | ||||
452 | inline uv_timer_t* Environment::timer_handle() { | |||
453 | return &timer_handle_; | |||
454 | } | |||
455 | ||||
456 | inline Environment* Environment::from_immediate_check_handle( | |||
457 | uv_check_t* handle) { | |||
458 | return ContainerOf(&Environment::immediate_check_handle_, handle); | |||
459 | } | |||
460 | ||||
461 | inline uv_check_t* Environment::immediate_check_handle() { | |||
462 | return &immediate_check_handle_; | |||
463 | } | |||
464 | ||||
465 | inline uv_idle_t* Environment::immediate_idle_handle() { | |||
466 | return &immediate_idle_handle_; | |||
467 | } | |||
468 | ||||
469 | inline 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 | ||||
475 | template <typename T, typename OnCloseCallback> | |||
476 | inline 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 | ||||
497 | void Environment::IncreaseWaitingRequestCounter() { | |||
498 | request_waiting_++; | |||
499 | } | |||
500 | ||||
501 | void 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 | ||||
506 | inline uv_loop_t* Environment::event_loop() const { | |||
507 | return isolate_data()->event_loop(); | |||
508 | } | |||
509 | ||||
510 | inline 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 | |||
521 | inline bool Environment::is_in_inspector_console_call() const { | |||
522 | return is_in_inspector_console_call_; | |||
523 | } | |||
524 | ||||
525 | inline void Environment::set_is_in_inspector_console_call(bool value) { | |||
526 | is_in_inspector_console_call_ = value; | |||
527 | } | |||
528 | #endif | |||
529 | ||||
530 | inline AsyncHooks* Environment::async_hooks() { | |||
531 | return &async_hooks_; | |||
532 | } | |||
533 | ||||
534 | inline ImmediateInfo* Environment::immediate_info() { | |||
535 | return &immediate_info_; | |||
536 | } | |||
537 | ||||
538 | inline TickInfo* Environment::tick_info() { | |||
539 | return &tick_info_; | |||
540 | } | |||
541 | ||||
542 | inline uint64_t Environment::timer_base() const { | |||
543 | return timer_base_; | |||
544 | } | |||
545 | ||||
546 | inline std::shared_ptr<KVStore> Environment::env_vars() { | |||
547 | return env_vars_; | |||
548 | } | |||
549 | ||||
550 | inline void Environment::set_env_vars(std::shared_ptr<KVStore> env_vars) { | |||
551 | env_vars_ = env_vars; | |||
552 | } | |||
553 | ||||
554 | inline bool Environment::printed_error() const { | |||
555 | return printed_error_; | |||
556 | } | |||
557 | ||||
558 | inline void Environment::set_printed_error(bool value) { | |||
559 | printed_error_ = value; | |||
560 | } | |||
561 | ||||
562 | inline void Environment::set_trace_sync_io(bool value) { | |||
563 | trace_sync_io_ = value; | |||
564 | } | |||
565 | ||||
566 | inline bool Environment::abort_on_uncaught_exception() const { | |||
567 | return options_->abort_on_uncaught_exception; | |||
568 | } | |||
569 | ||||
570 | inline void Environment::set_force_context_aware(bool value) { | |||
571 | options_->force_context_aware = value; | |||
572 | } | |||
573 | ||||
574 | inline bool Environment::force_context_aware() const { | |||
575 | return options_->force_context_aware; | |||
576 | } | |||
577 | ||||
578 | inline void Environment::set_abort_on_uncaught_exception(bool value) { | |||
579 | options_->abort_on_uncaught_exception = value; | |||
580 | } | |||
581 | ||||
582 | inline AliasedUint32Array& Environment::should_abort_on_uncaught_toggle() { | |||
583 | return should_abort_on_uncaught_toggle_; | |||
584 | } | |||
585 | ||||
586 | inline AliasedInt32Array& Environment::stream_base_state() { | |||
587 | return stream_base_state_; | |||
588 | } | |||
589 | ||||
590 | inline uint32_t Environment::get_next_module_id() { | |||
591 | return module_id_counter_++; | |||
592 | } | |||
593 | inline uint32_t Environment::get_next_script_id() { | |||
594 | return script_id_counter_++; | |||
595 | } | |||
596 | inline uint32_t Environment::get_next_function_id() { | |||
597 | return function_id_counter_++; | |||
598 | } | |||
599 | ||||
600 | ShouldNotAbortOnUncaughtScope::ShouldNotAbortOnUncaughtScope( | |||
601 | Environment* env) | |||
602 | : env_(env) { | |||
603 | env_->PushShouldNotAbortOnUncaughtScope(); | |||
604 | } | |||
605 | ||||
606 | ShouldNotAbortOnUncaughtScope::~ShouldNotAbortOnUncaughtScope() { | |||
607 | Close(); | |||
608 | } | |||
609 | ||||
610 | void ShouldNotAbortOnUncaughtScope::Close() { | |||
611 | if (env_ != nullptr) { | |||
612 | env_->PopShouldNotAbortOnUncaughtScope(); | |||
613 | env_ = nullptr; | |||
614 | } | |||
615 | } | |||
616 | ||||
617 | inline void Environment::PushShouldNotAbortOnUncaughtScope() { | |||
618 | should_not_abort_scope_counter_++; | |||
619 | } | |||
620 | ||||
621 | inline void Environment::PopShouldNotAbortOnUncaughtScope() { | |||
622 | should_not_abort_scope_counter_--; | |||
623 | } | |||
624 | ||||
625 | inline bool Environment::inside_should_not_abort_on_uncaught_scope() const { | |||
626 | return should_not_abort_scope_counter_ > 0; | |||
627 | } | |||
628 | ||||
629 | inline std::vector<double>* Environment::destroy_async_id_list() { | |||
630 | return &destroy_async_id_list_; | |||
631 | } | |||
632 | ||||
633 | inline 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 | ||||
638 | inline double Environment::execution_async_id() { | |||
639 | return async_hooks()->async_id_fields()[AsyncHooks::kExecutionAsyncId]; | |||
640 | } | |||
641 | ||||
642 | inline double Environment::trigger_async_id() { | |||
643 | return async_hooks()->async_id_fields()[AsyncHooks::kTriggerAsyncId]; | |||
644 | } | |||
645 | ||||
646 | inline 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 | ||||
655 | inline std::shared_ptr<EnvironmentOptions> Environment::options() { | |||
656 | return options_; | |||
657 | } | |||
658 | ||||
659 | inline const std::vector<std::string>& Environment::argv() { | |||
660 | return argv_; | |||
661 | } | |||
662 | ||||
663 | inline const std::vector<std::string>& Environment::exec_argv() { | |||
664 | return exec_argv_; | |||
665 | } | |||
666 | ||||
667 | inline const std::string& Environment::exec_path() const { | |||
668 | return exec_path_; | |||
669 | } | |||
670 | ||||
671 | inline 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 | |||
688 | inline void Environment::set_coverage_directory(const char* dir) { | |||
689 | coverage_directory_ = std::string(dir); | |||
690 | } | |||
691 | ||||
692 | inline 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 | ||||
698 | inline profiler::V8CoverageConnection* Environment::coverage_connection() { | |||
699 | return coverage_connection_.get(); | |||
700 | } | |||
701 | ||||
702 | inline const std::string& Environment::coverage_directory() const { | |||
703 | return coverage_directory_; | |||
704 | } | |||
705 | ||||
706 | inline 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 | ||||
712 | inline profiler::V8CpuProfilerConnection* | |||
713 | Environment::cpu_profiler_connection() { | |||
714 | return cpu_profiler_connection_.get(); | |||
715 | } | |||
716 | ||||
717 | inline void Environment::set_cpu_prof_interval(uint64_t interval) { | |||
718 | cpu_prof_interval_ = interval; | |||
719 | } | |||
720 | ||||
721 | inline uint64_t Environment::cpu_prof_interval() const { | |||
722 | return cpu_prof_interval_; | |||
723 | } | |||
724 | ||||
725 | inline void Environment::set_cpu_prof_name(const std::string& name) { | |||
726 | cpu_prof_name_ = name; | |||
727 | } | |||
728 | ||||
729 | inline const std::string& Environment::cpu_prof_name() const { | |||
730 | return cpu_prof_name_; | |||
731 | } | |||
732 | ||||
733 | inline void Environment::set_cpu_prof_dir(const std::string& dir) { | |||
734 | cpu_prof_dir_ = dir; | |||
735 | } | |||
736 | ||||
737 | inline const std::string& Environment::cpu_prof_dir() const { | |||
738 | return cpu_prof_dir_; | |||
739 | } | |||
740 | ||||
741 | inline 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 | ||||
747 | inline profiler::V8HeapProfilerConnection* | |||
748 | Environment::heap_profiler_connection() { | |||
749 | return heap_profiler_connection_.get(); | |||
750 | } | |||
751 | ||||
752 | inline void Environment::set_heap_prof_name(const std::string& name) { | |||
753 | heap_prof_name_ = name; | |||
754 | } | |||
755 | ||||
756 | inline const std::string& Environment::heap_prof_name() const { | |||
757 | return heap_prof_name_; | |||
758 | } | |||
759 | ||||
760 | inline void Environment::set_heap_prof_dir(const std::string& dir) { | |||
761 | heap_prof_dir_ = dir; | |||
762 | } | |||
763 | ||||
764 | inline const std::string& Environment::heap_prof_dir() const { | |||
765 | return heap_prof_dir_; | |||
766 | } | |||
767 | ||||
768 | inline void Environment::set_heap_prof_interval(uint64_t interval) { | |||
769 | heap_prof_interval_ = interval; | |||
770 | } | |||
771 | ||||
772 | inline uint64_t Environment::heap_prof_interval() const { | |||
773 | return heap_prof_interval_; | |||
774 | } | |||
775 | ||||
776 | #endif // HAVE_INSPECTOR | |||
777 | ||||
778 | inline | |||
779 | std::shared_ptr<ExclusiveAccess<HostPort>> Environment::inspector_host_port() { | |||
780 | return inspector_host_port_; | |||
781 | } | |||
782 | ||||
783 | inline std::shared_ptr<PerIsolateOptions> IsolateData::options() { | |||
784 | return options_; | |||
785 | } | |||
786 | ||||
787 | inline void IsolateData::set_options( | |||
788 | std::shared_ptr<PerIsolateOptions> options) { | |||
789 | options_ = std::move(options); | |||
790 | } | |||
791 | ||||
792 | template <typename Fn> | |||
793 | void 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 | ||||
804 | template <typename Fn> | |||
805 | void 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 | ||||
816 | template <typename Fn> | |||
817 | void 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 | ||||
829 | inline bool Environment::can_call_into_js() const { | |||
830 | return can_call_into_js_ && !is_stopping(); | |||
831 | } | |||
832 | ||||
833 | inline void Environment::set_can_call_into_js(bool can_call_into_js) { | |||
834 | can_call_into_js_ = can_call_into_js; | |||
835 | } | |||
836 | ||||
837 | inline bool Environment::has_run_bootstrapping_code() const { | |||
838 | return has_run_bootstrapping_code_; | |||
839 | } | |||
840 | ||||
841 | inline 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 | ||||
849 | inline bool Environment::has_serialized_options() const { | |||
850 | return has_serialized_options_; | |||
851 | } | |||
852 | ||||
853 | inline void Environment::set_has_serialized_options(bool value) { | |||
854 | has_serialized_options_ = value; | |||
855 | } | |||
856 | ||||
857 | inline bool Environment::is_main_thread() const { | |||
858 | return worker_context() == nullptr; | |||
859 | } | |||
860 | ||||
861 | inline bool Environment::no_native_addons() const { | |||
862 | return (flags_ & EnvironmentFlags::kNoNativeAddons) || | |||
863 | !options_->allow_native_addons; | |||
864 | } | |||
865 | ||||
866 | inline bool Environment::should_not_register_esm_loader() const { | |||
867 | return flags_ & EnvironmentFlags::kNoRegisterESMLoader; | |||
868 | } | |||
869 | ||||
870 | inline bool Environment::owns_process_state() const { | |||
871 | return flags_ & EnvironmentFlags::kOwnsProcessState; | |||
872 | } | |||
873 | ||||
874 | inline bool Environment::owns_inspector() const { | |||
875 | return flags_ & EnvironmentFlags::kOwnsInspector; | |||
876 | } | |||
877 | ||||
878 | inline bool Environment::should_create_inspector() const { | |||
879 | return (flags_ & EnvironmentFlags::kNoCreateInspector) == 0; | |||
880 | } | |||
881 | ||||
882 | inline bool Environment::tracks_unmanaged_fds() const { | |||
883 | return flags_ & EnvironmentFlags::kTrackUnmanagedFds; | |||
884 | } | |||
885 | ||||
886 | inline bool Environment::hide_console_windows() const { | |||
887 | return flags_ & EnvironmentFlags::kHideConsoleWindows; | |||
888 | } | |||
889 | ||||
890 | inline bool Environment::no_global_search_paths() const { | |||
891 | return (flags_ & EnvironmentFlags::kNoGlobalSearchPaths) || | |||
892 | !options_->global_search_paths; | |||
893 | } | |||
894 | ||||
895 | inline 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 | ||||
904 | bool Environment::filehandle_close_warning() const { | |||
905 | return emit_filehandle_warning_; | |||
906 | } | |||
907 | ||||
908 | void Environment::set_filehandle_close_warning(bool on) { | |||
909 | emit_filehandle_warning_ = on; | |||
910 | } | |||
911 | ||||
912 | void Environment::set_source_maps_enabled(bool on) { | |||
913 | source_maps_enabled_ = on; | |||
914 | } | |||
915 | ||||
916 | bool Environment::source_maps_enabled() const { | |||
917 | return source_maps_enabled_; | |||
918 | } | |||
919 | ||||
920 | inline uint64_t Environment::thread_id() const { | |||
921 | return thread_id_; | |||
922 | } | |||
923 | ||||
924 | inline worker::Worker* Environment::worker_context() const { | |||
925 | return isolate_data()->worker_context(); | |||
926 | } | |||
927 | ||||
928 | inline void Environment::add_sub_worker_context(worker::Worker* context) { | |||
929 | sub_worker_contexts_.insert(context); | |||
930 | } | |||
931 | ||||
932 | inline void Environment::remove_sub_worker_context(worker::Worker* context) { | |||
933 | sub_worker_contexts_.erase(context); | |||
934 | } | |||
935 | ||||
936 | template <typename Fn> | |||
937 | inline void Environment::ForEachWorker(Fn&& iterator) { | |||
938 | for (worker::Worker* w : sub_worker_contexts_) iterator(w); | |||
939 | } | |||
940 | ||||
941 | inline 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 | ||||
950 | inline bool Environment::is_stopping() const { | |||
951 | return is_stopping_.load(); | |||
952 | } | |||
953 | ||||
954 | inline void Environment::set_stopping(bool value) { | |||
955 | is_stopping_.store(value); | |||
956 | } | |||
957 | ||||
958 | inline std::list<node_module>* Environment::extra_linked_bindings() { | |||
959 | return &extra_linked_bindings_; | |||
960 | } | |||
961 | ||||
962 | inline node_module* Environment::extra_linked_bindings_head() { | |||
963 | return extra_linked_bindings_.size() > 0 ? | |||
964 | &extra_linked_bindings_.front() : nullptr; | |||
965 | } | |||
966 | ||||
967 | inline node_module* Environment::extra_linked_bindings_tail() { | |||
968 | return extra_linked_bindings_.size() > 0 ? | |||
969 | &extra_linked_bindings_.back() : nullptr; | |||
970 | } | |||
971 | ||||
972 | inline const Mutex& Environment::extra_linked_bindings_mutex() const { | |||
973 | return extra_linked_bindings_mutex_; | |||
974 | } | |||
975 | ||||
976 | inline performance::PerformanceState* Environment::performance_state() { | |||
977 | return performance_state_.get(); | |||
978 | } | |||
979 | ||||
980 | inline IsolateData* Environment::isolate_data() const { | |||
981 | return isolate_data_; | |||
982 | } | |||
983 | ||||
984 | inline 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 | ||||
994 | inline 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 | ||||
1006 | inline void Environment::ThrowError(const char* errmsg) { | |||
1007 | ThrowError(v8::Exception::Error, errmsg); | |||
1008 | } | |||
1009 | ||||
1010 | inline void Environment::ThrowTypeError(const char* errmsg) { | |||
1011 | ThrowError(v8::Exception::TypeError, errmsg); | |||
1012 | } | |||
1013 | ||||
1014 | inline void Environment::ThrowRangeError(const char* errmsg) { | |||
1015 | ThrowError(v8::Exception::RangeError, errmsg); | |||
1016 | } | |||
1017 | ||||
1018 | inline 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 | ||||
1025 | inline 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 | ||||
1033 | inline 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 | ||||
1042 | inline 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 | ||||
1058 | inline 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 | ||||
1076 | inline 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 | ||||
1095 | inline 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 | ||||
1113 | inline 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 | ||||
1128 | inline 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 | ||||
1144 | inline 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 | ||||
1159 | inline 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 | ||||
1167 | inline 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 | ||||
1180 | void 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 | ||||
1188 | void Environment::RemoveCleanupHook(CleanupCallback fn, void* arg) { | |||
1189 | CleanupHookCallback search { fn, arg, 0 }; | |||
1190 | cleanup_hooks_.erase(search); | |||
1191 | } | |||
1192 | ||||
1193 | size_t CleanupHookCallback::Hash::operator()( | |||
1194 | const CleanupHookCallback& cb) const { | |||
1195 | return std::hash<void*>()(cb.arg_); | |||
1196 | } | |||
1197 | ||||
1198 | bool CleanupHookCallback::Equal::operator()( | |||
1199 | const CleanupHookCallback& a, const CleanupHookCallback& b) const { | |||
1200 | return a.fn_ == b.fn_ && a.arg_ == b.arg_; | |||
1201 | } | |||
1202 | ||||
1203 | BaseObject* CleanupHookCallback::GetBaseObject() const { | |||
1204 | if (fn_ == BaseObject::DeleteMe) | |||
1205 | return static_cast<BaseObject*>(arg_); | |||
1206 | else | |||
1207 | return nullptr; | |||
1208 | } | |||
1209 | ||||
1210 | template <typename T> | |||
1211 | void 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 | ||||
1219 | template <typename T> | |||
1220 | void 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 | ||||
1230 | void Environment::modify_base_object_count(int64_t delta) { | |||
1231 | base_object_count_ += delta; | |||
1232 | } | |||
1233 | ||||
1234 | int64_t Environment::base_object_created_after_bootstrap() const { | |||
1235 | return base_object_count_ - base_object_created_by_bootstrap_; | |||
1236 | } | |||
1237 | ||||
1238 | int64_t Environment::base_object_count() const { | |||
1239 | return base_object_count_; | |||
1240 | } | |||
1241 | ||||
1242 | void 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 | ||||
1247 | void 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 | ||||
1294 | v8::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_ |
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 | |
33 | namespace node { |
34 | |
35 | BaseObject::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 | |
46 | BaseObject::~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 | |
69 | void 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 | |
74 | v8::Global<v8::Object>& BaseObject::persistent() { |
75 | return persistent_handle_; |
76 | } |
77 | |
78 | |
79 | v8::Local<v8::Object> BaseObject::object() const { |
80 | return PersistentToLocal::Default(env()->isolate(), persistent_handle_); |
81 | } |
82 | |
83 | v8::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 | |
93 | Environment* BaseObject::env() const { |
94 | return env_; |
95 | } |
96 | |
97 | BaseObject* 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 | |
105 | template <typename T> |
106 | T* BaseObject::FromJSObject(v8::Local<v8::Value> object) { |
107 | return static_cast<T*>(FromJSObject(object)); |
108 | } |
109 | |
110 | |
111 | void 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 | |
132 | void BaseObject::OnGCCollect() { |
133 | delete this; |
134 | } |
135 | |
136 | void BaseObject::ClearWeak() { |
137 | if (has_pointer_data()) |
138 | pointer_data()->wants_weak_jsobj = false; |
139 | |
140 | persistent_handle_.ClearWeak(); |
141 | } |
142 | |
143 | bool 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 | |
151 | void 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 | |
158 | v8::Local<v8::FunctionTemplate> |
159 | BaseObject::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 | |
168 | template <int Field> |
169 | void 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 | |
175 | template <int Field, bool (v8::Value::* typecheck)() const> |
176 | void 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 | |
184 | bool BaseObject::has_pointer_data() const { |
185 | return pointer_data_ != nullptr; |
186 | } |
187 | |
188 | BaseObject::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 | |
199 | void 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); |
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); |
203 | unsigned int new_refcount = --metadata->strong_ptr_count; |
204 | if (new_refcount == 0) { |
205 | if (metadata->is_detached) { |
206 | OnGCCollect(); |
207 | } else if (metadata->wants_weak_jsobj && !persistent_handle_.IsEmpty()) { |
208 | MakeWeak(); |
209 | } |
210 | } |
211 | } |
212 | |
213 | void 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 | |
219 | template <typename T, bool kIsWeak> |
220 | BaseObject::PointerData* |
221 | BaseObjectPtrImpl<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 | |
231 | template <typename T, bool kIsWeak> |
232 | BaseObject* 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 | |
242 | template <typename T, bool kIsWeak> |
243 | BaseObjectPtrImpl<T, kIsWeak>::~BaseObjectPtrImpl() { |
244 | if (kIsWeak) { |
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) { |
251 | get()->decrease_refcount(); |
252 | } |
253 | } |
254 | |
255 | template <typename T, bool kIsWeak> |
256 | BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl() { |
257 | data_.target = nullptr; |
258 | } |
259 | |
260 | template <typename T, bool kIsWeak> |
261 | BaseObjectPtrImpl<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 | |
275 | template <typename T, bool kIsWeak> |
276 | template <typename U, bool kW> |
277 | BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl( |
278 | const BaseObjectPtrImpl<U, kW>& other) |
279 | : BaseObjectPtrImpl(other.get()) {} |
280 | |
281 | template <typename T, bool kIsWeak> |
282 | BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(const BaseObjectPtrImpl& other) |
283 | : BaseObjectPtrImpl(other.get()) {} |
284 | |
285 | template <typename T, bool kIsWeak> |
286 | template <typename U, bool kW> |
287 | BaseObjectPtrImpl<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 | |
294 | template <typename T, bool kIsWeak> |
295 | BaseObjectPtrImpl<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 | |
302 | template <typename T, bool kIsWeak> |
303 | BaseObjectPtrImpl<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 | |
311 | template <typename T, bool kIsWeak> |
312 | BaseObjectPtrImpl<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 | |
319 | template <typename T, bool kIsWeak> |
320 | void BaseObjectPtrImpl<T, kIsWeak>::reset(T* ptr) { |
321 | *this = BaseObjectPtrImpl(ptr); |
322 | } |
323 | |
324 | template <typename T, bool kIsWeak> |
325 | T* BaseObjectPtrImpl<T, kIsWeak>::get() const { |
326 | return static_cast<T*>(get_base_object()); |
327 | } |
328 | |
329 | template <typename T, bool kIsWeak> |
330 | T& BaseObjectPtrImpl<T, kIsWeak>::operator*() const { |
331 | return *get(); |
332 | } |
333 | |
334 | template <typename T, bool kIsWeak> |
335 | T* BaseObjectPtrImpl<T, kIsWeak>::operator->() const { |
336 | return get(); |
337 | } |
338 | |
339 | template <typename T, bool kIsWeak> |
340 | BaseObjectPtrImpl<T, kIsWeak>::operator bool() const { |
341 | return get() != nullptr; |
342 | } |
343 | |
344 | template <typename T, bool kIsWeak> |
345 | template <typename U, bool kW> |
346 | bool BaseObjectPtrImpl<T, kIsWeak>::operator ==( |
347 | const BaseObjectPtrImpl<U, kW>& other) const { |
348 | return get() == other.get(); |
349 | } |
350 | |
351 | template <typename T, bool kIsWeak> |
352 | template <typename U, bool kW> |
353 | bool BaseObjectPtrImpl<T, kIsWeak>::operator !=( |
354 | const BaseObjectPtrImpl<U, kW>& other) const { |
355 | return get() != other.get(); |
356 | } |
357 | |
358 | template <typename T, typename... Args> |
359 | BaseObjectPtr<T> MakeBaseObject(Args&&... args) { |
360 | return BaseObjectPtr<T>(new T(std::forward<Args>(args)...)); |
361 | } |
362 | |
363 | template <typename T, typename... Args> |
364 | BaseObjectPtr<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_ |