1 // Copyright Joyent, Inc. and other Node contributors.
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:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
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.
22 #ifndef SRC_ENV_INL_H_
23 #define SRC_ENV_INL_H_
37 inline Environment::GCInfo::GCInfo()
38 : type_(static_cast<v8::GCType>(0)),
39 flags_(static_cast<v8::GCCallbackFlags>(0)),
43 inline Environment::GCInfo::GCInfo(v8::Isolate* isolate,
45 v8::GCCallbackFlags flags,
49 timestamp_(timestamp) {
50 isolate->GetHeapStatistics(&stats_);
53 inline v8::GCType Environment::GCInfo::type() const {
57 inline v8::GCCallbackFlags Environment::GCInfo::flags() const {
61 inline v8::HeapStatistics* Environment::GCInfo::stats() const {
62 // TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
63 // lands and makes it way into a stable release.
64 return const_cast<v8::HeapStatistics*>(&stats_);
67 inline uint64_t Environment::GCInfo::timestamp() const {
71 inline Environment::IsolateData* Environment::IsolateData::Get(
72 v8::Isolate* isolate) {
73 return static_cast<IsolateData*>(isolate->GetData(kIsolateSlot));
76 inline Environment::IsolateData* Environment::IsolateData::GetOrCreate(
77 v8::Isolate* isolate) {
78 IsolateData* isolate_data = Get(isolate);
79 if (isolate_data == NULL) {
80 isolate_data = new IsolateData(isolate);
81 isolate->SetData(kIsolateSlot, isolate_data);
83 isolate_data->ref_count_ += 1;
87 inline void Environment::IsolateData::Put() {
88 if (--ref_count_ == 0) {
89 isolate()->SetData(kIsolateSlot, NULL);
94 inline Environment::IsolateData::IsolateData(v8::Isolate* isolate)
95 : event_loop_(uv_default_loop()),
97 #define V(PropertyName, StringValue) \
98 PropertyName ## _(isolate, FIXED_ONE_BYTE_STRING(isolate, StringValue)),
99 PER_ISOLATE_STRING_PROPERTIES(V)
102 QUEUE_INIT(&gc_tracker_queue_);
105 inline uv_loop_t* Environment::IsolateData::event_loop() const {
109 inline v8::Isolate* Environment::IsolateData::isolate() const {
113 inline Environment::AsyncListener::AsyncListener() {
114 for (int i = 0; i < kFieldsCount; ++i)
118 inline uint32_t* Environment::AsyncListener::fields() {
122 inline int Environment::AsyncListener::fields_count() const {
126 inline bool Environment::AsyncListener::has_listener() const {
127 return fields_[kHasListener] > 0;
130 inline uint32_t Environment::AsyncListener::watched_providers() const {
131 return fields_[kWatchedProviders];
134 inline Environment::DomainFlag::DomainFlag() {
135 for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
138 inline uint32_t* Environment::DomainFlag::fields() {
142 inline int Environment::DomainFlag::fields_count() const {
146 inline uint32_t Environment::DomainFlag::count() const {
147 return fields_[kCount];
150 inline Environment::TickInfo::TickInfo() : in_tick_(false), last_threw_(false) {
151 for (int i = 0; i < kFieldsCount; ++i)
155 inline uint32_t* Environment::TickInfo::fields() {
159 inline int Environment::TickInfo::fields_count() const {
163 inline bool Environment::TickInfo::in_tick() const {
167 inline uint32_t Environment::TickInfo::index() const {
168 return fields_[kIndex];
171 inline bool Environment::TickInfo::last_threw() const {
175 inline uint32_t Environment::TickInfo::length() const {
176 return fields_[kLength];
179 inline void Environment::TickInfo::set_in_tick(bool value) {
183 inline void Environment::TickInfo::set_index(uint32_t value) {
184 fields_[kIndex] = value;
187 inline void Environment::TickInfo::set_last_threw(bool value) {
191 inline Environment* Environment::New(v8::Local<v8::Context> context) {
192 Environment* env = new Environment(context);
193 context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, env);
197 inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
198 return GetCurrent(isolate->GetCurrentContext());
201 inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
202 return static_cast<Environment*>(
203 context->GetAlignedPointerFromEmbedderData(kContextEmbedderDataIndex));
206 inline Environment* Environment::GetCurrentChecked(v8::Isolate* isolate) {
207 if (isolate == NULL) {
210 return GetCurrentChecked(isolate->GetCurrentContext());
214 inline Environment* Environment::GetCurrentChecked(
215 v8::Local<v8::Context> context) {
216 if (context.IsEmpty()) {
219 return GetCurrent(context);
223 inline Environment::Environment(v8::Local<v8::Context> context)
224 : isolate_(context->GetIsolate()),
225 isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())),
226 using_smalloc_alloc_cb_(false),
227 using_domains_(false),
228 printed_error_(false),
229 context_(context->GetIsolate(), context) {
230 // We'll be creating new objects so make sure we've entered the context.
231 v8::HandleScope handle_scope(isolate());
232 v8::Context::Scope context_scope(context);
233 set_binding_cache_object(v8::Object::New(isolate()));
234 set_module_load_list_array(v8::Array::New(isolate()));
235 RB_INIT(&cares_task_list_);
236 QUEUE_INIT(&gc_tracker_queue_);
239 inline Environment::~Environment() {
240 v8::HandleScope handle_scope(isolate());
242 context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, NULL);
243 #define V(PropertyName, TypeName) PropertyName ## _.Reset();
244 ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
246 isolate_data()->Put();
249 inline void Environment::Dispose() {
253 inline v8::Isolate* Environment::isolate() const {
257 inline bool Environment::has_async_listener() const {
258 // The const_cast is okay, it doesn't violate conceptual const-ness.
259 return const_cast<Environment*>(this)->async_listener()->has_listener();
262 inline uint32_t Environment::watched_providers() const {
263 // The const_cast is okay, it doesn't violate conceptual const-ness.
264 return const_cast<Environment*>(this)->async_listener()->watched_providers();
267 inline bool Environment::in_domain() const {
268 // The const_cast is okay, it doesn't violate conceptual const-ness.
269 return using_domains() &&
270 const_cast<Environment*>(this)->domain_flag()->count() > 0;
273 inline Environment* Environment::from_immediate_check_handle(
274 uv_check_t* handle) {
275 return CONTAINER_OF(handle, Environment, immediate_check_handle_);
278 inline uv_check_t* Environment::immediate_check_handle() {
279 return &immediate_check_handle_;
282 inline uv_idle_t* Environment::immediate_idle_handle() {
283 return &immediate_idle_handle_;
286 inline Environment* Environment::from_idle_prepare_handle(
287 uv_prepare_t* handle) {
288 return CONTAINER_OF(handle, Environment, idle_prepare_handle_);
291 inline uv_prepare_t* Environment::idle_prepare_handle() {
292 return &idle_prepare_handle_;
295 inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
296 return CONTAINER_OF(handle, Environment, idle_check_handle_);
299 inline uv_check_t* Environment::idle_check_handle() {
300 return &idle_check_handle_;
303 inline uv_loop_t* Environment::event_loop() const {
304 return isolate_data()->event_loop();
307 inline Environment::AsyncListener* Environment::async_listener() {
308 return &async_listener_count_;
311 inline Environment::DomainFlag* Environment::domain_flag() {
312 return &domain_flag_;
315 inline Environment::TickInfo* Environment::tick_info() {
319 inline bool Environment::using_smalloc_alloc_cb() const {
320 return using_smalloc_alloc_cb_;
323 inline void Environment::set_using_smalloc_alloc_cb(bool value) {
324 using_smalloc_alloc_cb_ = value;
327 inline bool Environment::using_domains() const {
328 return using_domains_;
331 inline void Environment::set_using_domains(bool value) {
332 using_domains_ = value;
335 inline bool Environment::printed_error() const {
336 return printed_error_;
339 inline void Environment::set_printed_error(bool value) {
340 printed_error_ = value;
343 inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
344 return CONTAINER_OF(handle, Environment, cares_timer_handle_);
347 inline uv_timer_t* Environment::cares_timer_handle() {
348 return &cares_timer_handle_;
351 inline ares_channel Environment::cares_channel() {
352 return cares_channel_;
355 // Only used in the call to ares_init_options().
356 inline ares_channel* Environment::cares_channel_ptr() {
357 return &cares_channel_;
360 inline ares_task_list* Environment::cares_task_list() {
361 return &cares_task_list_;
364 inline Environment::IsolateData* Environment::isolate_data() const {
365 return isolate_data_;
368 // this would have been a template function were it not for the fact that g++
369 // sometimes fails to resolve it...
370 #define THROW_ERROR(fun) \
372 v8::HandleScope scope(isolate); \
373 isolate->ThrowException(fun(OneByteString(isolate, errmsg))); \
377 inline void Environment::ThrowError(v8::Isolate* isolate, const char* errmsg) {
378 THROW_ERROR(v8::Exception::Error);
381 inline void Environment::ThrowTypeError(v8::Isolate* isolate,
382 const char* errmsg) {
383 THROW_ERROR(v8::Exception::TypeError);
386 inline void Environment::ThrowRangeError(v8::Isolate* isolate,
387 const char* errmsg) {
388 THROW_ERROR(v8::Exception::RangeError);
391 inline void Environment::ThrowError(const char* errmsg) {
392 ThrowError(isolate(), errmsg);
395 inline void Environment::ThrowTypeError(const char* errmsg) {
396 ThrowTypeError(isolate(), errmsg);
399 inline void Environment::ThrowRangeError(const char* errmsg) {
400 ThrowRangeError(isolate(), errmsg);
403 inline void Environment::ThrowErrnoException(int errorno,
407 isolate()->ThrowException(
408 ErrnoException(isolate(), errorno, syscall, message, path));
411 inline void Environment::ThrowUVException(int errorno,
415 isolate()->ThrowException(
416 UVException(isolate(), errorno, syscall, message, path));
419 #define V(PropertyName, StringValue) \
421 v8::Local<v8::String> Environment::IsolateData::PropertyName() const { \
422 /* Strings are immutable so casting away const-ness here is okay. */ \
423 return const_cast<IsolateData*>(this)->PropertyName ## _.Get(isolate()); \
425 PER_ISOLATE_STRING_PROPERTIES(V)
428 #define V(PropertyName, StringValue) \
429 inline v8::Local<v8::String> Environment::PropertyName() const { \
430 return isolate_data()->PropertyName(); \
432 PER_ISOLATE_STRING_PROPERTIES(V)
435 #define V(PropertyName, TypeName) \
436 inline v8::Local<TypeName> Environment::PropertyName() const { \
437 return StrongPersistentToLocal(PropertyName ## _); \
439 inline void Environment::set_ ## PropertyName(v8::Local<TypeName> value) { \
440 PropertyName ## _.Reset(isolate(), value); \
442 ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
445 #undef ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES
446 #undef PER_ISOLATE_STRING_PROPERTIES
450 #endif // SRC_ENV_INL_H_