| 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_ |