1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "api.h"
31
32 #include "arguments.h"
33 #include "bootstrapper.h"
34 #include "compiler.h"
35 #include "debug.h"
36 #include "deoptimizer.h"
37 #include "execution.h"
38 #include "global-handles.h"
39 #include "heap-profiler.h"
40 #include "messages.h"
41 #include "parser.h"
42 #include "platform.h"
43 #include "profile-generator-inl.h"
44 #include "runtime-profiler.h"
45 #include "serialize.h"
46 #include "snapshot.h"
47 #include "v8threads.h"
48 #include "version.h"
49 #include "vm-state-inl.h"
50
51 #include "../include/v8-profiler.h"
52 #include "../include/v8-testing.h"
53
54 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
55
56 // TODO(isolates): avoid repeated TLS reads in function prologues.
57 #ifdef ENABLE_VMSTATE_TRACKING
58 #define ENTER_V8(isolate) \
59 ASSERT((isolate)->IsInitialized()); \
60 i::VMState __state__((isolate), i::OTHER)
61 #define LEAVE_V8(isolate) \
62 i::VMState __state__((isolate), i::EXTERNAL)
63 #else
64 #define ENTER_V8(isolate) ((void) 0)
65 #define LEAVE_V8(isolate) ((void) 0)
66 #endif
67
68 namespace v8 {
69
70 #define ON_BAILOUT(isolate, location, code) \
71 if (IsDeadCheck(isolate, location) || \
72 IsExecutionTerminatingCheck(isolate)) { \
73 code; \
74 UNREACHABLE(); \
75 }
76
77
78 #define EXCEPTION_PREAMBLE(isolate) \
79 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \
80 ASSERT(!(isolate)->external_caught_exception()); \
81 bool has_pending_exception = false
82
83
84 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \
85 do { \
86 i::HandleScopeImplementer* handle_scope_implementer = \
87 (isolate)->handle_scope_implementer(); \
88 handle_scope_implementer->DecrementCallDepth(); \
89 if (has_pending_exception) { \
90 if (handle_scope_implementer->CallDepthIsZero() && \
91 (isolate)->is_out_of_memory()) { \
92 if (!(isolate)->ignore_out_of_memory()) \
93 i::V8::FatalProcessOutOfMemory(NULL); \
94 } \
95 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \
96 (isolate)->OptionalRescheduleException(call_depth_is_zero); \
97 return value; \
98 } \
99 } while (false)
100
101 // TODO(isolates): Add a parameter to this macro for an isolate.
102
103 #define API_ENTRY_CHECK(msg) \
104 do { \
105 if (v8::Locker::IsActive()) { \
106 ApiCheck(i::Isolate::Current()->thread_manager()-> \
107 IsLockedByCurrentThread(), \
108 msg, \
109 "Entering the V8 API without proper locking in place"); \
110 } \
111 } while (false)
112
113
114 // --- E x c e p t i o n B e h a v i o r ---
115
116
DefaultFatalErrorHandler(const char * location,const char * message)117 static void DefaultFatalErrorHandler(const char* location,
118 const char* message) {
119 #ifdef ENABLE_VMSTATE_TRACKING
120 i::VMState __state__(i::Isolate::Current(), i::OTHER);
121 #endif
122 API_Fatal(location, message);
123 }
124
125
GetFatalErrorHandler()126 static FatalErrorCallback GetFatalErrorHandler() {
127 i::Isolate* isolate = i::Isolate::Current();
128 if (isolate->exception_behavior() == NULL) {
129 isolate->set_exception_behavior(DefaultFatalErrorHandler);
130 }
131 return isolate->exception_behavior();
132 }
133
134
FatalProcessOutOfMemory(const char * location)135 void i::FatalProcessOutOfMemory(const char* location) {
136 i::V8::FatalProcessOutOfMemory(location, false);
137 }
138
139
140 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
141 // The default fatal error handler is called and execution is stopped.
FatalProcessOutOfMemory(const char * location,bool take_snapshot)142 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
143 i::HeapStats heap_stats;
144 int start_marker;
145 heap_stats.start_marker = &start_marker;
146 int new_space_size;
147 heap_stats.new_space_size = &new_space_size;
148 int new_space_capacity;
149 heap_stats.new_space_capacity = &new_space_capacity;
150 intptr_t old_pointer_space_size;
151 heap_stats.old_pointer_space_size = &old_pointer_space_size;
152 intptr_t old_pointer_space_capacity;
153 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
154 intptr_t old_data_space_size;
155 heap_stats.old_data_space_size = &old_data_space_size;
156 intptr_t old_data_space_capacity;
157 heap_stats.old_data_space_capacity = &old_data_space_capacity;
158 intptr_t code_space_size;
159 heap_stats.code_space_size = &code_space_size;
160 intptr_t code_space_capacity;
161 heap_stats.code_space_capacity = &code_space_capacity;
162 intptr_t map_space_size;
163 heap_stats.map_space_size = &map_space_size;
164 intptr_t map_space_capacity;
165 heap_stats.map_space_capacity = &map_space_capacity;
166 intptr_t cell_space_size;
167 heap_stats.cell_space_size = &cell_space_size;
168 intptr_t cell_space_capacity;
169 heap_stats.cell_space_capacity = &cell_space_capacity;
170 intptr_t lo_space_size;
171 heap_stats.lo_space_size = &lo_space_size;
172 int global_handle_count;
173 heap_stats.global_handle_count = &global_handle_count;
174 int weak_global_handle_count;
175 heap_stats.weak_global_handle_count = &weak_global_handle_count;
176 int pending_global_handle_count;
177 heap_stats.pending_global_handle_count = &pending_global_handle_count;
178 int near_death_global_handle_count;
179 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
180 int destroyed_global_handle_count;
181 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
182 intptr_t memory_allocator_size;
183 heap_stats.memory_allocator_size = &memory_allocator_size;
184 intptr_t memory_allocator_capacity;
185 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
186 int objects_per_type[LAST_TYPE + 1] = {0};
187 heap_stats.objects_per_type = objects_per_type;
188 int size_per_type[LAST_TYPE + 1] = {0};
189 heap_stats.size_per_type = size_per_type;
190 int os_error;
191 heap_stats.os_error = &os_error;
192 int end_marker;
193 heap_stats.end_marker = &end_marker;
194 i::Isolate* isolate = i::Isolate::Current();
195 isolate->heap()->RecordStats(&heap_stats, take_snapshot);
196 i::V8::SetFatalError();
197 FatalErrorCallback callback = GetFatalErrorHandler();
198 {
199 LEAVE_V8(isolate);
200 callback(location, "Allocation failed - process out of memory");
201 }
202 // If the callback returns, we stop execution.
203 UNREACHABLE();
204 }
205
206
ReportApiFailure(const char * location,const char * message)207 bool Utils::ReportApiFailure(const char* location, const char* message) {
208 FatalErrorCallback callback = GetFatalErrorHandler();
209 callback(location, message);
210 i::V8::SetFatalError();
211 return false;
212 }
213
214
IsDead()215 bool V8::IsDead() {
216 return i::V8::IsDead();
217 }
218
219
ApiCheck(bool condition,const char * location,const char * message)220 static inline bool ApiCheck(bool condition,
221 const char* location,
222 const char* message) {
223 return condition ? true : Utils::ReportApiFailure(location, message);
224 }
225
226
ReportV8Dead(const char * location)227 static bool ReportV8Dead(const char* location) {
228 FatalErrorCallback callback = GetFatalErrorHandler();
229 callback(location, "V8 is no longer usable");
230 return true;
231 }
232
233
ReportEmptyHandle(const char * location)234 static bool ReportEmptyHandle(const char* location) {
235 FatalErrorCallback callback = GetFatalErrorHandler();
236 callback(location, "Reading from empty handle");
237 return true;
238 }
239
240
241 /**
242 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
243 * out of memory at some point this check will fail. It should be called on
244 * entry to all methods that touch anything in the heap, except destructors
245 * which you sometimes can't avoid calling after the vm has crashed. Functions
246 * that call EnsureInitialized or ON_BAILOUT don't have to also call
247 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
248 * can arrange to return if the VM is dead. This is needed to ensure that no VM
249 * heap allocations are attempted on a dead VM. EnsureInitialized has the
250 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
251 * yet been done.
252 */
IsDeadCheck(i::Isolate * isolate,const char * location)253 static inline bool IsDeadCheck(i::Isolate* isolate, const char* location) {
254 return !isolate->IsInitialized()
255 && i::V8::IsDead() ? ReportV8Dead(location) : false;
256 }
257
258
IsExecutionTerminatingCheck(i::Isolate * isolate)259 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
260 if (!isolate->IsInitialized()) return false;
261 if (isolate->has_scheduled_exception()) {
262 return isolate->scheduled_exception() ==
263 isolate->heap()->termination_exception();
264 }
265 return false;
266 }
267
268
EmptyCheck(const char * location,v8::Handle<v8::Data> obj)269 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
270 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
271 }
272
273
EmptyCheck(const char * location,const v8::Data * obj)274 static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
275 return (obj == 0) ? ReportEmptyHandle(location) : false;
276 }
277
278 // --- S t a t i c s ---
279
280
InitializeHelper()281 static bool InitializeHelper() {
282 if (i::Snapshot::Initialize()) return true;
283 return i::V8::Initialize(NULL);
284 }
285
286
EnsureInitializedForIsolate(i::Isolate * isolate,const char * location)287 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
288 const char* location) {
289 if (IsDeadCheck(isolate, location)) return false;
290 if (isolate != NULL) {
291 if (isolate->IsInitialized()) return true;
292 }
293 return ApiCheck(InitializeHelper(), location, "Error initializing V8");
294 }
295
296 // Some initializing API functions are called early and may be
297 // called on a thread different from static initializer thread.
298 // If Isolate API is used, Isolate::Enter() will initialize TLS so
299 // Isolate::Current() works. If it's a legacy case, then the thread
300 // may not have TLS initialized yet. However, in initializing APIs it
301 // may be too early to call EnsureInitialized() - some pre-init
302 // parameters still have to be configured.
EnterIsolateIfNeeded()303 static inline i::Isolate* EnterIsolateIfNeeded() {
304 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
305 if (isolate != NULL)
306 return isolate;
307
308 i::Isolate::EnterDefaultIsolate();
309 isolate = i::Isolate::Current();
310 return isolate;
311 }
312
313
SetFatalErrorHandler(FatalErrorCallback that)314 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
315 i::Isolate* isolate = EnterIsolateIfNeeded();
316 isolate->set_exception_behavior(that);
317 }
318
319
320 #ifdef DEBUG
ZapHandleRange(i::Object ** begin,i::Object ** end)321 void ImplementationUtilities::ZapHandleRange(i::Object** begin,
322 i::Object** end) {
323 i::HandleScope::ZapRange(begin, end);
324 }
325 #endif
326
327
SetFlagsFromString(const char * str,int length)328 void V8::SetFlagsFromString(const char* str, int length) {
329 i::FlagList::SetFlagsFromString(str, length);
330 }
331
332
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)333 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
334 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
335 }
336
337
ThrowException(v8::Handle<v8::Value> value)338 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
339 i::Isolate* isolate = i::Isolate::Current();
340 if (IsDeadCheck(isolate, "v8::ThrowException()")) {
341 return v8::Handle<Value>();
342 }
343 ENTER_V8(isolate);
344 // If we're passed an empty handle, we throw an undefined exception
345 // to deal more gracefully with out of memory situations.
346 if (value.IsEmpty()) {
347 isolate->ScheduleThrow(isolate->heap()->undefined_value());
348 } else {
349 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
350 }
351 return v8::Undefined();
352 }
353
354
355 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
356
357
RegisteredExtension(Extension * extension)358 RegisteredExtension::RegisteredExtension(Extension* extension)
359 : extension_(extension), state_(UNVISITED) { }
360
361
Register(RegisteredExtension * that)362 void RegisteredExtension::Register(RegisteredExtension* that) {
363 that->next_ = first_extension_;
364 first_extension_ = that;
365 }
366
367
RegisterExtension(Extension * that)368 void RegisterExtension(Extension* that) {
369 RegisteredExtension* extension = new RegisteredExtension(that);
370 RegisteredExtension::Register(extension);
371 }
372
373
Extension(const char * name,const char * source,int dep_count,const char ** deps)374 Extension::Extension(const char* name,
375 const char* source,
376 int dep_count,
377 const char** deps)
378 : name_(name),
379 source_(source),
380 dep_count_(dep_count),
381 deps_(deps),
382 auto_enable_(false) { }
383
384
Undefined()385 v8::Handle<Primitive> Undefined() {
386 i::Isolate* isolate = i::Isolate::Current();
387 if (!EnsureInitializedForIsolate(isolate, "v8::Undefined()")) {
388 return v8::Handle<v8::Primitive>();
389 }
390 return v8::Handle<Primitive>(ToApi<Primitive>(
391 isolate->factory()->undefined_value()));
392 }
393
394
Null()395 v8::Handle<Primitive> Null() {
396 i::Isolate* isolate = i::Isolate::Current();
397 if (!EnsureInitializedForIsolate(isolate, "v8::Null()")) {
398 return v8::Handle<v8::Primitive>();
399 }
400 return v8::Handle<Primitive>(
401 ToApi<Primitive>(isolate->factory()->null_value()));
402 }
403
404
True()405 v8::Handle<Boolean> True() {
406 i::Isolate* isolate = i::Isolate::Current();
407 if (!EnsureInitializedForIsolate(isolate, "v8::True()")) {
408 return v8::Handle<Boolean>();
409 }
410 return v8::Handle<Boolean>(
411 ToApi<Boolean>(isolate->factory()->true_value()));
412 }
413
414
False()415 v8::Handle<Boolean> False() {
416 i::Isolate* isolate = i::Isolate::Current();
417 if (!EnsureInitializedForIsolate(isolate, "v8::False()")) {
418 return v8::Handle<Boolean>();
419 }
420 return v8::Handle<Boolean>(
421 ToApi<Boolean>(isolate->factory()->false_value()));
422 }
423
424
ResourceConstraints()425 ResourceConstraints::ResourceConstraints()
426 : max_young_space_size_(0),
427 max_old_space_size_(0),
428 max_executable_size_(0),
429 stack_limit_(NULL) { }
430
431
SetResourceConstraints(ResourceConstraints * constraints)432 bool SetResourceConstraints(ResourceConstraints* constraints) {
433 i::Isolate* isolate = EnterIsolateIfNeeded();
434
435 int young_space_size = constraints->max_young_space_size();
436 int old_gen_size = constraints->max_old_space_size();
437 int max_executable_size = constraints->max_executable_size();
438 if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
439 // After initialization it's too late to change Heap constraints.
440 ASSERT(!isolate->IsInitialized());
441 bool result = isolate->heap()->ConfigureHeap(young_space_size / 2,
442 old_gen_size,
443 max_executable_size);
444 if (!result) return false;
445 }
446 if (constraints->stack_limit() != NULL) {
447 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
448 isolate->stack_guard()->SetStackLimit(limit);
449 }
450 return true;
451 }
452
453
GlobalizeReference(i::Object ** obj)454 i::Object** V8::GlobalizeReference(i::Object** obj) {
455 i::Isolate* isolate = i::Isolate::Current();
456 if (IsDeadCheck(isolate, "V8::Persistent::New")) return NULL;
457 LOG_API(isolate, "Persistent::New");
458 i::Handle<i::Object> result =
459 isolate->global_handles()->Create(*obj);
460 return result.location();
461 }
462
463
MakeWeak(i::Object ** object,void * parameters,WeakReferenceCallback callback)464 void V8::MakeWeak(i::Object** object, void* parameters,
465 WeakReferenceCallback callback) {
466 i::Isolate* isolate = i::Isolate::Current();
467 LOG_API(isolate, "MakeWeak");
468 isolate->global_handles()->MakeWeak(object, parameters,
469 callback);
470 }
471
472
ClearWeak(i::Object ** obj)473 void V8::ClearWeak(i::Object** obj) {
474 i::Isolate* isolate = i::Isolate::Current();
475 LOG_API(isolate, "ClearWeak");
476 isolate->global_handles()->ClearWeakness(obj);
477 }
478
479
IsGlobalNearDeath(i::Object ** obj)480 bool V8::IsGlobalNearDeath(i::Object** obj) {
481 i::Isolate* isolate = i::Isolate::Current();
482 LOG_API(isolate, "IsGlobalNearDeath");
483 if (!isolate->IsInitialized()) return false;
484 return i::GlobalHandles::IsNearDeath(obj);
485 }
486
487
IsGlobalWeak(i::Object ** obj)488 bool V8::IsGlobalWeak(i::Object** obj) {
489 i::Isolate* isolate = i::Isolate::Current();
490 LOG_API(isolate, "IsGlobalWeak");
491 if (!isolate->IsInitialized()) return false;
492 return i::GlobalHandles::IsWeak(obj);
493 }
494
495
DisposeGlobal(i::Object ** obj)496 void V8::DisposeGlobal(i::Object** obj) {
497 i::Isolate* isolate = i::Isolate::Current();
498 LOG_API(isolate, "DisposeGlobal");
499 if (!isolate->IsInitialized()) return;
500 isolate->global_handles()->Destroy(obj);
501 }
502
503 // --- H a n d l e s ---
504
505
HandleScope()506 HandleScope::HandleScope() {
507 API_ENTRY_CHECK("HandleScope::HandleScope");
508 i::Isolate* isolate = i::Isolate::Current();
509 v8::ImplementationUtilities::HandleScopeData* current =
510 isolate->handle_scope_data();
511 isolate_ = isolate;
512 prev_next_ = current->next;
513 prev_limit_ = current->limit;
514 is_closed_ = false;
515 current->level++;
516 }
517
518
~HandleScope()519 HandleScope::~HandleScope() {
520 if (!is_closed_) {
521 Leave();
522 }
523 }
524
525
Leave()526 void HandleScope::Leave() {
527 ASSERT(isolate_ == i::Isolate::Current());
528 v8::ImplementationUtilities::HandleScopeData* current =
529 isolate_->handle_scope_data();
530 current->level--;
531 ASSERT(current->level >= 0);
532 current->next = prev_next_;
533 if (current->limit != prev_limit_) {
534 current->limit = prev_limit_;
535 i::HandleScope::DeleteExtensions(isolate_);
536 }
537
538 #ifdef DEBUG
539 i::HandleScope::ZapRange(prev_next_, prev_limit_);
540 #endif
541 }
542
543
NumberOfHandles()544 int HandleScope::NumberOfHandles() {
545 EnsureInitializedForIsolate(
546 i::Isolate::Current(), "HandleScope::NumberOfHandles");
547 return i::HandleScope::NumberOfHandles();
548 }
549
550
CreateHandle(i::Object * value)551 i::Object** HandleScope::CreateHandle(i::Object* value) {
552 return i::HandleScope::CreateHandle(value, i::Isolate::Current());
553 }
554
555
CreateHandle(i::HeapObject * value)556 i::Object** HandleScope::CreateHandle(i::HeapObject* value) {
557 ASSERT(value->IsHeapObject());
558 return reinterpret_cast<i::Object**>(
559 i::HandleScope::CreateHandle(value, value->GetIsolate()));
560 }
561
562
Enter()563 void Context::Enter() {
564 // TODO(isolates): Context should have a pointer to isolate.
565 i::Isolate* isolate = i::Isolate::Current();
566 if (IsDeadCheck(isolate, "v8::Context::Enter()")) return;
567 ENTER_V8(isolate);
568
569 i::Handle<i::Context> env = Utils::OpenHandle(this);
570 isolate->handle_scope_implementer()->EnterContext(env);
571
572 isolate->handle_scope_implementer()->SaveContext(isolate->context());
573 isolate->set_context(*env);
574 }
575
576
Exit()577 void Context::Exit() {
578 // TODO(isolates): Context should have a pointer to isolate.
579 i::Isolate* isolate = i::Isolate::Current();
580 if (!isolate->IsInitialized()) return;
581
582 if (!ApiCheck(isolate->handle_scope_implementer()->LeaveLastContext(),
583 "v8::Context::Exit()",
584 "Cannot exit non-entered context")) {
585 return;
586 }
587
588 // Content of 'last_context' could be NULL.
589 i::Context* last_context =
590 isolate->handle_scope_implementer()->RestoreContext();
591 isolate->set_context(last_context);
592 }
593
594
SetData(v8::Handle<String> data)595 void Context::SetData(v8::Handle<String> data) {
596 // TODO(isolates): Context should have a pointer to isolate.
597 i::Isolate* isolate = i::Isolate::Current();
598 if (IsDeadCheck(isolate, "v8::Context::SetData()")) return;
599 ENTER_V8(isolate);
600 {
601 i::HandleScope scope(isolate);
602 i::Handle<i::Context> env = Utils::OpenHandle(this);
603 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
604 ASSERT(env->IsGlobalContext());
605 if (env->IsGlobalContext()) {
606 env->set_data(*raw_data);
607 }
608 }
609 }
610
611
GetData()612 v8::Local<v8::Value> Context::GetData() {
613 // TODO(isolates): Context should have a pointer to isolate.
614 i::Isolate* isolate = i::Isolate::Current();
615 if (IsDeadCheck(isolate, "v8::Context::GetData()")) {
616 return v8::Local<Value>();
617 }
618 ENTER_V8(isolate);
619 i::Object* raw_result = NULL;
620 {
621 i::HandleScope scope(isolate);
622 i::Handle<i::Context> env = Utils::OpenHandle(this);
623 ASSERT(env->IsGlobalContext());
624 if (env->IsGlobalContext()) {
625 raw_result = env->data();
626 } else {
627 return Local<Value>();
628 }
629 }
630 i::Handle<i::Object> result(raw_result);
631 return Utils::ToLocal(result);
632 }
633
634
RawClose(i::Object ** value)635 i::Object** v8::HandleScope::RawClose(i::Object** value) {
636 if (!ApiCheck(!is_closed_,
637 "v8::HandleScope::Close()",
638 "Local scope has already been closed")) {
639 return 0;
640 }
641 LOG_API(isolate_, "CloseHandleScope");
642
643 // Read the result before popping the handle block.
644 i::Object* result = NULL;
645 if (value != NULL) {
646 result = *value;
647 }
648 is_closed_ = true;
649 Leave();
650
651 if (value == NULL) {
652 return NULL;
653 }
654
655 // Allocate a new handle on the previous handle block.
656 i::Handle<i::Object> handle(result);
657 return handle.location();
658 }
659
660
661 // --- N e a n d e r ---
662
663
664 // A constructor cannot easily return an error value, therefore it is necessary
665 // to check for a dead VM with ON_BAILOUT before constructing any Neander
666 // objects. To remind you about this there is no HandleScope in the
667 // NeanderObject constructor. When you add one to the site calling the
668 // constructor you should check that you ensured the VM was not dead first.
NeanderObject(int size)669 NeanderObject::NeanderObject(int size) {
670 i::Isolate* isolate = i::Isolate::Current();
671 EnsureInitializedForIsolate(isolate, "v8::Nowhere");
672 ENTER_V8(isolate);
673 value_ = isolate->factory()->NewNeanderObject();
674 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
675 value_->set_elements(*elements);
676 }
677
678
size()679 int NeanderObject::size() {
680 return i::FixedArray::cast(value_->elements())->length();
681 }
682
683
NeanderArray()684 NeanderArray::NeanderArray() : obj_(2) {
685 obj_.set(0, i::Smi::FromInt(0));
686 }
687
688
length()689 int NeanderArray::length() {
690 return i::Smi::cast(obj_.get(0))->value();
691 }
692
693
get(int offset)694 i::Object* NeanderArray::get(int offset) {
695 ASSERT(0 <= offset);
696 ASSERT(offset < length());
697 return obj_.get(offset + 1);
698 }
699
700
701 // This method cannot easily return an error value, therefore it is necessary
702 // to check for a dead VM with ON_BAILOUT before calling it. To remind you
703 // about this there is no HandleScope in this method. When you add one to the
704 // site calling this method you should check that you ensured the VM was not
705 // dead first.
add(i::Handle<i::Object> value)706 void NeanderArray::add(i::Handle<i::Object> value) {
707 int length = this->length();
708 int size = obj_.size();
709 if (length == size - 1) {
710 i::Handle<i::FixedArray> new_elms = FACTORY->NewFixedArray(2 * size);
711 for (int i = 0; i < length; i++)
712 new_elms->set(i + 1, get(i));
713 obj_.value()->set_elements(*new_elms);
714 }
715 obj_.set(length + 1, *value);
716 obj_.set(0, i::Smi::FromInt(length + 1));
717 }
718
719
set(int index,i::Object * value)720 void NeanderArray::set(int index, i::Object* value) {
721 if (index < 0 || index >= this->length()) return;
722 obj_.set(index + 1, value);
723 }
724
725
726 // --- T e m p l a t e ---
727
728
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)729 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
730 that->set_tag(i::Smi::FromInt(type));
731 }
732
733
Set(v8::Handle<String> name,v8::Handle<Data> value,v8::PropertyAttribute attribute)734 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
735 v8::PropertyAttribute attribute) {
736 i::Isolate* isolate = i::Isolate::Current();
737 if (IsDeadCheck(isolate, "v8::Template::Set()")) return;
738 ENTER_V8(isolate);
739 i::HandleScope scope(isolate);
740 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
741 if (list->IsUndefined()) {
742 list = NeanderArray().value();
743 Utils::OpenHandle(this)->set_property_list(*list);
744 }
745 NeanderArray array(list);
746 array.add(Utils::OpenHandle(*name));
747 array.add(Utils::OpenHandle(*value));
748 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
749 }
750
751
752 // --- F u n c t i o n T e m p l a t e ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)753 static void InitializeFunctionTemplate(
754 i::Handle<i::FunctionTemplateInfo> info) {
755 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
756 info->set_flag(0);
757 }
758
759
PrototypeTemplate()760 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
761 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
762 if (IsDeadCheck(isolate, "v8::FunctionTemplate::PrototypeTemplate()")) {
763 return Local<ObjectTemplate>();
764 }
765 ENTER_V8(isolate);
766 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
767 if (result->IsUndefined()) {
768 result = Utils::OpenHandle(*ObjectTemplate::New());
769 Utils::OpenHandle(this)->set_prototype_template(*result);
770 }
771 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
772 }
773
774
Inherit(v8::Handle<FunctionTemplate> value)775 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
776 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
777 if (IsDeadCheck(isolate, "v8::FunctionTemplate::Inherit()")) return;
778 ENTER_V8(isolate);
779 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
780 }
781
782
New(InvocationCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature)783 Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
784 v8::Handle<Value> data, v8::Handle<Signature> signature) {
785 i::Isolate* isolate = i::Isolate::Current();
786 EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
787 LOG_API(isolate, "FunctionTemplate::New");
788 ENTER_V8(isolate);
789 i::Handle<i::Struct> struct_obj =
790 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
791 i::Handle<i::FunctionTemplateInfo> obj =
792 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
793 InitializeFunctionTemplate(obj);
794 int next_serial_number = isolate->next_serial_number();
795 isolate->set_next_serial_number(next_serial_number + 1);
796 obj->set_serial_number(i::Smi::FromInt(next_serial_number));
797 if (callback != 0) {
798 if (data.IsEmpty()) data = v8::Undefined();
799 Utils::ToLocal(obj)->SetCallHandler(callback, data);
800 }
801 obj->set_undetectable(false);
802 obj->set_needs_access_check(false);
803
804 if (!signature.IsEmpty())
805 obj->set_signature(*Utils::OpenHandle(*signature));
806 return Utils::ToLocal(obj);
807 }
808
809
New(Handle<FunctionTemplate> receiver,int argc,Handle<FunctionTemplate> argv[])810 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
811 int argc, Handle<FunctionTemplate> argv[]) {
812 i::Isolate* isolate = i::Isolate::Current();
813 EnsureInitializedForIsolate(isolate, "v8::Signature::New()");
814 LOG_API(isolate, "Signature::New");
815 ENTER_V8(isolate);
816 i::Handle<i::Struct> struct_obj =
817 isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
818 i::Handle<i::SignatureInfo> obj =
819 i::Handle<i::SignatureInfo>::cast(struct_obj);
820 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
821 if (argc > 0) {
822 i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc);
823 for (int i = 0; i < argc; i++) {
824 if (!argv[i].IsEmpty())
825 args->set(i, *Utils::OpenHandle(*argv[i]));
826 }
827 obj->set_args(*args);
828 }
829 return Utils::ToLocal(obj);
830 }
831
832
New(Handle<FunctionTemplate> type)833 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
834 Handle<FunctionTemplate> types[1] = { type };
835 return TypeSwitch::New(1, types);
836 }
837
838
New(int argc,Handle<FunctionTemplate> types[])839 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
840 i::Isolate* isolate = i::Isolate::Current();
841 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
842 LOG_API(isolate, "TypeSwitch::New");
843 ENTER_V8(isolate);
844 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
845 for (int i = 0; i < argc; i++)
846 vector->set(i, *Utils::OpenHandle(*types[i]));
847 i::Handle<i::Struct> struct_obj =
848 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
849 i::Handle<i::TypeSwitchInfo> obj =
850 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
851 obj->set_types(*vector);
852 return Utils::ToLocal(obj);
853 }
854
855
match(v8::Handle<Value> value)856 int TypeSwitch::match(v8::Handle<Value> value) {
857 i::Isolate* isolate = i::Isolate::Current();
858 LOG_API(isolate, "TypeSwitch::match");
859 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
860 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
861 i::FixedArray* types = i::FixedArray::cast(info->types());
862 for (int i = 0; i < types->length(); i++) {
863 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
864 return i + 1;
865 }
866 return 0;
867 }
868
869
870 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
871 i::Handle<i::Object> proxy = FromCData(cdata); \
872 (obj)->setter(*proxy); \
873 } while (false)
874
875
SetCallHandler(InvocationCallback callback,v8::Handle<Value> data)876 void FunctionTemplate::SetCallHandler(InvocationCallback callback,
877 v8::Handle<Value> data) {
878 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
879 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetCallHandler()")) return;
880 ENTER_V8(isolate);
881 i::HandleScope scope(isolate);
882 i::Handle<i::Struct> struct_obj =
883 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
884 i::Handle<i::CallHandlerInfo> obj =
885 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
886 SET_FIELD_WRAPPED(obj, set_callback, callback);
887 if (data.IsEmpty()) data = v8::Undefined();
888 obj->set_data(*Utils::OpenHandle(*data));
889 Utils::OpenHandle(this)->set_call_code(*obj);
890 }
891
892
MakeAccessorInfo(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes)893 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
894 v8::Handle<String> name,
895 AccessorGetter getter,
896 AccessorSetter setter,
897 v8::Handle<Value> data,
898 v8::AccessControl settings,
899 v8::PropertyAttribute attributes) {
900 i::Handle<i::AccessorInfo> obj = FACTORY->NewAccessorInfo();
901 ASSERT(getter != NULL);
902 SET_FIELD_WRAPPED(obj, set_getter, getter);
903 SET_FIELD_WRAPPED(obj, set_setter, setter);
904 if (data.IsEmpty()) data = v8::Undefined();
905 obj->set_data(*Utils::OpenHandle(*data));
906 obj->set_name(*Utils::OpenHandle(*name));
907 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
908 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
909 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
910 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
911 return obj;
912 }
913
914
AddInstancePropertyAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes)915 void FunctionTemplate::AddInstancePropertyAccessor(
916 v8::Handle<String> name,
917 AccessorGetter getter,
918 AccessorSetter setter,
919 v8::Handle<Value> data,
920 v8::AccessControl settings,
921 v8::PropertyAttribute attributes) {
922 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
923 if (IsDeadCheck(isolate,
924 "v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
925 return;
926 }
927 ENTER_V8(isolate);
928 i::HandleScope scope(isolate);
929
930 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
931 getter, setter, data,
932 settings, attributes);
933 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
934 if (list->IsUndefined()) {
935 list = NeanderArray().value();
936 Utils::OpenHandle(this)->set_property_accessors(*list);
937 }
938 NeanderArray array(list);
939 array.add(obj);
940 }
941
942
InstanceTemplate()943 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
944 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
945 if (IsDeadCheck(isolate, "v8::FunctionTemplate::InstanceTemplate()")
946 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
947 return Local<ObjectTemplate>();
948 ENTER_V8(isolate);
949 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
950 Local<ObjectTemplate> templ =
951 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
952 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
953 }
954 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
955 Utils::OpenHandle(this)->instance_template()));
956 return Utils::ToLocal(result);
957 }
958
959
SetClassName(Handle<String> name)960 void FunctionTemplate::SetClassName(Handle<String> name) {
961 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
962 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetClassName()")) return;
963 ENTER_V8(isolate);
964 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
965 }
966
967
SetHiddenPrototype(bool value)968 void FunctionTemplate::SetHiddenPrototype(bool value) {
969 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
970 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetHiddenPrototype()")) {
971 return;
972 }
973 ENTER_V8(isolate);
974 Utils::OpenHandle(this)->set_hidden_prototype(value);
975 }
976
977
SetNamedInstancePropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)978 void FunctionTemplate::SetNamedInstancePropertyHandler(
979 NamedPropertyGetter getter,
980 NamedPropertySetter setter,
981 NamedPropertyQuery query,
982 NamedPropertyDeleter remover,
983 NamedPropertyEnumerator enumerator,
984 Handle<Value> data) {
985 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
986 if (IsDeadCheck(isolate,
987 "v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
988 return;
989 }
990 ENTER_V8(isolate);
991 i::HandleScope scope(isolate);
992 i::Handle<i::Struct> struct_obj =
993 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
994 i::Handle<i::InterceptorInfo> obj =
995 i::Handle<i::InterceptorInfo>::cast(struct_obj);
996
997 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
998 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
999 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1000 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1001 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1002
1003 if (data.IsEmpty()) data = v8::Undefined();
1004 obj->set_data(*Utils::OpenHandle(*data));
1005 Utils::OpenHandle(this)->set_named_property_handler(*obj);
1006 }
1007
1008
SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)1009 void FunctionTemplate::SetIndexedInstancePropertyHandler(
1010 IndexedPropertyGetter getter,
1011 IndexedPropertySetter setter,
1012 IndexedPropertyQuery query,
1013 IndexedPropertyDeleter remover,
1014 IndexedPropertyEnumerator enumerator,
1015 Handle<Value> data) {
1016 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1017 if (IsDeadCheck(isolate,
1018 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
1019 return;
1020 }
1021 ENTER_V8(isolate);
1022 i::HandleScope scope(isolate);
1023 i::Handle<i::Struct> struct_obj =
1024 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1025 i::Handle<i::InterceptorInfo> obj =
1026 i::Handle<i::InterceptorInfo>::cast(struct_obj);
1027
1028 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1029 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1030 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1031 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1032 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1033
1034 if (data.IsEmpty()) data = v8::Undefined();
1035 obj->set_data(*Utils::OpenHandle(*data));
1036 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
1037 }
1038
1039
SetInstanceCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)1040 void FunctionTemplate::SetInstanceCallAsFunctionHandler(
1041 InvocationCallback callback,
1042 Handle<Value> data) {
1043 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1044 if (IsDeadCheck(isolate,
1045 "v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
1046 return;
1047 }
1048 ENTER_V8(isolate);
1049 i::HandleScope scope(isolate);
1050 i::Handle<i::Struct> struct_obj =
1051 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1052 i::Handle<i::CallHandlerInfo> obj =
1053 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1054 SET_FIELD_WRAPPED(obj, set_callback, callback);
1055 if (data.IsEmpty()) data = v8::Undefined();
1056 obj->set_data(*Utils::OpenHandle(*data));
1057 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
1058 }
1059
1060
1061 // --- O b j e c t T e m p l a t e ---
1062
1063
New()1064 Local<ObjectTemplate> ObjectTemplate::New() {
1065 return New(Local<FunctionTemplate>());
1066 }
1067
1068
New(v8::Handle<FunctionTemplate> constructor)1069 Local<ObjectTemplate> ObjectTemplate::New(
1070 v8::Handle<FunctionTemplate> constructor) {
1071 i::Isolate* isolate = i::Isolate::Current();
1072 if (IsDeadCheck(isolate, "v8::ObjectTemplate::New()")) {
1073 return Local<ObjectTemplate>();
1074 }
1075 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
1076 LOG_API(isolate, "ObjectTemplate::New");
1077 ENTER_V8(isolate);
1078 i::Handle<i::Struct> struct_obj =
1079 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1080 i::Handle<i::ObjectTemplateInfo> obj =
1081 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1082 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1083 if (!constructor.IsEmpty())
1084 obj->set_constructor(*Utils::OpenHandle(*constructor));
1085 obj->set_internal_field_count(i::Smi::FromInt(0));
1086 return Utils::ToLocal(obj);
1087 }
1088
1089
1090 // Ensure that the object template has a constructor. If no
1091 // constructor is available we create one.
EnsureConstructor(ObjectTemplate * object_template)1092 static void EnsureConstructor(ObjectTemplate* object_template) {
1093 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
1094 Local<FunctionTemplate> templ = FunctionTemplate::New();
1095 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1096 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1097 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1098 }
1099 }
1100
1101
SetAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute)1102 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1103 AccessorGetter getter,
1104 AccessorSetter setter,
1105 v8::Handle<Value> data,
1106 AccessControl settings,
1107 PropertyAttribute attribute) {
1108 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1109 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return;
1110 ENTER_V8(isolate);
1111 i::HandleScope scope(isolate);
1112 EnsureConstructor(this);
1113 i::FunctionTemplateInfo* constructor =
1114 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1115 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1116 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1117 getter,
1118 setter,
1119 data,
1120 settings,
1121 attribute);
1122 }
1123
1124
SetNamedPropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)1125 void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1126 NamedPropertySetter setter,
1127 NamedPropertyQuery query,
1128 NamedPropertyDeleter remover,
1129 NamedPropertyEnumerator enumerator,
1130 Handle<Value> data) {
1131 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1132 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) {
1133 return;
1134 }
1135 ENTER_V8(isolate);
1136 i::HandleScope scope(isolate);
1137 EnsureConstructor(this);
1138 i::FunctionTemplateInfo* constructor =
1139 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1140 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1141 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1142 setter,
1143 query,
1144 remover,
1145 enumerator,
1146 data);
1147 }
1148
1149
MarkAsUndetectable()1150 void ObjectTemplate::MarkAsUndetectable() {
1151 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1152 if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUndetectable()")) return;
1153 ENTER_V8(isolate);
1154 i::HandleScope scope(isolate);
1155 EnsureConstructor(this);
1156 i::FunctionTemplateInfo* constructor =
1157 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1158 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1159 cons->set_undetectable(true);
1160 }
1161
1162
SetAccessCheckCallbacks(NamedSecurityCallback named_callback,IndexedSecurityCallback indexed_callback,Handle<Value> data,bool turned_on_by_default)1163 void ObjectTemplate::SetAccessCheckCallbacks(
1164 NamedSecurityCallback named_callback,
1165 IndexedSecurityCallback indexed_callback,
1166 Handle<Value> data,
1167 bool turned_on_by_default) {
1168 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1169 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessCheckCallbacks()")) {
1170 return;
1171 }
1172 ENTER_V8(isolate);
1173 i::HandleScope scope(isolate);
1174 EnsureConstructor(this);
1175
1176 i::Handle<i::Struct> struct_info =
1177 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1178 i::Handle<i::AccessCheckInfo> info =
1179 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1180
1181 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1182 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1183
1184 if (data.IsEmpty()) data = v8::Undefined();
1185 info->set_data(*Utils::OpenHandle(*data));
1186
1187 i::FunctionTemplateInfo* constructor =
1188 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1189 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1190 cons->set_access_check_info(*info);
1191 cons->set_needs_access_check(turned_on_by_default);
1192 }
1193
1194
SetIndexedPropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)1195 void ObjectTemplate::SetIndexedPropertyHandler(
1196 IndexedPropertyGetter getter,
1197 IndexedPropertySetter setter,
1198 IndexedPropertyQuery query,
1199 IndexedPropertyDeleter remover,
1200 IndexedPropertyEnumerator enumerator,
1201 Handle<Value> data) {
1202 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1203 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetIndexedPropertyHandler()")) {
1204 return;
1205 }
1206 ENTER_V8(isolate);
1207 i::HandleScope scope(isolate);
1208 EnsureConstructor(this);
1209 i::FunctionTemplateInfo* constructor =
1210 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1211 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1212 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1213 setter,
1214 query,
1215 remover,
1216 enumerator,
1217 data);
1218 }
1219
1220
SetCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)1221 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1222 Handle<Value> data) {
1223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1224 if (IsDeadCheck(isolate,
1225 "v8::ObjectTemplate::SetCallAsFunctionHandler()")) {
1226 return;
1227 }
1228 ENTER_V8(isolate);
1229 i::HandleScope scope(isolate);
1230 EnsureConstructor(this);
1231 i::FunctionTemplateInfo* constructor =
1232 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1233 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1234 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1235 }
1236
1237
InternalFieldCount()1238 int ObjectTemplate::InternalFieldCount() {
1239 if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(),
1240 "v8::ObjectTemplate::InternalFieldCount()")) {
1241 return 0;
1242 }
1243 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1244 }
1245
1246
SetInternalFieldCount(int value)1247 void ObjectTemplate::SetInternalFieldCount(int value) {
1248 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1249 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetInternalFieldCount()")) {
1250 return;
1251 }
1252 if (!ApiCheck(i::Smi::IsValid(value),
1253 "v8::ObjectTemplate::SetInternalFieldCount()",
1254 "Invalid internal field count")) {
1255 return;
1256 }
1257 ENTER_V8(isolate);
1258 if (value > 0) {
1259 // The internal field count is set by the constructor function's
1260 // construct code, so we ensure that there is a constructor
1261 // function to do the setting.
1262 EnsureConstructor(this);
1263 }
1264 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1265 }
1266
1267
1268 // --- S c r i p t D a t a ---
1269
1270
PreCompile(const char * input,int length)1271 ScriptData* ScriptData::PreCompile(const char* input, int length) {
1272 i::Utf8ToUC16CharacterStream stream(
1273 reinterpret_cast<const unsigned char*>(input), length);
1274 return i::ParserApi::PreParse(&stream, NULL);
1275 }
1276
1277
PreCompile(v8::Handle<String> source)1278 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1279 i::Handle<i::String> str = Utils::OpenHandle(*source);
1280 if (str->IsExternalTwoByteString()) {
1281 i::ExternalTwoByteStringUC16CharacterStream stream(
1282 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
1283 return i::ParserApi::PreParse(&stream, NULL);
1284 } else {
1285 i::GenericStringUC16CharacterStream stream(str, 0, str->length());
1286 return i::ParserApi::PreParse(&stream, NULL);
1287 }
1288 }
1289
1290
New(const char * data,int length)1291 ScriptData* ScriptData::New(const char* data, int length) {
1292 // Return an empty ScriptData if the length is obviously invalid.
1293 if (length % sizeof(unsigned) != 0) {
1294 return new i::ScriptDataImpl();
1295 }
1296
1297 // Copy the data to ensure it is properly aligned.
1298 int deserialized_data_length = length / sizeof(unsigned);
1299 // If aligned, don't create a copy of the data.
1300 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1301 return new i::ScriptDataImpl(data, length);
1302 }
1303 // Copy the data to align it.
1304 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
1305 i::OS::MemCopy(deserialized_data, data, length);
1306
1307 return new i::ScriptDataImpl(
1308 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
1309 }
1310
1311
1312 // --- S c r i p t ---
1313
1314
New(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * pre_data,v8::Handle<String> script_data)1315 Local<Script> Script::New(v8::Handle<String> source,
1316 v8::ScriptOrigin* origin,
1317 v8::ScriptData* pre_data,
1318 v8::Handle<String> script_data) {
1319 i::Isolate* isolate = i::Isolate::Current();
1320 ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
1321 LOG_API(isolate, "Script::New");
1322 ENTER_V8(isolate);
1323 i::Handle<i::String> str = Utils::OpenHandle(*source);
1324 i::Handle<i::Object> name_obj;
1325 int line_offset = 0;
1326 int column_offset = 0;
1327 if (origin != NULL) {
1328 if (!origin->ResourceName().IsEmpty()) {
1329 name_obj = Utils::OpenHandle(*origin->ResourceName());
1330 }
1331 if (!origin->ResourceLineOffset().IsEmpty()) {
1332 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1333 }
1334 if (!origin->ResourceColumnOffset().IsEmpty()) {
1335 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1336 }
1337 }
1338 EXCEPTION_PREAMBLE(isolate);
1339 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
1340 // We assert that the pre-data is sane, even though we can actually
1341 // handle it if it turns out not to be in release mode.
1342 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
1343 // If the pre-data isn't sane we simply ignore it
1344 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1345 pre_data_impl = NULL;
1346 }
1347 i::Handle<i::SharedFunctionInfo> result =
1348 i::Compiler::Compile(str,
1349 name_obj,
1350 line_offset,
1351 column_offset,
1352 NULL,
1353 pre_data_impl,
1354 Utils::OpenHandle(*script_data),
1355 i::NOT_NATIVES_CODE);
1356 has_pending_exception = result.is_null();
1357 EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
1358 return Local<Script>(ToApi<Script>(result));
1359 }
1360
1361
New(v8::Handle<String> source,v8::Handle<Value> file_name)1362 Local<Script> Script::New(v8::Handle<String> source,
1363 v8::Handle<Value> file_name) {
1364 ScriptOrigin origin(file_name);
1365 return New(source, &origin);
1366 }
1367
1368
Compile(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * pre_data,v8::Handle<String> script_data)1369 Local<Script> Script::Compile(v8::Handle<String> source,
1370 v8::ScriptOrigin* origin,
1371 v8::ScriptData* pre_data,
1372 v8::Handle<String> script_data) {
1373 i::Isolate* isolate = i::Isolate::Current();
1374 ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>());
1375 LOG_API(isolate, "Script::Compile");
1376 ENTER_V8(isolate);
1377 Local<Script> generic = New(source, origin, pre_data, script_data);
1378 if (generic.IsEmpty())
1379 return generic;
1380 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1381 i::Handle<i::SharedFunctionInfo> function =
1382 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1383 i::Handle<i::JSFunction> result =
1384 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1385 function,
1386 isolate->global_context());
1387 return Local<Script>(ToApi<Script>(result));
1388 }
1389
1390
Compile(v8::Handle<String> source,v8::Handle<Value> file_name,v8::Handle<String> script_data)1391 Local<Script> Script::Compile(v8::Handle<String> source,
1392 v8::Handle<Value> file_name,
1393 v8::Handle<String> script_data) {
1394 ScriptOrigin origin(file_name);
1395 return Compile(source, &origin, 0, script_data);
1396 }
1397
1398
Run()1399 Local<Value> Script::Run() {
1400 i::Isolate* isolate = i::Isolate::Current();
1401 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1402 LOG_API(isolate, "Script::Run");
1403 ENTER_V8(isolate);
1404 i::Object* raw_result = NULL;
1405 {
1406 i::HandleScope scope(isolate);
1407 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1408 i::Handle<i::JSFunction> fun;
1409 if (obj->IsSharedFunctionInfo()) {
1410 i::Handle<i::SharedFunctionInfo>
1411 function_info(i::SharedFunctionInfo::cast(*obj), isolate);
1412 fun = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1413 function_info, isolate->global_context());
1414 } else {
1415 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
1416 }
1417 EXCEPTION_PREAMBLE(isolate);
1418 i::Handle<i::Object> receiver(
1419 isolate->context()->global_proxy(), isolate);
1420 i::Handle<i::Object> result =
1421 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1422 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
1423 raw_result = *result;
1424 }
1425 i::Handle<i::Object> result(raw_result, isolate);
1426 return Utils::ToLocal(result);
1427 }
1428
1429
OpenScript(Script * script)1430 static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1431 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1432 i::Handle<i::SharedFunctionInfo> result;
1433 if (obj->IsSharedFunctionInfo()) {
1434 result =
1435 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1436 } else {
1437 result =
1438 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1439 }
1440 return result;
1441 }
1442
1443
Id()1444 Local<Value> Script::Id() {
1445 i::Isolate* isolate = i::Isolate::Current();
1446 ON_BAILOUT(isolate, "v8::Script::Id()", return Local<Value>());
1447 LOG_API(isolate, "Script::Id");
1448 i::Object* raw_id = NULL;
1449 {
1450 i::HandleScope scope(isolate);
1451 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1452 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1453 i::Handle<i::Object> id(script->id());
1454 raw_id = *id;
1455 }
1456 i::Handle<i::Object> id(raw_id);
1457 return Utils::ToLocal(id);
1458 }
1459
1460
SetData(v8::Handle<String> data)1461 void Script::SetData(v8::Handle<String> data) {
1462 i::Isolate* isolate = i::Isolate::Current();
1463 ON_BAILOUT(isolate, "v8::Script::SetData()", return);
1464 LOG_API(isolate, "Script::SetData");
1465 {
1466 i::HandleScope scope(isolate);
1467 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1468 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1469 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1470 script->set_data(*raw_data);
1471 }
1472 }
1473
1474
1475 // --- E x c e p t i o n s ---
1476
1477
TryCatch()1478 v8::TryCatch::TryCatch()
1479 : next_(i::Isolate::Current()->try_catch_handler_address()),
1480 exception_(HEAP->the_hole_value()),
1481 message_(i::Smi::FromInt(0)),
1482 is_verbose_(false),
1483 can_continue_(true),
1484 capture_message_(true),
1485 rethrow_(false) {
1486 i::Isolate::Current()->RegisterTryCatchHandler(this);
1487 }
1488
1489
~TryCatch()1490 v8::TryCatch::~TryCatch() {
1491 i::Isolate* isolate = i::Isolate::Current();
1492 if (rethrow_) {
1493 v8::HandleScope scope;
1494 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1495 isolate->UnregisterTryCatchHandler(this);
1496 v8::ThrowException(exc);
1497 } else {
1498 isolate->UnregisterTryCatchHandler(this);
1499 }
1500 }
1501
1502
HasCaught() const1503 bool v8::TryCatch::HasCaught() const {
1504 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1505 }
1506
1507
CanContinue() const1508 bool v8::TryCatch::CanContinue() const {
1509 return can_continue_;
1510 }
1511
1512
ReThrow()1513 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1514 if (!HasCaught()) return v8::Local<v8::Value>();
1515 rethrow_ = true;
1516 return v8::Undefined();
1517 }
1518
1519
Exception() const1520 v8::Local<Value> v8::TryCatch::Exception() const {
1521 if (HasCaught()) {
1522 // Check for out of memory exception.
1523 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1524 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1525 } else {
1526 return v8::Local<Value>();
1527 }
1528 }
1529
1530
StackTrace() const1531 v8::Local<Value> v8::TryCatch::StackTrace() const {
1532 if (HasCaught()) {
1533 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1534 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1535 v8::HandleScope scope;
1536 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1537 i::Handle<i::String> name = FACTORY->LookupAsciiSymbol("stack");
1538 if (!obj->HasProperty(*name))
1539 return v8::Local<Value>();
1540 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1541 } else {
1542 return v8::Local<Value>();
1543 }
1544 }
1545
1546
Message() const1547 v8::Local<v8::Message> v8::TryCatch::Message() const {
1548 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1549 i::Object* message = reinterpret_cast<i::Object*>(message_);
1550 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1551 } else {
1552 return v8::Local<v8::Message>();
1553 }
1554 }
1555
1556
Reset()1557 void v8::TryCatch::Reset() {
1558 exception_ = HEAP->the_hole_value();
1559 message_ = i::Smi::FromInt(0);
1560 }
1561
1562
SetVerbose(bool value)1563 void v8::TryCatch::SetVerbose(bool value) {
1564 is_verbose_ = value;
1565 }
1566
1567
SetCaptureMessage(bool value)1568 void v8::TryCatch::SetCaptureMessage(bool value) {
1569 capture_message_ = value;
1570 }
1571
1572
1573 // --- M e s s a g e ---
1574
1575
Get() const1576 Local<String> Message::Get() const {
1577 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1578 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
1579 ENTER_V8(isolate);
1580 HandleScope scope;
1581 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1582 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1583 Local<String> result = Utils::ToLocal(raw_result);
1584 return scope.Close(result);
1585 }
1586
1587
GetScriptResourceName() const1588 v8::Handle<Value> Message::GetScriptResourceName() const {
1589 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1590 if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceName()")) {
1591 return Local<String>();
1592 }
1593 ENTER_V8(isolate);
1594 HandleScope scope;
1595 i::Handle<i::JSMessageObject> message =
1596 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1597 // Return this.script.name.
1598 i::Handle<i::JSValue> script =
1599 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
1600 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1601 return scope.Close(Utils::ToLocal(resource_name));
1602 }
1603
1604
GetScriptData() const1605 v8::Handle<Value> Message::GetScriptData() const {
1606 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1607 if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceData()")) {
1608 return Local<Value>();
1609 }
1610 ENTER_V8(isolate);
1611 HandleScope scope;
1612 i::Handle<i::JSMessageObject> message =
1613 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1614 // Return this.script.data.
1615 i::Handle<i::JSValue> script =
1616 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
1617 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1618 return scope.Close(Utils::ToLocal(data));
1619 }
1620
1621
GetStackTrace() const1622 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1623 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1624 if (IsDeadCheck(isolate, "v8::Message::GetStackTrace()")) {
1625 return Local<v8::StackTrace>();
1626 }
1627 ENTER_V8(isolate);
1628 HandleScope scope;
1629 i::Handle<i::JSMessageObject> message =
1630 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1631 i::Handle<i::Object> stackFramesObj(message->stack_frames());
1632 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1633 i::Handle<i::JSArray> stackTrace =
1634 i::Handle<i::JSArray>::cast(stackFramesObj);
1635 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1636 }
1637
1638
CallV8HeapFunction(const char * name,i::Handle<i::Object> recv,int argc,i::Object ** argv[],bool * has_pending_exception)1639 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1640 i::Handle<i::Object> recv,
1641 int argc,
1642 i::Object** argv[],
1643 bool* has_pending_exception) {
1644 i::Isolate* isolate = i::Isolate::Current();
1645 i::Handle<i::String> fmt_str = isolate->factory()->LookupAsciiSymbol(name);
1646 i::Object* object_fun =
1647 isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str);
1648 i::Handle<i::JSFunction> fun =
1649 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1650 i::Handle<i::Object> value =
1651 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1652 return value;
1653 }
1654
1655
CallV8HeapFunction(const char * name,i::Handle<i::Object> data,bool * has_pending_exception)1656 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1657 i::Handle<i::Object> data,
1658 bool* has_pending_exception) {
1659 i::Object** argv[1] = { data.location() };
1660 return CallV8HeapFunction(name,
1661 i::Isolate::Current()->js_builtins_object(),
1662 1,
1663 argv,
1664 has_pending_exception);
1665 }
1666
1667
GetLineNumber() const1668 int Message::GetLineNumber() const {
1669 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1670 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
1671 ENTER_V8(isolate);
1672 i::HandleScope scope(isolate);
1673
1674 EXCEPTION_PREAMBLE(isolate);
1675 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1676 Utils::OpenHandle(this),
1677 &has_pending_exception);
1678 EXCEPTION_BAILOUT_CHECK(isolate, 0);
1679 return static_cast<int>(result->Number());
1680 }
1681
1682
GetStartPosition() const1683 int Message::GetStartPosition() const {
1684 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1685 if (IsDeadCheck(isolate, "v8::Message::GetStartPosition()")) return 0;
1686 ENTER_V8(isolate);
1687 i::HandleScope scope(isolate);
1688 i::Handle<i::JSMessageObject> message =
1689 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1690 return message->start_position();
1691 }
1692
1693
GetEndPosition() const1694 int Message::GetEndPosition() const {
1695 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1696 if (IsDeadCheck(isolate, "v8::Message::GetEndPosition()")) return 0;
1697 ENTER_V8(isolate);
1698 i::HandleScope scope(isolate);
1699 i::Handle<i::JSMessageObject> message =
1700 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1701 return message->end_position();
1702 }
1703
1704
GetStartColumn() const1705 int Message::GetStartColumn() const {
1706 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1707 if (IsDeadCheck(isolate, "v8::Message::GetStartColumn()")) {
1708 return kNoColumnInfo;
1709 }
1710 ENTER_V8(isolate);
1711 i::HandleScope scope(isolate);
1712 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1713 EXCEPTION_PREAMBLE(isolate);
1714 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1715 "GetPositionInLine",
1716 data_obj,
1717 &has_pending_exception);
1718 EXCEPTION_BAILOUT_CHECK(isolate, 0);
1719 return static_cast<int>(start_col_obj->Number());
1720 }
1721
1722
GetEndColumn() const1723 int Message::GetEndColumn() const {
1724 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1725 if (IsDeadCheck(isolate, "v8::Message::GetEndColumn()")) return kNoColumnInfo;
1726 ENTER_V8(isolate);
1727 i::HandleScope scope(isolate);
1728 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1729 EXCEPTION_PREAMBLE(isolate);
1730 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1731 "GetPositionInLine",
1732 data_obj,
1733 &has_pending_exception);
1734 EXCEPTION_BAILOUT_CHECK(isolate, 0);
1735 i::Handle<i::JSMessageObject> message =
1736 i::Handle<i::JSMessageObject>::cast(data_obj);
1737 int start = message->start_position();
1738 int end = message->end_position();
1739 return static_cast<int>(start_col_obj->Number()) + (end - start);
1740 }
1741
1742
GetSourceLine() const1743 Local<String> Message::GetSourceLine() const {
1744 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1745 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
1746 ENTER_V8(isolate);
1747 HandleScope scope;
1748 EXCEPTION_PREAMBLE(isolate);
1749 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1750 Utils::OpenHandle(this),
1751 &has_pending_exception);
1752 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
1753 if (result->IsString()) {
1754 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1755 } else {
1756 return Local<String>();
1757 }
1758 }
1759
1760
PrintCurrentStackTrace(FILE * out)1761 void Message::PrintCurrentStackTrace(FILE* out) {
1762 i::Isolate* isolate = i::Isolate::Current();
1763 if (IsDeadCheck(isolate, "v8::Message::PrintCurrentStackTrace()")) return;
1764 ENTER_V8(isolate);
1765 isolate->PrintCurrentStackTrace(out);
1766 }
1767
1768
1769 // --- S t a c k T r a c e ---
1770
GetFrame(uint32_t index) const1771 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1772 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1773 if (IsDeadCheck(isolate, "v8::StackTrace::GetFrame()")) {
1774 return Local<StackFrame>();
1775 }
1776 ENTER_V8(isolate);
1777 HandleScope scope;
1778 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1779 i::Object* raw_object = self->GetElementNoExceptionThrown(index);
1780 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
1781 return scope.Close(Utils::StackFrameToLocal(obj));
1782 }
1783
1784
GetFrameCount() const1785 int StackTrace::GetFrameCount() const {
1786 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1787 if (IsDeadCheck(isolate, "v8::StackTrace::GetFrameCount()")) return -1;
1788 ENTER_V8(isolate);
1789 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1790 }
1791
1792
AsArray()1793 Local<Array> StackTrace::AsArray() {
1794 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1795 if (IsDeadCheck(isolate, "v8::StackTrace::AsArray()")) Local<Array>();
1796 ENTER_V8(isolate);
1797 return Utils::ToLocal(Utils::OpenHandle(this));
1798 }
1799
1800
CurrentStackTrace(int frame_limit,StackTraceOptions options)1801 Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1802 StackTraceOptions options) {
1803 i::Isolate* isolate = i::Isolate::Current();
1804 if (IsDeadCheck(isolate, "v8::StackTrace::CurrentStackTrace()")) {
1805 Local<StackTrace>();
1806 }
1807 ENTER_V8(isolate);
1808 i::Handle<i::JSArray> stackTrace =
1809 isolate->CaptureCurrentStackTrace(frame_limit, options);
1810 return Utils::StackTraceToLocal(stackTrace);
1811 }
1812
1813
1814 // --- S t a c k F r a m e ---
1815
GetLineNumber() const1816 int StackFrame::GetLineNumber() const {
1817 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1818 if (IsDeadCheck(isolate, "v8::StackFrame::GetLineNumber()")) {
1819 return Message::kNoLineNumberInfo;
1820 }
1821 ENTER_V8(isolate);
1822 i::HandleScope scope(isolate);
1823 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1824 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1825 if (!line->IsSmi()) {
1826 return Message::kNoLineNumberInfo;
1827 }
1828 return i::Smi::cast(*line)->value();
1829 }
1830
1831
GetColumn() const1832 int StackFrame::GetColumn() const {
1833 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1834 if (IsDeadCheck(isolate, "v8::StackFrame::GetColumn()")) {
1835 return Message::kNoColumnInfo;
1836 }
1837 ENTER_V8(isolate);
1838 i::HandleScope scope(isolate);
1839 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1840 i::Handle<i::Object> column = GetProperty(self, "column");
1841 if (!column->IsSmi()) {
1842 return Message::kNoColumnInfo;
1843 }
1844 return i::Smi::cast(*column)->value();
1845 }
1846
1847
GetScriptName() const1848 Local<String> StackFrame::GetScriptName() const {
1849 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1850 if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptName()")) {
1851 return Local<String>();
1852 }
1853 ENTER_V8(isolate);
1854 HandleScope scope;
1855 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1856 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1857 if (!name->IsString()) {
1858 return Local<String>();
1859 }
1860 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1861 }
1862
1863
GetScriptNameOrSourceURL() const1864 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
1865 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1866 if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptNameOrSourceURL()")) {
1867 return Local<String>();
1868 }
1869 ENTER_V8(isolate);
1870 HandleScope scope;
1871 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1872 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
1873 if (!name->IsString()) {
1874 return Local<String>();
1875 }
1876 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1877 }
1878
1879
GetFunctionName() const1880 Local<String> StackFrame::GetFunctionName() const {
1881 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1882 if (IsDeadCheck(isolate, "v8::StackFrame::GetFunctionName()")) {
1883 return Local<String>();
1884 }
1885 ENTER_V8(isolate);
1886 HandleScope scope;
1887 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1888 i::Handle<i::Object> name = GetProperty(self, "functionName");
1889 if (!name->IsString()) {
1890 return Local<String>();
1891 }
1892 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1893 }
1894
1895
IsEval() const1896 bool StackFrame::IsEval() const {
1897 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1898 if (IsDeadCheck(isolate, "v8::StackFrame::IsEval()")) return false;
1899 ENTER_V8(isolate);
1900 i::HandleScope scope(isolate);
1901 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1902 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1903 return is_eval->IsTrue();
1904 }
1905
1906
IsConstructor() const1907 bool StackFrame::IsConstructor() const {
1908 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1909 if (IsDeadCheck(isolate, "v8::StackFrame::IsConstructor()")) return false;
1910 ENTER_V8(isolate);
1911 i::HandleScope scope(isolate);
1912 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1913 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1914 return is_constructor->IsTrue();
1915 }
1916
1917
1918 // --- D a t a ---
1919
IsUndefined() const1920 bool Value::IsUndefined() const {
1921 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUndefined()")) {
1922 return false;
1923 }
1924 return Utils::OpenHandle(this)->IsUndefined();
1925 }
1926
1927
IsNull() const1928 bool Value::IsNull() const {
1929 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNull()")) return false;
1930 return Utils::OpenHandle(this)->IsNull();
1931 }
1932
1933
IsTrue() const1934 bool Value::IsTrue() const {
1935 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsTrue()")) return false;
1936 return Utils::OpenHandle(this)->IsTrue();
1937 }
1938
1939
IsFalse() const1940 bool Value::IsFalse() const {
1941 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFalse()")) return false;
1942 return Utils::OpenHandle(this)->IsFalse();
1943 }
1944
1945
IsFunction() const1946 bool Value::IsFunction() const {
1947 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFunction()")) {
1948 return false;
1949 }
1950 return Utils::OpenHandle(this)->IsJSFunction();
1951 }
1952
1953
FullIsString() const1954 bool Value::FullIsString() const {
1955 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsString()")) return false;
1956 bool result = Utils::OpenHandle(this)->IsString();
1957 ASSERT_EQ(result, QuickIsString());
1958 return result;
1959 }
1960
1961
IsArray() const1962 bool Value::IsArray() const {
1963 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsArray()")) return false;
1964 return Utils::OpenHandle(this)->IsJSArray();
1965 }
1966
1967
IsObject() const1968 bool Value::IsObject() const {
1969 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsObject()")) return false;
1970 return Utils::OpenHandle(this)->IsJSObject();
1971 }
1972
1973
IsNumber() const1974 bool Value::IsNumber() const {
1975 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNumber()")) return false;
1976 return Utils::OpenHandle(this)->IsNumber();
1977 }
1978
1979
IsBoolean() const1980 bool Value::IsBoolean() const {
1981 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsBoolean()")) {
1982 return false;
1983 }
1984 return Utils::OpenHandle(this)->IsBoolean();
1985 }
1986
1987
IsExternal() const1988 bool Value::IsExternal() const {
1989 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsExternal()")) {
1990 return false;
1991 }
1992 return Utils::OpenHandle(this)->IsProxy();
1993 }
1994
1995
IsInt32() const1996 bool Value::IsInt32() const {
1997 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsInt32()")) return false;
1998 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1999 if (obj->IsSmi()) return true;
2000 if (obj->IsNumber()) {
2001 double value = obj->Number();
2002 return i::FastI2D(i::FastD2I(value)) == value;
2003 }
2004 return false;
2005 }
2006
2007
IsUint32() const2008 bool Value::IsUint32() const {
2009 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUint32()")) return false;
2010 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2011 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2012 if (obj->IsNumber()) {
2013 double value = obj->Number();
2014 return i::FastUI2D(i::FastD2UI(value)) == value;
2015 }
2016 return false;
2017 }
2018
2019
IsDate() const2020 bool Value::IsDate() const {
2021 i::Isolate* isolate = i::Isolate::Current();
2022 if (IsDeadCheck(isolate, "v8::Value::IsDate()")) return false;
2023 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2024 return obj->HasSpecificClassOf(isolate->heap()->Date_symbol());
2025 }
2026
2027
IsRegExp() const2028 bool Value::IsRegExp() const {
2029 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false;
2030 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2031 return obj->IsJSRegExp();
2032 }
2033
2034
ToString() const2035 Local<String> Value::ToString() const {
2036 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2037 i::Handle<i::Object> str;
2038 if (obj->IsString()) {
2039 str = obj;
2040 } else {
2041 i::Isolate* isolate = i::Isolate::Current();
2042 if (IsDeadCheck(isolate, "v8::Value::ToString()")) {
2043 return Local<String>();
2044 }
2045 LOG_API(isolate, "ToString");
2046 ENTER_V8(isolate);
2047 EXCEPTION_PREAMBLE(isolate);
2048 str = i::Execution::ToString(obj, &has_pending_exception);
2049 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2050 }
2051 return Local<String>(ToApi<String>(str));
2052 }
2053
2054
ToDetailString() const2055 Local<String> Value::ToDetailString() const {
2056 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2057 i::Handle<i::Object> str;
2058 if (obj->IsString()) {
2059 str = obj;
2060 } else {
2061 i::Isolate* isolate = i::Isolate::Current();
2062 if (IsDeadCheck(isolate, "v8::Value::ToDetailString()")) {
2063 return Local<String>();
2064 }
2065 LOG_API(isolate, "ToDetailString");
2066 ENTER_V8(isolate);
2067 EXCEPTION_PREAMBLE(isolate);
2068 str = i::Execution::ToDetailString(obj, &has_pending_exception);
2069 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2070 }
2071 return Local<String>(ToApi<String>(str));
2072 }
2073
2074
ToObject() const2075 Local<v8::Object> Value::ToObject() const {
2076 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2077 i::Handle<i::Object> val;
2078 if (obj->IsJSObject()) {
2079 val = obj;
2080 } else {
2081 i::Isolate* isolate = i::Isolate::Current();
2082 if (IsDeadCheck(isolate, "v8::Value::ToObject()")) {
2083 return Local<v8::Object>();
2084 }
2085 LOG_API(isolate, "ToObject");
2086 ENTER_V8(isolate);
2087 EXCEPTION_PREAMBLE(isolate);
2088 val = i::Execution::ToObject(obj, &has_pending_exception);
2089 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2090 }
2091 return Local<v8::Object>(ToApi<Object>(val));
2092 }
2093
2094
ToBoolean() const2095 Local<Boolean> Value::ToBoolean() const {
2096 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2097 if (obj->IsBoolean()) {
2098 return Local<Boolean>(ToApi<Boolean>(obj));
2099 } else {
2100 i::Isolate* isolate = i::Isolate::Current();
2101 if (IsDeadCheck(isolate, "v8::Value::ToBoolean()")) {
2102 return Local<Boolean>();
2103 }
2104 LOG_API(isolate, "ToBoolean");
2105 ENTER_V8(isolate);
2106 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
2107 return Local<Boolean>(ToApi<Boolean>(val));
2108 }
2109 }
2110
2111
ToNumber() const2112 Local<Number> Value::ToNumber() const {
2113 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2114 i::Handle<i::Object> num;
2115 if (obj->IsNumber()) {
2116 num = obj;
2117 } else {
2118 i::Isolate* isolate = i::Isolate::Current();
2119 if (IsDeadCheck(isolate, "v8::Value::ToNumber()")) {
2120 return Local<Number>();
2121 }
2122 LOG_API(isolate, "ToNumber");
2123 ENTER_V8(isolate);
2124 EXCEPTION_PREAMBLE(isolate);
2125 num = i::Execution::ToNumber(obj, &has_pending_exception);
2126 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2127 }
2128 return Local<Number>(ToApi<Number>(num));
2129 }
2130
2131
ToInteger() const2132 Local<Integer> Value::ToInteger() const {
2133 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2134 i::Handle<i::Object> num;
2135 if (obj->IsSmi()) {
2136 num = obj;
2137 } else {
2138 i::Isolate* isolate = i::Isolate::Current();
2139 if (IsDeadCheck(isolate, "v8::Value::ToInteger()")) return Local<Integer>();
2140 LOG_API(isolate, "ToInteger");
2141 ENTER_V8(isolate);
2142 EXCEPTION_PREAMBLE(isolate);
2143 num = i::Execution::ToInteger(obj, &has_pending_exception);
2144 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2145 }
2146 return Local<Integer>(ToApi<Integer>(num));
2147 }
2148
2149
CheckCast(v8::Value * that)2150 void External::CheckCast(v8::Value* that) {
2151 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Cast()")) return;
2152 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2153 ApiCheck(obj->IsProxy(),
2154 "v8::External::Cast()",
2155 "Could not convert to external");
2156 }
2157
2158
CheckCast(Value * that)2159 void v8::Object::CheckCast(Value* that) {
2160 if (IsDeadCheck(i::Isolate::Current(), "v8::Object::Cast()")) return;
2161 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2162 ApiCheck(obj->IsJSObject(),
2163 "v8::Object::Cast()",
2164 "Could not convert to object");
2165 }
2166
2167
CheckCast(Value * that)2168 void v8::Function::CheckCast(Value* that) {
2169 if (IsDeadCheck(i::Isolate::Current(), "v8::Function::Cast()")) return;
2170 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2171 ApiCheck(obj->IsJSFunction(),
2172 "v8::Function::Cast()",
2173 "Could not convert to function");
2174 }
2175
2176
CheckCast(v8::Value * that)2177 void v8::String::CheckCast(v8::Value* that) {
2178 if (IsDeadCheck(i::Isolate::Current(), "v8::String::Cast()")) return;
2179 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2180 ApiCheck(obj->IsString(),
2181 "v8::String::Cast()",
2182 "Could not convert to string");
2183 }
2184
2185
CheckCast(v8::Value * that)2186 void v8::Number::CheckCast(v8::Value* that) {
2187 if (IsDeadCheck(i::Isolate::Current(), "v8::Number::Cast()")) return;
2188 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2189 ApiCheck(obj->IsNumber(),
2190 "v8::Number::Cast()",
2191 "Could not convert to number");
2192 }
2193
2194
CheckCast(v8::Value * that)2195 void v8::Integer::CheckCast(v8::Value* that) {
2196 if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Cast()")) return;
2197 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2198 ApiCheck(obj->IsNumber(),
2199 "v8::Integer::Cast()",
2200 "Could not convert to number");
2201 }
2202
2203
CheckCast(Value * that)2204 void v8::Array::CheckCast(Value* that) {
2205 if (IsDeadCheck(i::Isolate::Current(), "v8::Array::Cast()")) return;
2206 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2207 ApiCheck(obj->IsJSArray(),
2208 "v8::Array::Cast()",
2209 "Could not convert to array");
2210 }
2211
2212
CheckCast(v8::Value * that)2213 void v8::Date::CheckCast(v8::Value* that) {
2214 i::Isolate* isolate = i::Isolate::Current();
2215 if (IsDeadCheck(isolate, "v8::Date::Cast()")) return;
2216 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2217 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_symbol()),
2218 "v8::Date::Cast()",
2219 "Could not convert to date");
2220 }
2221
2222
CheckCast(v8::Value * that)2223 void v8::RegExp::CheckCast(v8::Value* that) {
2224 if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return;
2225 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2226 ApiCheck(obj->IsJSRegExp(),
2227 "v8::RegExp::Cast()",
2228 "Could not convert to regular expression");
2229 }
2230
2231
BooleanValue() const2232 bool Value::BooleanValue() const {
2233 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2234 if (obj->IsBoolean()) {
2235 return obj->IsTrue();
2236 } else {
2237 i::Isolate* isolate = i::Isolate::Current();
2238 if (IsDeadCheck(isolate, "v8::Value::BooleanValue()")) return false;
2239 LOG_API(isolate, "BooleanValue");
2240 ENTER_V8(isolate);
2241 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2242 return value->IsTrue();
2243 }
2244 }
2245
2246
NumberValue() const2247 double Value::NumberValue() const {
2248 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2249 i::Handle<i::Object> num;
2250 if (obj->IsNumber()) {
2251 num = obj;
2252 } else {
2253 i::Isolate* isolate = i::Isolate::Current();
2254 if (IsDeadCheck(isolate, "v8::Value::NumberValue()")) {
2255 return i::OS::nan_value();
2256 }
2257 LOG_API(isolate, "NumberValue");
2258 ENTER_V8(isolate);
2259 EXCEPTION_PREAMBLE(isolate);
2260 num = i::Execution::ToNumber(obj, &has_pending_exception);
2261 EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value());
2262 }
2263 return num->Number();
2264 }
2265
2266
IntegerValue() const2267 int64_t Value::IntegerValue() const {
2268 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2269 i::Handle<i::Object> num;
2270 if (obj->IsNumber()) {
2271 num = obj;
2272 } else {
2273 i::Isolate* isolate = i::Isolate::Current();
2274 if (IsDeadCheck(isolate, "v8::Value::IntegerValue()")) return 0;
2275 LOG_API(isolate, "IntegerValue");
2276 ENTER_V8(isolate);
2277 EXCEPTION_PREAMBLE(isolate);
2278 num = i::Execution::ToInteger(obj, &has_pending_exception);
2279 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2280 }
2281 if (num->IsSmi()) {
2282 return i::Smi::cast(*num)->value();
2283 } else {
2284 return static_cast<int64_t>(num->Number());
2285 }
2286 }
2287
2288
ToInt32() const2289 Local<Int32> Value::ToInt32() const {
2290 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2291 i::Handle<i::Object> num;
2292 if (obj->IsSmi()) {
2293 num = obj;
2294 } else {
2295 i::Isolate* isolate = i::Isolate::Current();
2296 if (IsDeadCheck(isolate, "v8::Value::ToInt32()")) return Local<Int32>();
2297 LOG_API(isolate, "ToInt32");
2298 ENTER_V8(isolate);
2299 EXCEPTION_PREAMBLE(isolate);
2300 num = i::Execution::ToInt32(obj, &has_pending_exception);
2301 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2302 }
2303 return Local<Int32>(ToApi<Int32>(num));
2304 }
2305
2306
ToUint32() const2307 Local<Uint32> Value::ToUint32() const {
2308 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2309 i::Handle<i::Object> num;
2310 if (obj->IsSmi()) {
2311 num = obj;
2312 } else {
2313 i::Isolate* isolate = i::Isolate::Current();
2314 if (IsDeadCheck(isolate, "v8::Value::ToUint32()")) return Local<Uint32>();
2315 LOG_API(isolate, "ToUInt32");
2316 ENTER_V8(isolate);
2317 EXCEPTION_PREAMBLE(isolate);
2318 num = i::Execution::ToUint32(obj, &has_pending_exception);
2319 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2320 }
2321 return Local<Uint32>(ToApi<Uint32>(num));
2322 }
2323
2324
ToArrayIndex() const2325 Local<Uint32> Value::ToArrayIndex() const {
2326 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2327 if (obj->IsSmi()) {
2328 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2329 return Local<Uint32>();
2330 }
2331 i::Isolate* isolate = i::Isolate::Current();
2332 if (IsDeadCheck(isolate, "v8::Value::ToArrayIndex()")) return Local<Uint32>();
2333 LOG_API(isolate, "ToArrayIndex");
2334 ENTER_V8(isolate);
2335 EXCEPTION_PREAMBLE(isolate);
2336 i::Handle<i::Object> string_obj =
2337 i::Execution::ToString(obj, &has_pending_exception);
2338 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2339 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2340 uint32_t index;
2341 if (str->AsArrayIndex(&index)) {
2342 i::Handle<i::Object> value;
2343 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2344 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2345 } else {
2346 value = isolate->factory()->NewNumber(index);
2347 }
2348 return Utils::Uint32ToLocal(value);
2349 }
2350 return Local<Uint32>();
2351 }
2352
2353
Int32Value() const2354 int32_t Value::Int32Value() const {
2355 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2356 if (obj->IsSmi()) {
2357 return i::Smi::cast(*obj)->value();
2358 } else {
2359 i::Isolate* isolate = i::Isolate::Current();
2360 if (IsDeadCheck(isolate, "v8::Value::Int32Value()")) return 0;
2361 LOG_API(isolate, "Int32Value (slow)");
2362 ENTER_V8(isolate);
2363 EXCEPTION_PREAMBLE(isolate);
2364 i::Handle<i::Object> num =
2365 i::Execution::ToInt32(obj, &has_pending_exception);
2366 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2367 if (num->IsSmi()) {
2368 return i::Smi::cast(*num)->value();
2369 } else {
2370 return static_cast<int32_t>(num->Number());
2371 }
2372 }
2373 }
2374
2375
Equals(Handle<Value> that) const2376 bool Value::Equals(Handle<Value> that) const {
2377 i::Isolate* isolate = i::Isolate::Current();
2378 if (IsDeadCheck(isolate, "v8::Value::Equals()")
2379 || EmptyCheck("v8::Value::Equals()", this)
2380 || EmptyCheck("v8::Value::Equals()", that)) {
2381 return false;
2382 }
2383 LOG_API(isolate, "Equals");
2384 ENTER_V8(isolate);
2385 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2386 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2387 // If both obj and other are JSObjects, we'd better compare by identity
2388 // immediately when going into JS builtin. The reason is Invoke
2389 // would overwrite global object receiver with global proxy.
2390 if (obj->IsJSObject() && other->IsJSObject()) {
2391 return *obj == *other;
2392 }
2393 i::Object** args[1] = { other.location() };
2394 EXCEPTION_PREAMBLE(isolate);
2395 i::Handle<i::Object> result =
2396 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2397 EXCEPTION_BAILOUT_CHECK(isolate, false);
2398 return *result == i::Smi::FromInt(i::EQUAL);
2399 }
2400
2401
StrictEquals(Handle<Value> that) const2402 bool Value::StrictEquals(Handle<Value> that) const {
2403 i::Isolate* isolate = i::Isolate::Current();
2404 if (IsDeadCheck(isolate, "v8::Value::StrictEquals()")
2405 || EmptyCheck("v8::Value::StrictEquals()", this)
2406 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2407 return false;
2408 }
2409 LOG_API(isolate, "StrictEquals");
2410 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2411 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2412 // Must check HeapNumber first, since NaN !== NaN.
2413 if (obj->IsHeapNumber()) {
2414 if (!other->IsNumber()) return false;
2415 double x = obj->Number();
2416 double y = other->Number();
2417 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2418 return x == y && !isnan(x) && !isnan(y);
2419 } else if (*obj == *other) { // Also covers Booleans.
2420 return true;
2421 } else if (obj->IsSmi()) {
2422 return other->IsNumber() && obj->Number() == other->Number();
2423 } else if (obj->IsString()) {
2424 return other->IsString() &&
2425 i::String::cast(*obj)->Equals(i::String::cast(*other));
2426 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2427 return other->IsUndefined() || other->IsUndetectableObject();
2428 } else {
2429 return false;
2430 }
2431 }
2432
2433
Uint32Value() const2434 uint32_t Value::Uint32Value() const {
2435 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2436 if (obj->IsSmi()) {
2437 return i::Smi::cast(*obj)->value();
2438 } else {
2439 i::Isolate* isolate = i::Isolate::Current();
2440 if (IsDeadCheck(isolate, "v8::Value::Uint32Value()")) return 0;
2441 LOG_API(isolate, "Uint32Value");
2442 ENTER_V8(isolate);
2443 EXCEPTION_PREAMBLE(isolate);
2444 i::Handle<i::Object> num =
2445 i::Execution::ToUint32(obj, &has_pending_exception);
2446 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2447 if (num->IsSmi()) {
2448 return i::Smi::cast(*num)->value();
2449 } else {
2450 return static_cast<uint32_t>(num->Number());
2451 }
2452 }
2453 }
2454
2455
Set(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)2456 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2457 v8::PropertyAttribute attribs) {
2458 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2459 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
2460 ENTER_V8(isolate);
2461 i::HandleScope scope(isolate);
2462 i::Handle<i::Object> self = Utils::OpenHandle(this);
2463 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2464 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2465 EXCEPTION_PREAMBLE(isolate);
2466 i::Handle<i::Object> obj = i::SetProperty(
2467 self,
2468 key_obj,
2469 value_obj,
2470 static_cast<PropertyAttributes>(attribs),
2471 i::kNonStrictMode);
2472 has_pending_exception = obj.is_null();
2473 EXCEPTION_BAILOUT_CHECK(isolate, false);
2474 return true;
2475 }
2476
2477
Set(uint32_t index,v8::Handle<Value> value)2478 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2479 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2480 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
2481 ENTER_V8(isolate);
2482 i::HandleScope scope(isolate);
2483 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2484 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2485 EXCEPTION_PREAMBLE(isolate);
2486 i::Handle<i::Object> obj = i::SetElement(
2487 self,
2488 index,
2489 value_obj,
2490 i::kNonStrictMode);
2491 has_pending_exception = obj.is_null();
2492 EXCEPTION_BAILOUT_CHECK(isolate, false);
2493 return true;
2494 }
2495
2496
ForceSet(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)2497 bool v8::Object::ForceSet(v8::Handle<Value> key,
2498 v8::Handle<Value> value,
2499 v8::PropertyAttribute attribs) {
2500 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2501 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
2502 ENTER_V8(isolate);
2503 i::HandleScope scope(isolate);
2504 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2505 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2506 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2507 EXCEPTION_PREAMBLE(isolate);
2508 i::Handle<i::Object> obj = i::ForceSetProperty(
2509 self,
2510 key_obj,
2511 value_obj,
2512 static_cast<PropertyAttributes>(attribs));
2513 has_pending_exception = obj.is_null();
2514 EXCEPTION_BAILOUT_CHECK(isolate, false);
2515 return true;
2516 }
2517
2518
ForceDelete(v8::Handle<Value> key)2519 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2520 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2521 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
2522 ENTER_V8(isolate);
2523 i::HandleScope scope(isolate);
2524 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2525 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2526
2527 // When turning on access checks for a global object deoptimize all functions
2528 // as optimized code does not always handle access checks.
2529 i::Deoptimizer::DeoptimizeGlobalObject(*self);
2530
2531 EXCEPTION_PREAMBLE(isolate);
2532 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2533 has_pending_exception = obj.is_null();
2534 EXCEPTION_BAILOUT_CHECK(isolate, false);
2535 return obj->IsTrue();
2536 }
2537
2538
Get(v8::Handle<Value> key)2539 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2540 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2541 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
2542 ENTER_V8(isolate);
2543 i::Handle<i::Object> self = Utils::OpenHandle(this);
2544 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2545 EXCEPTION_PREAMBLE(isolate);
2546 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2547 has_pending_exception = result.is_null();
2548 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
2549 return Utils::ToLocal(result);
2550 }
2551
2552
Get(uint32_t index)2553 Local<Value> v8::Object::Get(uint32_t index) {
2554 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2555 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
2556 ENTER_V8(isolate);
2557 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2558 EXCEPTION_PREAMBLE(isolate);
2559 i::Handle<i::Object> result = i::GetElement(self, index);
2560 has_pending_exception = result.is_null();
2561 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
2562 return Utils::ToLocal(result);
2563 }
2564
2565
GetPrototype()2566 Local<Value> v8::Object::GetPrototype() {
2567 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2568 ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
2569 return Local<v8::Value>());
2570 ENTER_V8(isolate);
2571 i::Handle<i::Object> self = Utils::OpenHandle(this);
2572 i::Handle<i::Object> result = i::GetPrototype(self);
2573 return Utils::ToLocal(result);
2574 }
2575
2576
SetPrototype(Handle<Value> value)2577 bool v8::Object::SetPrototype(Handle<Value> value) {
2578 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2579 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
2580 ENTER_V8(isolate);
2581 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2582 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2583 // We do not allow exceptions thrown while setting the prototype
2584 // to propagate outside.
2585 TryCatch try_catch;
2586 EXCEPTION_PREAMBLE(isolate);
2587 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2588 has_pending_exception = result.is_null();
2589 EXCEPTION_BAILOUT_CHECK(isolate, false);
2590 return true;
2591 }
2592
2593
FindInstanceInPrototypeChain(v8::Handle<FunctionTemplate> tmpl)2594 Local<Object> v8::Object::FindInstanceInPrototypeChain(
2595 v8::Handle<FunctionTemplate> tmpl) {
2596 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2597 ON_BAILOUT(isolate,
2598 "v8::Object::FindInstanceInPrototypeChain()",
2599 return Local<v8::Object>());
2600 ENTER_V8(isolate);
2601 i::JSObject* object = *Utils::OpenHandle(this);
2602 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2603 while (!object->IsInstanceOf(tmpl_info)) {
2604 i::Object* prototype = object->GetPrototype();
2605 if (!prototype->IsJSObject()) return Local<Object>();
2606 object = i::JSObject::cast(prototype);
2607 }
2608 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2609 }
2610
2611
GetPropertyNames()2612 Local<Array> v8::Object::GetPropertyNames() {
2613 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2614 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
2615 return Local<v8::Array>());
2616 ENTER_V8(isolate);
2617 i::HandleScope scope(isolate);
2618 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2619 i::Handle<i::FixedArray> value =
2620 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2621 // Because we use caching to speed up enumeration it is important
2622 // to never change the result of the basic enumeration function so
2623 // we clone the result.
2624 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
2625 i::Handle<i::JSArray> result =
2626 isolate->factory()->NewJSArrayWithElements(elms);
2627 return Utils::ToLocal(scope.CloseAndEscape(result));
2628 }
2629
2630
ObjectProtoToString()2631 Local<String> v8::Object::ObjectProtoToString() {
2632 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2633 ON_BAILOUT(isolate, "v8::Object::ObjectProtoToString()",
2634 return Local<v8::String>());
2635 ENTER_V8(isolate);
2636 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2637
2638 i::Handle<i::Object> name(self->class_name());
2639
2640 // Native implementation of Object.prototype.toString (v8natives.js):
2641 // var c = %ClassOf(this);
2642 // if (c === 'Arguments') c = 'Object';
2643 // return "[object " + c + "]";
2644
2645 if (!name->IsString()) {
2646 return v8::String::New("[object ]");
2647
2648 } else {
2649 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2650 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2651 return v8::String::New("[object Object]");
2652
2653 } else {
2654 const char* prefix = "[object ";
2655 Local<String> str = Utils::ToLocal(class_name);
2656 const char* postfix = "]";
2657
2658 int prefix_len = i::StrLength(prefix);
2659 int str_len = str->Length();
2660 int postfix_len = i::StrLength(postfix);
2661
2662 int buf_len = prefix_len + str_len + postfix_len;
2663 i::ScopedVector<char> buf(buf_len);
2664
2665 // Write prefix.
2666 char* ptr = buf.start();
2667 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2668 ptr += prefix_len;
2669
2670 // Write real content.
2671 str->WriteAscii(ptr, 0, str_len);
2672 ptr += str_len;
2673
2674 // Write postfix.
2675 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2676
2677 // Copy the buffer into a heap-allocated string and return it.
2678 Local<String> result = v8::String::New(buf.start(), buf_len);
2679 return result;
2680 }
2681 }
2682 }
2683
2684
GetConstructorName()2685 Local<String> v8::Object::GetConstructorName() {
2686 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2687 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
2688 return Local<v8::String>());
2689 ENTER_V8(isolate);
2690 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2691 i::Handle<i::String> name(self->constructor_name());
2692 return Utils::ToLocal(name);
2693 }
2694
2695
Delete(v8::Handle<String> key)2696 bool v8::Object::Delete(v8::Handle<String> key) {
2697 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2698 ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
2699 ENTER_V8(isolate);
2700 i::HandleScope scope(isolate);
2701 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2702 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2703 return i::DeleteProperty(self, key_obj)->IsTrue();
2704 }
2705
2706
Has(v8::Handle<String> key)2707 bool v8::Object::Has(v8::Handle<String> key) {
2708 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2709 ON_BAILOUT(isolate, "v8::Object::Has()", return false);
2710 ENTER_V8(isolate);
2711 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2712 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2713 return self->HasProperty(*key_obj);
2714 }
2715
2716
Delete(uint32_t index)2717 bool v8::Object::Delete(uint32_t index) {
2718 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2719 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
2720 return false);
2721 ENTER_V8(isolate);
2722 HandleScope scope;
2723 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2724 return i::DeleteElement(self, index)->IsTrue();
2725 }
2726
2727
Has(uint32_t index)2728 bool v8::Object::Has(uint32_t index) {
2729 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2730 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
2731 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2732 return self->HasElement(index);
2733 }
2734
2735
SetAccessor(Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attributes)2736 bool Object::SetAccessor(Handle<String> name,
2737 AccessorGetter getter,
2738 AccessorSetter setter,
2739 v8::Handle<Value> data,
2740 AccessControl settings,
2741 PropertyAttribute attributes) {
2742 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2743 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
2744 ENTER_V8(isolate);
2745 i::HandleScope scope(isolate);
2746 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2747 getter, setter, data,
2748 settings, attributes);
2749 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2750 return !result.is_null() && !result->IsUndefined();
2751 }
2752
2753
HasRealNamedProperty(Handle<String> key)2754 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2755 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2756 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
2757 return false);
2758 return Utils::OpenHandle(this)->HasRealNamedProperty(
2759 *Utils::OpenHandle(*key));
2760 }
2761
2762
HasRealIndexedProperty(uint32_t index)2763 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2764 ON_BAILOUT(Utils::OpenHandle(this)->GetIsolate(),
2765 "v8::Object::HasRealIndexedProperty()",
2766 return false);
2767 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2768 }
2769
2770
HasRealNamedCallbackProperty(Handle<String> key)2771 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2772 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2773 ON_BAILOUT(isolate,
2774 "v8::Object::HasRealNamedCallbackProperty()",
2775 return false);
2776 ENTER_V8(isolate);
2777 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2778 *Utils::OpenHandle(*key));
2779 }
2780
2781
HasNamedLookupInterceptor()2782 bool v8::Object::HasNamedLookupInterceptor() {
2783 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2784 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
2785 return false);
2786 return Utils::OpenHandle(this)->HasNamedInterceptor();
2787 }
2788
2789
HasIndexedLookupInterceptor()2790 bool v8::Object::HasIndexedLookupInterceptor() {
2791 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2792 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
2793 return false);
2794 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2795 }
2796
2797
GetPropertyByLookup(i::Isolate * isolate,i::Handle<i::JSObject> receiver,i::Handle<i::String> name,i::LookupResult * lookup)2798 static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
2799 i::Handle<i::JSObject> receiver,
2800 i::Handle<i::String> name,
2801 i::LookupResult* lookup) {
2802 if (!lookup->IsProperty()) {
2803 // No real property was found.
2804 return Local<Value>();
2805 }
2806
2807 // If the property being looked up is a callback, it can throw
2808 // an exception.
2809 EXCEPTION_PREAMBLE(isolate);
2810 i::Handle<i::Object> result = i::GetProperty(receiver, name, lookup);
2811 has_pending_exception = result.is_null();
2812 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
2813
2814 return Utils::ToLocal(result);
2815 }
2816
2817
GetRealNamedPropertyInPrototypeChain(Handle<String> key)2818 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2819 Handle<String> key) {
2820 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2821 ON_BAILOUT(isolate,
2822 "v8::Object::GetRealNamedPropertyInPrototypeChain()",
2823 return Local<Value>());
2824 ENTER_V8(isolate);
2825 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2826 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2827 i::LookupResult lookup;
2828 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
2829 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
2830 }
2831
2832
GetRealNamedProperty(Handle<String> key)2833 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2834 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2835 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
2836 return Local<Value>());
2837 ENTER_V8(isolate);
2838 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2839 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2840 i::LookupResult lookup;
2841 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
2842 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
2843 }
2844
2845
2846 // Turns on access checks by copying the map and setting the check flag.
2847 // Because the object gets a new map, existing inline cache caching
2848 // the old map of this object will fail.
TurnOnAccessCheck()2849 void v8::Object::TurnOnAccessCheck() {
2850 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2851 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
2852 ENTER_V8(isolate);
2853 i::HandleScope scope(isolate);
2854 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2855
2856 // When turning on access checks for a global object deoptimize all functions
2857 // as optimized code does not always handle access checks.
2858 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
2859
2860 i::Handle<i::Map> new_map =
2861 isolate->factory()->CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2862 new_map->set_is_access_check_needed(true);
2863 obj->set_map(*new_map);
2864 }
2865
2866
IsDirty()2867 bool v8::Object::IsDirty() {
2868 return Utils::OpenHandle(this)->IsDirty();
2869 }
2870
2871
Clone()2872 Local<v8::Object> v8::Object::Clone() {
2873 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2874 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
2875 ENTER_V8(isolate);
2876 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2877 EXCEPTION_PREAMBLE(isolate);
2878 i::Handle<i::JSObject> result = i::Copy(self);
2879 has_pending_exception = result.is_null();
2880 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2881 return Utils::ToLocal(result);
2882 }
2883
2884
GetCreationContext(i::JSObject * object)2885 static i::Context* GetCreationContext(i::JSObject* object) {
2886 i::Object* constructor = object->map()->constructor();
2887 i::JSFunction* function;
2888 if (!constructor->IsJSFunction()) {
2889 // API functions have null as a constructor,
2890 // but any JSFunction knows its context immediately.
2891 ASSERT(object->IsJSFunction() &&
2892 i::JSFunction::cast(object)->shared()->IsApiFunction());
2893 function = i::JSFunction::cast(object);
2894 } else {
2895 function = i::JSFunction::cast(constructor);
2896 }
2897 return function->context()->global_context();
2898 }
2899
2900
CreationContext()2901 Local<v8::Context> v8::Object::CreationContext() {
2902 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2903 ON_BAILOUT(isolate,
2904 "v8::Object::CreationContext()", return Local<v8::Context>());
2905 ENTER_V8(isolate);
2906 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2907 i::Context* context = GetCreationContext(*self);
2908 return Utils::ToLocal(i::Handle<i::Context>(context));
2909 }
2910
2911
GetIdentityHash()2912 int v8::Object::GetIdentityHash() {
2913 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2914 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
2915 ENTER_V8(isolate);
2916 i::HandleScope scope(isolate);
2917 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2918 i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true));
2919 if (!hidden_props_obj->IsJSObject()) {
2920 // We failed to create hidden properties. That's a detached
2921 // global proxy.
2922 ASSERT(hidden_props_obj->IsUndefined());
2923 return 0;
2924 }
2925 i::Handle<i::JSObject> hidden_props =
2926 i::Handle<i::JSObject>::cast(hidden_props_obj);
2927 i::Handle<i::String> hash_symbol = isolate->factory()->identity_hash_symbol();
2928 if (hidden_props->HasLocalProperty(*hash_symbol)) {
2929 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2930 CHECK(!hash.is_null());
2931 CHECK(hash->IsSmi());
2932 return i::Smi::cast(*hash)->value();
2933 }
2934
2935 int hash_value;
2936 int attempts = 0;
2937 do {
2938 // Generate a random 32-bit hash value but limit range to fit
2939 // within a smi.
2940 hash_value = i::V8::Random(self->GetIsolate()) & i::Smi::kMaxValue;
2941 attempts++;
2942 } while (hash_value == 0 && attempts < 30);
2943 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2944 CHECK(!i::SetLocalPropertyIgnoreAttributes(
2945 hidden_props,
2946 hash_symbol,
2947 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2948 static_cast<PropertyAttributes>(None)).is_null());
2949
2950 return hash_value;
2951 }
2952
2953
SetHiddenValue(v8::Handle<v8::String> key,v8::Handle<v8::Value> value)2954 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2955 v8::Handle<v8::Value> value) {
2956 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2957 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
2958 ENTER_V8(isolate);
2959 i::HandleScope scope(isolate);
2960 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2961 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2962 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2963 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2964 EXCEPTION_PREAMBLE(isolate);
2965 i::Handle<i::Object> obj = i::SetProperty(
2966 hidden_props,
2967 key_obj,
2968 value_obj,
2969 static_cast<PropertyAttributes>(None),
2970 i::kNonStrictMode);
2971 has_pending_exception = obj.is_null();
2972 EXCEPTION_BAILOUT_CHECK(isolate, false);
2973 return true;
2974 }
2975
2976
GetHiddenValue(v8::Handle<v8::String> key)2977 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2978 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2979 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
2980 return Local<v8::Value>());
2981 ENTER_V8(isolate);
2982 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2983 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2984 if (hidden_props->IsUndefined()) {
2985 return v8::Local<v8::Value>();
2986 }
2987 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2988 EXCEPTION_PREAMBLE(isolate);
2989 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2990 has_pending_exception = result.is_null();
2991 EXCEPTION_BAILOUT_CHECK(isolate, v8::Local<v8::Value>());
2992 if (result->IsUndefined()) {
2993 return v8::Local<v8::Value>();
2994 }
2995 return Utils::ToLocal(result);
2996 }
2997
2998
DeleteHiddenValue(v8::Handle<v8::String> key)2999 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3000 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3001 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3002 ENTER_V8(isolate);
3003 i::HandleScope scope(isolate);
3004 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3005 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
3006 if (hidden_props->IsUndefined()) {
3007 return true;
3008 }
3009 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
3010 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3011 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
3012 }
3013
3014
3015 namespace {
3016
PrepareExternalArrayElements(i::Handle<i::JSObject> object,void * data,ExternalArrayType array_type,int length)3017 void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3018 void* data,
3019 ExternalArrayType array_type,
3020 int length) {
3021 i::Isolate* isolate = object->GetIsolate();
3022 i::Handle<i::ExternalArray> array =
3023 isolate->factory()->NewExternalArray(length, array_type, data);
3024
3025 // If the object already has external elements, create a new, unique
3026 // map if the element type is now changing, because assumptions about
3027 // generated code based on the receiver's map will be invalid.
3028 i::Handle<i::HeapObject> elements(object->elements());
3029 bool cant_reuse_map =
3030 elements->map()->IsUndefined() ||
3031 !elements->map()->has_external_array_elements() ||
3032 elements->map() != isolate->heap()->MapForExternalArrayType(array_type);
3033 if (cant_reuse_map) {
3034 i::Handle<i::Map> external_array_map =
3035 isolate->factory()->GetExternalArrayElementsMap(
3036 i::Handle<i::Map>(object->map()),
3037 array_type,
3038 object->HasFastProperties());
3039 object->set_map(*external_array_map);
3040 }
3041 object->set_elements(*array);
3042 }
3043
3044 } // namespace
3045
3046
SetIndexedPropertiesToPixelData(uint8_t * data,int length)3047 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3048 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3049 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3050 ENTER_V8(isolate);
3051 i::HandleScope scope(isolate);
3052 if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength,
3053 "v8::Object::SetIndexedPropertiesToPixelData()",
3054 "length exceeds max acceptable value")) {
3055 return;
3056 }
3057 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3058 if (!ApiCheck(!self->IsJSArray(),
3059 "v8::Object::SetIndexedPropertiesToPixelData()",
3060 "JSArray is not supported")) {
3061 return;
3062 }
3063 PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
3064 }
3065
3066
HasIndexedPropertiesInPixelData()3067 bool v8::Object::HasIndexedPropertiesInPixelData() {
3068 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3069 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3070 return false);
3071 return self->HasExternalPixelElements();
3072 }
3073
3074
GetIndexedPropertiesPixelData()3075 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3076 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3077 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3078 return NULL);
3079 if (self->HasExternalPixelElements()) {
3080 return i::ExternalPixelArray::cast(self->elements())->
3081 external_pixel_pointer();
3082 } else {
3083 return NULL;
3084 }
3085 }
3086
3087
GetIndexedPropertiesPixelDataLength()3088 int v8::Object::GetIndexedPropertiesPixelDataLength() {
3089 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3090 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3091 return -1);
3092 if (self->HasExternalPixelElements()) {
3093 return i::ExternalPixelArray::cast(self->elements())->length();
3094 } else {
3095 return -1;
3096 }
3097 }
3098
SetIndexedPropertiesToExternalArrayData(void * data,ExternalArrayType array_type,int length)3099 void v8::Object::SetIndexedPropertiesToExternalArrayData(
3100 void* data,
3101 ExternalArrayType array_type,
3102 int length) {
3103 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3104 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3105 ENTER_V8(isolate);
3106 i::HandleScope scope(isolate);
3107 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
3108 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3109 "length exceeds max acceptable value")) {
3110 return;
3111 }
3112 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3113 if (!ApiCheck(!self->IsJSArray(),
3114 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3115 "JSArray is not supported")) {
3116 return;
3117 }
3118 PrepareExternalArrayElements(self, data, array_type, length);
3119 }
3120
3121
HasIndexedPropertiesInExternalArrayData()3122 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3123 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3124 ON_BAILOUT(self->GetIsolate(),
3125 "v8::HasIndexedPropertiesInExternalArrayData()",
3126 return false);
3127 return self->HasExternalArrayElements();
3128 }
3129
3130
GetIndexedPropertiesExternalArrayData()3131 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3132 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3133 ON_BAILOUT(self->GetIsolate(),
3134 "v8::GetIndexedPropertiesExternalArrayData()",
3135 return NULL);
3136 if (self->HasExternalArrayElements()) {
3137 return i::ExternalArray::cast(self->elements())->external_pointer();
3138 } else {
3139 return NULL;
3140 }
3141 }
3142
3143
GetIndexedPropertiesExternalArrayDataType()3144 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3145 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3146 ON_BAILOUT(self->GetIsolate(),
3147 "v8::GetIndexedPropertiesExternalArrayDataType()",
3148 return static_cast<ExternalArrayType>(-1));
3149 switch (self->elements()->map()->instance_type()) {
3150 case i::EXTERNAL_BYTE_ARRAY_TYPE:
3151 return kExternalByteArray;
3152 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3153 return kExternalUnsignedByteArray;
3154 case i::EXTERNAL_SHORT_ARRAY_TYPE:
3155 return kExternalShortArray;
3156 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3157 return kExternalUnsignedShortArray;
3158 case i::EXTERNAL_INT_ARRAY_TYPE:
3159 return kExternalIntArray;
3160 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3161 return kExternalUnsignedIntArray;
3162 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
3163 return kExternalFloatArray;
3164 case i::EXTERNAL_PIXEL_ARRAY_TYPE:
3165 return kExternalPixelArray;
3166 default:
3167 return static_cast<ExternalArrayType>(-1);
3168 }
3169 }
3170
3171
GetIndexedPropertiesExternalArrayDataLength()3172 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3173 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3174 ON_BAILOUT(self->GetIsolate(),
3175 "v8::GetIndexedPropertiesExternalArrayDataLength()",
3176 return 0);
3177 if (self->HasExternalArrayElements()) {
3178 return i::ExternalArray::cast(self->elements())->length();
3179 } else {
3180 return -1;
3181 }
3182 }
3183
3184
NewInstance() const3185 Local<v8::Object> Function::NewInstance() const {
3186 return NewInstance(0, NULL);
3187 }
3188
3189
NewInstance(int argc,v8::Handle<v8::Value> argv[]) const3190 Local<v8::Object> Function::NewInstance(int argc,
3191 v8::Handle<v8::Value> argv[]) const {
3192 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3193 ON_BAILOUT(isolate, "v8::Function::NewInstance()",
3194 return Local<v8::Object>());
3195 LOG_API(isolate, "Function::NewInstance");
3196 ENTER_V8(isolate);
3197 HandleScope scope;
3198 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
3199 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3200 i::Object*** args = reinterpret_cast<i::Object***>(argv);
3201 EXCEPTION_PREAMBLE(isolate);
3202 i::Handle<i::Object> returned =
3203 i::Execution::New(function, argc, args, &has_pending_exception);
3204 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
3205 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
3206 }
3207
3208
Call(v8::Handle<v8::Object> recv,int argc,v8::Handle<v8::Value> argv[])3209 Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
3210 v8::Handle<v8::Value> argv[]) {
3211 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3212 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
3213 LOG_API(isolate, "Function::Call");
3214 ENTER_V8(isolate);
3215 i::Object* raw_result = NULL;
3216 {
3217 i::HandleScope scope(isolate);
3218 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
3219 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3220 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3221 i::Object*** args = reinterpret_cast<i::Object***>(argv);
3222 EXCEPTION_PREAMBLE(isolate);
3223 i::Handle<i::Object> returned =
3224 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
3225 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3226 raw_result = *returned;
3227 }
3228 i::Handle<i::Object> result(raw_result);
3229 return Utils::ToLocal(result);
3230 }
3231
3232
SetName(v8::Handle<v8::String> name)3233 void Function::SetName(v8::Handle<v8::String> name) {
3234 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3235 ENTER_V8(isolate);
3236 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3237 func->shared()->set_name(*Utils::OpenHandle(*name));
3238 }
3239
3240
GetName() const3241 Handle<Value> Function::GetName() const {
3242 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3243 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
3244 }
3245
3246
GetScriptOrigin() const3247 ScriptOrigin Function::GetScriptOrigin() const {
3248 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3249 if (func->shared()->script()->IsScript()) {
3250 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
3251 v8::ScriptOrigin origin(
3252 Utils::ToLocal(i::Handle<i::Object>(script->name())),
3253 v8::Integer::New(script->line_offset()->value()),
3254 v8::Integer::New(script->column_offset()->value()));
3255 return origin;
3256 }
3257 return v8::ScriptOrigin(Handle<Value>());
3258 }
3259
3260
3261 const int Function::kLineOffsetNotFound = -1;
3262
3263
GetScriptLineNumber() const3264 int Function::GetScriptLineNumber() const {
3265 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3266 if (func->shared()->script()->IsScript()) {
3267 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
3268 return i::GetScriptLineNumber(script, func->shared()->start_position());
3269 }
3270 return kLineOffsetNotFound;
3271 }
3272
3273
Length() const3274 int String::Length() const {
3275 i::Handle<i::String> str = Utils::OpenHandle(this);
3276 if (IsDeadCheck(str->GetIsolate(), "v8::String::Length()")) return 0;
3277 return str->length();
3278 }
3279
3280
Utf8Length() const3281 int String::Utf8Length() const {
3282 i::Handle<i::String> str = Utils::OpenHandle(this);
3283 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0;
3284 return str->Utf8Length();
3285 }
3286
3287
WriteUtf8(char * buffer,int capacity,int * nchars_ref,WriteHints hints) const3288 int String::WriteUtf8(char* buffer,
3289 int capacity,
3290 int* nchars_ref,
3291 WriteHints hints) const {
3292 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3293 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
3294 LOG_API(isolate, "String::WriteUtf8");
3295 ENTER_V8(isolate);
3296 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3297 i::Handle<i::String> str = Utils::OpenHandle(this);
3298 isolate->string_tracker()->RecordWrite(str);
3299 if (hints & HINT_MANY_WRITES_EXPECTED) {
3300 // Flatten the string for efficiency. This applies whether we are
3301 // using StringInputBuffer or Get(i) to access the characters.
3302 str->TryFlatten();
3303 }
3304 write_input_buffer.Reset(0, *str);
3305 int len = str->length();
3306 // Encode the first K - 3 bytes directly into the buffer since we
3307 // know there's room for them. If no capacity is given we copy all
3308 // of them here.
3309 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3310 int i;
3311 int pos = 0;
3312 int nchars = 0;
3313 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3314 i::uc32 c = write_input_buffer.GetNext();
3315 int written = unibrow::Utf8::Encode(buffer + pos, c);
3316 pos += written;
3317 nchars++;
3318 }
3319 if (i < len) {
3320 // For the last characters we need to check the length for each one
3321 // because they may be longer than the remaining space in the
3322 // buffer.
3323 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3324 for (; i < len && pos < capacity; i++) {
3325 i::uc32 c = write_input_buffer.GetNext();
3326 int written = unibrow::Utf8::Encode(intermediate, c);
3327 if (pos + written <= capacity) {
3328 for (int j = 0; j < written; j++)
3329 buffer[pos + j] = intermediate[j];
3330 pos += written;
3331 nchars++;
3332 } else {
3333 // We've reached the end of the buffer
3334 break;
3335 }
3336 }
3337 }
3338 if (nchars_ref != NULL) *nchars_ref = nchars;
3339 if (i == len && (capacity == -1 || pos < capacity))
3340 buffer[pos++] = '\0';
3341 return pos;
3342 }
3343
3344
WriteAscii(char * buffer,int start,int length,WriteHints hints) const3345 int String::WriteAscii(char* buffer,
3346 int start,
3347 int length,
3348 WriteHints hints) const {
3349 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3350 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0;
3351 LOG_API(isolate, "String::WriteAscii");
3352 ENTER_V8(isolate);
3353 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3354 ASSERT(start >= 0 && length >= -1);
3355 i::Handle<i::String> str = Utils::OpenHandle(this);
3356 isolate->string_tracker()->RecordWrite(str);
3357 if (hints & HINT_MANY_WRITES_EXPECTED) {
3358 // Flatten the string for efficiency. This applies whether we are
3359 // using StringInputBuffer or Get(i) to access the characters.
3360 str->TryFlatten();
3361 }
3362 int end = length;
3363 if ( (length == -1) || (length > str->length() - start) )
3364 end = str->length() - start;
3365 if (end < 0) return 0;
3366 write_input_buffer.Reset(start, *str);
3367 int i;
3368 for (i = 0; i < end; i++) {
3369 char c = static_cast<char>(write_input_buffer.GetNext());
3370 if (c == '\0') c = ' ';
3371 buffer[i] = c;
3372 }
3373 if (length == -1 || i < length)
3374 buffer[i] = '\0';
3375 return i;
3376 }
3377
3378
Write(uint16_t * buffer,int start,int length,WriteHints hints) const3379 int String::Write(uint16_t* buffer,
3380 int start,
3381 int length,
3382 WriteHints hints) const {
3383 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3384 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0;
3385 LOG_API(isolate, "String::Write");
3386 ENTER_V8(isolate);
3387 ASSERT(start >= 0 && length >= -1);
3388 i::Handle<i::String> str = Utils::OpenHandle(this);
3389 isolate->string_tracker()->RecordWrite(str);
3390 if (hints & HINT_MANY_WRITES_EXPECTED) {
3391 // Flatten the string for efficiency. This applies whether we are
3392 // using StringInputBuffer or Get(i) to access the characters.
3393 str->TryFlatten();
3394 }
3395 int end = start + length;
3396 if ((length == -1) || (length > str->length() - start) )
3397 end = str->length();
3398 if (end < 0) return 0;
3399 i::String::WriteToFlat(*str, buffer, start, end);
3400 if (length == -1 || end - start < length) {
3401 buffer[end - start] = '\0';
3402 }
3403 return end - start;
3404 }
3405
3406
IsExternal() const3407 bool v8::String::IsExternal() const {
3408 i::Handle<i::String> str = Utils::OpenHandle(this);
3409 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternal()")) {
3410 return false;
3411 }
3412 EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
3413 return i::StringShape(*str).IsExternalTwoByte();
3414 }
3415
3416
IsExternalAscii() const3417 bool v8::String::IsExternalAscii() const {
3418 i::Handle<i::String> str = Utils::OpenHandle(this);
3419 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) {
3420 return false;
3421 }
3422 return i::StringShape(*str).IsExternalAscii();
3423 }
3424
3425
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const3426 void v8::String::VerifyExternalStringResource(
3427 v8::String::ExternalStringResource* value) const {
3428 i::Handle<i::String> str = Utils::OpenHandle(this);
3429 v8::String::ExternalStringResource* expected;
3430 if (i::StringShape(*str).IsExternalTwoByte()) {
3431 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3432 expected = reinterpret_cast<ExternalStringResource*>(resource);
3433 } else {
3434 expected = NULL;
3435 }
3436 CHECK_EQ(expected, value);
3437 }
3438
3439
3440 v8::String::ExternalAsciiStringResource*
GetExternalAsciiStringResource() const3441 v8::String::GetExternalAsciiStringResource() const {
3442 i::Handle<i::String> str = Utils::OpenHandle(this);
3443 if (IsDeadCheck(str->GetIsolate(),
3444 "v8::String::GetExternalAsciiStringResource()")) {
3445 return NULL;
3446 }
3447 if (i::StringShape(*str).IsExternalAscii()) {
3448 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3449 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3450 } else {
3451 return NULL;
3452 }
3453 }
3454
3455
Value() const3456 double Number::Value() const {
3457 if (IsDeadCheck(i::Isolate::Current(), "v8::Number::Value()")) return 0;
3458 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3459 return obj->Number();
3460 }
3461
3462
Value() const3463 bool Boolean::Value() const {
3464 if (IsDeadCheck(i::Isolate::Current(), "v8::Boolean::Value()")) return false;
3465 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3466 return obj->IsTrue();
3467 }
3468
3469
Value() const3470 int64_t Integer::Value() const {
3471 if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Value()")) return 0;
3472 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3473 if (obj->IsSmi()) {
3474 return i::Smi::cast(*obj)->value();
3475 } else {
3476 return static_cast<int64_t>(obj->Number());
3477 }
3478 }
3479
3480
Value() const3481 int32_t Int32::Value() const {
3482 if (IsDeadCheck(i::Isolate::Current(), "v8::Int32::Value()")) return 0;
3483 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3484 if (obj->IsSmi()) {
3485 return i::Smi::cast(*obj)->value();
3486 } else {
3487 return static_cast<int32_t>(obj->Number());
3488 }
3489 }
3490
3491
Value() const3492 uint32_t Uint32::Value() const {
3493 if (IsDeadCheck(i::Isolate::Current(), "v8::Uint32::Value()")) return 0;
3494 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3495 if (obj->IsSmi()) {
3496 return i::Smi::cast(*obj)->value();
3497 } else {
3498 return static_cast<uint32_t>(obj->Number());
3499 }
3500 }
3501
3502
InternalFieldCount()3503 int v8::Object::InternalFieldCount() {
3504 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3505 if (IsDeadCheck(obj->GetIsolate(), "v8::Object::InternalFieldCount()")) {
3506 return 0;
3507 }
3508 return obj->GetInternalFieldCount();
3509 }
3510
3511
CheckedGetInternalField(int index)3512 Local<Value> v8::Object::CheckedGetInternalField(int index) {
3513 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3514 if (IsDeadCheck(obj->GetIsolate(), "v8::Object::GetInternalField()")) {
3515 return Local<Value>();
3516 }
3517 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3518 "v8::Object::GetInternalField()",
3519 "Reading internal field out of bounds")) {
3520 return Local<Value>();
3521 }
3522 i::Handle<i::Object> value(obj->GetInternalField(index));
3523 Local<Value> result = Utils::ToLocal(value);
3524 #ifdef DEBUG
3525 Local<Value> unchecked = UncheckedGetInternalField(index);
3526 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3527 #endif
3528 return result;
3529 }
3530
3531
SetInternalField(int index,v8::Handle<Value> value)3532 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3533 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3534 i::Isolate* isolate = obj->GetIsolate();
3535 if (IsDeadCheck(isolate, "v8::Object::SetInternalField()")) {
3536 return;
3537 }
3538 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3539 "v8::Object::SetInternalField()",
3540 "Writing internal field out of bounds")) {
3541 return;
3542 }
3543 ENTER_V8(isolate);
3544 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3545 obj->SetInternalField(index, *val);
3546 }
3547
3548
CanBeEncodedAsSmi(void * ptr)3549 static bool CanBeEncodedAsSmi(void* ptr) {
3550 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
3551 return ((address & i::kEncodablePointerMask) == 0);
3552 }
3553
3554
EncodeAsSmi(void * ptr)3555 static i::Smi* EncodeAsSmi(void* ptr) {
3556 ASSERT(CanBeEncodedAsSmi(ptr));
3557 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
3558 i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift);
3559 ASSERT(i::Internals::HasSmiTag(result));
3560 ASSERT_EQ(result, i::Smi::FromInt(result->value()));
3561 ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result));
3562 return result;
3563 }
3564
3565
SetPointerInInternalField(int index,void * value)3566 void v8::Object::SetPointerInInternalField(int index, void* value) {
3567 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3568 ENTER_V8(isolate);
3569 if (CanBeEncodedAsSmi(value)) {
3570 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
3571 } else {
3572 HandleScope scope;
3573 i::Handle<i::Proxy> proxy =
3574 isolate->factory()->NewProxy(
3575 reinterpret_cast<i::Address>(value), i::TENURED);
3576 if (!proxy.is_null())
3577 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
3578 }
3579 ASSERT_EQ(value, GetPointerFromInternalField(index));
3580 }
3581
3582
3583 // --- E n v i r o n m e n t ---
3584
3585
Initialize()3586 bool v8::V8::Initialize() {
3587 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
3588 if (isolate != NULL && isolate->IsInitialized()) {
3589 return true;
3590 }
3591 return InitializeHelper();
3592 }
3593
3594
Dispose()3595 bool v8::V8::Dispose() {
3596 i::Isolate* isolate = i::Isolate::Current();
3597 if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
3598 "v8::V8::Dispose()",
3599 "Use v8::Isolate::Dispose() for a non-default isolate.")) {
3600 return false;
3601 }
3602 i::V8::TearDown();
3603 return true;
3604 }
3605
3606
HeapStatistics()3607 HeapStatistics::HeapStatistics(): total_heap_size_(0),
3608 total_heap_size_executable_(0),
3609 used_heap_size_(0),
3610 heap_size_limit_(0) { }
3611
3612
GetHeapStatistics(HeapStatistics * heap_statistics)3613 void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3614 i::Heap* heap = i::Isolate::Current()->heap();
3615 heap_statistics->set_total_heap_size(heap->CommittedMemory());
3616 heap_statistics->set_total_heap_size_executable(
3617 heap->CommittedMemoryExecutable());
3618 heap_statistics->set_used_heap_size(heap->SizeOfObjects());
3619 heap_statistics->set_heap_size_limit(heap->MaxReserved());
3620 }
3621
3622
IdleNotification()3623 bool v8::V8::IdleNotification() {
3624 // Returning true tells the caller that it need not
3625 // continue to call IdleNotification.
3626 if (!i::Isolate::Current()->IsInitialized()) return true;
3627 return i::V8::IdleNotification();
3628 }
3629
3630
LowMemoryNotification()3631 void v8::V8::LowMemoryNotification() {
3632 i::Isolate* isolate = i::Isolate::Current();
3633 if (!isolate->IsInitialized()) return;
3634 isolate->heap()->CollectAllGarbage(true);
3635 }
3636
3637
ContextDisposedNotification()3638 int v8::V8::ContextDisposedNotification() {
3639 i::Isolate* isolate = i::Isolate::Current();
3640 if (!isolate->IsInitialized()) return 0;
3641 return isolate->heap()->NotifyContextDisposed();
3642 }
3643
3644
GetVersion()3645 const char* v8::V8::GetVersion() {
3646 return i::Version::GetVersion();
3647 }
3648
3649
3650 static i::Handle<i::FunctionTemplateInfo>
EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ)3651 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3652 if (templ->constructor()->IsUndefined()) {
3653 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3654 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3655 templ->set_constructor(*Utils::OpenHandle(*constructor));
3656 }
3657 return i::Handle<i::FunctionTemplateInfo>(
3658 i::FunctionTemplateInfo::cast(templ->constructor()));
3659 }
3660
3661
New(v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)3662 Persistent<Context> v8::Context::New(
3663 v8::ExtensionConfiguration* extensions,
3664 v8::Handle<ObjectTemplate> global_template,
3665 v8::Handle<Value> global_object) {
3666 i::Isolate* isolate = i::Isolate::Current();
3667 EnsureInitializedForIsolate(isolate, "v8::Context::New()");
3668 LOG_API(isolate, "Context::New");
3669 ON_BAILOUT(isolate, "v8::Context::New()", return Persistent<Context>());
3670
3671 // Enter V8 via an ENTER_V8 scope.
3672 i::Handle<i::Context> env;
3673 {
3674 ENTER_V8(isolate);
3675 v8::Handle<ObjectTemplate> proxy_template = global_template;
3676 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3677 i::Handle<i::FunctionTemplateInfo> global_constructor;
3678
3679 if (!global_template.IsEmpty()) {
3680 // Make sure that the global_template has a constructor.
3681 global_constructor =
3682 EnsureConstructor(Utils::OpenHandle(*global_template));
3683
3684 // Create a fresh template for the global proxy object.
3685 proxy_template = ObjectTemplate::New();
3686 proxy_constructor =
3687 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3688
3689 // Set the global template to be the prototype template of
3690 // global proxy template.
3691 proxy_constructor->set_prototype_template(
3692 *Utils::OpenHandle(*global_template));
3693
3694 // Migrate security handlers from global_template to
3695 // proxy_template. Temporarily removing access check
3696 // information from the global template.
3697 if (!global_constructor->access_check_info()->IsUndefined()) {
3698 proxy_constructor->set_access_check_info(
3699 global_constructor->access_check_info());
3700 proxy_constructor->set_needs_access_check(
3701 global_constructor->needs_access_check());
3702 global_constructor->set_needs_access_check(false);
3703 global_constructor->set_access_check_info(
3704 isolate->heap()->undefined_value());
3705 }
3706 }
3707
3708 // Create the environment.
3709 env = isolate->bootstrapper()->CreateEnvironment(
3710 Utils::OpenHandle(*global_object),
3711 proxy_template,
3712 extensions);
3713
3714 // Restore the access check info on the global template.
3715 if (!global_template.IsEmpty()) {
3716 ASSERT(!global_constructor.is_null());
3717 ASSERT(!proxy_constructor.is_null());
3718 global_constructor->set_access_check_info(
3719 proxy_constructor->access_check_info());
3720 global_constructor->set_needs_access_check(
3721 proxy_constructor->needs_access_check());
3722 }
3723 isolate->runtime_profiler()->Reset();
3724 }
3725 // Leave V8.
3726
3727 if (env.is_null())
3728 return Persistent<Context>();
3729 return Persistent<Context>(Utils::ToLocal(env));
3730 }
3731
3732
SetSecurityToken(Handle<Value> token)3733 void v8::Context::SetSecurityToken(Handle<Value> token) {
3734 i::Isolate* isolate = i::Isolate::Current();
3735 if (IsDeadCheck(isolate, "v8::Context::SetSecurityToken()")) {
3736 return;
3737 }
3738 ENTER_V8(isolate);
3739 i::Handle<i::Context> env = Utils::OpenHandle(this);
3740 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3741 env->set_security_token(*token_handle);
3742 }
3743
3744
UseDefaultSecurityToken()3745 void v8::Context::UseDefaultSecurityToken() {
3746 i::Isolate* isolate = i::Isolate::Current();
3747 if (IsDeadCheck(isolate,
3748 "v8::Context::UseDefaultSecurityToken()")) {
3749 return;
3750 }
3751 ENTER_V8(isolate);
3752 i::Handle<i::Context> env = Utils::OpenHandle(this);
3753 env->set_security_token(env->global());
3754 }
3755
3756
GetSecurityToken()3757 Handle<Value> v8::Context::GetSecurityToken() {
3758 i::Isolate* isolate = i::Isolate::Current();
3759 if (IsDeadCheck(isolate, "v8::Context::GetSecurityToken()")) {
3760 return Handle<Value>();
3761 }
3762 i::Handle<i::Context> env = Utils::OpenHandle(this);
3763 i::Object* security_token = env->security_token();
3764 i::Handle<i::Object> token_handle(security_token);
3765 return Utils::ToLocal(token_handle);
3766 }
3767
3768
HasOutOfMemoryException()3769 bool Context::HasOutOfMemoryException() {
3770 i::Handle<i::Context> env = Utils::OpenHandle(this);
3771 return env->has_out_of_memory();
3772 }
3773
3774
InContext()3775 bool Context::InContext() {
3776 return i::Isolate::Current()->context() != NULL;
3777 }
3778
3779
GetEntered()3780 v8::Local<v8::Context> Context::GetEntered() {
3781 i::Isolate* isolate = i::Isolate::Current();
3782 if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) {
3783 return Local<Context>();
3784 }
3785 i::Handle<i::Object> last =
3786 isolate->handle_scope_implementer()->LastEnteredContext();
3787 if (last.is_null()) return Local<Context>();
3788 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3789 return Utils::ToLocal(context);
3790 }
3791
3792
GetCurrent()3793 v8::Local<v8::Context> Context::GetCurrent() {
3794 i::Isolate* isolate = i::Isolate::Current();
3795 if (IsDeadCheck(isolate, "v8::Context::GetCurrent()")) {
3796 return Local<Context>();
3797 }
3798 i::Handle<i::Object> current = isolate->global_context();
3799 if (current.is_null()) return Local<Context>();
3800 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
3801 return Utils::ToLocal(context);
3802 }
3803
3804
GetCalling()3805 v8::Local<v8::Context> Context::GetCalling() {
3806 i::Isolate* isolate = i::Isolate::Current();
3807 if (IsDeadCheck(isolate, "v8::Context::GetCalling()")) {
3808 return Local<Context>();
3809 }
3810 i::Handle<i::Object> calling =
3811 isolate->GetCallingGlobalContext();
3812 if (calling.is_null()) return Local<Context>();
3813 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3814 return Utils::ToLocal(context);
3815 }
3816
3817
Global()3818 v8::Local<v8::Object> Context::Global() {
3819 if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) {
3820 return Local<v8::Object>();
3821 }
3822 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3823 i::Handle<i::Context> context =
3824 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3825 i::Handle<i::Object> global(context->global_proxy());
3826 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3827 }
3828
3829
DetachGlobal()3830 void Context::DetachGlobal() {
3831 i::Isolate* isolate = i::Isolate::Current();
3832 if (IsDeadCheck(isolate, "v8::Context::DetachGlobal()")) return;
3833 ENTER_V8(isolate);
3834 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3835 i::Handle<i::Context> context =
3836 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3837 isolate->bootstrapper()->DetachGlobal(context);
3838 }
3839
3840
ReattachGlobal(Handle<Object> global_object)3841 void Context::ReattachGlobal(Handle<Object> global_object) {
3842 i::Isolate* isolate = i::Isolate::Current();
3843 if (IsDeadCheck(isolate, "v8::Context::ReattachGlobal()")) return;
3844 ENTER_V8(isolate);
3845 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3846 i::Handle<i::Context> context =
3847 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3848 isolate->bootstrapper()->ReattachGlobal(
3849 context,
3850 Utils::OpenHandle(*global_object));
3851 }
3852
3853
SetWrapperClassId(i::Object ** global_handle,uint16_t class_id)3854 void V8::SetWrapperClassId(i::Object** global_handle, uint16_t class_id) {
3855 i::GlobalHandles::SetWrapperClassId(global_handle, class_id);
3856 }
3857
3858
NewInstance()3859 Local<v8::Object> ObjectTemplate::NewInstance() {
3860 i::Isolate* isolate = i::Isolate::Current();
3861 ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
3862 return Local<v8::Object>());
3863 LOG_API(isolate, "ObjectTemplate::NewInstance");
3864 ENTER_V8(isolate);
3865 EXCEPTION_PREAMBLE(isolate);
3866 i::Handle<i::Object> obj =
3867 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3868 &has_pending_exception);
3869 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
3870 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3871 }
3872
3873
GetFunction()3874 Local<v8::Function> FunctionTemplate::GetFunction() {
3875 i::Isolate* isolate = i::Isolate::Current();
3876 ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
3877 return Local<v8::Function>());
3878 LOG_API(isolate, "FunctionTemplate::GetFunction");
3879 ENTER_V8(isolate);
3880 EXCEPTION_PREAMBLE(isolate);
3881 i::Handle<i::Object> obj =
3882 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3883 &has_pending_exception);
3884 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
3885 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3886 }
3887
3888
HasInstance(v8::Handle<v8::Value> value)3889 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3890 ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
3891 return false);
3892 i::Object* obj = *Utils::OpenHandle(*value);
3893 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3894 }
3895
3896
ExternalNewImpl(void * data)3897 static Local<External> ExternalNewImpl(void* data) {
3898 return Utils::ToLocal(FACTORY->NewProxy(static_cast<i::Address>(data)));
3899 }
3900
ExternalValueImpl(i::Handle<i::Object> obj)3901 static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3902 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3903 }
3904
3905
Wrap(void * data)3906 Local<Value> v8::External::Wrap(void* data) {
3907 i::Isolate* isolate = i::Isolate::Current();
3908 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3909 EnsureInitializedForIsolate(isolate, "v8::External::Wrap()");
3910 LOG_API(isolate, "External::Wrap");
3911 ENTER_V8(isolate);
3912
3913 v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
3914 ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
3915 : v8::Local<v8::Value>(ExternalNewImpl(data));
3916
3917 ASSERT_EQ(data, Unwrap(result));
3918 return result;
3919 }
3920
3921
SlowGetPointerFromInternalField(int index)3922 void* v8::Object::SlowGetPointerFromInternalField(int index) {
3923 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3924 i::Object* value = obj->GetInternalField(index);
3925 if (value->IsSmi()) {
3926 return i::Internals::GetExternalPointerFromSmi(value);
3927 } else if (value->IsProxy()) {
3928 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3929 } else {
3930 return NULL;
3931 }
3932 }
3933
3934
FullUnwrap(v8::Handle<v8::Value> wrapper)3935 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3936 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Unwrap()")) return 0;
3937 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3938 void* result;
3939 if (obj->IsSmi()) {
3940 result = i::Internals::GetExternalPointerFromSmi(*obj);
3941 } else if (obj->IsProxy()) {
3942 result = ExternalValueImpl(obj);
3943 } else {
3944 result = NULL;
3945 }
3946 ASSERT_EQ(result, QuickUnwrap(wrapper));
3947 return result;
3948 }
3949
3950
New(void * data)3951 Local<External> v8::External::New(void* data) {
3952 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3953 i::Isolate* isolate = i::Isolate::Current();
3954 EnsureInitializedForIsolate(isolate, "v8::External::New()");
3955 LOG_API(isolate, "External::New");
3956 ENTER_V8(isolate);
3957 return ExternalNewImpl(data);
3958 }
3959
3960
Value() const3961 void* External::Value() const {
3962 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Value()")) return 0;
3963 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3964 return ExternalValueImpl(obj);
3965 }
3966
3967
Empty()3968 Local<String> v8::String::Empty() {
3969 i::Isolate* isolate = i::Isolate::Current();
3970 EnsureInitializedForIsolate(isolate, "v8::String::Empty()");
3971 LOG_API(isolate, "String::Empty()");
3972 return Utils::ToLocal(isolate->factory()->empty_symbol());
3973 }
3974
3975
New(const char * data,int length)3976 Local<String> v8::String::New(const char* data, int length) {
3977 i::Isolate* isolate = i::Isolate::Current();
3978 EnsureInitializedForIsolate(isolate, "v8::String::New()");
3979 LOG_API(isolate, "String::New(char)");
3980 if (length == 0) return Empty();
3981 ENTER_V8(isolate);
3982 if (length == -1) length = i::StrLength(data);
3983 i::Handle<i::String> result =
3984 isolate->factory()->NewStringFromUtf8(
3985 i::Vector<const char>(data, length));
3986 return Utils::ToLocal(result);
3987 }
3988
3989
Concat(Handle<String> left,Handle<String> right)3990 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3991 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3992 i::Isolate* isolate = left_string->GetIsolate();
3993 EnsureInitializedForIsolate(isolate, "v8::String::New()");
3994 LOG_API(isolate, "String::New(char)");
3995 ENTER_V8(isolate);
3996 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3997 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
3998 right_string);
3999 return Utils::ToLocal(result);
4000 }
4001
4002
NewUndetectable(const char * data,int length)4003 Local<String> v8::String::NewUndetectable(const char* data, int length) {
4004 i::Isolate* isolate = i::Isolate::Current();
4005 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()");
4006 LOG_API(isolate, "String::NewUndetectable(char)");
4007 ENTER_V8(isolate);
4008 if (length == -1) length = i::StrLength(data);
4009 i::Handle<i::String> result =
4010 isolate->factory()->NewStringFromUtf8(
4011 i::Vector<const char>(data, length));
4012 result->MarkAsUndetectable();
4013 return Utils::ToLocal(result);
4014 }
4015
4016
TwoByteStringLength(const uint16_t * data)4017 static int TwoByteStringLength(const uint16_t* data) {
4018 int length = 0;
4019 while (data[length] != '\0') length++;
4020 return length;
4021 }
4022
4023
New(const uint16_t * data,int length)4024 Local<String> v8::String::New(const uint16_t* data, int length) {
4025 i::Isolate* isolate = i::Isolate::Current();
4026 EnsureInitializedForIsolate(isolate, "v8::String::New()");
4027 LOG_API(isolate, "String::New(uint16_)");
4028 if (length == 0) return Empty();
4029 ENTER_V8(isolate);
4030 if (length == -1) length = TwoByteStringLength(data);
4031 i::Handle<i::String> result =
4032 isolate->factory()->NewStringFromTwoByte(
4033 i::Vector<const uint16_t>(data, length));
4034 return Utils::ToLocal(result);
4035 }
4036
4037
NewUndetectable(const uint16_t * data,int length)4038 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
4039 i::Isolate* isolate = i::Isolate::Current();
4040 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()");
4041 LOG_API(isolate, "String::NewUndetectable(uint16_)");
4042 ENTER_V8(isolate);
4043 if (length == -1) length = TwoByteStringLength(data);
4044 i::Handle<i::String> result =
4045 isolate->factory()->NewStringFromTwoByte(
4046 i::Vector<const uint16_t>(data, length));
4047 result->MarkAsUndetectable();
4048 return Utils::ToLocal(result);
4049 }
4050
4051
NewExternalStringHandle(i::Isolate * isolate,v8::String::ExternalStringResource * resource)4052 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
4053 v8::String::ExternalStringResource* resource) {
4054 i::Handle<i::String> result =
4055 isolate->factory()->NewExternalStringFromTwoByte(resource);
4056 return result;
4057 }
4058
4059
NewExternalAsciiStringHandle(i::Isolate * isolate,v8::String::ExternalAsciiStringResource * resource)4060 i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
4061 v8::String::ExternalAsciiStringResource* resource) {
4062 i::Handle<i::String> result =
4063 isolate->factory()->NewExternalStringFromAscii(resource);
4064 return result;
4065 }
4066
4067
NewExternal(v8::String::ExternalStringResource * resource)4068 Local<String> v8::String::NewExternal(
4069 v8::String::ExternalStringResource* resource) {
4070 i::Isolate* isolate = i::Isolate::Current();
4071 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
4072 LOG_API(isolate, "String::NewExternal");
4073 ENTER_V8(isolate);
4074 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
4075 isolate->heap()->external_string_table()->AddString(*result);
4076 return Utils::ToLocal(result);
4077 }
4078
4079
MakeExternal(v8::String::ExternalStringResource * resource)4080 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
4081 i::Handle<i::String> obj = Utils::OpenHandle(this);
4082 i::Isolate* isolate = obj->GetIsolate();
4083 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false;
4084 if (i::StringShape(*obj).IsExternalTwoByte()) {
4085 return false; // Already an external string.
4086 }
4087 ENTER_V8(isolate);
4088 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
4089 return false;
4090 }
4091 bool result = obj->MakeExternal(resource);
4092 if (result && !obj->IsSymbol()) {
4093 isolate->heap()->external_string_table()->AddString(*obj);
4094 }
4095 return result;
4096 }
4097
4098
NewExternal(v8::String::ExternalAsciiStringResource * resource)4099 Local<String> v8::String::NewExternal(
4100 v8::String::ExternalAsciiStringResource* resource) {
4101 i::Isolate* isolate = i::Isolate::Current();
4102 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
4103 LOG_API(isolate, "String::NewExternal");
4104 ENTER_V8(isolate);
4105 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
4106 isolate->heap()->external_string_table()->AddString(*result);
4107 return Utils::ToLocal(result);
4108 }
4109
4110
MakeExternal(v8::String::ExternalAsciiStringResource * resource)4111 bool v8::String::MakeExternal(
4112 v8::String::ExternalAsciiStringResource* resource) {
4113 i::Handle<i::String> obj = Utils::OpenHandle(this);
4114 i::Isolate* isolate = obj->GetIsolate();
4115 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false;
4116 if (i::StringShape(*obj).IsExternalTwoByte()) {
4117 return false; // Already an external string.
4118 }
4119 ENTER_V8(isolate);
4120 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
4121 return false;
4122 }
4123 bool result = obj->MakeExternal(resource);
4124 if (result && !obj->IsSymbol()) {
4125 isolate->heap()->external_string_table()->AddString(*obj);
4126 }
4127 return result;
4128 }
4129
4130
CanMakeExternal()4131 bool v8::String::CanMakeExternal() {
4132 i::Handle<i::String> obj = Utils::OpenHandle(this);
4133 i::Isolate* isolate = obj->GetIsolate();
4134 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false;
4135 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
4136 return false;
4137 }
4138 int size = obj->Size(); // Byte size of the original string.
4139 if (size < i::ExternalString::kSize)
4140 return false;
4141 i::StringShape shape(*obj);
4142 return !shape.IsExternal();
4143 }
4144
4145
New()4146 Local<v8::Object> v8::Object::New() {
4147 i::Isolate* isolate = i::Isolate::Current();
4148 EnsureInitializedForIsolate(isolate, "v8::Object::New()");
4149 LOG_API(isolate, "Object::New");
4150 ENTER_V8(isolate);
4151 i::Handle<i::JSObject> obj =
4152 isolate->factory()->NewJSObject(isolate->object_function());
4153 return Utils::ToLocal(obj);
4154 }
4155
4156
New(double time)4157 Local<v8::Value> v8::Date::New(double time) {
4158 i::Isolate* isolate = i::Isolate::Current();
4159 EnsureInitializedForIsolate(isolate, "v8::Date::New()");
4160 LOG_API(isolate, "Date::New");
4161 if (isnan(time)) {
4162 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
4163 time = i::OS::nan_value();
4164 }
4165 ENTER_V8(isolate);
4166 EXCEPTION_PREAMBLE(isolate);
4167 i::Handle<i::Object> obj =
4168 i::Execution::NewDate(time, &has_pending_exception);
4169 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>());
4170 return Utils::ToLocal(obj);
4171 }
4172
4173
NumberValue() const4174 double v8::Date::NumberValue() const {
4175 i::Isolate* isolate = i::Isolate::Current();
4176 if (IsDeadCheck(isolate, "v8::Date::NumberValue()")) return 0;
4177 LOG_API(isolate, "Date::NumberValue");
4178 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4179 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
4180 return jsvalue->value()->Number();
4181 }
4182
4183
DateTimeConfigurationChangeNotification()4184 void v8::Date::DateTimeConfigurationChangeNotification() {
4185 i::Isolate* isolate = i::Isolate::Current();
4186 ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
4187 return);
4188 LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification");
4189 ENTER_V8(isolate);
4190
4191 i::HandleScope scope(isolate);
4192 // Get the function ResetDateCache (defined in date-delay.js).
4193 i::Handle<i::String> func_name_str =
4194 isolate->factory()->LookupAsciiSymbol("ResetDateCache");
4195 i::MaybeObject* result =
4196 isolate->js_builtins_object()->GetProperty(*func_name_str);
4197 i::Object* object_func;
4198 if (!result->ToObject(&object_func)) {
4199 return;
4200 }
4201
4202 if (object_func->IsJSFunction()) {
4203 i::Handle<i::JSFunction> func =
4204 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
4205
4206 // Call ResetDateCache(0 but expect no exceptions:
4207 bool caught_exception = false;
4208 i::Execution::TryCall(func,
4209 isolate->js_builtins_object(),
4210 0,
4211 NULL,
4212 &caught_exception);
4213 }
4214 }
4215
4216
RegExpFlagsToString(RegExp::Flags flags)4217 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
4218 char flags_buf[3];
4219 int num_flags = 0;
4220 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
4221 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
4222 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
4223 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
4224 return FACTORY->LookupSymbol(
4225 i::Vector<const char>(flags_buf, num_flags));
4226 }
4227
4228
New(Handle<String> pattern,Flags flags)4229 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
4230 Flags flags) {
4231 i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
4232 EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
4233 LOG_API(isolate, "RegExp::New");
4234 ENTER_V8(isolate);
4235 EXCEPTION_PREAMBLE(isolate);
4236 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
4237 Utils::OpenHandle(*pattern),
4238 RegExpFlagsToString(flags),
4239 &has_pending_exception);
4240 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
4241 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
4242 }
4243
4244
GetSource() const4245 Local<v8::String> v8::RegExp::GetSource() const {
4246 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4247 if (IsDeadCheck(isolate, "v8::RegExp::GetSource()")) {
4248 return Local<v8::String>();
4249 }
4250 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
4251 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
4252 }
4253
4254
4255 // Assert that the static flags cast in GetFlags is valid.
4256 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
4257 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
4258 static_cast<int>(i::JSRegExp::internal_flag))
4259 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
4260 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
4261 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
4262 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
4263 #undef REGEXP_FLAG_ASSERT_EQ
4264
GetFlags() const4265 v8::RegExp::Flags v8::RegExp::GetFlags() const {
4266 if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::GetFlags()")) {
4267 return v8::RegExp::kNone;
4268 }
4269 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
4270 return static_cast<RegExp::Flags>(obj->GetFlags().value());
4271 }
4272
4273
New(int length)4274 Local<v8::Array> v8::Array::New(int length) {
4275 i::Isolate* isolate = i::Isolate::Current();
4276 EnsureInitializedForIsolate(isolate, "v8::Array::New()");
4277 LOG_API(isolate, "Array::New");
4278 ENTER_V8(isolate);
4279 int real_length = length > 0 ? length : 0;
4280 i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length);
4281 i::Handle<i::Object> length_obj =
4282 isolate->factory()->NewNumberFromInt(real_length);
4283 obj->set_length(*length_obj);
4284 return Utils::ToLocal(obj);
4285 }
4286
4287
Length() const4288 uint32_t v8::Array::Length() const {
4289 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4290 if (IsDeadCheck(isolate, "v8::Array::Length()")) return 0;
4291 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
4292 i::Object* length = obj->length();
4293 if (length->IsSmi()) {
4294 return i::Smi::cast(length)->value();
4295 } else {
4296 return static_cast<uint32_t>(length->Number());
4297 }
4298 }
4299
4300
CloneElementAt(uint32_t index)4301 Local<Object> Array::CloneElementAt(uint32_t index) {
4302 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4303 ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
4304 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
4305 if (!self->HasFastElements()) {
4306 return Local<Object>();
4307 }
4308 i::FixedArray* elms = i::FixedArray::cast(self->elements());
4309 i::Object* paragon = elms->get(index);
4310 if (!paragon->IsJSObject()) {
4311 return Local<Object>();
4312 }
4313 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
4314 EXCEPTION_PREAMBLE(isolate);
4315 ENTER_V8(isolate);
4316 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
4317 has_pending_exception = result.is_null();
4318 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
4319 return Utils::ToLocal(result);
4320 }
4321
4322
NewSymbol(const char * data,int length)4323 Local<String> v8::String::NewSymbol(const char* data, int length) {
4324 i::Isolate* isolate = i::Isolate::Current();
4325 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()");
4326 LOG_API(isolate, "String::NewSymbol(char)");
4327 ENTER_V8(isolate);
4328 if (length == -1) length = i::StrLength(data);
4329 i::Handle<i::String> result =
4330 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length));
4331 return Utils::ToLocal(result);
4332 }
4333
4334
New(double value)4335 Local<Number> v8::Number::New(double value) {
4336 i::Isolate* isolate = i::Isolate::Current();
4337 EnsureInitializedForIsolate(isolate, "v8::Number::New()");
4338 if (isnan(value)) {
4339 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
4340 value = i::OS::nan_value();
4341 }
4342 ENTER_V8(isolate);
4343 i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
4344 return Utils::NumberToLocal(result);
4345 }
4346
4347
New(int32_t value)4348 Local<Integer> v8::Integer::New(int32_t value) {
4349 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4350 EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
4351 if (i::Smi::IsValid(value)) {
4352 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
4353 isolate));
4354 }
4355 ENTER_V8(isolate);
4356 i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
4357 return Utils::IntegerToLocal(result);
4358 }
4359
4360
NewFromUnsigned(uint32_t value)4361 Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
4362 bool fits_into_int32_t = (value & (1 << 31)) == 0;
4363 if (fits_into_int32_t) {
4364 return Integer::New(static_cast<int32_t>(value));
4365 }
4366 i::Isolate* isolate = i::Isolate::Current();
4367 ENTER_V8(isolate);
4368 i::Handle<i::Object> result = isolate->factory()->NewNumber(value);
4369 return Utils::IntegerToLocal(result);
4370 }
4371
4372
IgnoreOutOfMemoryException()4373 void V8::IgnoreOutOfMemoryException() {
4374 EnterIsolateIfNeeded()->set_ignore_out_of_memory(true);
4375 }
4376
4377
AddMessageListener(MessageCallback that,Handle<Value> data)4378 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
4379 i::Isolate* isolate = i::Isolate::Current();
4380 EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
4381 ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
4382 ENTER_V8(isolate);
4383 i::HandleScope scope(isolate);
4384 NeanderArray listeners(isolate->factory()->message_listeners());
4385 NeanderObject obj(2);
4386 obj.set(0, *isolate->factory()->NewProxy(FUNCTION_ADDR(that)));
4387 obj.set(1, data.IsEmpty() ?
4388 isolate->heap()->undefined_value() :
4389 *Utils::OpenHandle(*data));
4390 listeners.add(obj.value());
4391 return true;
4392 }
4393
4394
RemoveMessageListeners(MessageCallback that)4395 void V8::RemoveMessageListeners(MessageCallback that) {
4396 i::Isolate* isolate = i::Isolate::Current();
4397 EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
4398 ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
4399 ENTER_V8(isolate);
4400 i::HandleScope scope(isolate);
4401 NeanderArray listeners(isolate->factory()->message_listeners());
4402 for (int i = 0; i < listeners.length(); i++) {
4403 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
4404
4405 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
4406 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
4407 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
4408 listeners.set(i, isolate->heap()->undefined_value());
4409 }
4410 }
4411 }
4412
4413
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)4414 void V8::SetCaptureStackTraceForUncaughtExceptions(
4415 bool capture,
4416 int frame_limit,
4417 StackTrace::StackTraceOptions options) {
4418 i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
4419 capture,
4420 frame_limit,
4421 options);
4422 }
4423
4424
SetCounterFunction(CounterLookupCallback callback)4425 void V8::SetCounterFunction(CounterLookupCallback callback) {
4426 i::Isolate* isolate = EnterIsolateIfNeeded();
4427 if (IsDeadCheck(isolate, "v8::V8::SetCounterFunction()")) return;
4428 isolate->stats_table()->SetCounterFunction(callback);
4429 }
4430
SetCreateHistogramFunction(CreateHistogramCallback callback)4431 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
4432 i::Isolate* isolate = EnterIsolateIfNeeded();
4433 if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return;
4434 isolate->stats_table()->SetCreateHistogramFunction(callback);
4435 }
4436
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)4437 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
4438 i::Isolate* isolate = EnterIsolateIfNeeded();
4439 if (IsDeadCheck(isolate, "v8::V8::SetAddHistogramSampleFunction()")) return;
4440 isolate->stats_table()->
4441 SetAddHistogramSampleFunction(callback);
4442 }
4443
EnableSlidingStateWindow()4444 void V8::EnableSlidingStateWindow() {
4445 i::Isolate* isolate = i::Isolate::Current();
4446 if (IsDeadCheck(isolate, "v8::V8::EnableSlidingStateWindow()")) return;
4447 isolate->logger()->EnableSlidingStateWindow();
4448 }
4449
4450
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)4451 void V8::SetFailedAccessCheckCallbackFunction(
4452 FailedAccessCheckCallback callback) {
4453 i::Isolate* isolate = i::Isolate::Current();
4454 if (IsDeadCheck(isolate, "v8::V8::SetFailedAccessCheckCallbackFunction()")) {
4455 return;
4456 }
4457 isolate->SetFailedAccessCheckCallback(callback);
4458 }
4459
AddObjectGroup(Persistent<Value> * objects,size_t length,RetainedObjectInfo * info)4460 void V8::AddObjectGroup(Persistent<Value>* objects,
4461 size_t length,
4462 RetainedObjectInfo* info) {
4463 i::Isolate* isolate = i::Isolate::Current();
4464 if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return;
4465 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
4466 isolate->global_handles()->AddObjectGroup(
4467 reinterpret_cast<i::Object***>(objects), length, info);
4468 }
4469
4470
AddImplicitReferences(Persistent<Object> parent,Persistent<Value> * children,size_t length)4471 void V8::AddImplicitReferences(Persistent<Object> parent,
4472 Persistent<Value>* children,
4473 size_t length) {
4474 i::Isolate* isolate = i::Isolate::Current();
4475 if (IsDeadCheck(isolate, "v8::V8::AddImplicitReferences()")) return;
4476 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
4477 isolate->global_handles()->AddImplicitReferences(
4478 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*parent)).location(),
4479 reinterpret_cast<i::Object***>(children), length);
4480 }
4481
4482
AdjustAmountOfExternalAllocatedMemory(int change_in_bytes)4483 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
4484 i::Isolate* isolate = i::Isolate::Current();
4485 if (IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) {
4486 return 0;
4487 }
4488 return isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
4489 change_in_bytes);
4490 }
4491
4492
SetGlobalGCPrologueCallback(GCCallback callback)4493 void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
4494 i::Isolate* isolate = i::Isolate::Current();
4495 if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCPrologueCallback()")) return;
4496 isolate->heap()->SetGlobalGCPrologueCallback(callback);
4497 }
4498
4499
SetGlobalGCEpilogueCallback(GCCallback callback)4500 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
4501 i::Isolate* isolate = i::Isolate::Current();
4502 if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCEpilogueCallback()")) return;
4503 isolate->heap()->SetGlobalGCEpilogueCallback(callback);
4504 }
4505
4506
AddGCPrologueCallback(GCPrologueCallback callback,GCType gc_type)4507 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
4508 i::Isolate* isolate = i::Isolate::Current();
4509 if (IsDeadCheck(isolate, "v8::V8::AddGCPrologueCallback()")) return;
4510 isolate->heap()->AddGCPrologueCallback(callback, gc_type);
4511 }
4512
4513
RemoveGCPrologueCallback(GCPrologueCallback callback)4514 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
4515 i::Isolate* isolate = i::Isolate::Current();
4516 if (IsDeadCheck(isolate, "v8::V8::RemoveGCPrologueCallback()")) return;
4517 isolate->heap()->RemoveGCPrologueCallback(callback);
4518 }
4519
4520
AddGCEpilogueCallback(GCEpilogueCallback callback,GCType gc_type)4521 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
4522 i::Isolate* isolate = i::Isolate::Current();
4523 if (IsDeadCheck(isolate, "v8::V8::AddGCEpilogueCallback()")) return;
4524 isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
4525 }
4526
4527
RemoveGCEpilogueCallback(GCEpilogueCallback callback)4528 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
4529 i::Isolate* isolate = i::Isolate::Current();
4530 if (IsDeadCheck(isolate, "v8::V8::RemoveGCEpilogueCallback()")) return;
4531 isolate->heap()->RemoveGCEpilogueCallback(callback);
4532 }
4533
4534
AddMemoryAllocationCallback(MemoryAllocationCallback callback,ObjectSpace space,AllocationAction action)4535 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4536 ObjectSpace space,
4537 AllocationAction action) {
4538 i::Isolate* isolate = i::Isolate::Current();
4539 if (IsDeadCheck(isolate, "v8::V8::AddMemoryAllocationCallback()")) return;
4540 isolate->memory_allocator()->AddMemoryAllocationCallback(
4541 callback, space, action);
4542 }
4543
4544
RemoveMemoryAllocationCallback(MemoryAllocationCallback callback)4545 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4546 i::Isolate* isolate = i::Isolate::Current();
4547 if (IsDeadCheck(isolate, "v8::V8::RemoveMemoryAllocationCallback()")) return;
4548 isolate->memory_allocator()->RemoveMemoryAllocationCallback(
4549 callback);
4550 }
4551
4552
PauseProfiler()4553 void V8::PauseProfiler() {
4554 #ifdef ENABLE_LOGGING_AND_PROFILING
4555 PauseProfilerEx(PROFILER_MODULE_CPU);
4556 #endif
4557 }
4558
4559
ResumeProfiler()4560 void V8::ResumeProfiler() {
4561 #ifdef ENABLE_LOGGING_AND_PROFILING
4562 ResumeProfilerEx(PROFILER_MODULE_CPU);
4563 #endif
4564 }
4565
4566
IsProfilerPaused()4567 bool V8::IsProfilerPaused() {
4568 #ifdef ENABLE_LOGGING_AND_PROFILING
4569 return LOGGER->GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4570 #else
4571 return true;
4572 #endif
4573 }
4574
4575
ResumeProfilerEx(int flags,int tag)4576 void V8::ResumeProfilerEx(int flags, int tag) {
4577 #ifdef ENABLE_LOGGING_AND_PROFILING
4578 i::Isolate* isolate = i::Isolate::Current();
4579 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4580 // Snapshot mode: resume modules, perform GC, then pause only
4581 // those modules which haven't been started prior to making a
4582 // snapshot.
4583
4584 // Make a GC prior to taking a snapshot.
4585 isolate->heap()->CollectAllGarbage(false);
4586 // Reset snapshot flag and CPU module flags.
4587 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4588 const int current_flags = isolate->logger()->GetActiveProfilerModules();
4589 isolate->logger()->ResumeProfiler(flags, tag);
4590 isolate->heap()->CollectAllGarbage(false);
4591 isolate->logger()->PauseProfiler(~current_flags & flags, tag);
4592 } else {
4593 isolate->logger()->ResumeProfiler(flags, tag);
4594 }
4595 #endif
4596 }
4597
4598
PauseProfilerEx(int flags,int tag)4599 void V8::PauseProfilerEx(int flags, int tag) {
4600 #ifdef ENABLE_LOGGING_AND_PROFILING
4601 LOGGER->PauseProfiler(flags, tag);
4602 #endif
4603 }
4604
4605
GetActiveProfilerModules()4606 int V8::GetActiveProfilerModules() {
4607 #ifdef ENABLE_LOGGING_AND_PROFILING
4608 return LOGGER->GetActiveProfilerModules();
4609 #else
4610 return PROFILER_MODULE_NONE;
4611 #endif
4612 }
4613
4614
GetLogLines(int from_pos,char * dest_buf,int max_size)4615 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4616 #ifdef ENABLE_LOGGING_AND_PROFILING
4617 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
4618 return LOGGER->GetLogLines(from_pos, dest_buf, max_size);
4619 #endif
4620 return 0;
4621 }
4622
4623
GetCurrentThreadId()4624 int V8::GetCurrentThreadId() {
4625 i::Isolate* isolate = i::Isolate::Current();
4626 EnsureInitializedForIsolate(isolate, "V8::GetCurrentThreadId()");
4627 return isolate->thread_id().ToInteger();
4628 }
4629
4630
TerminateExecution(int thread_id)4631 void V8::TerminateExecution(int thread_id) {
4632 i::Isolate* isolate = i::Isolate::Current();
4633 if (!isolate->IsInitialized()) return;
4634 API_ENTRY_CHECK("V8::TerminateExecution()");
4635 // If the thread_id identifies the current thread just terminate
4636 // execution right away. Otherwise, ask the thread manager to
4637 // terminate the thread with the given id if any.
4638 i::ThreadId internal_tid = i::ThreadId::FromInteger(thread_id);
4639 if (isolate->thread_id().Equals(internal_tid)) {
4640 isolate->stack_guard()->TerminateExecution();
4641 } else {
4642 isolate->thread_manager()->TerminateExecution(internal_tid);
4643 }
4644 }
4645
4646
TerminateExecution(Isolate * isolate)4647 void V8::TerminateExecution(Isolate* isolate) {
4648 // If no isolate is supplied, use the default isolate.
4649 if (isolate != NULL) {
4650 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
4651 } else {
4652 i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution();
4653 }
4654 }
4655
4656
IsExecutionTerminating()4657 bool V8::IsExecutionTerminating() {
4658 i::Isolate* isolate = i::Isolate::Current();
4659 return IsExecutionTerminatingCheck(isolate);
4660 }
4661
4662
GetCurrent()4663 Isolate* Isolate::GetCurrent() {
4664 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4665 return reinterpret_cast<Isolate*>(isolate);
4666 }
4667
4668
New()4669 Isolate* Isolate::New() {
4670 i::Isolate* isolate = new i::Isolate();
4671 return reinterpret_cast<Isolate*>(isolate);
4672 }
4673
4674
Dispose()4675 void Isolate::Dispose() {
4676 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
4677 if (!ApiCheck(!isolate->IsInUse(),
4678 "v8::Isolate::Dispose()",
4679 "Disposing the isolate that is entered by a thread.")) {
4680 return;
4681 }
4682 isolate->TearDown();
4683 }
4684
4685
Enter()4686 void Isolate::Enter() {
4687 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
4688 isolate->Enter();
4689 }
4690
4691
Exit()4692 void Isolate::Exit() {
4693 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
4694 isolate->Exit();
4695 }
4696
4697
Utf8Value(v8::Handle<v8::Value> obj)4698 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4699 i::Isolate* isolate = i::Isolate::Current();
4700 if (IsDeadCheck(isolate, "v8::String::Utf8Value::Utf8Value()")) return;
4701 if (obj.IsEmpty()) {
4702 str_ = NULL;
4703 length_ = 0;
4704 return;
4705 }
4706 ENTER_V8(isolate);
4707 i::HandleScope scope(isolate);
4708 TryCatch try_catch;
4709 Handle<String> str = obj->ToString();
4710 if (str.IsEmpty()) {
4711 str_ = NULL;
4712 length_ = 0;
4713 } else {
4714 length_ = str->Utf8Length();
4715 str_ = i::NewArray<char>(length_ + 1);
4716 str->WriteUtf8(str_);
4717 }
4718 }
4719
4720
~Utf8Value()4721 String::Utf8Value::~Utf8Value() {
4722 i::DeleteArray(str_);
4723 }
4724
4725
AsciiValue(v8::Handle<v8::Value> obj)4726 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4727 i::Isolate* isolate = i::Isolate::Current();
4728 if (IsDeadCheck(isolate, "v8::String::AsciiValue::AsciiValue()")) return;
4729 if (obj.IsEmpty()) {
4730 str_ = NULL;
4731 length_ = 0;
4732 return;
4733 }
4734 ENTER_V8(isolate);
4735 i::HandleScope scope(isolate);
4736 TryCatch try_catch;
4737 Handle<String> str = obj->ToString();
4738 if (str.IsEmpty()) {
4739 str_ = NULL;
4740 length_ = 0;
4741 } else {
4742 length_ = str->Length();
4743 str_ = i::NewArray<char>(length_ + 1);
4744 str->WriteAscii(str_);
4745 }
4746 }
4747
4748
~AsciiValue()4749 String::AsciiValue::~AsciiValue() {
4750 i::DeleteArray(str_);
4751 }
4752
4753
Value(v8::Handle<v8::Value> obj)4754 String::Value::Value(v8::Handle<v8::Value> obj) {
4755 i::Isolate* isolate = i::Isolate::Current();
4756 if (IsDeadCheck(isolate, "v8::String::Value::Value()")) return;
4757 if (obj.IsEmpty()) {
4758 str_ = NULL;
4759 length_ = 0;
4760 return;
4761 }
4762 ENTER_V8(isolate);
4763 i::HandleScope scope(isolate);
4764 TryCatch try_catch;
4765 Handle<String> str = obj->ToString();
4766 if (str.IsEmpty()) {
4767 str_ = NULL;
4768 length_ = 0;
4769 } else {
4770 length_ = str->Length();
4771 str_ = i::NewArray<uint16_t>(length_ + 1);
4772 str->Write(str_);
4773 }
4774 }
4775
4776
~Value()4777 String::Value::~Value() {
4778 i::DeleteArray(str_);
4779 }
4780
RangeError(v8::Handle<v8::String> raw_message)4781 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4782 i::Isolate* isolate = i::Isolate::Current();
4783 LOG_API(isolate, "RangeError");
4784 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
4785 ENTER_V8(isolate);
4786 i::Object* error;
4787 {
4788 i::HandleScope scope(isolate);
4789 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4790 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
4791 error = *result;
4792 }
4793 i::Handle<i::Object> result(error);
4794 return Utils::ToLocal(result);
4795 }
4796
ReferenceError(v8::Handle<v8::String> raw_message)4797 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4798 i::Isolate* isolate = i::Isolate::Current();
4799 LOG_API(isolate, "ReferenceError");
4800 ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
4801 ENTER_V8(isolate);
4802 i::Object* error;
4803 {
4804 i::HandleScope scope(isolate);
4805 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4806 i::Handle<i::Object> result =
4807 isolate->factory()->NewReferenceError(message);
4808 error = *result;
4809 }
4810 i::Handle<i::Object> result(error);
4811 return Utils::ToLocal(result);
4812 }
4813
SyntaxError(v8::Handle<v8::String> raw_message)4814 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4815 i::Isolate* isolate = i::Isolate::Current();
4816 LOG_API(isolate, "SyntaxError");
4817 ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
4818 ENTER_V8(isolate);
4819 i::Object* error;
4820 {
4821 i::HandleScope scope(isolate);
4822 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4823 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
4824 error = *result;
4825 }
4826 i::Handle<i::Object> result(error);
4827 return Utils::ToLocal(result);
4828 }
4829
TypeError(v8::Handle<v8::String> raw_message)4830 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4831 i::Isolate* isolate = i::Isolate::Current();
4832 LOG_API(isolate, "TypeError");
4833 ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
4834 ENTER_V8(isolate);
4835 i::Object* error;
4836 {
4837 i::HandleScope scope(isolate);
4838 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4839 i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
4840 error = *result;
4841 }
4842 i::Handle<i::Object> result(error);
4843 return Utils::ToLocal(result);
4844 }
4845
Error(v8::Handle<v8::String> raw_message)4846 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4847 i::Isolate* isolate = i::Isolate::Current();
4848 LOG_API(isolate, "Error");
4849 ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
4850 ENTER_V8(isolate);
4851 i::Object* error;
4852 {
4853 i::HandleScope scope(isolate);
4854 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4855 i::Handle<i::Object> result = isolate->factory()->NewError(message);
4856 error = *result;
4857 }
4858 i::Handle<i::Object> result(error);
4859 return Utils::ToLocal(result);
4860 }
4861
4862
4863 // --- D e b u g S u p p o r t ---
4864
4865 #ifdef ENABLE_DEBUGGER_SUPPORT
4866
EventCallbackWrapper(const v8::Debug::EventDetails & event_details)4867 static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4868 i::Isolate* isolate = i::Isolate::Current();
4869 if (isolate->debug_event_callback() != NULL) {
4870 isolate->debug_event_callback()(event_details.GetEvent(),
4871 event_details.GetExecutionState(),
4872 event_details.GetEventData(),
4873 event_details.GetCallbackData());
4874 }
4875 }
4876
4877
SetDebugEventListener(EventCallback that,Handle<Value> data)4878 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4879 i::Isolate* isolate = i::Isolate::Current();
4880 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
4881 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
4882 ENTER_V8(isolate);
4883
4884 isolate->set_debug_event_callback(that);
4885
4886 i::HandleScope scope(isolate);
4887 i::Handle<i::Object> proxy = isolate->factory()->undefined_value();
4888 if (that != NULL) {
4889 proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4890 }
4891 isolate->debugger()->SetEventListener(proxy, Utils::OpenHandle(*data));
4892 return true;
4893 }
4894
4895
SetDebugEventListener2(EventCallback2 that,Handle<Value> data)4896 bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4897 i::Isolate* isolate = i::Isolate::Current();
4898 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()");
4899 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false);
4900 ENTER_V8(isolate);
4901 i::HandleScope scope(isolate);
4902 i::Handle<i::Object> proxy = isolate->factory()->undefined_value();
4903 if (that != NULL) {
4904 proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(that));
4905 }
4906 isolate->debugger()->SetEventListener(proxy,
4907 Utils::OpenHandle(*data));
4908 return true;
4909 }
4910
4911
SetDebugEventListener(v8::Handle<v8::Object> that,Handle<Value> data)4912 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4913 Handle<Value> data) {
4914 i::Isolate* isolate = i::Isolate::Current();
4915 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
4916 ENTER_V8(isolate);
4917 isolate->debugger()->SetEventListener(Utils::OpenHandle(*that),
4918 Utils::OpenHandle(*data));
4919 return true;
4920 }
4921
4922
DebugBreak(Isolate * isolate)4923 void Debug::DebugBreak(Isolate* isolate) {
4924 // If no isolate is supplied, use the default isolate.
4925 if (isolate != NULL) {
4926 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
4927 } else {
4928 i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak();
4929 }
4930 }
4931
4932
CancelDebugBreak(Isolate * isolate)4933 void Debug::CancelDebugBreak(Isolate* isolate) {
4934 // If no isolate is supplied, use the default isolate.
4935 if (isolate != NULL) {
4936 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
4937 internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
4938 } else {
4939 i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK);
4940 }
4941 }
4942
4943
DebugBreakForCommand(ClientData * data,Isolate * isolate)4944 void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) {
4945 // If no isolate is supplied, use the default isolate.
4946 if (isolate != NULL) {
4947 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
4948 internal_isolate->debugger()->EnqueueDebugCommand(data);
4949 } else {
4950 i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data);
4951 }
4952 }
4953
4954
MessageHandlerWrapper(const v8::Debug::Message & message)4955 static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4956 i::Isolate* isolate = i::Isolate::Current();
4957 if (isolate->message_handler()) {
4958 v8::String::Value json(message.GetJSON());
4959 (isolate->message_handler())(*json, json.length(), message.GetClientData());
4960 }
4961 }
4962
4963
SetMessageHandler(v8::Debug::MessageHandler handler,bool message_handler_thread)4964 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4965 bool message_handler_thread) {
4966 i::Isolate* isolate = i::Isolate::Current();
4967 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
4968 ENTER_V8(isolate);
4969
4970 // Message handler thread not supported any more. Parameter temporally left in
4971 // the API for client compatibility reasons.
4972 CHECK(!message_handler_thread);
4973
4974 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4975 isolate->set_message_handler(handler);
4976 if (handler != NULL) {
4977 isolate->debugger()->SetMessageHandler(MessageHandlerWrapper);
4978 } else {
4979 isolate->debugger()->SetMessageHandler(NULL);
4980 }
4981 }
4982
4983
SetMessageHandler2(v8::Debug::MessageHandler2 handler)4984 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4985 i::Isolate* isolate = i::Isolate::Current();
4986 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
4987 ENTER_V8(isolate);
4988 isolate->debugger()->SetMessageHandler(handler);
4989 }
4990
4991
SendCommand(const uint16_t * command,int length,ClientData * client_data,Isolate * isolate)4992 void Debug::SendCommand(const uint16_t* command, int length,
4993 ClientData* client_data,
4994 Isolate* isolate) {
4995 // If no isolate is supplied, use the default isolate.
4996 if (isolate != NULL) {
4997 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
4998 internal_isolate->debugger()->ProcessCommand(
4999 i::Vector<const uint16_t>(command, length), client_data);
5000 } else {
5001 i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand(
5002 i::Vector<const uint16_t>(command, length), client_data);
5003 }
5004 }
5005
5006
SetHostDispatchHandler(HostDispatchHandler handler,int period)5007 void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
5008 int period) {
5009 i::Isolate* isolate = i::Isolate::Current();
5010 EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler");
5011 ENTER_V8(isolate);
5012 isolate->debugger()->SetHostDispatchHandler(handler, period);
5013 }
5014
5015
SetDebugMessageDispatchHandler(DebugMessageDispatchHandler handler,bool provide_locker)5016 void Debug::SetDebugMessageDispatchHandler(
5017 DebugMessageDispatchHandler handler, bool provide_locker) {
5018 i::Isolate* isolate = i::Isolate::Current();
5019 EnsureInitializedForIsolate(isolate,
5020 "v8::Debug::SetDebugMessageDispatchHandler");
5021 ENTER_V8(isolate);
5022 isolate->debugger()->SetDebugMessageDispatchHandler(
5023 handler, provide_locker);
5024 }
5025
5026
Call(v8::Handle<v8::Function> fun,v8::Handle<v8::Value> data)5027 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
5028 v8::Handle<v8::Value> data) {
5029 i::Isolate* isolate = i::Isolate::Current();
5030 if (!isolate->IsInitialized()) return Local<Value>();
5031 ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
5032 ENTER_V8(isolate);
5033 i::Handle<i::Object> result;
5034 EXCEPTION_PREAMBLE(isolate);
5035 if (data.IsEmpty()) {
5036 result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
5037 isolate->factory()->undefined_value(),
5038 &has_pending_exception);
5039 } else {
5040 result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
5041 Utils::OpenHandle(*data),
5042 &has_pending_exception);
5043 }
5044 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
5045 return Utils::ToLocal(result);
5046 }
5047
5048
GetMirror(v8::Handle<v8::Value> obj)5049 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
5050 i::Isolate* isolate = i::Isolate::Current();
5051 if (!isolate->IsInitialized()) return Local<Value>();
5052 ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
5053 ENTER_V8(isolate);
5054 v8::HandleScope scope;
5055 i::Debug* isolate_debug = isolate->debug();
5056 isolate_debug->Load();
5057 i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global());
5058 i::Handle<i::String> name =
5059 isolate->factory()->LookupAsciiSymbol("MakeMirror");
5060 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
5061 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
5062 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
5063 const int kArgc = 1;
5064 v8::Handle<v8::Value> argv[kArgc] = { obj };
5065 EXCEPTION_PREAMBLE(isolate);
5066 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
5067 kArgc,
5068 argv);
5069 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
5070 return scope.Close(result);
5071 }
5072
5073
EnableAgent(const char * name,int port,bool wait_for_connection)5074 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
5075 return i::Isolate::Current()->debugger()->StartAgent(name, port,
5076 wait_for_connection);
5077 }
5078
ProcessDebugMessages()5079 void Debug::ProcessDebugMessages() {
5080 i::Execution::ProcessDebugMesssages(true);
5081 }
5082
GetDebugContext()5083 Local<Context> Debug::GetDebugContext() {
5084 i::Isolate* isolate = i::Isolate::Current();
5085 EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
5086 ENTER_V8(isolate);
5087 return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext());
5088 }
5089
5090 #endif // ENABLE_DEBUGGER_SUPPORT
5091
5092
5093 #ifdef ENABLE_LOGGING_AND_PROFILING
5094
GetFunctionName() const5095 Handle<String> CpuProfileNode::GetFunctionName() const {
5096 i::Isolate* isolate = i::Isolate::Current();
5097 IsDeadCheck(isolate, "v8::CpuProfileNode::GetFunctionName");
5098 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
5099 const i::CodeEntry* entry = node->entry();
5100 if (!entry->has_name_prefix()) {
5101 return Handle<String>(ToApi<String>(
5102 isolate->factory()->LookupAsciiSymbol(entry->name())));
5103 } else {
5104 return Handle<String>(ToApi<String>(isolate->factory()->NewConsString(
5105 isolate->factory()->LookupAsciiSymbol(entry->name_prefix()),
5106 isolate->factory()->LookupAsciiSymbol(entry->name()))));
5107 }
5108 }
5109
5110
GetScriptResourceName() const5111 Handle<String> CpuProfileNode::GetScriptResourceName() const {
5112 i::Isolate* isolate = i::Isolate::Current();
5113 IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName");
5114 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
5115 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
5116 node->entry()->resource_name())));
5117 }
5118
5119
GetLineNumber() const5120 int CpuProfileNode::GetLineNumber() const {
5121 i::Isolate* isolate = i::Isolate::Current();
5122 IsDeadCheck(isolate, "v8::CpuProfileNode::GetLineNumber");
5123 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
5124 }
5125
5126
GetTotalTime() const5127 double CpuProfileNode::GetTotalTime() const {
5128 i::Isolate* isolate = i::Isolate::Current();
5129 IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalTime");
5130 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
5131 }
5132
5133
GetSelfTime() const5134 double CpuProfileNode::GetSelfTime() const {
5135 i::Isolate* isolate = i::Isolate::Current();
5136 IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfTime");
5137 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
5138 }
5139
5140
GetTotalSamplesCount() const5141 double CpuProfileNode::GetTotalSamplesCount() const {
5142 i::Isolate* isolate = i::Isolate::Current();
5143 IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalSamplesCount");
5144 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
5145 }
5146
5147
GetSelfSamplesCount() const5148 double CpuProfileNode::GetSelfSamplesCount() const {
5149 i::Isolate* isolate = i::Isolate::Current();
5150 IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfSamplesCount");
5151 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
5152 }
5153
5154
GetCallUid() const5155 unsigned CpuProfileNode::GetCallUid() const {
5156 i::Isolate* isolate = i::Isolate::Current();
5157 IsDeadCheck(isolate, "v8::CpuProfileNode::GetCallUid");
5158 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
5159 }
5160
5161
GetChildrenCount() const5162 int CpuProfileNode::GetChildrenCount() const {
5163 i::Isolate* isolate = i::Isolate::Current();
5164 IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount");
5165 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
5166 }
5167
5168
GetChild(int index) const5169 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
5170 i::Isolate* isolate = i::Isolate::Current();
5171 IsDeadCheck(isolate, "v8::CpuProfileNode::GetChild");
5172 const i::ProfileNode* child =
5173 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
5174 return reinterpret_cast<const CpuProfileNode*>(child);
5175 }
5176
5177
Delete()5178 void CpuProfile::Delete() {
5179 i::Isolate* isolate = i::Isolate::Current();
5180 IsDeadCheck(isolate, "v8::CpuProfile::Delete");
5181 i::CpuProfiler::DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
5182 if (i::CpuProfiler::GetProfilesCount() == 0 &&
5183 !i::CpuProfiler::HasDetachedProfiles()) {
5184 // If this was the last profile, clean up all accessory data as well.
5185 i::CpuProfiler::DeleteAllProfiles();
5186 }
5187 }
5188
5189
GetUid() const5190 unsigned CpuProfile::GetUid() const {
5191 i::Isolate* isolate = i::Isolate::Current();
5192 IsDeadCheck(isolate, "v8::CpuProfile::GetUid");
5193 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
5194 }
5195
5196
GetTitle() const5197 Handle<String> CpuProfile::GetTitle() const {
5198 i::Isolate* isolate = i::Isolate::Current();
5199 IsDeadCheck(isolate, "v8::CpuProfile::GetTitle");
5200 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
5201 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
5202 profile->title())));
5203 }
5204
5205
GetBottomUpRoot() const5206 const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
5207 i::Isolate* isolate = i::Isolate::Current();
5208 IsDeadCheck(isolate, "v8::CpuProfile::GetBottomUpRoot");
5209 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
5210 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
5211 }
5212
5213
GetTopDownRoot() const5214 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
5215 i::Isolate* isolate = i::Isolate::Current();
5216 IsDeadCheck(isolate, "v8::CpuProfile::GetTopDownRoot");
5217 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
5218 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
5219 }
5220
5221
GetProfilesCount()5222 int CpuProfiler::GetProfilesCount() {
5223 i::Isolate* isolate = i::Isolate::Current();
5224 IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount");
5225 return i::CpuProfiler::GetProfilesCount();
5226 }
5227
5228
GetProfile(int index,Handle<Value> security_token)5229 const CpuProfile* CpuProfiler::GetProfile(int index,
5230 Handle<Value> security_token) {
5231 i::Isolate* isolate = i::Isolate::Current();
5232 IsDeadCheck(isolate, "v8::CpuProfiler::GetProfile");
5233 return reinterpret_cast<const CpuProfile*>(
5234 i::CpuProfiler::GetProfile(
5235 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
5236 index));
5237 }
5238
5239
FindProfile(unsigned uid,Handle<Value> security_token)5240 const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
5241 Handle<Value> security_token) {
5242 i::Isolate* isolate = i::Isolate::Current();
5243 IsDeadCheck(isolate, "v8::CpuProfiler::FindProfile");
5244 return reinterpret_cast<const CpuProfile*>(
5245 i::CpuProfiler::FindProfile(
5246 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
5247 uid));
5248 }
5249
5250
StartProfiling(Handle<String> title)5251 void CpuProfiler::StartProfiling(Handle<String> title) {
5252 i::Isolate* isolate = i::Isolate::Current();
5253 IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling");
5254 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
5255 }
5256
5257
StopProfiling(Handle<String> title,Handle<Value> security_token)5258 const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
5259 Handle<Value> security_token) {
5260 i::Isolate* isolate = i::Isolate::Current();
5261 IsDeadCheck(isolate, "v8::CpuProfiler::StopProfiling");
5262 return reinterpret_cast<const CpuProfile*>(
5263 i::CpuProfiler::StopProfiling(
5264 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
5265 *Utils::OpenHandle(*title)));
5266 }
5267
5268
DeleteAllProfiles()5269 void CpuProfiler::DeleteAllProfiles() {
5270 i::Isolate* isolate = i::Isolate::Current();
5271 IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles");
5272 i::CpuProfiler::DeleteAllProfiles();
5273 }
5274
5275
ToInternal(const HeapGraphEdge * edge)5276 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
5277 return const_cast<i::HeapGraphEdge*>(
5278 reinterpret_cast<const i::HeapGraphEdge*>(edge));
5279 }
5280
GetType() const5281 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
5282 i::Isolate* isolate = i::Isolate::Current();
5283 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetType");
5284 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
5285 }
5286
5287
GetName() const5288 Handle<Value> HeapGraphEdge::GetName() const {
5289 i::Isolate* isolate = i::Isolate::Current();
5290 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetName");
5291 i::HeapGraphEdge* edge = ToInternal(this);
5292 switch (edge->type()) {
5293 case i::HeapGraphEdge::kContextVariable:
5294 case i::HeapGraphEdge::kInternal:
5295 case i::HeapGraphEdge::kProperty:
5296 case i::HeapGraphEdge::kShortcut:
5297 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
5298 edge->name())));
5299 case i::HeapGraphEdge::kElement:
5300 case i::HeapGraphEdge::kHidden:
5301 return Handle<Number>(ToApi<Number>(isolate->factory()->NewNumberFromInt(
5302 edge->index())));
5303 default: UNREACHABLE();
5304 }
5305 return v8::Undefined();
5306 }
5307
5308
GetFromNode() const5309 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
5310 i::Isolate* isolate = i::Isolate::Current();
5311 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetFromNode");
5312 const i::HeapEntry* from = ToInternal(this)->From();
5313 return reinterpret_cast<const HeapGraphNode*>(from);
5314 }
5315
5316
GetToNode() const5317 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
5318 i::Isolate* isolate = i::Isolate::Current();
5319 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetToNode");
5320 const i::HeapEntry* to = ToInternal(this)->to();
5321 return reinterpret_cast<const HeapGraphNode*>(to);
5322 }
5323
5324
ToInternal(const HeapGraphNode * entry)5325 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
5326 return const_cast<i::HeapEntry*>(
5327 reinterpret_cast<const i::HeapEntry*>(entry));
5328 }
5329
5330
GetType() const5331 HeapGraphNode::Type HeapGraphNode::GetType() const {
5332 i::Isolate* isolate = i::Isolate::Current();
5333 IsDeadCheck(isolate, "v8::HeapGraphNode::GetType");
5334 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
5335 }
5336
5337
GetName() const5338 Handle<String> HeapGraphNode::GetName() const {
5339 i::Isolate* isolate = i::Isolate::Current();
5340 IsDeadCheck(isolate, "v8::HeapGraphNode::GetName");
5341 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
5342 ToInternal(this)->name())));
5343 }
5344
5345
GetId() const5346 uint64_t HeapGraphNode::GetId() const {
5347 i::Isolate* isolate = i::Isolate::Current();
5348 IsDeadCheck(isolate, "v8::HeapGraphNode::GetId");
5349 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
5350 return ToInternal(this)->id();
5351 }
5352
5353
GetInstancesCount() const5354 int HeapGraphNode::GetInstancesCount() const {
5355 i::Isolate* isolate = i::Isolate::Current();
5356 IsDeadCheck(isolate, "v8::HeapGraphNode::GetInstancesCount");
5357 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
5358 return static_cast<int>(ToInternal(this)->id());
5359 }
5360
5361
GetSelfSize() const5362 int HeapGraphNode::GetSelfSize() const {
5363 i::Isolate* isolate = i::Isolate::Current();
5364 IsDeadCheck(isolate, "v8::HeapGraphNode::GetSelfSize");
5365 return ToInternal(this)->self_size();
5366 }
5367
5368
GetRetainedSize(bool exact) const5369 int HeapGraphNode::GetRetainedSize(bool exact) const {
5370 i::Isolate* isolate = i::Isolate::Current();
5371 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainedSize");
5372 return ToInternal(this)->RetainedSize(exact);
5373 }
5374
5375
GetChildrenCount() const5376 int HeapGraphNode::GetChildrenCount() const {
5377 i::Isolate* isolate = i::Isolate::Current();
5378 IsDeadCheck(isolate, "v8::HeapSnapshot::GetChildrenCount");
5379 return ToInternal(this)->children().length();
5380 }
5381
5382
GetChild(int index) const5383 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
5384 i::Isolate* isolate = i::Isolate::Current();
5385 IsDeadCheck(isolate, "v8::HeapSnapshot::GetChild");
5386 return reinterpret_cast<const HeapGraphEdge*>(
5387 &ToInternal(this)->children()[index]);
5388 }
5389
5390
GetRetainersCount() const5391 int HeapGraphNode::GetRetainersCount() const {
5392 i::Isolate* isolate = i::Isolate::Current();
5393 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainersCount");
5394 return ToInternal(this)->retainers().length();
5395 }
5396
5397
GetRetainer(int index) const5398 const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
5399 i::Isolate* isolate = i::Isolate::Current();
5400 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainer");
5401 return reinterpret_cast<const HeapGraphEdge*>(
5402 ToInternal(this)->retainers()[index]);
5403 }
5404
5405
GetDominatorNode() const5406 const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
5407 i::Isolate* isolate = i::Isolate::Current();
5408 IsDeadCheck(isolate, "v8::HeapSnapshot::GetDominatorNode");
5409 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
5410 }
5411
5412
ToInternal(const HeapSnapshot * snapshot)5413 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
5414 return const_cast<i::HeapSnapshot*>(
5415 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
5416 }
5417
5418
Delete()5419 void HeapSnapshot::Delete() {
5420 i::Isolate* isolate = i::Isolate::Current();
5421 IsDeadCheck(isolate, "v8::HeapSnapshot::Delete");
5422 if (i::HeapProfiler::GetSnapshotsCount() > 1) {
5423 ToInternal(this)->Delete();
5424 } else {
5425 // If this is the last snapshot, clean up all accessory data as well.
5426 i::HeapProfiler::DeleteAllSnapshots();
5427 }
5428 }
5429
5430
GetType() const5431 HeapSnapshot::Type HeapSnapshot::GetType() const {
5432 i::Isolate* isolate = i::Isolate::Current();
5433 IsDeadCheck(isolate, "v8::HeapSnapshot::GetType");
5434 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
5435 }
5436
5437
GetUid() const5438 unsigned HeapSnapshot::GetUid() const {
5439 i::Isolate* isolate = i::Isolate::Current();
5440 IsDeadCheck(isolate, "v8::HeapSnapshot::GetUid");
5441 return ToInternal(this)->uid();
5442 }
5443
5444
GetTitle() const5445 Handle<String> HeapSnapshot::GetTitle() const {
5446 i::Isolate* isolate = i::Isolate::Current();
5447 IsDeadCheck(isolate, "v8::HeapSnapshot::GetTitle");
5448 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol(
5449 ToInternal(this)->title())));
5450 }
5451
5452
GetRoot() const5453 const HeapGraphNode* HeapSnapshot::GetRoot() const {
5454 i::Isolate* isolate = i::Isolate::Current();
5455 IsDeadCheck(isolate, "v8::HeapSnapshot::GetHead");
5456 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
5457 }
5458
5459
GetNodeById(uint64_t id) const5460 const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
5461 i::Isolate* isolate = i::Isolate::Current();
5462 IsDeadCheck(isolate, "v8::HeapSnapshot::GetNodeById");
5463 return reinterpret_cast<const HeapGraphNode*>(
5464 ToInternal(this)->GetEntryById(id));
5465 }
5466
5467
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const5468 void HeapSnapshot::Serialize(OutputStream* stream,
5469 HeapSnapshot::SerializationFormat format) const {
5470 i::Isolate* isolate = i::Isolate::Current();
5471 IsDeadCheck(isolate, "v8::HeapSnapshot::Serialize");
5472 ApiCheck(format == kJSON,
5473 "v8::HeapSnapshot::Serialize",
5474 "Unknown serialization format");
5475 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
5476 "v8::HeapSnapshot::Serialize",
5477 "Unsupported output encoding");
5478 ApiCheck(stream->GetChunkSize() > 0,
5479 "v8::HeapSnapshot::Serialize",
5480 "Invalid stream chunk size");
5481 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
5482 serializer.Serialize(stream);
5483 }
5484
5485
GetSnapshotsCount()5486 int HeapProfiler::GetSnapshotsCount() {
5487 i::Isolate* isolate = i::Isolate::Current();
5488 IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshotsCount");
5489 return i::HeapProfiler::GetSnapshotsCount();
5490 }
5491
5492
GetSnapshot(int index)5493 const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
5494 i::Isolate* isolate = i::Isolate::Current();
5495 IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshot");
5496 return reinterpret_cast<const HeapSnapshot*>(
5497 i::HeapProfiler::GetSnapshot(index));
5498 }
5499
5500
FindSnapshot(unsigned uid)5501 const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
5502 i::Isolate* isolate = i::Isolate::Current();
5503 IsDeadCheck(isolate, "v8::HeapProfiler::FindSnapshot");
5504 return reinterpret_cast<const HeapSnapshot*>(
5505 i::HeapProfiler::FindSnapshot(uid));
5506 }
5507
5508
TakeSnapshot(Handle<String> title,HeapSnapshot::Type type,ActivityControl * control)5509 const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
5510 HeapSnapshot::Type type,
5511 ActivityControl* control) {
5512 i::Isolate* isolate = i::Isolate::Current();
5513 IsDeadCheck(isolate, "v8::HeapProfiler::TakeSnapshot");
5514 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
5515 switch (type) {
5516 case HeapSnapshot::kFull:
5517 internal_type = i::HeapSnapshot::kFull;
5518 break;
5519 case HeapSnapshot::kAggregated:
5520 internal_type = i::HeapSnapshot::kAggregated;
5521 break;
5522 default:
5523 UNREACHABLE();
5524 }
5525 return reinterpret_cast<const HeapSnapshot*>(
5526 i::HeapProfiler::TakeSnapshot(
5527 *Utils::OpenHandle(*title), internal_type, control));
5528 }
5529
5530
DeleteAllSnapshots()5531 void HeapProfiler::DeleteAllSnapshots() {
5532 i::Isolate* isolate = i::Isolate::Current();
5533 IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots");
5534 i::HeapProfiler::DeleteAllSnapshots();
5535 }
5536
5537
DefineWrapperClass(uint16_t class_id,WrapperInfoCallback callback)5538 void HeapProfiler::DefineWrapperClass(uint16_t class_id,
5539 WrapperInfoCallback callback) {
5540 i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id,
5541 callback);
5542 }
5543
5544 #endif // ENABLE_LOGGING_AND_PROFILING
5545
5546
5547 v8::Testing::StressType internal::Testing::stress_type_ =
5548 v8::Testing::kStressTypeOpt;
5549
5550
SetStressRunType(Testing::StressType type)5551 void Testing::SetStressRunType(Testing::StressType type) {
5552 internal::Testing::set_stress_type(type);
5553 }
5554
GetStressRuns()5555 int Testing::GetStressRuns() {
5556 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
5557 #ifdef DEBUG
5558 // In debug mode the code runs much slower so stressing will only make two
5559 // runs.
5560 return 2;
5561 #else
5562 return 5;
5563 #endif
5564 }
5565
5566
SetFlagsFromString(const char * flags)5567 static void SetFlagsFromString(const char* flags) {
5568 V8::SetFlagsFromString(flags, i::StrLength(flags));
5569 }
5570
5571
PrepareStressRun(int run)5572 void Testing::PrepareStressRun(int run) {
5573 static const char* kLazyOptimizations =
5574 "--prepare-always-opt --nolimit-inlining "
5575 "--noalways-opt --noopt-eagerly";
5576 static const char* kEagerOptimizations = "--opt-eagerly";
5577 static const char* kForcedOptimizations = "--always-opt";
5578
5579 // If deoptimization stressed turn on frequent deoptimization. If no value
5580 // is spefified through --deopt-every-n-times use a default default value.
5581 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
5582 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
5583 internal::FLAG_deopt_every_n_times == 0) {
5584 SetFlagsFromString(kDeoptEvery13Times);
5585 }
5586
5587 #ifdef DEBUG
5588 // As stressing in debug mode only make two runs skip the deopt stressing
5589 // here.
5590 if (run == GetStressRuns() - 1) {
5591 SetFlagsFromString(kForcedOptimizations);
5592 } else {
5593 SetFlagsFromString(kEagerOptimizations);
5594 SetFlagsFromString(kLazyOptimizations);
5595 }
5596 #else
5597 if (run == GetStressRuns() - 1) {
5598 SetFlagsFromString(kForcedOptimizations);
5599 } else if (run == GetStressRuns() - 2) {
5600 SetFlagsFromString(kEagerOptimizations);
5601 } else {
5602 SetFlagsFromString(kLazyOptimizations);
5603 }
5604 #endif
5605 }
5606
5607
DeoptimizeAll()5608 void Testing::DeoptimizeAll() {
5609 internal::Deoptimizer::DeoptimizeAll();
5610 }
5611
5612
5613 namespace internal {
5614
5615
FreeThreadResources()5616 void HandleScopeImplementer::FreeThreadResources() {
5617 Free();
5618 }
5619
5620
ArchiveThread(char * storage)5621 char* HandleScopeImplementer::ArchiveThread(char* storage) {
5622 Isolate* isolate = Isolate::Current();
5623 v8::ImplementationUtilities::HandleScopeData* current =
5624 isolate->handle_scope_data();
5625 handle_scope_data_ = *current;
5626 memcpy(storage, this, sizeof(*this));
5627
5628 ResetAfterArchive();
5629 current->Initialize();
5630
5631 return storage + ArchiveSpacePerThread();
5632 }
5633
5634
ArchiveSpacePerThread()5635 int HandleScopeImplementer::ArchiveSpacePerThread() {
5636 return sizeof(HandleScopeImplementer);
5637 }
5638
5639
RestoreThread(char * storage)5640 char* HandleScopeImplementer::RestoreThread(char* storage) {
5641 memcpy(this, storage, sizeof(*this));
5642 *Isolate::Current()->handle_scope_data() = handle_scope_data_;
5643 return storage + ArchiveSpacePerThread();
5644 }
5645
5646
IterateThis(ObjectVisitor * v)5647 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
5648 // Iterate over all handles in the blocks except for the last.
5649 for (int i = blocks()->length() - 2; i >= 0; --i) {
5650 Object** block = blocks()->at(i);
5651 v->VisitPointers(block, &block[kHandleBlockSize]);
5652 }
5653
5654 // Iterate over live handles in the last block (if any).
5655 if (!blocks()->is_empty()) {
5656 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
5657 }
5658
5659 if (!saved_contexts_.is_empty()) {
5660 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
5661 v->VisitPointers(start, start + saved_contexts_.length());
5662 }
5663 }
5664
5665
Iterate(ObjectVisitor * v)5666 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
5667 v8::ImplementationUtilities::HandleScopeData* current =
5668 Isolate::Current()->handle_scope_data();
5669 handle_scope_data_ = *current;
5670 IterateThis(v);
5671 }
5672
5673
Iterate(ObjectVisitor * v,char * storage)5674 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
5675 HandleScopeImplementer* scope_implementer =
5676 reinterpret_cast<HandleScopeImplementer*>(storage);
5677 scope_implementer->IterateThis(v);
5678 return storage + ArchiveSpacePerThread();
5679 }
5680
5681 } } // namespace v8::internal
5682