4578f6ebc0270f83911b948eac776fbe8a75f9ec
[platform/upstream/nodejs.git] / src / env-inl.h
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_ENV_INL_H_
23 #define SRC_ENV_INL_H_
24
25 #include "env.h"
26 #include "util.h"
27 #include "util-inl.h"
28 #include "uv.h"
29 #include "v8.h"
30
31 #include <stddef.h>
32 #include <stdint.h>
33
34 namespace node {
35
36 inline Environment::IsolateData* Environment::IsolateData::GetOrCreate(
37     v8::Isolate* isolate) {
38   IsolateData* isolate_data = static_cast<IsolateData*>(isolate->GetData());
39   if (isolate_data == NULL) {
40     isolate_data = new IsolateData(isolate);
41     isolate->SetData(isolate_data);
42   }
43   isolate_data->ref_count_ += 1;
44   return isolate_data;
45 }
46
47 inline void Environment::IsolateData::Put() {
48   if (--ref_count_ == 0) {
49     isolate()->SetData(NULL);
50     delete this;
51   }
52 }
53
54 inline Environment::IsolateData::IsolateData(v8::Isolate* isolate)
55     : event_loop_(uv_default_loop()),
56       isolate_(isolate),
57 #define V(PropertyName, StringValue)                                          \
58     PropertyName ## _(isolate, FIXED_ONE_BYTE_STRING(isolate, StringValue)),
59     PER_ISOLATE_STRING_PROPERTIES(V)
60 #undef V
61     ref_count_(0) {
62 }
63
64 inline uv_loop_t* Environment::IsolateData::event_loop() const {
65   return event_loop_;
66 }
67
68 inline v8::Isolate* Environment::IsolateData::isolate() const {
69   return isolate_;
70 }
71
72 inline Environment::AsyncListener::AsyncListener() {
73   for (int i = 0; i < kFieldsCount; ++i)
74     fields_[i] = 0;
75 }
76
77 inline uint32_t* Environment::AsyncListener::fields() {
78   return fields_;
79 }
80
81 inline int Environment::AsyncListener::fields_count() const {
82   return kFieldsCount;
83 }
84
85 inline uint32_t Environment::AsyncListener::count() const {
86   return fields_[kCount];
87 }
88
89 inline Environment::TickInfo::TickInfo() : in_tick_(false), last_threw_(false) {
90   for (int i = 0; i < kFieldsCount; ++i)
91     fields_[i] = 0;
92 }
93
94 inline uint32_t* Environment::TickInfo::fields() {
95   return fields_;
96 }
97
98 inline int Environment::TickInfo::fields_count() const {
99   return kFieldsCount;
100 }
101
102 inline bool Environment::TickInfo::in_tick() const {
103   return in_tick_;
104 }
105
106 inline uint32_t Environment::TickInfo::index() const {
107   return fields_[kIndex];
108 }
109
110 inline bool Environment::TickInfo::last_threw() const {
111   return last_threw_;
112 }
113
114 inline uint32_t Environment::TickInfo::length() const {
115   return fields_[kLength];
116 }
117
118 inline void Environment::TickInfo::set_in_tick(bool value) {
119   in_tick_ = value;
120 }
121
122 inline void Environment::TickInfo::set_index(uint32_t value) {
123   fields_[kIndex] = value;
124 }
125
126 inline void Environment::TickInfo::set_last_threw(bool value) {
127   last_threw_ = value;
128 }
129
130 inline Environment* Environment::New(v8::Local<v8::Context> context) {
131   Environment* env = new Environment(context);
132   context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, env);
133   return env;
134 }
135
136 inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
137   return GetCurrent(isolate->GetCurrentContext());
138 }
139
140 inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
141   return static_cast<Environment*>(
142       context->GetAlignedPointerFromEmbedderData(kContextEmbedderDataIndex));
143 }
144
145 inline Environment* Environment::GetCurrentChecked(v8::Isolate* isolate) {
146   if (isolate == NULL) {
147     return NULL;
148   } else {
149     return GetCurrentChecked(isolate->GetCurrentContext());
150   }
151 }
152
153 inline Environment* Environment::GetCurrentChecked(
154     v8::Local<v8::Context> context) {
155   if (context.IsEmpty()) {
156     return NULL;
157   } else {
158     return GetCurrent(context);
159   }
160 }
161
162 inline Environment::Environment(v8::Local<v8::Context> context)
163     : isolate_(context->GetIsolate()),
164       isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())),
165       using_smalloc_alloc_cb_(false),
166       context_(context->GetIsolate(), context) {
167   // We'll be creating new objects so make sure we've entered the context.
168   v8::HandleScope handle_scope(isolate());
169   v8::Context::Scope context_scope(context);
170   set_binding_cache_object(v8::Object::New());
171   set_module_load_list_array(v8::Array::New());
172   RB_INIT(&cares_task_list_);
173 }
174
175 inline Environment::~Environment() {
176   context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, NULL);
177 #define V(PropertyName, TypeName) PropertyName ## _.Dispose();
178   ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
179 #undef V
180   isolate_data()->Put();
181 }
182
183 inline void Environment::Dispose() {
184   delete this;
185 }
186
187 inline v8::Isolate* Environment::isolate() const {
188   return isolate_;
189 }
190
191 inline bool Environment::has_async_listeners() const {
192   // The const_cast is okay, it doesn't violate conceptual const-ness.
193   return const_cast<Environment*>(this)->async_listener()->count() > 0;
194 }
195
196 inline Environment* Environment::from_immediate_check_handle(
197     uv_check_t* handle) {
198   return CONTAINER_OF(handle, Environment, immediate_check_handle_);
199 }
200
201 inline uv_check_t* Environment::immediate_check_handle() {
202   return &immediate_check_handle_;
203 }
204
205 inline uv_idle_t* Environment::immediate_idle_handle() {
206   return &immediate_idle_handle_;
207 }
208
209 inline Environment* Environment::from_idle_prepare_handle(
210     uv_prepare_t* handle) {
211   return CONTAINER_OF(handle, Environment, idle_prepare_handle_);
212 }
213
214 inline uv_prepare_t* Environment::idle_prepare_handle() {
215   return &idle_prepare_handle_;
216 }
217
218 inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
219   return CONTAINER_OF(handle, Environment, idle_check_handle_);
220 }
221
222 inline uv_check_t* Environment::idle_check_handle() {
223   return &idle_check_handle_;
224 }
225
226 inline uv_loop_t* Environment::event_loop() const {
227   return isolate_data()->event_loop();
228 }
229
230 inline Environment::AsyncListener* Environment::async_listener() {
231   return &async_listener_count_;
232 }
233
234 inline Environment::TickInfo* Environment::tick_info() {
235   return &tick_info_;
236 }
237
238 inline bool Environment::using_smalloc_alloc_cb() const {
239   return using_smalloc_alloc_cb_;
240 }
241
242 inline void Environment::set_using_smalloc_alloc_cb(bool value) {
243   using_smalloc_alloc_cb_ = value;
244 }
245
246 inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
247   return CONTAINER_OF(handle, Environment, cares_timer_handle_);
248 }
249
250 inline uv_timer_t* Environment::cares_timer_handle() {
251   return &cares_timer_handle_;
252 }
253
254 inline ares_channel Environment::cares_channel() {
255   return cares_channel_;
256 }
257
258 // Only used in the call to ares_init_options().
259 inline ares_channel* Environment::cares_channel_ptr() {
260   return &cares_channel_;
261 }
262
263 inline ares_task_list* Environment::cares_task_list() {
264   return &cares_task_list_;
265 }
266
267 inline Environment::IsolateData* Environment::isolate_data() const {
268   return isolate_data_;
269 }
270
271 #define V(PropertyName, StringValue)                                          \
272   inline                                                                      \
273   v8::Local<v8::String> Environment::IsolateData::PropertyName() const {      \
274     /* Strings are immutable so casting away const-ness here is okay. */      \
275     return const_cast<IsolateData*>(this)->PropertyName ## _.Get(isolate());  \
276   }
277   PER_ISOLATE_STRING_PROPERTIES(V)
278 #undef V
279
280 #define V(PropertyName, StringValue)                                          \
281   inline v8::Local<v8::String> Environment::PropertyName() const {            \
282     return isolate_data()->PropertyName();                                    \
283   }
284   PER_ISOLATE_STRING_PROPERTIES(V)
285 #undef V
286
287 #define V(PropertyName, TypeName)                                             \
288   inline v8::Local<TypeName> Environment::PropertyName() const {              \
289     return StrongPersistentToLocal(PropertyName ## _);                        \
290   }                                                                           \
291   inline void Environment::set_ ## PropertyName(v8::Local<TypeName> value) {  \
292     PropertyName ## _.Reset(isolate(), value);                                \
293   }
294   ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
295 #undef V
296
297 #undef ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES
298 #undef PER_ISOLATE_STRING_PROPERTIES
299
300 }  // namespace node
301
302 #endif  // SRC_ENV_INL_H_