1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/api.h"
6
7 #include <string.h> // For memcpy, strlen.
8 #ifdef V8_USE_ADDRESS_SANITIZER
9 #include <sanitizer/asan_interface.h>
10 #endif // V8_USE_ADDRESS_SANITIZER
11 #include <cmath> // For isnan.
12 #include "include/v8-debug.h"
13 #include "include/v8-profiler.h"
14 #include "include/v8-testing.h"
15 #include "src/assert-scope.h"
16 #include "src/bootstrapper.h"
17 #include "src/code-stubs.h"
18 #include "src/compiler.h"
19 #include "src/conversions-inl.h"
20 #include "src/counters.h"
21 #include "src/cpu-profiler.h"
22 #include "src/debug.h"
23 #include "src/deoptimizer.h"
24 #include "src/execution.h"
25 #include "src/global-handles.h"
26 #include "src/heap-profiler.h"
27 #include "src/heap-snapshot-generator-inl.h"
28 #include "src/icu_util.h"
29 #include "src/json-parser.h"
30 #include "src/messages.h"
31 #ifdef COMPRESS_STARTUP_DATA_BZ2
32 #include "src/natives.h"
33 #endif
34 #include "src/parser.h"
35 #include "src/platform.h"
36 #include "src/platform/time.h"
37 #include "src/profile-generator-inl.h"
38 #include "src/property-details.h"
39 #include "src/property.h"
40 #include "src/runtime.h"
41 #include "src/runtime-profiler.h"
42 #include "src/scanner-character-streams.h"
43 #include "src/simulator.h"
44 #include "src/snapshot.h"
45 #include "src/unicode-inl.h"
46 #include "src/utils/random-number-generator.h"
47 #include "src/v8threads.h"
48 #include "src/version.h"
49 #include "src/vm-state-inl.h"
50
51
52 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
53
54 #define ENTER_V8(isolate) \
55 ASSERT((isolate)->IsInitialized()); \
56 i::VMState<i::OTHER> __state__((isolate))
57
58 namespace v8 {
59
60 #define ON_BAILOUT(isolate, location, code) \
61 if (IsExecutionTerminatingCheck(isolate)) { \
62 code; \
63 UNREACHABLE(); \
64 }
65
66
67 #define EXCEPTION_PREAMBLE(isolate) \
68 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \
69 ASSERT(!(isolate)->external_caught_exception()); \
70 bool has_pending_exception = false
71
72
73 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback) \
74 do { \
75 i::HandleScopeImplementer* handle_scope_implementer = \
76 (isolate)->handle_scope_implementer(); \
77 handle_scope_implementer->DecrementCallDepth(); \
78 if (has_pending_exception) { \
79 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \
80 (isolate)->OptionalRescheduleException(call_depth_is_zero); \
81 do_callback \
82 return value; \
83 } \
84 do_callback \
85 } while (false)
86
87
88 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value) \
89 EXCEPTION_BAILOUT_CHECK_GENERIC( \
90 isolate, value, isolate->FireCallCompletedCallback();)
91
92
93 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \
94 EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
95
96
97 // --- E x c e p t i o n B e h a v i o r ---
98
99
FatalProcessOutOfMemory(const char * location)100 void i::FatalProcessOutOfMemory(const char* location) {
101 i::V8::FatalProcessOutOfMemory(location, false);
102 }
103
104
105 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
106 // The default fatal error handler is called and execution is stopped.
FatalProcessOutOfMemory(const char * location,bool take_snapshot)107 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
108 i::HeapStats heap_stats;
109 int start_marker;
110 heap_stats.start_marker = &start_marker;
111 int new_space_size;
112 heap_stats.new_space_size = &new_space_size;
113 int new_space_capacity;
114 heap_stats.new_space_capacity = &new_space_capacity;
115 intptr_t old_pointer_space_size;
116 heap_stats.old_pointer_space_size = &old_pointer_space_size;
117 intptr_t old_pointer_space_capacity;
118 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
119 intptr_t old_data_space_size;
120 heap_stats.old_data_space_size = &old_data_space_size;
121 intptr_t old_data_space_capacity;
122 heap_stats.old_data_space_capacity = &old_data_space_capacity;
123 intptr_t code_space_size;
124 heap_stats.code_space_size = &code_space_size;
125 intptr_t code_space_capacity;
126 heap_stats.code_space_capacity = &code_space_capacity;
127 intptr_t map_space_size;
128 heap_stats.map_space_size = &map_space_size;
129 intptr_t map_space_capacity;
130 heap_stats.map_space_capacity = &map_space_capacity;
131 intptr_t cell_space_size;
132 heap_stats.cell_space_size = &cell_space_size;
133 intptr_t cell_space_capacity;
134 heap_stats.cell_space_capacity = &cell_space_capacity;
135 intptr_t property_cell_space_size;
136 heap_stats.property_cell_space_size = &property_cell_space_size;
137 intptr_t property_cell_space_capacity;
138 heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
139 intptr_t lo_space_size;
140 heap_stats.lo_space_size = &lo_space_size;
141 int global_handle_count;
142 heap_stats.global_handle_count = &global_handle_count;
143 int weak_global_handle_count;
144 heap_stats.weak_global_handle_count = &weak_global_handle_count;
145 int pending_global_handle_count;
146 heap_stats.pending_global_handle_count = &pending_global_handle_count;
147 int near_death_global_handle_count;
148 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
149 int free_global_handle_count;
150 heap_stats.free_global_handle_count = &free_global_handle_count;
151 intptr_t memory_allocator_size;
152 heap_stats.memory_allocator_size = &memory_allocator_size;
153 intptr_t memory_allocator_capacity;
154 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
155 int objects_per_type[LAST_TYPE + 1] = {0};
156 heap_stats.objects_per_type = objects_per_type;
157 int size_per_type[LAST_TYPE + 1] = {0};
158 heap_stats.size_per_type = size_per_type;
159 int os_error;
160 heap_stats.os_error = &os_error;
161 int end_marker;
162 heap_stats.end_marker = &end_marker;
163 i::Isolate* isolate = i::Isolate::Current();
164 if (isolate->heap()->HasBeenSetUp()) {
165 // BUG(1718): Don't use the take_snapshot since we don't support
166 // HeapIterator here without doing a special GC.
167 isolate->heap()->RecordStats(&heap_stats, false);
168 }
169 Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
170 // If the fatal error handler returns, we stop execution.
171 FATAL("API fatal error handler returned after process out of memory");
172 }
173
174
ReportApiFailure(const char * location,const char * message)175 void Utils::ReportApiFailure(const char* location, const char* message) {
176 i::Isolate* isolate = i::Isolate::Current();
177 FatalErrorCallback callback = isolate->exception_behavior();
178 if (callback == NULL) {
179 i::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n",
180 location, message);
181 i::OS::Abort();
182 } else {
183 callback(location, message);
184 }
185 isolate->SignalFatalError();
186 }
187
188
IsDead()189 bool V8::IsDead() {
190 i::Isolate* isolate = i::Isolate::Current();
191 return isolate->IsDead();
192 }
193
194
IsExecutionTerminatingCheck(i::Isolate * isolate)195 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
196 if (!isolate->IsInitialized()) return false;
197 if (isolate->has_scheduled_exception()) {
198 return isolate->scheduled_exception() ==
199 isolate->heap()->termination_exception();
200 }
201 return false;
202 }
203
204
205 // --- S t a t i c s ---
206
207
InitializeHelper(i::Isolate * isolate)208 static bool InitializeHelper(i::Isolate* isolate) {
209 // If the isolate has a function entry hook, it needs to re-build all its
210 // code stubs with entry hooks embedded, so let's deserialize a snapshot.
211 if (isolate == NULL || isolate->function_entry_hook() == NULL) {
212 if (i::Snapshot::Initialize())
213 return true;
214 }
215 return i::V8::Initialize(NULL);
216 }
217
218
EnsureInitializedForIsolate(i::Isolate * isolate,const char * location)219 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
220 const char* location) {
221 return (isolate != NULL && isolate->IsInitialized()) ||
222 Utils::ApiCheck(InitializeHelper(isolate),
223 location,
224 "Error initializing V8");
225 }
226
227
StartupDataDecompressor()228 StartupDataDecompressor::StartupDataDecompressor()
229 : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
230 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
231 raw_data[i] = NULL;
232 }
233 }
234
235
~StartupDataDecompressor()236 StartupDataDecompressor::~StartupDataDecompressor() {
237 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
238 i::DeleteArray(raw_data[i]);
239 }
240 i::DeleteArray(raw_data);
241 }
242
243
Decompress()244 int StartupDataDecompressor::Decompress() {
245 int compressed_data_count = V8::GetCompressedStartupDataCount();
246 StartupData* compressed_data =
247 i::NewArray<StartupData>(compressed_data_count);
248 V8::GetCompressedStartupData(compressed_data);
249 for (int i = 0; i < compressed_data_count; ++i) {
250 char* decompressed = raw_data[i] =
251 i::NewArray<char>(compressed_data[i].raw_size);
252 if (compressed_data[i].compressed_size != 0) {
253 int result = DecompressData(decompressed,
254 &compressed_data[i].raw_size,
255 compressed_data[i].data,
256 compressed_data[i].compressed_size);
257 if (result != 0) return result;
258 } else {
259 ASSERT_EQ(0, compressed_data[i].raw_size);
260 }
261 compressed_data[i].data = decompressed;
262 }
263 V8::SetDecompressedStartupData(compressed_data);
264 i::DeleteArray(compressed_data);
265 return 0;
266 }
267
268
GetCompressedStartupDataAlgorithm()269 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() {
270 #ifdef COMPRESS_STARTUP_DATA_BZ2
271 return StartupData::kBZip2;
272 #else
273 return StartupData::kUncompressed;
274 #endif
275 }
276
277
278 enum CompressedStartupDataItems {
279 kSnapshot = 0,
280 kSnapshotContext,
281 kLibraries,
282 kExperimentalLibraries,
283 kCompressedStartupDataCount
284 };
285
286
GetCompressedStartupDataCount()287 int V8::GetCompressedStartupDataCount() {
288 #ifdef COMPRESS_STARTUP_DATA_BZ2
289 return kCompressedStartupDataCount;
290 #else
291 return 0;
292 #endif
293 }
294
295
GetCompressedStartupData(StartupData * compressed_data)296 void V8::GetCompressedStartupData(StartupData* compressed_data) {
297 #ifdef COMPRESS_STARTUP_DATA_BZ2
298 compressed_data[kSnapshot].data =
299 reinterpret_cast<const char*>(i::Snapshot::data());
300 compressed_data[kSnapshot].compressed_size = i::Snapshot::size();
301 compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size();
302
303 compressed_data[kSnapshotContext].data =
304 reinterpret_cast<const char*>(i::Snapshot::context_data());
305 compressed_data[kSnapshotContext].compressed_size =
306 i::Snapshot::context_size();
307 compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size();
308
309 i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource();
310 compressed_data[kLibraries].data =
311 reinterpret_cast<const char*>(libraries_source.start());
312 compressed_data[kLibraries].compressed_size = libraries_source.length();
313 compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize();
314
315 i::Vector<const i::byte> exp_libraries_source =
316 i::ExperimentalNatives::GetScriptsSource();
317 compressed_data[kExperimentalLibraries].data =
318 reinterpret_cast<const char*>(exp_libraries_source.start());
319 compressed_data[kExperimentalLibraries].compressed_size =
320 exp_libraries_source.length();
321 compressed_data[kExperimentalLibraries].raw_size =
322 i::ExperimentalNatives::GetRawScriptsSize();
323 #endif
324 }
325
326
SetDecompressedStartupData(StartupData * decompressed_data)327 void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
328 #ifdef COMPRESS_STARTUP_DATA_BZ2
329 ASSERT_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size);
330 i::Snapshot::set_raw_data(
331 reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data));
332
333 ASSERT_EQ(i::Snapshot::context_raw_size(),
334 decompressed_data[kSnapshotContext].raw_size);
335 i::Snapshot::set_context_raw_data(
336 reinterpret_cast<const i::byte*>(
337 decompressed_data[kSnapshotContext].data));
338
339 ASSERT_EQ(i::Natives::GetRawScriptsSize(),
340 decompressed_data[kLibraries].raw_size);
341 i::Vector<const char> libraries_source(
342 decompressed_data[kLibraries].data,
343 decompressed_data[kLibraries].raw_size);
344 i::Natives::SetRawScriptsSource(libraries_source);
345
346 ASSERT_EQ(i::ExperimentalNatives::GetRawScriptsSize(),
347 decompressed_data[kExperimentalLibraries].raw_size);
348 i::Vector<const char> exp_libraries_source(
349 decompressed_data[kExperimentalLibraries].data,
350 decompressed_data[kExperimentalLibraries].raw_size);
351 i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
352 #endif
353 }
354
355
SetFatalErrorHandler(FatalErrorCallback that)356 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
357 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
358 isolate->set_exception_behavior(that);
359 }
360
361
SetAllowCodeGenerationFromStringsCallback(AllowCodeGenerationFromStringsCallback callback)362 void V8::SetAllowCodeGenerationFromStringsCallback(
363 AllowCodeGenerationFromStringsCallback callback) {
364 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
365 isolate->set_allow_code_gen_callback(callback);
366 }
367
368
SetFlagsFromString(const char * str,int length)369 void V8::SetFlagsFromString(const char* str, int length) {
370 i::FlagList::SetFlagsFromString(str, length);
371 }
372
373
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)374 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
375 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
376 }
377
378
379 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
380
381
RegisteredExtension(Extension * extension)382 RegisteredExtension::RegisteredExtension(Extension* extension)
383 : extension_(extension) { }
384
385
Register(RegisteredExtension * that)386 void RegisteredExtension::Register(RegisteredExtension* that) {
387 that->next_ = first_extension_;
388 first_extension_ = that;
389 }
390
391
UnregisterAll()392 void RegisteredExtension::UnregisterAll() {
393 RegisteredExtension* re = first_extension_;
394 while (re != NULL) {
395 RegisteredExtension* next = re->next();
396 delete re;
397 re = next;
398 }
399 }
400
401
RegisterExtension(Extension * that)402 void RegisterExtension(Extension* that) {
403 RegisteredExtension* extension = new RegisteredExtension(that);
404 RegisteredExtension::Register(extension);
405 }
406
407
Extension(const char * name,const char * source,int dep_count,const char ** deps,int source_length)408 Extension::Extension(const char* name,
409 const char* source,
410 int dep_count,
411 const char** deps,
412 int source_length)
413 : name_(name),
414 source_length_(source_length >= 0 ?
415 source_length :
416 (source ? static_cast<int>(strlen(source)) : 0)),
417 source_(source, source_length_),
418 dep_count_(dep_count),
419 deps_(deps),
420 auto_enable_(false) {
421 CHECK(source != NULL || source_length_ == 0);
422 }
423
424
ResourceConstraints()425 ResourceConstraints::ResourceConstraints()
426 : max_semi_space_size_(0),
427 max_old_space_size_(0),
428 max_executable_size_(0),
429 stack_limit_(NULL),
430 max_available_threads_(0),
431 code_range_size_(0) { }
432
ConfigureDefaults(uint64_t physical_memory,uint64_t virtual_memory_limit,uint32_t number_of_processors)433 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
434 uint64_t virtual_memory_limit,
435 uint32_t number_of_processors) {
436 #if V8_OS_ANDROID
437 // Android has higher physical memory requirements before raising the maximum
438 // heap size limits since it has no swap space.
439 const uint64_t low_limit = 512ul * i::MB;
440 const uint64_t medium_limit = 1ul * i::GB;
441 const uint64_t high_limit = 2ul * i::GB;
442 #else
443 const uint64_t low_limit = 512ul * i::MB;
444 const uint64_t medium_limit = 768ul * i::MB;
445 const uint64_t high_limit = 1ul * i::GB;
446 #endif
447
448 if (physical_memory <= low_limit) {
449 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice);
450 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice);
451 set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice);
452 } else if (physical_memory <= medium_limit) {
453 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice);
454 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice);
455 set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice);
456 } else if (physical_memory <= high_limit) {
457 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice);
458 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice);
459 set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice);
460 } else {
461 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice);
462 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice);
463 set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
464 }
465
466 set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
467
468 if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
469 // Reserve no more than 1/8 of the memory for the code range, but at most
470 // kMaximalCodeRangeSize.
471 set_code_range_size(
472 i::Min(i::kMaximalCodeRangeSize / i::MB,
473 static_cast<size_t>((virtual_memory_limit >> 3) / i::MB)));
474 }
475 }
476
477
SetResourceConstraints(Isolate * v8_isolate,ResourceConstraints * constraints)478 bool SetResourceConstraints(Isolate* v8_isolate,
479 ResourceConstraints* constraints) {
480 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
481 int semi_space_size = constraints->max_semi_space_size();
482 int old_space_size = constraints->max_old_space_size();
483 int max_executable_size = constraints->max_executable_size();
484 size_t code_range_size = constraints->code_range_size();
485 if (semi_space_size != 0 || old_space_size != 0 ||
486 max_executable_size != 0 || code_range_size != 0) {
487 // After initialization it's too late to change Heap constraints.
488 ASSERT(!isolate->IsInitialized());
489 bool result = isolate->heap()->ConfigureHeap(semi_space_size,
490 old_space_size,
491 max_executable_size,
492 code_range_size);
493 if (!result) return false;
494 }
495 if (constraints->stack_limit() != NULL) {
496 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
497 isolate->stack_guard()->SetStackLimit(limit);
498 }
499
500 isolate->set_max_available_threads(constraints->max_available_threads());
501 return true;
502 }
503
504
GlobalizeReference(i::Isolate * isolate,i::Object ** obj)505 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
506 LOG_API(isolate, "Persistent::New");
507 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
508 #ifdef DEBUG
509 (*obj)->ObjectVerify();
510 #endif // DEBUG
511 return result.location();
512 }
513
514
CopyPersistent(i::Object ** obj)515 i::Object** V8::CopyPersistent(i::Object** obj) {
516 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
517 #ifdef DEBUG
518 (*obj)->ObjectVerify();
519 #endif // DEBUG
520 return result.location();
521 }
522
523
MakeWeak(i::Object ** object,void * parameters,WeakCallback weak_callback)524 void V8::MakeWeak(i::Object** object,
525 void* parameters,
526 WeakCallback weak_callback) {
527 i::GlobalHandles::MakeWeak(object, parameters, weak_callback);
528 }
529
530
ClearWeak(i::Object ** obj)531 void* V8::ClearWeak(i::Object** obj) {
532 return i::GlobalHandles::ClearWeakness(obj);
533 }
534
535
DisposeGlobal(i::Object ** obj)536 void V8::DisposeGlobal(i::Object** obj) {
537 i::GlobalHandles::Destroy(obj);
538 }
539
540
Eternalize(Isolate * v8_isolate,Value * value,int * index)541 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
542 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
543 i::Object* object = *Utils::OpenHandle(value);
544 isolate->eternal_handles()->Create(isolate, object, index);
545 }
546
547
GetEternal(Isolate * v8_isolate,int index)548 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
549 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
550 return Utils::ToLocal(isolate->eternal_handles()->Get(index));
551 }
552
553
554 // --- H a n d l e s ---
555
556
HandleScope(Isolate * isolate)557 HandleScope::HandleScope(Isolate* isolate) {
558 Initialize(isolate);
559 }
560
561
Initialize(Isolate * isolate)562 void HandleScope::Initialize(Isolate* isolate) {
563 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
564 // We do not want to check the correct usage of the Locker class all over the
565 // place, so we do it only here: Without a HandleScope, an embedder can do
566 // almost nothing, so it is enough to check in this central place.
567 Utils::ApiCheck(!v8::Locker::IsActive() ||
568 internal_isolate->thread_manager()->IsLockedByCurrentThread(),
569 "HandleScope::HandleScope",
570 "Entering the V8 API without proper locking in place");
571 i::HandleScopeData* current = internal_isolate->handle_scope_data();
572 isolate_ = internal_isolate;
573 prev_next_ = current->next;
574 prev_limit_ = current->limit;
575 current->level++;
576 }
577
578
~HandleScope()579 HandleScope::~HandleScope() {
580 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
581 }
582
583
NumberOfHandles(Isolate * isolate)584 int HandleScope::NumberOfHandles(Isolate* isolate) {
585 return i::HandleScope::NumberOfHandles(
586 reinterpret_cast<i::Isolate*>(isolate));
587 }
588
589
CreateHandle(i::Isolate * isolate,i::Object * value)590 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
591 return i::HandleScope::CreateHandle(isolate, value);
592 }
593
594
CreateHandle(i::HeapObject * heap_object,i::Object * value)595 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
596 i::Object* value) {
597 ASSERT(heap_object->IsHeapObject());
598 return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
599 }
600
601
EscapableHandleScope(Isolate * v8_isolate)602 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
603 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
604 escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
605 Initialize(v8_isolate);
606 }
607
608
Escape(i::Object ** escape_value)609 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
610 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
611 Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(),
612 "EscapeableHandleScope::Escape",
613 "Escape value set twice");
614 if (escape_value == NULL) {
615 *escape_slot_ = heap->undefined_value();
616 return NULL;
617 }
618 *escape_slot_ = *escape_value;
619 return escape_slot_;
620 }
621
622
Enter()623 void Context::Enter() {
624 i::Handle<i::Context> env = Utils::OpenHandle(this);
625 i::Isolate* isolate = env->GetIsolate();
626 ENTER_V8(isolate);
627 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
628 impl->EnterContext(env);
629 impl->SaveContext(isolate->context());
630 isolate->set_context(*env);
631 }
632
633
Exit()634 void Context::Exit() {
635 i::Handle<i::Context> env = Utils::OpenHandle(this);
636 i::Isolate* isolate = env->GetIsolate();
637 ENTER_V8(isolate);
638 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
639 if (!Utils::ApiCheck(impl->LastEnteredContextWas(env),
640 "v8::Context::Exit()",
641 "Cannot exit non-entered context")) {
642 return;
643 }
644 impl->LeaveContext();
645 isolate->set_context(impl->RestoreContext());
646 }
647
648
DecodeSmiToAligned(i::Object * value,const char * location)649 static void* DecodeSmiToAligned(i::Object* value, const char* location) {
650 Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
651 return reinterpret_cast<void*>(value);
652 }
653
654
EncodeAlignedAsSmi(void * value,const char * location)655 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
656 i::Smi* smi = reinterpret_cast<i::Smi*>(value);
657 Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
658 return smi;
659 }
660
661
EmbedderDataFor(Context * context,int index,bool can_grow,const char * location)662 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
663 int index,
664 bool can_grow,
665 const char* location) {
666 i::Handle<i::Context> env = Utils::OpenHandle(context);
667 bool ok =
668 Utils::ApiCheck(env->IsNativeContext(),
669 location,
670 "Not a native context") &&
671 Utils::ApiCheck(index >= 0, location, "Negative index");
672 if (!ok) return i::Handle<i::FixedArray>();
673 i::Handle<i::FixedArray> data(env->embedder_data());
674 if (index < data->length()) return data;
675 if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
676 return i::Handle<i::FixedArray>();
677 }
678 int new_size = i::Max(index, data->length() << 1) + 1;
679 data = i::FixedArray::CopySize(data, new_size);
680 env->set_embedder_data(*data);
681 return data;
682 }
683
684
SlowGetEmbedderData(int index)685 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
686 const char* location = "v8::Context::GetEmbedderData()";
687 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
688 if (data.is_null()) return Local<Value>();
689 i::Handle<i::Object> result(data->get(index), data->GetIsolate());
690 return Utils::ToLocal(result);
691 }
692
693
SetEmbedderData(int index,v8::Handle<Value> value)694 void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
695 const char* location = "v8::Context::SetEmbedderData()";
696 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
697 if (data.is_null()) return;
698 i::Handle<i::Object> val = Utils::OpenHandle(*value);
699 data->set(index, *val);
700 ASSERT_EQ(*Utils::OpenHandle(*value),
701 *Utils::OpenHandle(*GetEmbedderData(index)));
702 }
703
704
SlowGetAlignedPointerFromEmbedderData(int index)705 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
706 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
707 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
708 if (data.is_null()) return NULL;
709 return DecodeSmiToAligned(data->get(index), location);
710 }
711
712
SetAlignedPointerInEmbedderData(int index,void * value)713 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
714 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
715 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
716 data->set(index, EncodeAlignedAsSmi(value, location));
717 ASSERT_EQ(value, GetAlignedPointerFromEmbedderData(index));
718 }
719
720
721 // --- N e a n d e r ---
722
723
724 // A constructor cannot easily return an error value, therefore it is necessary
725 // to check for a dead VM with ON_BAILOUT before constructing any Neander
726 // objects. To remind you about this there is no HandleScope in the
727 // NeanderObject constructor. When you add one to the site calling the
728 // constructor you should check that you ensured the VM was not dead first.
NeanderObject(v8::internal::Isolate * isolate,int size)729 NeanderObject::NeanderObject(v8::internal::Isolate* isolate, int size) {
730 EnsureInitializedForIsolate(isolate, "v8::Nowhere");
731 ENTER_V8(isolate);
732 value_ = isolate->factory()->NewNeanderObject();
733 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
734 value_->set_elements(*elements);
735 }
736
737
size()738 int NeanderObject::size() {
739 return i::FixedArray::cast(value_->elements())->length();
740 }
741
742
NeanderArray(v8::internal::Isolate * isolate)743 NeanderArray::NeanderArray(v8::internal::Isolate* isolate) : obj_(isolate, 2) {
744 obj_.set(0, i::Smi::FromInt(0));
745 }
746
747
length()748 int NeanderArray::length() {
749 return i::Smi::cast(obj_.get(0))->value();
750 }
751
752
get(int offset)753 i::Object* NeanderArray::get(int offset) {
754 ASSERT(0 <= offset);
755 ASSERT(offset < length());
756 return obj_.get(offset + 1);
757 }
758
759
760 // This method cannot easily return an error value, therefore it is necessary
761 // to check for a dead VM with ON_BAILOUT before calling it. To remind you
762 // about this there is no HandleScope in this method. When you add one to the
763 // site calling this method you should check that you ensured the VM was not
764 // dead first.
add(i::Handle<i::Object> value)765 void NeanderArray::add(i::Handle<i::Object> value) {
766 int length = this->length();
767 int size = obj_.size();
768 if (length == size - 1) {
769 i::Factory* factory = i::Isolate::Current()->factory();
770 i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size);
771 for (int i = 0; i < length; i++)
772 new_elms->set(i + 1, get(i));
773 obj_.value()->set_elements(*new_elms);
774 }
775 obj_.set(length + 1, *value);
776 obj_.set(0, i::Smi::FromInt(length + 1));
777 }
778
779
set(int index,i::Object * value)780 void NeanderArray::set(int index, i::Object* value) {
781 if (index < 0 || index >= this->length()) return;
782 obj_.set(index + 1, value);
783 }
784
785
786 // --- T e m p l a t e ---
787
788
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)789 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
790 that->set_tag(i::Smi::FromInt(type));
791 }
792
793
TemplateSet(i::Isolate * isolate,v8::Template * templ,int length,v8::Handle<v8::Data> * data)794 static void TemplateSet(i::Isolate* isolate,
795 v8::Template* templ,
796 int length,
797 v8::Handle<v8::Data>* data) {
798 i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
799 if (list->IsUndefined()) {
800 list = NeanderArray(isolate).value();
801 Utils::OpenHandle(templ)->set_property_list(*list);
802 }
803 NeanderArray array(list);
804 array.add(isolate->factory()->NewNumberFromInt(length));
805 for (int i = 0; i < length; i++) {
806 i::Handle<i::Object> value = data[i].IsEmpty() ?
807 i::Handle<i::Object>(isolate->factory()->undefined_value()) :
808 Utils::OpenHandle(*data[i]);
809 array.add(value);
810 }
811 }
812
813
Set(v8::Handle<String> name,v8::Handle<Data> value,v8::PropertyAttribute attribute)814 void Template::Set(v8::Handle<String> name,
815 v8::Handle<Data> value,
816 v8::PropertyAttribute attribute) {
817 i::Isolate* isolate = i::Isolate::Current();
818 ENTER_V8(isolate);
819 i::HandleScope scope(isolate);
820 const int kSize = 3;
821 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
822 v8::Handle<v8::Data> data[kSize] = {
823 name,
824 value,
825 v8::Integer::New(v8_isolate, attribute)};
826 TemplateSet(isolate, this, kSize, data);
827 }
828
829
SetAccessorProperty(v8::Local<v8::String> name,v8::Local<FunctionTemplate> getter,v8::Local<FunctionTemplate> setter,v8::PropertyAttribute attribute,v8::AccessControl access_control)830 void Template::SetAccessorProperty(
831 v8::Local<v8::String> name,
832 v8::Local<FunctionTemplate> getter,
833 v8::Local<FunctionTemplate> setter,
834 v8::PropertyAttribute attribute,
835 v8::AccessControl access_control) {
836 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
837 ENTER_V8(isolate);
838 ASSERT(!name.IsEmpty());
839 ASSERT(!getter.IsEmpty() || !setter.IsEmpty());
840 i::HandleScope scope(isolate);
841 const int kSize = 5;
842 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
843 v8::Handle<v8::Data> data[kSize] = {
844 name,
845 getter,
846 setter,
847 v8::Integer::New(v8_isolate, attribute),
848 v8::Integer::New(v8_isolate, access_control)};
849 TemplateSet(isolate, this, kSize, data);
850 }
851
852
853 // --- F u n c t i o n T e m p l a t e ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)854 static void InitializeFunctionTemplate(
855 i::Handle<i::FunctionTemplateInfo> info) {
856 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
857 info->set_flag(0);
858 }
859
860
PrototypeTemplate()861 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
862 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
863 ENTER_V8(i_isolate);
864 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
865 i_isolate);
866 if (result->IsUndefined()) {
867 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(i_isolate);
868 result = Utils::OpenHandle(*ObjectTemplate::New(isolate));
869 Utils::OpenHandle(this)->set_prototype_template(*result);
870 }
871 return ToApiHandle<ObjectTemplate>(result);
872 }
873
874
Inherit(v8::Handle<FunctionTemplate> value)875 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
876 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
877 ENTER_V8(isolate);
878 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
879 }
880
881
FunctionTemplateNew(i::Isolate * isolate,FunctionCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature,int length,bool do_not_cache)882 static Local<FunctionTemplate> FunctionTemplateNew(
883 i::Isolate* isolate,
884 FunctionCallback callback,
885 v8::Handle<Value> data,
886 v8::Handle<Signature> signature,
887 int length,
888 bool do_not_cache) {
889 i::Handle<i::Struct> struct_obj =
890 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
891 i::Handle<i::FunctionTemplateInfo> obj =
892 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
893 InitializeFunctionTemplate(obj);
894 obj->set_do_not_cache(do_not_cache);
895 int next_serial_number = 0;
896 if (!do_not_cache) {
897 next_serial_number = isolate->next_serial_number() + 1;
898 isolate->set_next_serial_number(next_serial_number);
899 }
900 obj->set_serial_number(i::Smi::FromInt(next_serial_number));
901 if (callback != 0) {
902 if (data.IsEmpty()) {
903 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
904 }
905 Utils::ToLocal(obj)->SetCallHandler(callback, data);
906 }
907 obj->set_length(length);
908 obj->set_undetectable(false);
909 obj->set_needs_access_check(false);
910 if (!signature.IsEmpty())
911 obj->set_signature(*Utils::OpenHandle(*signature));
912 return Utils::ToLocal(obj);
913 }
914
New(Isolate * isolate,FunctionCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature,int length)915 Local<FunctionTemplate> FunctionTemplate::New(
916 Isolate* isolate,
917 FunctionCallback callback,
918 v8::Handle<Value> data,
919 v8::Handle<Signature> signature,
920 int length) {
921 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
922 EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()");
923 LOG_API(i_isolate, "FunctionTemplate::New");
924 ENTER_V8(i_isolate);
925 return FunctionTemplateNew(
926 i_isolate, callback, data, signature, length, false);
927 }
928
929
New(Isolate * isolate,Handle<FunctionTemplate> receiver,int argc,Handle<FunctionTemplate> argv[])930 Local<Signature> Signature::New(Isolate* isolate,
931 Handle<FunctionTemplate> receiver, int argc,
932 Handle<FunctionTemplate> argv[]) {
933 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
934 EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()");
935 LOG_API(i_isolate, "Signature::New");
936 ENTER_V8(i_isolate);
937 i::Handle<i::Struct> struct_obj =
938 i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
939 i::Handle<i::SignatureInfo> obj =
940 i::Handle<i::SignatureInfo>::cast(struct_obj);
941 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
942 if (argc > 0) {
943 i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
944 for (int i = 0; i < argc; i++) {
945 if (!argv[i].IsEmpty())
946 args->set(i, *Utils::OpenHandle(*argv[i]));
947 }
948 obj->set_args(*args);
949 }
950 return Utils::ToLocal(obj);
951 }
952
953
New(Isolate * isolate,Handle<FunctionTemplate> receiver)954 Local<AccessorSignature> AccessorSignature::New(
955 Isolate* isolate,
956 Handle<FunctionTemplate> receiver) {
957 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
958 }
959
960
961 template<typename Operation>
NewDescriptor(Isolate * isolate,const i::DeclaredAccessorDescriptorData & data,Data * previous_descriptor)962 static Local<Operation> NewDescriptor(
963 Isolate* isolate,
964 const i::DeclaredAccessorDescriptorData& data,
965 Data* previous_descriptor) {
966 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
967 i::Handle<i::DeclaredAccessorDescriptor> previous =
968 i::Handle<i::DeclaredAccessorDescriptor>();
969 if (previous_descriptor != NULL) {
970 previous = Utils::OpenHandle(
971 static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
972 }
973 i::Handle<i::DeclaredAccessorDescriptor> descriptor =
974 i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
975 return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
976 }
977
978
979 Local<RawOperationDescriptor>
NewInternalFieldDereference(Isolate * isolate,int internal_field)980 ObjectOperationDescriptor::NewInternalFieldDereference(
981 Isolate* isolate,
982 int internal_field) {
983 i::DeclaredAccessorDescriptorData data;
984 data.type = i::kDescriptorObjectDereference;
985 data.object_dereference_descriptor.internal_field = internal_field;
986 return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
987 }
988
989
NewRawShift(Isolate * isolate,int16_t byte_offset)990 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
991 Isolate* isolate,
992 int16_t byte_offset) {
993 i::DeclaredAccessorDescriptorData data;
994 data.type = i::kDescriptorPointerShift;
995 data.pointer_shift_descriptor.byte_offset = byte_offset;
996 return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
997 }
998
999
NewHandleDereference(Isolate * isolate)1000 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
1001 Isolate* isolate) {
1002 i::DeclaredAccessorDescriptorData data;
1003 data.type = i::kDescriptorReturnObject;
1004 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1005 }
1006
1007
NewRawDereference(Isolate * isolate)1008 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
1009 Isolate* isolate) {
1010 i::DeclaredAccessorDescriptorData data;
1011 data.type = i::kDescriptorPointerDereference;
1012 return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1013 }
1014
1015
NewPointerCompare(Isolate * isolate,void * compare_value)1016 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
1017 Isolate* isolate,
1018 void* compare_value) {
1019 i::DeclaredAccessorDescriptorData data;
1020 data.type = i::kDescriptorPointerCompare;
1021 data.pointer_compare_descriptor.compare_value = compare_value;
1022 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1023 }
1024
1025
NewPrimitiveValue(Isolate * isolate,DeclaredAccessorDescriptorDataType data_type,uint8_t bool_offset)1026 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
1027 Isolate* isolate,
1028 DeclaredAccessorDescriptorDataType data_type,
1029 uint8_t bool_offset) {
1030 i::DeclaredAccessorDescriptorData data;
1031 data.type = i::kDescriptorPrimitiveValue;
1032 data.primitive_value_descriptor.data_type = data_type;
1033 data.primitive_value_descriptor.bool_offset = bool_offset;
1034 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1035 }
1036
1037
1038 template<typename T>
NewBitmaskCompare(Isolate * isolate,T bitmask,T compare_value,RawOperationDescriptor * operation)1039 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
1040 Isolate* isolate,
1041 T bitmask,
1042 T compare_value,
1043 RawOperationDescriptor* operation) {
1044 i::DeclaredAccessorDescriptorData data;
1045 data.type = i::kDescriptorBitmaskCompare;
1046 data.bitmask_compare_descriptor.bitmask = bitmask;
1047 data.bitmask_compare_descriptor.compare_value = compare_value;
1048 data.bitmask_compare_descriptor.size = sizeof(T);
1049 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
1050 }
1051
1052
NewBitmaskCompare8(Isolate * isolate,uint8_t bitmask,uint8_t compare_value)1053 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
1054 Isolate* isolate,
1055 uint8_t bitmask,
1056 uint8_t compare_value) {
1057 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1058 }
1059
1060
NewBitmaskCompare16(Isolate * isolate,uint16_t bitmask,uint16_t compare_value)1061 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
1062 Isolate* isolate,
1063 uint16_t bitmask,
1064 uint16_t compare_value) {
1065 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1066 }
1067
1068
NewBitmaskCompare32(Isolate * isolate,uint32_t bitmask,uint32_t compare_value)1069 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
1070 Isolate* isolate,
1071 uint32_t bitmask,
1072 uint32_t compare_value) {
1073 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1074 }
1075
1076
New(Handle<FunctionTemplate> type)1077 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
1078 Handle<FunctionTemplate> types[1] = { type };
1079 return TypeSwitch::New(1, types);
1080 }
1081
1082
New(int argc,Handle<FunctionTemplate> types[])1083 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
1084 i::Isolate* isolate = i::Isolate::Current();
1085 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
1086 LOG_API(isolate, "TypeSwitch::New");
1087 ENTER_V8(isolate);
1088 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
1089 for (int i = 0; i < argc; i++)
1090 vector->set(i, *Utils::OpenHandle(*types[i]));
1091 i::Handle<i::Struct> struct_obj =
1092 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
1093 i::Handle<i::TypeSwitchInfo> obj =
1094 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
1095 obj->set_types(*vector);
1096 return Utils::ToLocal(obj);
1097 }
1098
1099
match(v8::Handle<Value> value)1100 int TypeSwitch::match(v8::Handle<Value> value) {
1101 i::Isolate* isolate = i::Isolate::Current();
1102 LOG_API(isolate, "TypeSwitch::match");
1103 USE(isolate);
1104 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
1105 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
1106 i::FixedArray* types = i::FixedArray::cast(info->types());
1107 for (int i = 0; i < types->length(); i++) {
1108 if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj))
1109 return i + 1;
1110 }
1111 return 0;
1112 }
1113
1114
1115 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
1116 i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
1117 (obj)->setter(*foreign); \
1118 } while (false)
1119
1120
SetCallHandler(FunctionCallback callback,v8::Handle<Value> data)1121 void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1122 v8::Handle<Value> data) {
1123 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1124 ENTER_V8(isolate);
1125 i::HandleScope scope(isolate);
1126 i::Handle<i::Struct> struct_obj =
1127 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1128 i::Handle<i::CallHandlerInfo> obj =
1129 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1130 SET_FIELD_WRAPPED(obj, set_callback, callback);
1131 if (data.IsEmpty()) {
1132 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1133 }
1134 obj->set_data(*Utils::OpenHandle(*data));
1135 Utils::OpenHandle(this)->set_call_code(*obj);
1136 }
1137
1138
SetAccessorInfoProperties(i::Handle<i::AccessorInfo> obj,v8::Handle<String> name,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1139 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
1140 i::Handle<i::AccessorInfo> obj,
1141 v8::Handle<String> name,
1142 v8::AccessControl settings,
1143 v8::PropertyAttribute attributes,
1144 v8::Handle<AccessorSignature> signature) {
1145 obj->set_name(*Utils::OpenHandle(*name));
1146 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1147 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1148 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
1149 if (!signature.IsEmpty()) {
1150 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1151 }
1152 return obj;
1153 }
1154
1155
1156 template<typename Getter, typename Setter>
MakeAccessorInfo(v8::Handle<String> name,Getter getter,Setter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1157 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1158 v8::Handle<String> name,
1159 Getter getter,
1160 Setter setter,
1161 v8::Handle<Value> data,
1162 v8::AccessControl settings,
1163 v8::PropertyAttribute attributes,
1164 v8::Handle<AccessorSignature> signature) {
1165 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1166 i::Handle<i::ExecutableAccessorInfo> obj =
1167 isolate->factory()->NewExecutableAccessorInfo();
1168 SET_FIELD_WRAPPED(obj, set_getter, getter);
1169 SET_FIELD_WRAPPED(obj, set_setter, setter);
1170 if (data.IsEmpty()) {
1171 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1172 }
1173 obj->set_data(*Utils::OpenHandle(*data));
1174 return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1175 }
1176
1177
MakeAccessorInfo(v8::Handle<String> name,v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,void * setter_ignored,void * data_ignored,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Handle<AccessorSignature> signature)1178 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1179 v8::Handle<String> name,
1180 v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
1181 void* setter_ignored,
1182 void* data_ignored,
1183 v8::AccessControl settings,
1184 v8::PropertyAttribute attributes,
1185 v8::Handle<AccessorSignature> signature) {
1186 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1187 if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
1188 i::Handle<i::DeclaredAccessorInfo> obj =
1189 isolate->factory()->NewDeclaredAccessorInfo();
1190 obj->set_descriptor(*Utils::OpenHandle(*descriptor));
1191 return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1192 }
1193
1194
InstanceTemplate()1195 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1196 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1197 if (!Utils::ApiCheck(!handle.is_null(),
1198 "v8::FunctionTemplate::InstanceTemplate()",
1199 "Reading from empty handle")) {
1200 return Local<ObjectTemplate>();
1201 }
1202 i::Isolate* isolate = handle->GetIsolate();
1203 ENTER_V8(isolate);
1204 if (handle->instance_template()->IsUndefined()) {
1205 Local<ObjectTemplate> templ =
1206 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1207 handle->set_instance_template(*Utils::OpenHandle(*templ));
1208 }
1209 i::Handle<i::ObjectTemplateInfo> result(
1210 i::ObjectTemplateInfo::cast(handle->instance_template()));
1211 return Utils::ToLocal(result);
1212 }
1213
1214
SetLength(int length)1215 void FunctionTemplate::SetLength(int length) {
1216 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1217 ENTER_V8(isolate);
1218 Utils::OpenHandle(this)->set_length(length);
1219 }
1220
1221
SetClassName(Handle<String> name)1222 void FunctionTemplate::SetClassName(Handle<String> name) {
1223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1224 ENTER_V8(isolate);
1225 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
1226 }
1227
1228
SetHiddenPrototype(bool value)1229 void FunctionTemplate::SetHiddenPrototype(bool value) {
1230 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1231 ENTER_V8(isolate);
1232 Utils::OpenHandle(this)->set_hidden_prototype(value);
1233 }
1234
1235
ReadOnlyPrototype()1236 void FunctionTemplate::ReadOnlyPrototype() {
1237 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1238 ENTER_V8(isolate);
1239 Utils::OpenHandle(this)->set_read_only_prototype(true);
1240 }
1241
1242
RemovePrototype()1243 void FunctionTemplate::RemovePrototype() {
1244 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1245 ENTER_V8(isolate);
1246 Utils::OpenHandle(this)->set_remove_prototype(true);
1247 }
1248
1249
1250 // --- O b j e c t T e m p l a t e ---
1251
1252
New(Isolate * isolate)1253 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
1254 return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
1255 }
1256
1257
New()1258 Local<ObjectTemplate> ObjectTemplate::New() {
1259 return New(i::Isolate::Current(), Local<FunctionTemplate>());
1260 }
1261
1262
New(i::Isolate * isolate,v8::Handle<FunctionTemplate> constructor)1263 Local<ObjectTemplate> ObjectTemplate::New(
1264 i::Isolate* isolate,
1265 v8::Handle<FunctionTemplate> constructor) {
1266 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
1267 LOG_API(isolate, "ObjectTemplate::New");
1268 ENTER_V8(isolate);
1269 i::Handle<i::Struct> struct_obj =
1270 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1271 i::Handle<i::ObjectTemplateInfo> obj =
1272 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1273 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1274 if (!constructor.IsEmpty())
1275 obj->set_constructor(*Utils::OpenHandle(*constructor));
1276 obj->set_internal_field_count(i::Smi::FromInt(0));
1277 return Utils::ToLocal(obj);
1278 }
1279
1280
1281 // Ensure that the object template has a constructor. If no
1282 // constructor is available we create one.
EnsureConstructor(i::Isolate * isolate,ObjectTemplate * object_template)1283 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1284 i::Isolate* isolate,
1285 ObjectTemplate* object_template) {
1286 i::Object* obj = Utils::OpenHandle(object_template)->constructor();
1287 if (!obj ->IsUndefined()) {
1288 i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
1289 return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1290 }
1291 Local<FunctionTemplate> templ =
1292 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1293 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1294 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1295 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1296 return constructor;
1297 }
1298
1299
AddPropertyToTemplate(i::Handle<i::TemplateInfo> info,i::Handle<i::AccessorInfo> obj)1300 static inline void AddPropertyToTemplate(
1301 i::Handle<i::TemplateInfo> info,
1302 i::Handle<i::AccessorInfo> obj) {
1303 i::Isolate* isolate = info->GetIsolate();
1304 i::Handle<i::Object> list(info->property_accessors(), isolate);
1305 if (list->IsUndefined()) {
1306 list = NeanderArray(isolate).value();
1307 info->set_property_accessors(*list);
1308 }
1309 NeanderArray array(list);
1310 array.add(obj);
1311 }
1312
1313
GetTemplateInfo(i::Isolate * isolate,Template * template_obj)1314 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1315 i::Isolate* isolate,
1316 Template* template_obj) {
1317 return Utils::OpenHandle(template_obj);
1318 }
1319
1320
1321 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor
GetTemplateInfo(i::Isolate * isolate,ObjectTemplate * object_template)1322 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1323 i::Isolate* isolate,
1324 ObjectTemplate* object_template) {
1325 EnsureConstructor(isolate, object_template);
1326 return Utils::OpenHandle(object_template);
1327 }
1328
1329
1330 template<typename Setter, typename Getter, typename Data, typename Template>
TemplateSetAccessor(Template * template_obj,v8::Local<String> name,Getter getter,Setter setter,Data data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature)1331 static bool TemplateSetAccessor(
1332 Template* template_obj,
1333 v8::Local<String> name,
1334 Getter getter,
1335 Setter setter,
1336 Data data,
1337 AccessControl settings,
1338 PropertyAttribute attribute,
1339 v8::Local<AccessorSignature> signature) {
1340 i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
1341 ENTER_V8(isolate);
1342 i::HandleScope scope(isolate);
1343 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
1344 name, getter, setter, data, settings, attribute, signature);
1345 if (obj.is_null()) return false;
1346 i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj);
1347 AddPropertyToTemplate(info, obj);
1348 return true;
1349 }
1350
1351
SetDeclaredAccessor(Local<String> name,Local<DeclaredAccessorDescriptor> descriptor,PropertyAttribute attribute,Local<AccessorSignature> signature,AccessControl settings)1352 bool Template::SetDeclaredAccessor(
1353 Local<String> name,
1354 Local<DeclaredAccessorDescriptor> descriptor,
1355 PropertyAttribute attribute,
1356 Local<AccessorSignature> signature,
1357 AccessControl settings) {
1358 void* null = NULL;
1359 return TemplateSetAccessor(
1360 this, name, descriptor, null, null, settings, attribute, signature);
1361 }
1362
1363
SetNativeDataProperty(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings)1364 void Template::SetNativeDataProperty(v8::Local<String> name,
1365 AccessorGetterCallback getter,
1366 AccessorSetterCallback setter,
1367 v8::Handle<Value> data,
1368 PropertyAttribute attribute,
1369 v8::Local<AccessorSignature> signature,
1370 AccessControl settings) {
1371 TemplateSetAccessor(
1372 this, name, getter, setter, data, settings, attribute, signature);
1373 }
1374
1375
SetAccessor(v8::Handle<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Handle<AccessorSignature> signature)1376 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1377 AccessorGetterCallback getter,
1378 AccessorSetterCallback setter,
1379 v8::Handle<Value> data,
1380 AccessControl settings,
1381 PropertyAttribute attribute,
1382 v8::Handle<AccessorSignature> signature) {
1383 TemplateSetAccessor(
1384 this, name, getter, setter, data, settings, attribute, signature);
1385 }
1386
1387
SetNamedPropertyHandler(NamedPropertyGetterCallback getter,NamedPropertySetterCallback setter,NamedPropertyQueryCallback query,NamedPropertyDeleterCallback remover,NamedPropertyEnumeratorCallback enumerator,Handle<Value> data)1388 void ObjectTemplate::SetNamedPropertyHandler(
1389 NamedPropertyGetterCallback getter,
1390 NamedPropertySetterCallback setter,
1391 NamedPropertyQueryCallback query,
1392 NamedPropertyDeleterCallback remover,
1393 NamedPropertyEnumeratorCallback enumerator,
1394 Handle<Value> data) {
1395 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1396 ENTER_V8(isolate);
1397 i::HandleScope scope(isolate);
1398 EnsureConstructor(isolate, this);
1399 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1400 Utils::OpenHandle(this)->constructor());
1401 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1402 i::Handle<i::Struct> struct_obj =
1403 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1404 i::Handle<i::InterceptorInfo> obj =
1405 i::Handle<i::InterceptorInfo>::cast(struct_obj);
1406
1407 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1408 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1409 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1410 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1411 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1412
1413 if (data.IsEmpty()) {
1414 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1415 }
1416 obj->set_data(*Utils::OpenHandle(*data));
1417 cons->set_named_property_handler(*obj);
1418 }
1419
1420
MarkAsUndetectable()1421 void ObjectTemplate::MarkAsUndetectable() {
1422 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1423 ENTER_V8(isolate);
1424 i::HandleScope scope(isolate);
1425 EnsureConstructor(isolate, this);
1426 i::FunctionTemplateInfo* constructor =
1427 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1428 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1429 cons->set_undetectable(true);
1430 }
1431
1432
SetAccessCheckCallbacks(NamedSecurityCallback named_callback,IndexedSecurityCallback indexed_callback,Handle<Value> data,bool turned_on_by_default)1433 void ObjectTemplate::SetAccessCheckCallbacks(
1434 NamedSecurityCallback named_callback,
1435 IndexedSecurityCallback indexed_callback,
1436 Handle<Value> data,
1437 bool turned_on_by_default) {
1438 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1439 ENTER_V8(isolate);
1440 i::HandleScope scope(isolate);
1441 EnsureConstructor(isolate, this);
1442
1443 i::Handle<i::Struct> struct_info =
1444 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1445 i::Handle<i::AccessCheckInfo> info =
1446 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1447
1448 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1449 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1450
1451 if (data.IsEmpty()) {
1452 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1453 }
1454 info->set_data(*Utils::OpenHandle(*data));
1455
1456 i::FunctionTemplateInfo* constructor =
1457 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1458 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1459 cons->set_access_check_info(*info);
1460 cons->set_needs_access_check(turned_on_by_default);
1461 }
1462
1463
SetIndexedPropertyHandler(IndexedPropertyGetterCallback getter,IndexedPropertySetterCallback setter,IndexedPropertyQueryCallback query,IndexedPropertyDeleterCallback remover,IndexedPropertyEnumeratorCallback enumerator,Handle<Value> data)1464 void ObjectTemplate::SetIndexedPropertyHandler(
1465 IndexedPropertyGetterCallback getter,
1466 IndexedPropertySetterCallback setter,
1467 IndexedPropertyQueryCallback query,
1468 IndexedPropertyDeleterCallback remover,
1469 IndexedPropertyEnumeratorCallback enumerator,
1470 Handle<Value> data) {
1471 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1472 ENTER_V8(isolate);
1473 i::HandleScope scope(isolate);
1474 EnsureConstructor(isolate, this);
1475 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1476 Utils::OpenHandle(this)->constructor());
1477 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1478 i::Handle<i::Struct> struct_obj =
1479 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1480 i::Handle<i::InterceptorInfo> obj =
1481 i::Handle<i::InterceptorInfo>::cast(struct_obj);
1482
1483 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1484 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1485 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1486 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1487 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1488
1489 if (data.IsEmpty()) {
1490 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1491 }
1492 obj->set_data(*Utils::OpenHandle(*data));
1493 cons->set_indexed_property_handler(*obj);
1494 }
1495
1496
SetCallAsFunctionHandler(FunctionCallback callback,Handle<Value> data)1497 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1498 Handle<Value> data) {
1499 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1500 ENTER_V8(isolate);
1501 i::HandleScope scope(isolate);
1502 EnsureConstructor(isolate, this);
1503 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1504 Utils::OpenHandle(this)->constructor());
1505 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1506 i::Handle<i::Struct> struct_obj =
1507 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1508 i::Handle<i::CallHandlerInfo> obj =
1509 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1510 SET_FIELD_WRAPPED(obj, set_callback, callback);
1511 if (data.IsEmpty()) {
1512 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1513 }
1514 obj->set_data(*Utils::OpenHandle(*data));
1515 cons->set_instance_call_handler(*obj);
1516 }
1517
1518
InternalFieldCount()1519 int ObjectTemplate::InternalFieldCount() {
1520 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1521 }
1522
1523
SetInternalFieldCount(int value)1524 void ObjectTemplate::SetInternalFieldCount(int value) {
1525 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1526 if (!Utils::ApiCheck(i::Smi::IsValid(value),
1527 "v8::ObjectTemplate::SetInternalFieldCount()",
1528 "Invalid internal field count")) {
1529 return;
1530 }
1531 ENTER_V8(isolate);
1532 if (value > 0) {
1533 // The internal field count is set by the constructor function's
1534 // construct code, so we ensure that there is a constructor
1535 // function to do the setting.
1536 EnsureConstructor(isolate, this);
1537 }
1538 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1539 }
1540
1541
1542 // --- S c r i p t s ---
1543
1544
1545 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1546 // JSFunction.
1547
CachedData(const uint8_t * data_,int length_,BufferPolicy buffer_policy_)1548 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
1549 BufferPolicy buffer_policy_)
1550 : data(data_), length(length_), buffer_policy(buffer_policy_) {}
1551
1552
~CachedData()1553 ScriptCompiler::CachedData::~CachedData() {
1554 if (buffer_policy == BufferOwned) {
1555 delete[] data;
1556 }
1557 }
1558
1559
BindToCurrentContext()1560 Local<Script> UnboundScript::BindToCurrentContext() {
1561 i::Handle<i::HeapObject> obj =
1562 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1563 i::Handle<i::SharedFunctionInfo>
1564 function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate());
1565 i::Handle<i::JSFunction> function =
1566 obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo(
1567 function_info, obj->GetIsolate()->global_context());
1568 return ToApiHandle<Script>(function);
1569 }
1570
1571
GetId()1572 int UnboundScript::GetId() {
1573 i::Handle<i::HeapObject> obj =
1574 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1575 i::Isolate* isolate = obj->GetIsolate();
1576 ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1);
1577 LOG_API(isolate, "v8::UnboundScript::GetId");
1578 {
1579 i::HandleScope scope(isolate);
1580 i::Handle<i::SharedFunctionInfo> function_info(
1581 i::SharedFunctionInfo::cast(*obj));
1582 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1583 return script->id()->value();
1584 }
1585 }
1586
1587
GetLineNumber(int code_pos)1588 int UnboundScript::GetLineNumber(int code_pos) {
1589 i::Handle<i::SharedFunctionInfo> obj =
1590 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1591 i::Isolate* isolate = obj->GetIsolate();
1592 ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1);
1593 LOG_API(isolate, "UnboundScript::GetLineNumber");
1594 if (obj->script()->IsScript()) {
1595 i::Handle<i::Script> script(i::Script::cast(obj->script()));
1596 return i::Script::GetLineNumber(script, code_pos);
1597 } else {
1598 return -1;
1599 }
1600 }
1601
1602
GetScriptName()1603 Handle<Value> UnboundScript::GetScriptName() {
1604 i::Handle<i::SharedFunctionInfo> obj =
1605 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1606 i::Isolate* isolate = obj->GetIsolate();
1607 ON_BAILOUT(isolate, "v8::UnboundScript::GetName()",
1608 return Handle<String>());
1609 LOG_API(isolate, "UnboundScript::GetName");
1610 if (obj->script()->IsScript()) {
1611 i::Object* name = i::Script::cast(obj->script())->name();
1612 return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
1613 } else {
1614 return Handle<String>();
1615 }
1616 }
1617
1618
Run()1619 Local<Value> Script::Run() {
1620 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
1621 // If execution is terminating, Compile(..)->Run() requires this
1622 // check.
1623 if (obj.is_null()) return Local<Value>();
1624 i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate();
1625 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1626 LOG_API(isolate, "Script::Run");
1627 ENTER_V8(isolate);
1628 i::Logger::TimerEventScope timer_scope(
1629 isolate, i::Logger::TimerEventScope::v8_execute);
1630 i::HandleScope scope(isolate);
1631 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
1632 EXCEPTION_PREAMBLE(isolate);
1633 i::Handle<i::Object> receiver(
1634 isolate->context()->global_proxy(), isolate);
1635 i::Handle<i::Object> result;
1636 has_pending_exception = !i::Execution::Call(
1637 isolate, fun, receiver, 0, NULL).ToHandle(&result);
1638 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
1639 return Utils::ToLocal(scope.CloseAndEscape(result));
1640 }
1641
1642
GetUnboundScript()1643 Local<UnboundScript> Script::GetUnboundScript() {
1644 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1645 return ToApiHandle<UnboundScript>(
1646 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()));
1647 }
1648
1649
CompileUnbound(Isolate * v8_isolate,Source * source,CompileOptions options)1650 Local<UnboundScript> ScriptCompiler::CompileUnbound(
1651 Isolate* v8_isolate,
1652 Source* source,
1653 CompileOptions options) {
1654 i::ScriptData* script_data_impl = NULL;
1655 i::CachedDataMode cached_data_mode = i::NO_CACHED_DATA;
1656 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1657 ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
1658 return Local<UnboundScript>());
1659 if (options & kProduceDataToCache) {
1660 cached_data_mode = i::PRODUCE_CACHED_DATA;
1661 ASSERT(source->cached_data == NULL);
1662 if (source->cached_data) {
1663 // Asked to produce cached data even though there is some already -> not
1664 // good. Fail the compilation.
1665 EXCEPTION_PREAMBLE(isolate);
1666 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(
1667 "invalid_cached_data", isolate->factory()->NewJSArray(0));
1668 isolate->Throw(*result);
1669 isolate->ReportPendingMessages();
1670 has_pending_exception = true;
1671 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1672 }
1673 } else if (source->cached_data) {
1674 cached_data_mode = i::CONSUME_CACHED_DATA;
1675 // ScriptData takes care of aligning, in case the data is not aligned
1676 // correctly.
1677 script_data_impl = i::ScriptData::New(
1678 reinterpret_cast<const char*>(source->cached_data->data),
1679 source->cached_data->length);
1680 // If the cached data is not valid, fail the compilation.
1681 if (script_data_impl == NULL || !script_data_impl->SanityCheck()) {
1682 EXCEPTION_PREAMBLE(isolate);
1683 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(
1684 "invalid_cached_data", isolate->factory()->NewJSArray(0));
1685 isolate->Throw(*result);
1686 isolate->ReportPendingMessages();
1687 delete script_data_impl;
1688 has_pending_exception = true;
1689 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1690 }
1691 }
1692
1693 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
1694 LOG_API(isolate, "ScriptCompiler::CompileUnbound");
1695 ENTER_V8(isolate);
1696 i::SharedFunctionInfo* raw_result = NULL;
1697 { i::HandleScope scope(isolate);
1698 i::Handle<i::Object> name_obj;
1699 int line_offset = 0;
1700 int column_offset = 0;
1701 bool is_shared_cross_origin = false;
1702 if (!source->resource_name.IsEmpty()) {
1703 name_obj = Utils::OpenHandle(*(source->resource_name));
1704 }
1705 if (!source->resource_line_offset.IsEmpty()) {
1706 line_offset = static_cast<int>(source->resource_line_offset->Value());
1707 }
1708 if (!source->resource_column_offset.IsEmpty()) {
1709 column_offset =
1710 static_cast<int>(source->resource_column_offset->Value());
1711 }
1712 if (!source->resource_is_shared_cross_origin.IsEmpty()) {
1713 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1714 is_shared_cross_origin =
1715 source->resource_is_shared_cross_origin == v8::True(v8_isolate);
1716 }
1717 EXCEPTION_PREAMBLE(isolate);
1718 i::Handle<i::SharedFunctionInfo> result =
1719 i::Compiler::CompileScript(str,
1720 name_obj,
1721 line_offset,
1722 column_offset,
1723 is_shared_cross_origin,
1724 isolate->global_context(),
1725 NULL,
1726 &script_data_impl,
1727 cached_data_mode,
1728 i::NOT_NATIVES_CODE);
1729 has_pending_exception = result.is_null();
1730 if (has_pending_exception && cached_data_mode == i::CONSUME_CACHED_DATA) {
1731 // This case won't happen during normal operation; we have compiled
1732 // successfully and produced cached data, and but the second compilation
1733 // of the same source code fails.
1734 delete script_data_impl;
1735 script_data_impl = NULL;
1736 }
1737 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1738 raw_result = *result;
1739 if ((options & kProduceDataToCache) && script_data_impl != NULL) {
1740 // script_data_impl now contains the data that was generated. source will
1741 // take the ownership.
1742 source->cached_data = new CachedData(
1743 reinterpret_cast<const uint8_t*>(script_data_impl->Data()),
1744 script_data_impl->Length(), CachedData::BufferOwned);
1745 script_data_impl->owns_store_ = false;
1746 }
1747 delete script_data_impl;
1748 }
1749 i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1750 return ToApiHandle<UnboundScript>(result);
1751 }
1752
1753
Compile(Isolate * v8_isolate,Source * source,CompileOptions options)1754 Local<Script> ScriptCompiler::Compile(
1755 Isolate* v8_isolate,
1756 Source* source,
1757 CompileOptions options) {
1758 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1759 ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
1760 LOG_API(isolate, "ScriptCompiler::CompiletBound()");
1761 ENTER_V8(isolate);
1762 Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
1763 if (generic.IsEmpty()) return Local<Script>();
1764 return generic->BindToCurrentContext();
1765 }
1766
1767
Compile(v8::Handle<String> source,v8::ScriptOrigin * origin)1768 Local<Script> Script::Compile(v8::Handle<String> source,
1769 v8::ScriptOrigin* origin) {
1770 i::Handle<i::String> str = Utils::OpenHandle(*source);
1771 if (origin) {
1772 ScriptCompiler::Source script_source(source, *origin);
1773 return ScriptCompiler::Compile(
1774 reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1775 &script_source);
1776 }
1777 ScriptCompiler::Source script_source(source);
1778 return ScriptCompiler::Compile(
1779 reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1780 &script_source);
1781 }
1782
1783
Compile(v8::Handle<String> source,v8::Handle<String> file_name)1784 Local<Script> Script::Compile(v8::Handle<String> source,
1785 v8::Handle<String> file_name) {
1786 ScriptOrigin origin(file_name);
1787 return Compile(source, &origin);
1788 }
1789
1790
1791 // --- E x c e p t i o n s ---
1792
1793
TryCatch()1794 v8::TryCatch::TryCatch()
1795 : isolate_(i::Isolate::Current()),
1796 next_(isolate_->try_catch_handler()),
1797 is_verbose_(false),
1798 can_continue_(true),
1799 capture_message_(true),
1800 rethrow_(false),
1801 has_terminated_(false) {
1802 Reset();
1803 js_stack_comparable_address_ = this;
1804 #ifdef V8_USE_ADDRESS_SANITIZER
1805 void* asan_fake_stack_handle = __asan_get_current_fake_stack();
1806 if (asan_fake_stack_handle != NULL) {
1807 js_stack_comparable_address_ = __asan_addr_is_in_fake_stack(
1808 asan_fake_stack_handle, js_stack_comparable_address_, NULL, NULL);
1809 CHECK(js_stack_comparable_address_ != NULL);
1810 }
1811 #endif
1812 // Special handling for simulators which have a separate JS stack.
1813 js_stack_comparable_address_ = reinterpret_cast<void*>(
1814 v8::internal::SimulatorStack::RegisterCTryCatch(
1815 reinterpret_cast<uintptr_t>(js_stack_comparable_address_)));
1816 isolate_->RegisterTryCatchHandler(this);
1817 }
1818
1819
~TryCatch()1820 v8::TryCatch::~TryCatch() {
1821 ASSERT(isolate_ == i::Isolate::Current());
1822 if (rethrow_) {
1823 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
1824 v8::HandleScope scope(isolate);
1825 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
1826 if (HasCaught() && capture_message_) {
1827 // If an exception was caught and rethrow_ is indicated, the saved
1828 // message, script, and location need to be restored to Isolate TLS
1829 // for reuse. capture_message_ needs to be disabled so that DoThrow()
1830 // does not create a new message.
1831 isolate_->thread_local_top()->rethrowing_message_ = true;
1832 isolate_->RestorePendingMessageFromTryCatch(this);
1833 }
1834 isolate_->UnregisterTryCatchHandler(this);
1835 v8::internal::SimulatorStack::UnregisterCTryCatch();
1836 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
1837 ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
1838 } else {
1839 isolate_->UnregisterTryCatchHandler(this);
1840 v8::internal::SimulatorStack::UnregisterCTryCatch();
1841 }
1842 }
1843
1844
HasCaught() const1845 bool v8::TryCatch::HasCaught() const {
1846 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1847 }
1848
1849
CanContinue() const1850 bool v8::TryCatch::CanContinue() const {
1851 return can_continue_;
1852 }
1853
1854
HasTerminated() const1855 bool v8::TryCatch::HasTerminated() const {
1856 return has_terminated_;
1857 }
1858
1859
ReThrow()1860 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1861 if (!HasCaught()) return v8::Local<v8::Value>();
1862 rethrow_ = true;
1863 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
1864 }
1865
1866
Exception() const1867 v8::Local<Value> v8::TryCatch::Exception() const {
1868 ASSERT(isolate_ == i::Isolate::Current());
1869 if (HasCaught()) {
1870 // Check for out of memory exception.
1871 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1872 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
1873 } else {
1874 return v8::Local<Value>();
1875 }
1876 }
1877
1878
StackTrace() const1879 v8::Local<Value> v8::TryCatch::StackTrace() const {
1880 ASSERT(isolate_ == i::Isolate::Current());
1881 if (HasCaught()) {
1882 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1883 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1884 i::HandleScope scope(isolate_);
1885 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
1886 i::Handle<i::String> name = isolate_->factory()->stack_string();
1887 if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>();
1888 i::Handle<i::Object> value;
1889 if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
1890 return v8::Local<Value>();
1891 }
1892 return v8::Utils::ToLocal(scope.CloseAndEscape(value));
1893 } else {
1894 return v8::Local<Value>();
1895 }
1896 }
1897
1898
Message() const1899 v8::Local<v8::Message> v8::TryCatch::Message() const {
1900 ASSERT(isolate_ == i::Isolate::Current());
1901 i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
1902 ASSERT(message->IsJSMessageObject() || message->IsTheHole());
1903 if (HasCaught() && !message->IsTheHole()) {
1904 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
1905 } else {
1906 return v8::Local<v8::Message>();
1907 }
1908 }
1909
1910
Reset()1911 void v8::TryCatch::Reset() {
1912 ASSERT(isolate_ == i::Isolate::Current());
1913 i::Object* the_hole = isolate_->heap()->the_hole_value();
1914 exception_ = the_hole;
1915 message_obj_ = the_hole;
1916 message_script_ = the_hole;
1917 message_start_pos_ = 0;
1918 message_end_pos_ = 0;
1919 }
1920
1921
SetVerbose(bool value)1922 void v8::TryCatch::SetVerbose(bool value) {
1923 is_verbose_ = value;
1924 }
1925
1926
SetCaptureMessage(bool value)1927 void v8::TryCatch::SetCaptureMessage(bool value) {
1928 capture_message_ = value;
1929 }
1930
1931
1932 // --- M e s s a g e ---
1933
1934
Get() const1935 Local<String> Message::Get() const {
1936 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1937 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
1938 ENTER_V8(isolate);
1939 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
1940 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1941 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
1942 Local<String> result = Utils::ToLocal(raw_result);
1943 return scope.Escape(result);
1944 }
1945
1946
GetScriptResourceName() const1947 v8::Handle<Value> Message::GetScriptResourceName() const {
1948 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1949 ENTER_V8(isolate);
1950 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
1951 i::Handle<i::JSMessageObject> message =
1952 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1953 // Return this.script.name.
1954 i::Handle<i::JSValue> script =
1955 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
1956 isolate));
1957 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name(),
1958 isolate);
1959 return scope.Escape(Utils::ToLocal(resource_name));
1960 }
1961
1962
GetStackTrace() const1963 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1964 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1965 ENTER_V8(isolate);
1966 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
1967 i::Handle<i::JSMessageObject> message =
1968 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1969 i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
1970 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1971 i::Handle<i::JSArray> stackTrace =
1972 i::Handle<i::JSArray>::cast(stackFramesObj);
1973 return scope.Escape(Utils::StackTraceToLocal(stackTrace));
1974 }
1975
1976
CallV8HeapFunction(const char * name,i::Handle<i::Object> recv,int argc,i::Handle<i::Object> argv[])1977 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
1978 const char* name,
1979 i::Handle<i::Object> recv,
1980 int argc,
1981 i::Handle<i::Object> argv[]) {
1982 i::Isolate* isolate = i::Isolate::Current();
1983 i::Handle<i::Object> object_fun =
1984 i::Object::GetProperty(
1985 isolate, isolate->js_builtins_object(), name).ToHandleChecked();
1986 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
1987 return i::Execution::Call(isolate, fun, recv, argc, argv);
1988 }
1989
1990
CallV8HeapFunction(const char * name,i::Handle<i::Object> data)1991 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
1992 const char* name,
1993 i::Handle<i::Object> data) {
1994 i::Handle<i::Object> argv[] = { data };
1995 return CallV8HeapFunction(name,
1996 i::Isolate::Current()->js_builtins_object(),
1997 ARRAY_SIZE(argv),
1998 argv);
1999 }
2000
2001
GetLineNumber() const2002 int Message::GetLineNumber() const {
2003 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2004 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
2005 ENTER_V8(isolate);
2006 i::HandleScope scope(isolate);
2007
2008 EXCEPTION_PREAMBLE(isolate);
2009 i::Handle<i::Object> result;
2010 has_pending_exception = !CallV8HeapFunction(
2011 "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result);
2012 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2013 return static_cast<int>(result->Number());
2014 }
2015
2016
GetStartPosition() const2017 int Message::GetStartPosition() const {
2018 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2019 ENTER_V8(isolate);
2020 i::HandleScope scope(isolate);
2021 i::Handle<i::JSMessageObject> message =
2022 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2023 return message->start_position();
2024 }
2025
2026
GetEndPosition() const2027 int Message::GetEndPosition() const {
2028 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2029 ENTER_V8(isolate);
2030 i::HandleScope scope(isolate);
2031 i::Handle<i::JSMessageObject> message =
2032 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2033 return message->end_position();
2034 }
2035
2036
GetStartColumn() const2037 int Message::GetStartColumn() const {
2038 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2039 ENTER_V8(isolate);
2040 i::HandleScope scope(isolate);
2041 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2042 EXCEPTION_PREAMBLE(isolate);
2043 i::Handle<i::Object> start_col_obj;
2044 has_pending_exception = !CallV8HeapFunction(
2045 "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2046 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2047 return static_cast<int>(start_col_obj->Number());
2048 }
2049
2050
GetEndColumn() const2051 int Message::GetEndColumn() const {
2052 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2053 ENTER_V8(isolate);
2054 i::HandleScope scope(isolate);
2055 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2056 EXCEPTION_PREAMBLE(isolate);
2057 i::Handle<i::Object> start_col_obj;
2058 has_pending_exception = !CallV8HeapFunction(
2059 "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2060 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2061 i::Handle<i::JSMessageObject> message =
2062 i::Handle<i::JSMessageObject>::cast(data_obj);
2063 int start = message->start_position();
2064 int end = message->end_position();
2065 return static_cast<int>(start_col_obj->Number()) + (end - start);
2066 }
2067
2068
IsSharedCrossOrigin() const2069 bool Message::IsSharedCrossOrigin() const {
2070 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2071 ENTER_V8(isolate);
2072 i::HandleScope scope(isolate);
2073 i::Handle<i::JSMessageObject> message =
2074 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2075 i::Handle<i::JSValue> script =
2076 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2077 isolate));
2078 return i::Script::cast(script->value())->is_shared_cross_origin();
2079 }
2080
2081
GetSourceLine() const2082 Local<String> Message::GetSourceLine() const {
2083 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2084 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
2085 ENTER_V8(isolate);
2086 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2087 EXCEPTION_PREAMBLE(isolate);
2088 i::Handle<i::Object> result;
2089 has_pending_exception = !CallV8HeapFunction(
2090 "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result);
2091 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
2092 if (result->IsString()) {
2093 return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
2094 } else {
2095 return Local<String>();
2096 }
2097 }
2098
2099
PrintCurrentStackTrace(Isolate * isolate,FILE * out)2100 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
2101 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2102 ENTER_V8(i_isolate);
2103 i_isolate->PrintCurrentStackTrace(out);
2104 }
2105
2106
2107 // --- S t a c k T r a c e ---
2108
GetFrame(uint32_t index) const2109 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
2110 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2111 ENTER_V8(isolate);
2112 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2113 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
2114 i::Handle<i::Object> obj =
2115 i::Object::GetElement(isolate, self, index).ToHandleChecked();
2116 i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
2117 return scope.Escape(Utils::StackFrameToLocal(jsobj));
2118 }
2119
2120
GetFrameCount() const2121 int StackTrace::GetFrameCount() const {
2122 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2123 ENTER_V8(isolate);
2124 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2125 }
2126
2127
AsArray()2128 Local<Array> StackTrace::AsArray() {
2129 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2130 ENTER_V8(isolate);
2131 return Utils::ToLocal(Utils::OpenHandle(this));
2132 }
2133
2134
CurrentStackTrace(Isolate * isolate,int frame_limit,StackTraceOptions options)2135 Local<StackTrace> StackTrace::CurrentStackTrace(
2136 Isolate* isolate,
2137 int frame_limit,
2138 StackTraceOptions options) {
2139 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2140 ENTER_V8(i_isolate);
2141 // TODO(dcarney): remove when ScriptDebugServer is fixed.
2142 options = static_cast<StackTraceOptions>(
2143 static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins);
2144 i::Handle<i::JSArray> stackTrace =
2145 i_isolate->CaptureCurrentStackTrace(frame_limit, options);
2146 return Utils::StackTraceToLocal(stackTrace);
2147 }
2148
2149
2150 // --- S t a c k F r a m e ---
2151
GetLineNumber() const2152 int StackFrame::GetLineNumber() const {
2153 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2154 ENTER_V8(isolate);
2155 i::HandleScope scope(isolate);
2156 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2157 i::Handle<i::Object> line = i::Object::GetProperty(
2158 isolate, self, "lineNumber").ToHandleChecked();
2159 if (!line->IsSmi()) {
2160 return Message::kNoLineNumberInfo;
2161 }
2162 return i::Smi::cast(*line)->value();
2163 }
2164
2165
GetColumn() const2166 int StackFrame::GetColumn() const {
2167 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2168 ENTER_V8(isolate);
2169 i::HandleScope scope(isolate);
2170 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2171 i::Handle<i::Object> column = i::Object::GetProperty(
2172 isolate, self, "column").ToHandleChecked();
2173 if (!column->IsSmi()) {
2174 return Message::kNoColumnInfo;
2175 }
2176 return i::Smi::cast(*column)->value();
2177 }
2178
2179
GetScriptId() const2180 int StackFrame::GetScriptId() const {
2181 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2182 ENTER_V8(isolate);
2183 i::HandleScope scope(isolate);
2184 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2185 i::Handle<i::Object> scriptId = i::Object::GetProperty(
2186 isolate, self, "scriptId").ToHandleChecked();
2187 if (!scriptId->IsSmi()) {
2188 return Message::kNoScriptIdInfo;
2189 }
2190 return i::Smi::cast(*scriptId)->value();
2191 }
2192
2193
GetScriptName() const2194 Local<String> StackFrame::GetScriptName() const {
2195 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2196 ENTER_V8(isolate);
2197 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2198 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2199 i::Handle<i::Object> name = i::Object::GetProperty(
2200 isolate, self, "scriptName").ToHandleChecked();
2201 if (!name->IsString()) {
2202 return Local<String>();
2203 }
2204 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name)));
2205 }
2206
2207
GetScriptNameOrSourceURL() const2208 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2209 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2210 ENTER_V8(isolate);
2211 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2212 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2213 i::Handle<i::Object> name = i::Object::GetProperty(
2214 isolate, self, "scriptNameOrSourceURL").ToHandleChecked();
2215 if (!name->IsString()) {
2216 return Local<String>();
2217 }
2218 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name)));
2219 }
2220
2221
GetFunctionName() const2222 Local<String> StackFrame::GetFunctionName() const {
2223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2224 ENTER_V8(isolate);
2225 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2226 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2227 i::Handle<i::Object> name = i::Object::GetProperty(
2228 isolate, self, "functionName").ToHandleChecked();
2229 if (!name->IsString()) {
2230 return Local<String>();
2231 }
2232 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name)));
2233 }
2234
2235
IsEval() const2236 bool StackFrame::IsEval() const {
2237 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2238 ENTER_V8(isolate);
2239 i::HandleScope scope(isolate);
2240 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2241 i::Handle<i::Object> is_eval = i::Object::GetProperty(
2242 isolate, self, "isEval").ToHandleChecked();
2243 return is_eval->IsTrue();
2244 }
2245
2246
IsConstructor() const2247 bool StackFrame::IsConstructor() const {
2248 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2249 ENTER_V8(isolate);
2250 i::HandleScope scope(isolate);
2251 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2252 i::Handle<i::Object> is_constructor = i::Object::GetProperty(
2253 isolate, self, "isConstructor").ToHandleChecked();
2254 return is_constructor->IsTrue();
2255 }
2256
2257
2258 // --- J S O N ---
2259
Parse(Local<String> json_string)2260 Local<Value> JSON::Parse(Local<String> json_string) {
2261 i::Handle<i::String> string = Utils::OpenHandle(*json_string);
2262 i::Isolate* isolate = string->GetIsolate();
2263 EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
2264 ENTER_V8(isolate);
2265 i::HandleScope scope(isolate);
2266 i::Handle<i::String> source = i::String::Flatten(string);
2267 EXCEPTION_PREAMBLE(isolate);
2268 i::MaybeHandle<i::Object> maybe_result =
2269 source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
2270 : i::JsonParser<false>::Parse(source);
2271 i::Handle<i::Object> result;
2272 has_pending_exception = !maybe_result.ToHandle(&result);
2273 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2274 return Utils::ToLocal(
2275 i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
2276 }
2277
2278
2279 // --- D a t a ---
2280
FullIsUndefined() const2281 bool Value::FullIsUndefined() const {
2282 bool result = Utils::OpenHandle(this)->IsUndefined();
2283 ASSERT_EQ(result, QuickIsUndefined());
2284 return result;
2285 }
2286
2287
FullIsNull() const2288 bool Value::FullIsNull() const {
2289 bool result = Utils::OpenHandle(this)->IsNull();
2290 ASSERT_EQ(result, QuickIsNull());
2291 return result;
2292 }
2293
2294
IsTrue() const2295 bool Value::IsTrue() const {
2296 return Utils::OpenHandle(this)->IsTrue();
2297 }
2298
2299
IsFalse() const2300 bool Value::IsFalse() const {
2301 return Utils::OpenHandle(this)->IsFalse();
2302 }
2303
2304
IsFunction() const2305 bool Value::IsFunction() const {
2306 return Utils::OpenHandle(this)->IsJSFunction();
2307 }
2308
2309
FullIsString() const2310 bool Value::FullIsString() const {
2311 bool result = Utils::OpenHandle(this)->IsString();
2312 ASSERT_EQ(result, QuickIsString());
2313 return result;
2314 }
2315
2316
IsSymbol() const2317 bool Value::IsSymbol() const {
2318 return Utils::OpenHandle(this)->IsSymbol();
2319 }
2320
2321
IsArray() const2322 bool Value::IsArray() const {
2323 return Utils::OpenHandle(this)->IsJSArray();
2324 }
2325
2326
IsArrayBuffer() const2327 bool Value::IsArrayBuffer() const {
2328 return Utils::OpenHandle(this)->IsJSArrayBuffer();
2329 }
2330
2331
IsArrayBufferView() const2332 bool Value::IsArrayBufferView() const {
2333 return Utils::OpenHandle(this)->IsJSArrayBufferView();
2334 }
2335
2336
IsTypedArray() const2337 bool Value::IsTypedArray() const {
2338 return Utils::OpenHandle(this)->IsJSTypedArray();
2339 }
2340
2341
2342 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \
2343 bool Value::Is##Type##Array() const { \
2344 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
2345 return obj->IsJSTypedArray() && \
2346 i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array; \
2347 }
2348
TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)2349 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
2350
2351 #undef VALUE_IS_TYPED_ARRAY
2352
2353
2354 bool Value::IsDataView() const {
2355 return Utils::OpenHandle(this)->IsJSDataView();
2356 }
2357
2358
IsObject() const2359 bool Value::IsObject() const {
2360 return Utils::OpenHandle(this)->IsJSObject();
2361 }
2362
2363
IsNumber() const2364 bool Value::IsNumber() const {
2365 return Utils::OpenHandle(this)->IsNumber();
2366 }
2367
2368
IsBoolean() const2369 bool Value::IsBoolean() const {
2370 return Utils::OpenHandle(this)->IsBoolean();
2371 }
2372
2373
IsExternal() const2374 bool Value::IsExternal() const {
2375 return Utils::OpenHandle(this)->IsExternal();
2376 }
2377
2378
IsInt32() const2379 bool Value::IsInt32() const {
2380 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2381 if (obj->IsSmi()) return true;
2382 if (obj->IsNumber()) {
2383 return i::IsInt32Double(obj->Number());
2384 }
2385 return false;
2386 }
2387
2388
IsUint32() const2389 bool Value::IsUint32() const {
2390 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2391 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2392 if (obj->IsNumber()) {
2393 double value = obj->Number();
2394 return !i::IsMinusZero(value) &&
2395 value >= 0 &&
2396 value <= i::kMaxUInt32 &&
2397 value == i::FastUI2D(i::FastD2UI(value));
2398 }
2399 return false;
2400 }
2401
2402
IsDate() const2403 bool Value::IsDate() const {
2404 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2405 if (!obj->IsHeapObject()) return false;
2406 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2407 return obj->HasSpecificClassOf(isolate->heap()->Date_string());
2408 }
2409
2410
IsStringObject() const2411 bool Value::IsStringObject() const {
2412 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2413 if (!obj->IsHeapObject()) return false;
2414 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2415 return obj->HasSpecificClassOf(isolate->heap()->String_string());
2416 }
2417
2418
IsSymbolObject() const2419 bool Value::IsSymbolObject() const {
2420 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2421 if (!obj->IsHeapObject()) return false;
2422 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2423 return obj->HasSpecificClassOf(isolate->heap()->Symbol_string());
2424 }
2425
2426
IsNumberObject() const2427 bool Value::IsNumberObject() const {
2428 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2429 if (!obj->IsHeapObject()) return false;
2430 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2431 return obj->HasSpecificClassOf(isolate->heap()->Number_string());
2432 }
2433
2434
CheckConstructor(i::Isolate * isolate,i::Handle<i::JSObject> obj,const char * class_name)2435 static bool CheckConstructor(i::Isolate* isolate,
2436 i::Handle<i::JSObject> obj,
2437 const char* class_name) {
2438 i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
2439 if (!constr->IsJSFunction()) return false;
2440 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
2441 return func->shared()->native() && constr.is_identical_to(
2442 i::Object::GetProperty(isolate,
2443 isolate->js_builtins_object(),
2444 class_name).ToHandleChecked());
2445 }
2446
2447
IsNativeError() const2448 bool Value::IsNativeError() const {
2449 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2450 if (obj->IsJSObject()) {
2451 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
2452 i::Isolate* isolate = js_obj->GetIsolate();
2453 return CheckConstructor(isolate, js_obj, "$Error") ||
2454 CheckConstructor(isolate, js_obj, "$EvalError") ||
2455 CheckConstructor(isolate, js_obj, "$RangeError") ||
2456 CheckConstructor(isolate, js_obj, "$ReferenceError") ||
2457 CheckConstructor(isolate, js_obj, "$SyntaxError") ||
2458 CheckConstructor(isolate, js_obj, "$TypeError") ||
2459 CheckConstructor(isolate, js_obj, "$URIError");
2460 } else {
2461 return false;
2462 }
2463 }
2464
2465
IsBooleanObject() const2466 bool Value::IsBooleanObject() const {
2467 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2468 if (!obj->IsHeapObject()) return false;
2469 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2470 return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
2471 }
2472
2473
IsRegExp() const2474 bool Value::IsRegExp() const {
2475 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2476 return obj->IsJSRegExp();
2477 }
2478
2479
ToString() const2480 Local<String> Value::ToString() const {
2481 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2482 i::Handle<i::Object> str;
2483 if (obj->IsString()) {
2484 str = obj;
2485 } else {
2486 i::Isolate* isolate = i::Isolate::Current();
2487 LOG_API(isolate, "ToString");
2488 ENTER_V8(isolate);
2489 EXCEPTION_PREAMBLE(isolate);
2490 has_pending_exception = !i::Execution::ToString(
2491 isolate, obj).ToHandle(&str);
2492 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2493 }
2494 return ToApiHandle<String>(str);
2495 }
2496
2497
ToDetailString() const2498 Local<String> Value::ToDetailString() const {
2499 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2500 i::Handle<i::Object> str;
2501 if (obj->IsString()) {
2502 str = obj;
2503 } else {
2504 i::Isolate* isolate = i::Isolate::Current();
2505 LOG_API(isolate, "ToDetailString");
2506 ENTER_V8(isolate);
2507 EXCEPTION_PREAMBLE(isolate);
2508 has_pending_exception = !i::Execution::ToDetailString(
2509 isolate, obj).ToHandle(&str);
2510 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2511 }
2512 return ToApiHandle<String>(str);
2513 }
2514
2515
ToObject() const2516 Local<v8::Object> Value::ToObject() const {
2517 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2518 i::Handle<i::Object> val;
2519 if (obj->IsJSObject()) {
2520 val = obj;
2521 } else {
2522 i::Isolate* isolate = i::Isolate::Current();
2523 LOG_API(isolate, "ToObject");
2524 ENTER_V8(isolate);
2525 EXCEPTION_PREAMBLE(isolate);
2526 has_pending_exception = !i::Execution::ToObject(
2527 isolate, obj).ToHandle(&val);
2528 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2529 }
2530 return ToApiHandle<Object>(val);
2531 }
2532
2533
ToBoolean() const2534 Local<Boolean> Value::ToBoolean() const {
2535 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2536 if (obj->IsBoolean()) {
2537 return ToApiHandle<Boolean>(obj);
2538 } else {
2539 i::Isolate* isolate = i::Isolate::Current();
2540 LOG_API(isolate, "ToBoolean");
2541 ENTER_V8(isolate);
2542 i::Handle<i::Object> val =
2543 isolate->factory()->ToBoolean(obj->BooleanValue());
2544 return ToApiHandle<Boolean>(val);
2545 }
2546 }
2547
2548
ToNumber() const2549 Local<Number> Value::ToNumber() const {
2550 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2551 i::Handle<i::Object> num;
2552 if (obj->IsNumber()) {
2553 num = obj;
2554 } else {
2555 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2556 LOG_API(isolate, "ToNumber");
2557 ENTER_V8(isolate);
2558 EXCEPTION_PREAMBLE(isolate);
2559 has_pending_exception = !i::Execution::ToNumber(
2560 isolate, obj).ToHandle(&num);
2561 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2562 }
2563 return ToApiHandle<Number>(num);
2564 }
2565
2566
ToInteger() const2567 Local<Integer> Value::ToInteger() const {
2568 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2569 i::Handle<i::Object> num;
2570 if (obj->IsSmi()) {
2571 num = obj;
2572 } else {
2573 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2574 LOG_API(isolate, "ToInteger");
2575 ENTER_V8(isolate);
2576 EXCEPTION_PREAMBLE(isolate);
2577 has_pending_exception = !i::Execution::ToInteger(
2578 isolate, obj).ToHandle(&num);
2579 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2580 }
2581 return ToApiHandle<Integer>(num);
2582 }
2583
2584
CheckInitializedImpl(v8::Isolate * external_isolate)2585 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
2586 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
2587 Utils::ApiCheck(isolate != NULL &&
2588 isolate->IsInitialized() &&
2589 !isolate->IsDead(),
2590 "v8::internal::Internals::CheckInitialized()",
2591 "Isolate is not initialized or V8 has died");
2592 }
2593
2594
CheckCast(v8::Value * that)2595 void External::CheckCast(v8::Value* that) {
2596 Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
2597 "v8::External::Cast()",
2598 "Could not convert to external");
2599 }
2600
2601
CheckCast(Value * that)2602 void v8::Object::CheckCast(Value* that) {
2603 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2604 Utils::ApiCheck(obj->IsJSObject(),
2605 "v8::Object::Cast()",
2606 "Could not convert to object");
2607 }
2608
2609
CheckCast(Value * that)2610 void v8::Function::CheckCast(Value* that) {
2611 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2612 Utils::ApiCheck(obj->IsJSFunction(),
2613 "v8::Function::Cast()",
2614 "Could not convert to function");
2615 }
2616
2617
CheckCast(v8::Value * that)2618 void v8::String::CheckCast(v8::Value* that) {
2619 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2620 Utils::ApiCheck(obj->IsString(),
2621 "v8::String::Cast()",
2622 "Could not convert to string");
2623 }
2624
2625
CheckCast(v8::Value * that)2626 void v8::Symbol::CheckCast(v8::Value* that) {
2627 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2628 Utils::ApiCheck(obj->IsSymbol(),
2629 "v8::Symbol::Cast()",
2630 "Could not convert to symbol");
2631 }
2632
2633
CheckCast(v8::Value * that)2634 void v8::Number::CheckCast(v8::Value* that) {
2635 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2636 Utils::ApiCheck(obj->IsNumber(),
2637 "v8::Number::Cast()",
2638 "Could not convert to number");
2639 }
2640
2641
CheckCast(v8::Value * that)2642 void v8::Integer::CheckCast(v8::Value* that) {
2643 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2644 Utils::ApiCheck(obj->IsNumber(),
2645 "v8::Integer::Cast()",
2646 "Could not convert to number");
2647 }
2648
2649
CheckCast(Value * that)2650 void v8::Array::CheckCast(Value* that) {
2651 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2652 Utils::ApiCheck(obj->IsJSArray(),
2653 "v8::Array::Cast()",
2654 "Could not convert to array");
2655 }
2656
2657
CheckCast(Value * that)2658 void v8::Promise::CheckCast(Value* that) {
2659 Utils::ApiCheck(that->IsPromise(),
2660 "v8::Promise::Cast()",
2661 "Could not convert to promise");
2662 }
2663
2664
CheckCast(Value * that)2665 void v8::Promise::Resolver::CheckCast(Value* that) {
2666 Utils::ApiCheck(that->IsPromise(),
2667 "v8::Promise::Resolver::Cast()",
2668 "Could not convert to promise resolver");
2669 }
2670
2671
CheckCast(Value * that)2672 void v8::ArrayBuffer::CheckCast(Value* that) {
2673 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2674 Utils::ApiCheck(obj->IsJSArrayBuffer(),
2675 "v8::ArrayBuffer::Cast()",
2676 "Could not convert to ArrayBuffer");
2677 }
2678
2679
CheckCast(Value * that)2680 void v8::ArrayBufferView::CheckCast(Value* that) {
2681 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2682 Utils::ApiCheck(obj->IsJSArrayBufferView(),
2683 "v8::ArrayBufferView::Cast()",
2684 "Could not convert to ArrayBufferView");
2685 }
2686
2687
CheckCast(Value * that)2688 void v8::TypedArray::CheckCast(Value* that) {
2689 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2690 Utils::ApiCheck(obj->IsJSTypedArray(),
2691 "v8::TypedArray::Cast()",
2692 "Could not convert to TypedArray");
2693 }
2694
2695
2696 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size) \
2697 void v8::Type##Array::CheckCast(Value* that) { \
2698 i::Handle<i::Object> obj = Utils::OpenHandle(that); \
2699 Utils::ApiCheck(obj->IsJSTypedArray() && \
2700 i::JSTypedArray::cast(*obj)->type() == \
2701 kExternal##Type##Array, \
2702 "v8::" #Type "Array::Cast()", \
2703 "Could not convert to " #Type "Array"); \
2704 }
2705
2706
TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)2707 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
2708
2709 #undef CHECK_TYPED_ARRAY_CAST
2710
2711
2712 void v8::DataView::CheckCast(Value* that) {
2713 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2714 Utils::ApiCheck(obj->IsJSDataView(),
2715 "v8::DataView::Cast()",
2716 "Could not convert to DataView");
2717 }
2718
2719
CheckCast(v8::Value * that)2720 void v8::Date::CheckCast(v8::Value* that) {
2721 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2722 i::Isolate* isolate = NULL;
2723 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2724 Utils::ApiCheck(isolate != NULL &&
2725 obj->HasSpecificClassOf(isolate->heap()->Date_string()),
2726 "v8::Date::Cast()",
2727 "Could not convert to date");
2728 }
2729
2730
CheckCast(v8::Value * that)2731 void v8::StringObject::CheckCast(v8::Value* that) {
2732 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2733 i::Isolate* isolate = NULL;
2734 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2735 Utils::ApiCheck(isolate != NULL &&
2736 obj->HasSpecificClassOf(isolate->heap()->String_string()),
2737 "v8::StringObject::Cast()",
2738 "Could not convert to StringObject");
2739 }
2740
2741
CheckCast(v8::Value * that)2742 void v8::SymbolObject::CheckCast(v8::Value* that) {
2743 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2744 i::Isolate* isolate = NULL;
2745 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2746 Utils::ApiCheck(isolate != NULL &&
2747 obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
2748 "v8::SymbolObject::Cast()",
2749 "Could not convert to SymbolObject");
2750 }
2751
2752
CheckCast(v8::Value * that)2753 void v8::NumberObject::CheckCast(v8::Value* that) {
2754 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2755 i::Isolate* isolate = NULL;
2756 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2757 Utils::ApiCheck(isolate != NULL &&
2758 obj->HasSpecificClassOf(isolate->heap()->Number_string()),
2759 "v8::NumberObject::Cast()",
2760 "Could not convert to NumberObject");
2761 }
2762
2763
CheckCast(v8::Value * that)2764 void v8::BooleanObject::CheckCast(v8::Value* that) {
2765 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2766 i::Isolate* isolate = NULL;
2767 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2768 Utils::ApiCheck(isolate != NULL &&
2769 obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
2770 "v8::BooleanObject::Cast()",
2771 "Could not convert to BooleanObject");
2772 }
2773
2774
CheckCast(v8::Value * that)2775 void v8::RegExp::CheckCast(v8::Value* that) {
2776 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2777 Utils::ApiCheck(obj->IsJSRegExp(),
2778 "v8::RegExp::Cast()",
2779 "Could not convert to regular expression");
2780 }
2781
2782
BooleanValue() const2783 bool Value::BooleanValue() const {
2784 return Utils::OpenHandle(this)->BooleanValue();
2785 }
2786
2787
NumberValue() const2788 double Value::NumberValue() const {
2789 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2790 i::Handle<i::Object> num;
2791 if (obj->IsNumber()) {
2792 num = obj;
2793 } else {
2794 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2795 LOG_API(isolate, "NumberValue");
2796 ENTER_V8(isolate);
2797 EXCEPTION_PREAMBLE(isolate);
2798 has_pending_exception = !i::Execution::ToNumber(
2799 isolate, obj).ToHandle(&num);
2800 EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value());
2801 }
2802 return num->Number();
2803 }
2804
2805
IntegerValue() const2806 int64_t Value::IntegerValue() const {
2807 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2808 i::Handle<i::Object> num;
2809 if (obj->IsNumber()) {
2810 num = obj;
2811 } else {
2812 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2813 LOG_API(isolate, "IntegerValue");
2814 ENTER_V8(isolate);
2815 EXCEPTION_PREAMBLE(isolate);
2816 has_pending_exception = !i::Execution::ToInteger(
2817 isolate, obj).ToHandle(&num);
2818 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2819 }
2820 if (num->IsSmi()) {
2821 return i::Smi::cast(*num)->value();
2822 } else {
2823 return static_cast<int64_t>(num->Number());
2824 }
2825 }
2826
2827
ToInt32() const2828 Local<Int32> Value::ToInt32() const {
2829 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2830 i::Handle<i::Object> num;
2831 if (obj->IsSmi()) {
2832 num = obj;
2833 } else {
2834 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2835 LOG_API(isolate, "ToInt32");
2836 ENTER_V8(isolate);
2837 EXCEPTION_PREAMBLE(isolate);
2838 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2839 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2840 }
2841 return ToApiHandle<Int32>(num);
2842 }
2843
2844
ToUint32() const2845 Local<Uint32> Value::ToUint32() const {
2846 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2847 i::Handle<i::Object> num;
2848 if (obj->IsSmi()) {
2849 num = obj;
2850 } else {
2851 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2852 LOG_API(isolate, "ToUInt32");
2853 ENTER_V8(isolate);
2854 EXCEPTION_PREAMBLE(isolate);
2855 has_pending_exception = !i::Execution::ToUint32(
2856 isolate, obj).ToHandle(&num);
2857 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2858 }
2859 return ToApiHandle<Uint32>(num);
2860 }
2861
2862
ToArrayIndex() const2863 Local<Uint32> Value::ToArrayIndex() const {
2864 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2865 if (obj->IsSmi()) {
2866 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2867 return Local<Uint32>();
2868 }
2869 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2870 LOG_API(isolate, "ToArrayIndex");
2871 ENTER_V8(isolate);
2872 EXCEPTION_PREAMBLE(isolate);
2873 i::Handle<i::Object> string_obj;
2874 has_pending_exception = !i::Execution::ToString(
2875 isolate, obj).ToHandle(&string_obj);
2876 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2877 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2878 uint32_t index;
2879 if (str->AsArrayIndex(&index)) {
2880 i::Handle<i::Object> value;
2881 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2882 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
2883 } else {
2884 value = isolate->factory()->NewNumber(index);
2885 }
2886 return Utils::Uint32ToLocal(value);
2887 }
2888 return Local<Uint32>();
2889 }
2890
2891
Int32Value() const2892 int32_t Value::Int32Value() const {
2893 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2894 if (obj->IsSmi()) {
2895 return i::Smi::cast(*obj)->value();
2896 } else {
2897 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2898 LOG_API(isolate, "Int32Value (slow)");
2899 ENTER_V8(isolate);
2900 EXCEPTION_PREAMBLE(isolate);
2901 i::Handle<i::Object> num;
2902 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2903 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2904 if (num->IsSmi()) {
2905 return i::Smi::cast(*num)->value();
2906 } else {
2907 return static_cast<int32_t>(num->Number());
2908 }
2909 }
2910 }
2911
2912
Equals(Handle<Value> that) const2913 bool Value::Equals(Handle<Value> that) const {
2914 i::Isolate* isolate = i::Isolate::Current();
2915 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2916 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2917 "v8::Value::Equals()",
2918 "Reading from empty handle")) {
2919 return false;
2920 }
2921 LOG_API(isolate, "Equals");
2922 ENTER_V8(isolate);
2923 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2924 // If both obj and other are JSObjects, we'd better compare by identity
2925 // immediately when going into JS builtin. The reason is Invoke
2926 // would overwrite global object receiver with global proxy.
2927 if (obj->IsJSObject() && other->IsJSObject()) {
2928 return *obj == *other;
2929 }
2930 i::Handle<i::Object> args[] = { other };
2931 EXCEPTION_PREAMBLE(isolate);
2932 i::Handle<i::Object> result;
2933 has_pending_exception = !CallV8HeapFunction(
2934 "EQUALS", obj, ARRAY_SIZE(args), args).ToHandle(&result);
2935 EXCEPTION_BAILOUT_CHECK(isolate, false);
2936 return *result == i::Smi::FromInt(i::EQUAL);
2937 }
2938
2939
StrictEquals(Handle<Value> that) const2940 bool Value::StrictEquals(Handle<Value> that) const {
2941 i::Isolate* isolate = i::Isolate::Current();
2942 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2943 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2944 "v8::Value::StrictEquals()",
2945 "Reading from empty handle")) {
2946 return false;
2947 }
2948 LOG_API(isolate, "StrictEquals");
2949 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2950 // Must check HeapNumber first, since NaN !== NaN.
2951 if (obj->IsHeapNumber()) {
2952 if (!other->IsNumber()) return false;
2953 double x = obj->Number();
2954 double y = other->Number();
2955 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2956 return x == y && !std::isnan(x) && !std::isnan(y);
2957 } else if (*obj == *other) { // Also covers Booleans.
2958 return true;
2959 } else if (obj->IsSmi()) {
2960 return other->IsNumber() && obj->Number() == other->Number();
2961 } else if (obj->IsString()) {
2962 return other->IsString() &&
2963 i::String::Equals(i::Handle<i::String>::cast(obj),
2964 i::Handle<i::String>::cast(other));
2965 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2966 return other->IsUndefined() || other->IsUndetectableObject();
2967 } else {
2968 return false;
2969 }
2970 }
2971
2972
SameValue(Handle<Value> that) const2973 bool Value::SameValue(Handle<Value> that) const {
2974 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2975 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2976 "v8::Value::SameValue()",
2977 "Reading from empty handle")) {
2978 return false;
2979 }
2980 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2981 return obj->SameValue(*other);
2982 }
2983
2984
Uint32Value() const2985 uint32_t Value::Uint32Value() const {
2986 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2987 if (obj->IsSmi()) {
2988 return i::Smi::cast(*obj)->value();
2989 } else {
2990 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2991 LOG_API(isolate, "Uint32Value");
2992 ENTER_V8(isolate);
2993 EXCEPTION_PREAMBLE(isolate);
2994 i::Handle<i::Object> num;
2995 has_pending_exception = !i::Execution::ToUint32(
2996 isolate, obj).ToHandle(&num);
2997 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2998 if (num->IsSmi()) {
2999 return i::Smi::cast(*num)->value();
3000 } else {
3001 return static_cast<uint32_t>(num->Number());
3002 }
3003 }
3004 }
3005
3006
Set(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)3007 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
3008 v8::PropertyAttribute attribs) {
3009 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3010 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3011 ENTER_V8(isolate);
3012 i::HandleScope scope(isolate);
3013 i::Handle<i::Object> self = Utils::OpenHandle(this);
3014 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3015 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3016 EXCEPTION_PREAMBLE(isolate);
3017 has_pending_exception = i::Runtime::SetObjectProperty(
3018 isolate,
3019 self,
3020 key_obj,
3021 value_obj,
3022 static_cast<PropertyAttributes>(attribs),
3023 i::SLOPPY).is_null();
3024 EXCEPTION_BAILOUT_CHECK(isolate, false);
3025 return true;
3026 }
3027
3028
Set(uint32_t index,v8::Handle<Value> value)3029 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
3030 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3031 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3032 ENTER_V8(isolate);
3033 i::HandleScope scope(isolate);
3034 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3035 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3036 EXCEPTION_PREAMBLE(isolate);
3037 has_pending_exception = i::JSObject::SetElement(
3038 self, index, value_obj, NONE, i::SLOPPY).is_null();
3039 EXCEPTION_BAILOUT_CHECK(isolate, false);
3040 return true;
3041 }
3042
3043
ForceSet(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)3044 bool v8::Object::ForceSet(v8::Handle<Value> key,
3045 v8::Handle<Value> value,
3046 v8::PropertyAttribute attribs) {
3047 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3048 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
3049 ENTER_V8(isolate);
3050 i::HandleScope scope(isolate);
3051 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3052 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3053 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3054 EXCEPTION_PREAMBLE(isolate);
3055 has_pending_exception = i::Runtime::ForceSetObjectProperty(
3056 self,
3057 key_obj,
3058 value_obj,
3059 static_cast<PropertyAttributes>(attribs)).is_null();
3060 EXCEPTION_BAILOUT_CHECK(isolate, false);
3061 return true;
3062 }
3063
3064
SetPrivate(v8::Handle<Private> key,v8::Handle<Value> value)3065 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
3066 return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
3067 value, DontEnum);
3068 }
3069
3070
ForceDelete(v8::Handle<Value> key)3071 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
3072 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3073 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
3074 ENTER_V8(isolate);
3075 i::HandleScope scope(isolate);
3076 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3077 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3078
3079 // When deleting a property on the global object using ForceDelete
3080 // deoptimize all functions as optimized code does not check for the hole
3081 // value with DontDelete properties. We have to deoptimize all contexts
3082 // because of possible cross-context inlined functions.
3083 if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
3084 i::Deoptimizer::DeoptimizeAll(isolate);
3085 }
3086
3087 EXCEPTION_PREAMBLE(isolate);
3088 i::Handle<i::Object> obj;
3089 has_pending_exception = !i::Runtime::DeleteObjectProperty(
3090 isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
3091 EXCEPTION_BAILOUT_CHECK(isolate, false);
3092 return obj->IsTrue();
3093 }
3094
3095
Get(v8::Handle<Value> key)3096 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
3097 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3098 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3099 ENTER_V8(isolate);
3100 i::Handle<i::Object> self = Utils::OpenHandle(this);
3101 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3102 EXCEPTION_PREAMBLE(isolate);
3103 i::Handle<i::Object> result;
3104 has_pending_exception =
3105 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
3106 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3107 return Utils::ToLocal(result);
3108 }
3109
3110
Get(uint32_t index)3111 Local<Value> v8::Object::Get(uint32_t index) {
3112 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3113 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3114 ENTER_V8(isolate);
3115 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3116 EXCEPTION_PREAMBLE(isolate);
3117 i::Handle<i::Object> result;
3118 has_pending_exception =
3119 !i::Object::GetElement(isolate, self, index).ToHandle(&result);
3120 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3121 return Utils::ToLocal(result);
3122 }
3123
3124
GetPrivate(v8::Handle<Private> key)3125 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) {
3126 return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3127 }
3128
3129
GetPropertyAttributes(v8::Handle<Value> key)3130 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
3131 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3132 ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()",
3133 return static_cast<PropertyAttribute>(NONE));
3134 ENTER_V8(isolate);
3135 i::HandleScope scope(isolate);
3136 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3137 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3138 if (!key_obj->IsName()) {
3139 EXCEPTION_PREAMBLE(isolate);
3140 has_pending_exception = !i::Execution::ToString(
3141 isolate, key_obj).ToHandle(&key_obj);
3142 EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3143 }
3144 i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
3145 PropertyAttributes result =
3146 i::JSReceiver::GetPropertyAttributes(self, key_name);
3147 if (result == ABSENT) return static_cast<PropertyAttribute>(NONE);
3148 return static_cast<PropertyAttribute>(result);
3149 }
3150
3151
GetPrototype()3152 Local<Value> v8::Object::GetPrototype() {
3153 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3154 ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
3155 ENTER_V8(isolate);
3156 i::Handle<i::Object> self = Utils::OpenHandle(this);
3157 i::Handle<i::Object> result(self->GetPrototype(isolate), isolate);
3158 return Utils::ToLocal(result);
3159 }
3160
3161
SetPrototype(Handle<Value> value)3162 bool v8::Object::SetPrototype(Handle<Value> value) {
3163 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3164 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
3165 ENTER_V8(isolate);
3166 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3167 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3168 // We do not allow exceptions thrown while setting the prototype
3169 // to propagate outside.
3170 TryCatch try_catch;
3171 EXCEPTION_PREAMBLE(isolate);
3172 i::MaybeHandle<i::Object> result = i::JSObject::SetPrototype(
3173 self, value_obj);
3174 has_pending_exception = result.is_null();
3175 EXCEPTION_BAILOUT_CHECK(isolate, false);
3176 return true;
3177 }
3178
3179
FindInstanceInPrototypeChain(v8::Handle<FunctionTemplate> tmpl)3180 Local<Object> v8::Object::FindInstanceInPrototypeChain(
3181 v8::Handle<FunctionTemplate> tmpl) {
3182 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3183 ON_BAILOUT(isolate,
3184 "v8::Object::FindInstanceInPrototypeChain()",
3185 return Local<v8::Object>());
3186 ENTER_V8(isolate);
3187 i::JSObject* object = *Utils::OpenHandle(this);
3188 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
3189 while (!tmpl_info->IsTemplateFor(object)) {
3190 i::Object* prototype = object->GetPrototype();
3191 if (!prototype->IsJSObject()) return Local<Object>();
3192 object = i::JSObject::cast(prototype);
3193 }
3194 return Utils::ToLocal(i::Handle<i::JSObject>(object));
3195 }
3196
3197
GetPropertyNames()3198 Local<Array> v8::Object::GetPropertyNames() {
3199 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3200 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
3201 return Local<v8::Array>());
3202 ENTER_V8(isolate);
3203 i::HandleScope scope(isolate);
3204 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3205 EXCEPTION_PREAMBLE(isolate);
3206 i::Handle<i::FixedArray> value;
3207 has_pending_exception = !i::JSReceiver::GetKeys(
3208 self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value);
3209 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3210 // Because we use caching to speed up enumeration it is important
3211 // to never change the result of the basic enumeration function so
3212 // we clone the result.
3213 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3214 i::Handle<i::JSArray> result =
3215 isolate->factory()->NewJSArrayWithElements(elms);
3216 return Utils::ToLocal(scope.CloseAndEscape(result));
3217 }
3218
3219
GetOwnPropertyNames()3220 Local<Array> v8::Object::GetOwnPropertyNames() {
3221 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3222 ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
3223 return Local<v8::Array>());
3224 ENTER_V8(isolate);
3225 i::HandleScope scope(isolate);
3226 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3227 EXCEPTION_PREAMBLE(isolate);
3228 i::Handle<i::FixedArray> value;
3229 has_pending_exception = !i::JSReceiver::GetKeys(
3230 self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
3231 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3232 // Because we use caching to speed up enumeration it is important
3233 // to never change the result of the basic enumeration function so
3234 // we clone the result.
3235 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3236 i::Handle<i::JSArray> result =
3237 isolate->factory()->NewJSArrayWithElements(elms);
3238 return Utils::ToLocal(scope.CloseAndEscape(result));
3239 }
3240
3241
ObjectProtoToString()3242 Local<String> v8::Object::ObjectProtoToString() {
3243 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
3244 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
3245 ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()",
3246 return Local<v8::String>());
3247 ENTER_V8(i_isolate);
3248 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3249
3250 i::Handle<i::Object> name(self->class_name(), i_isolate);
3251
3252 // Native implementation of Object.prototype.toString (v8natives.js):
3253 // var c = %_ClassOf(this);
3254 // if (c === 'Arguments') c = 'Object';
3255 // return "[object " + c + "]";
3256
3257 if (!name->IsString()) {
3258 return v8::String::NewFromUtf8(isolate, "[object ]");
3259 } else {
3260 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
3261 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) {
3262 return v8::String::NewFromUtf8(isolate, "[object Object]");
3263 } else {
3264 const char* prefix = "[object ";
3265 Local<String> str = Utils::ToLocal(class_name);
3266 const char* postfix = "]";
3267
3268 int prefix_len = i::StrLength(prefix);
3269 int str_len = str->Utf8Length();
3270 int postfix_len = i::StrLength(postfix);
3271
3272 int buf_len = prefix_len + str_len + postfix_len;
3273 i::ScopedVector<char> buf(buf_len);
3274
3275 // Write prefix.
3276 char* ptr = buf.start();
3277 i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
3278 ptr += prefix_len;
3279
3280 // Write real content.
3281 str->WriteUtf8(ptr, str_len);
3282 ptr += str_len;
3283
3284 // Write postfix.
3285 i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
3286
3287 // Copy the buffer into a heap-allocated string and return it.
3288 Local<String> result = v8::String::NewFromUtf8(
3289 isolate, buf.start(), String::kNormalString, buf_len);
3290 return result;
3291 }
3292 }
3293 }
3294
3295
GetConstructor()3296 Local<Value> v8::Object::GetConstructor() {
3297 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3298 ON_BAILOUT(isolate, "v8::Object::GetConstructor()",
3299 return Local<v8::Function>());
3300 ENTER_V8(isolate);
3301 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3302 i::Handle<i::Object> constructor(self->GetConstructor(), isolate);
3303 return Utils::ToLocal(constructor);
3304 }
3305
3306
GetConstructorName()3307 Local<String> v8::Object::GetConstructorName() {
3308 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3309 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
3310 return Local<v8::String>());
3311 ENTER_V8(isolate);
3312 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3313 i::Handle<i::String> name(self->constructor_name());
3314 return Utils::ToLocal(name);
3315 }
3316
3317
Delete(v8::Handle<Value> key)3318 bool v8::Object::Delete(v8::Handle<Value> key) {
3319 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3320 ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
3321 ENTER_V8(isolate);
3322 i::HandleScope scope(isolate);
3323 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3324 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3325 EXCEPTION_PREAMBLE(isolate);
3326 i::Handle<i::Object> obj;
3327 has_pending_exception = !i::Runtime::DeleteObjectProperty(
3328 isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
3329 EXCEPTION_BAILOUT_CHECK(isolate, false);
3330 return obj->IsTrue();
3331 }
3332
3333
DeletePrivate(v8::Handle<Private> key)3334 bool v8::Object::DeletePrivate(v8::Handle<Private> key) {
3335 return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3336 }
3337
3338
Has(v8::Handle<Value> key)3339 bool v8::Object::Has(v8::Handle<Value> key) {
3340 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3341 ON_BAILOUT(isolate, "v8::Object::Has()", return false);
3342 ENTER_V8(isolate);
3343 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
3344 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3345 EXCEPTION_PREAMBLE(isolate);
3346 i::Handle<i::Object> obj;
3347 has_pending_exception = !i::Runtime::HasObjectProperty(
3348 isolate, self, key_obj).ToHandle(&obj);
3349 EXCEPTION_BAILOUT_CHECK(isolate, false);
3350 return obj->IsTrue();
3351 }
3352
3353
HasPrivate(v8::Handle<Private> key)3354 bool v8::Object::HasPrivate(v8::Handle<Private> key) {
3355 // TODO(rossberg): this should use HasOwnProperty, but we'd need to
3356 // generalise that to a (noy yet existant) Name argument first.
3357 return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3358 }
3359
3360
Delete(uint32_t index)3361 bool v8::Object::Delete(uint32_t index) {
3362 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3363 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
3364 return false);
3365 ENTER_V8(isolate);
3366 HandleScope scope(reinterpret_cast<Isolate*>(isolate));
3367 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3368
3369 EXCEPTION_PREAMBLE(isolate);
3370 i::Handle<i::Object> obj;
3371 has_pending_exception =
3372 !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj);
3373 EXCEPTION_BAILOUT_CHECK(isolate, false);
3374 return obj->IsTrue();
3375 }
3376
3377
Has(uint32_t index)3378 bool v8::Object::Has(uint32_t index) {
3379 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3380 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
3381 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3382 return i::JSReceiver::HasElement(self, index);
3383 }
3384
3385
3386 template<typename Setter, typename Getter, typename Data>
ObjectSetAccessor(Object * obj,Handle<String> name,Setter getter,Getter setter,Data data,AccessControl settings,PropertyAttribute attributes)3387 static inline bool ObjectSetAccessor(Object* obj,
3388 Handle<String> name,
3389 Setter getter,
3390 Getter setter,
3391 Data data,
3392 AccessControl settings,
3393 PropertyAttribute attributes) {
3394 i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
3395 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
3396 ENTER_V8(isolate);
3397 i::HandleScope scope(isolate);
3398 v8::Handle<AccessorSignature> signature;
3399 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
3400 name, getter, setter, data, settings, attributes, signature);
3401 if (info.is_null()) return false;
3402 bool fast = Utils::OpenHandle(obj)->HasFastProperties();
3403 i::Handle<i::Object> result;
3404 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3405 isolate, result,
3406 i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
3407 false);
3408 if (result->IsUndefined()) return false;
3409 if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
3410 return true;
3411 }
3412
3413
SetAccessor(Handle<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attributes)3414 bool Object::SetAccessor(Handle<String> name,
3415 AccessorGetterCallback getter,
3416 AccessorSetterCallback setter,
3417 v8::Handle<Value> data,
3418 AccessControl settings,
3419 PropertyAttribute attributes) {
3420 return ObjectSetAccessor(
3421 this, name, getter, setter, data, settings, attributes);
3422 }
3423
3424
SetDeclaredAccessor(Local<String> name,Local<DeclaredAccessorDescriptor> descriptor,PropertyAttribute attributes,AccessControl settings)3425 bool Object::SetDeclaredAccessor(Local<String> name,
3426 Local<DeclaredAccessorDescriptor> descriptor,
3427 PropertyAttribute attributes,
3428 AccessControl settings) {
3429 void* null = NULL;
3430 return ObjectSetAccessor(
3431 this, name, descriptor, null, null, settings, attributes);
3432 }
3433
3434
SetAccessorProperty(Local<String> name,Local<Function> getter,Handle<Function> setter,PropertyAttribute attribute,AccessControl settings)3435 void Object::SetAccessorProperty(Local<String> name,
3436 Local<Function> getter,
3437 Handle<Function> setter,
3438 PropertyAttribute attribute,
3439 AccessControl settings) {
3440 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3441 ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return);
3442 ENTER_V8(isolate);
3443 i::HandleScope scope(isolate);
3444 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
3445 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
3446 if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
3447 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this),
3448 v8::Utils::OpenHandle(*name),
3449 getter_i,
3450 setter_i,
3451 static_cast<PropertyAttributes>(attribute),
3452 settings);
3453 }
3454
3455
HasOwnProperty(Handle<String> key)3456 bool v8::Object::HasOwnProperty(Handle<String> key) {
3457 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3458 ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
3459 return false);
3460 return i::JSReceiver::HasOwnProperty(
3461 Utils::OpenHandle(this), Utils::OpenHandle(*key));
3462 }
3463
3464
HasRealNamedProperty(Handle<String> key)3465 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
3466 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3467 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
3468 return false);
3469 return i::JSObject::HasRealNamedProperty(Utils::OpenHandle(this),
3470 Utils::OpenHandle(*key));
3471 }
3472
3473
HasRealIndexedProperty(uint32_t index)3474 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
3475 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3476 ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
3477 return false);
3478 return i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
3479 }
3480
3481
HasRealNamedCallbackProperty(Handle<String> key)3482 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
3483 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3484 ON_BAILOUT(isolate,
3485 "v8::Object::HasRealNamedCallbackProperty()",
3486 return false);
3487 ENTER_V8(isolate);
3488 return i::JSObject::HasRealNamedCallbackProperty(Utils::OpenHandle(this),
3489 Utils::OpenHandle(*key));
3490 }
3491
3492
HasNamedLookupInterceptor()3493 bool v8::Object::HasNamedLookupInterceptor() {
3494 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3495 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
3496 return false);
3497 return Utils::OpenHandle(this)->HasNamedInterceptor();
3498 }
3499
3500
HasIndexedLookupInterceptor()3501 bool v8::Object::HasIndexedLookupInterceptor() {
3502 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3503 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
3504 return false);
3505 return Utils::OpenHandle(this)->HasIndexedInterceptor();
3506 }
3507
3508
GetPropertyByLookup(i::Isolate * isolate,i::Handle<i::JSObject> receiver,i::Handle<i::String> name,i::LookupResult * lookup)3509 static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
3510 i::Handle<i::JSObject> receiver,
3511 i::Handle<i::String> name,
3512 i::LookupResult* lookup) {
3513 if (!lookup->IsProperty()) {
3514 // No real property was found.
3515 return Local<Value>();
3516 }
3517
3518 // If the property being looked up is a callback, it can throw
3519 // an exception.
3520 EXCEPTION_PREAMBLE(isolate);
3521 i::LookupIterator it(
3522 receiver, name, i::Handle<i::JSReceiver>(lookup->holder(), isolate),
3523 i::LookupIterator::SKIP_INTERCEPTOR);
3524 i::Handle<i::Object> result;
3525 has_pending_exception = !i::Object::GetProperty(&it).ToHandle(&result);
3526 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3527
3528 return Utils::ToLocal(result);
3529 }
3530
3531
GetRealNamedPropertyInPrototypeChain(Handle<String> key)3532 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
3533 Handle<String> key) {
3534 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3535 ON_BAILOUT(isolate,
3536 "v8::Object::GetRealNamedPropertyInPrototypeChain()",
3537 return Local<Value>());
3538 ENTER_V8(isolate);
3539 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3540 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3541 i::LookupResult lookup(isolate);
3542 self_obj->LookupRealNamedPropertyInPrototypes(key_obj, &lookup);
3543 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3544 }
3545
3546
GetRealNamedProperty(Handle<String> key)3547 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
3548 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3549 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
3550 return Local<Value>());
3551 ENTER_V8(isolate);
3552 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3553 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3554 i::LookupResult lookup(isolate);
3555 self_obj->LookupRealNamedProperty(key_obj, &lookup);
3556 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3557 }
3558
3559
3560 // Turns on access checks by copying the map and setting the check flag.
3561 // Because the object gets a new map, existing inline cache caching
3562 // the old map of this object will fail.
TurnOnAccessCheck()3563 void v8::Object::TurnOnAccessCheck() {
3564 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3565 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
3566 ENTER_V8(isolate);
3567 i::HandleScope scope(isolate);
3568 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3569
3570 // When turning on access checks for a global object deoptimize all functions
3571 // as optimized code does not always handle access checks.
3572 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
3573
3574 i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
3575 new_map->set_is_access_check_needed(true);
3576 obj->set_map(*new_map);
3577 }
3578
3579
IsDirty()3580 bool v8::Object::IsDirty() {
3581 return Utils::OpenHandle(this)->IsDirty();
3582 }
3583
3584
Clone()3585 Local<v8::Object> v8::Object::Clone() {
3586 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3587 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
3588 ENTER_V8(isolate);
3589 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3590 EXCEPTION_PREAMBLE(isolate);
3591 i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
3592 has_pending_exception = result.is_null();
3593 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3594 return Utils::ToLocal(result);
3595 }
3596
3597
CreationContext()3598 Local<v8::Context> v8::Object::CreationContext() {
3599 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3600 ON_BAILOUT(isolate,
3601 "v8::Object::CreationContext()", return Local<v8::Context>());
3602 ENTER_V8(isolate);
3603 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3604 i::Context* context = self->GetCreationContext();
3605 return Utils::ToLocal(i::Handle<i::Context>(context));
3606 }
3607
3608
GetIdentityHash()3609 int v8::Object::GetIdentityHash() {
3610 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3611 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
3612 ENTER_V8(isolate);
3613 i::HandleScope scope(isolate);
3614 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3615 return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
3616 }
3617
3618
SetHiddenValue(v8::Handle<v8::String> key,v8::Handle<v8::Value> value)3619 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
3620 v8::Handle<v8::Value> value) {
3621 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3622 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
3623 if (value.IsEmpty()) return DeleteHiddenValue(key);
3624 ENTER_V8(isolate);
3625 i::HandleScope scope(isolate);
3626 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3627 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3628 i::Handle<i::String> key_string =
3629 isolate->factory()->InternalizeString(key_obj);
3630 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3631 i::Handle<i::Object> result =
3632 i::JSObject::SetHiddenProperty(self, key_string, value_obj);
3633 return *result == *self;
3634 }
3635
3636
GetHiddenValue(v8::Handle<v8::String> key)3637 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
3638 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3639 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
3640 return Local<v8::Value>());
3641 ENTER_V8(isolate);
3642 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3643 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3644 i::Handle<i::String> key_string =
3645 isolate->factory()->InternalizeString(key_obj);
3646 i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate);
3647 if (result->IsTheHole()) return v8::Local<v8::Value>();
3648 return Utils::ToLocal(result);
3649 }
3650
3651
DeleteHiddenValue(v8::Handle<v8::String> key)3652 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3653 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3654 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3655 ENTER_V8(isolate);
3656 i::HandleScope scope(isolate);
3657 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3658 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3659 i::Handle<i::String> key_string =
3660 isolate->factory()->InternalizeString(key_obj);
3661 i::JSObject::DeleteHiddenProperty(self, key_string);
3662 return true;
3663 }
3664
3665
3666 namespace {
3667
GetElementsKindFromExternalArrayType(ExternalArrayType array_type)3668 static i::ElementsKind GetElementsKindFromExternalArrayType(
3669 ExternalArrayType array_type) {
3670 switch (array_type) {
3671 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \
3672 case kExternal##Type##Array: \
3673 return i::EXTERNAL_##TYPE##_ELEMENTS;
3674
3675 TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND)
3676 #undef ARRAY_TYPE_TO_ELEMENTS_KIND
3677 }
3678 UNREACHABLE();
3679 return i::DICTIONARY_ELEMENTS;
3680 }
3681
3682
PrepareExternalArrayElements(i::Handle<i::JSObject> object,void * data,ExternalArrayType array_type,int length)3683 void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3684 void* data,
3685 ExternalArrayType array_type,
3686 int length) {
3687 i::Isolate* isolate = object->GetIsolate();
3688 i::Handle<i::ExternalArray> array =
3689 isolate->factory()->NewExternalArray(length, array_type, data);
3690
3691 i::Handle<i::Map> external_array_map =
3692 i::JSObject::GetElementsTransitionMap(
3693 object,
3694 GetElementsKindFromExternalArrayType(array_type));
3695
3696 i::JSObject::SetMapAndElements(object, external_array_map, array);
3697 }
3698
3699 } // namespace
3700
3701
SetIndexedPropertiesToPixelData(uint8_t * data,int length)3702 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3703 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3704 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3705 ENTER_V8(isolate);
3706 i::HandleScope scope(isolate);
3707 if (!Utils::ApiCheck(length >= 0 &&
3708 length <= i::ExternalUint8ClampedArray::kMaxLength,
3709 "v8::Object::SetIndexedPropertiesToPixelData()",
3710 "length exceeds max acceptable value")) {
3711 return;
3712 }
3713 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3714 if (!Utils::ApiCheck(!self->IsJSArray(),
3715 "v8::Object::SetIndexedPropertiesToPixelData()",
3716 "JSArray is not supported")) {
3717 return;
3718 }
3719 PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length);
3720 }
3721
3722
HasIndexedPropertiesInPixelData()3723 bool v8::Object::HasIndexedPropertiesInPixelData() {
3724 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3725 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3726 return false);
3727 return self->HasExternalUint8ClampedElements();
3728 }
3729
3730
GetIndexedPropertiesPixelData()3731 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3732 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3733 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3734 return NULL);
3735 if (self->HasExternalUint8ClampedElements()) {
3736 return i::ExternalUint8ClampedArray::cast(self->elements())->
3737 external_uint8_clamped_pointer();
3738 } else {
3739 return NULL;
3740 }
3741 }
3742
3743
GetIndexedPropertiesPixelDataLength()3744 int v8::Object::GetIndexedPropertiesPixelDataLength() {
3745 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3746 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3747 return -1);
3748 if (self->HasExternalUint8ClampedElements()) {
3749 return i::ExternalUint8ClampedArray::cast(self->elements())->length();
3750 } else {
3751 return -1;
3752 }
3753 }
3754
3755
SetIndexedPropertiesToExternalArrayData(void * data,ExternalArrayType array_type,int length)3756 void v8::Object::SetIndexedPropertiesToExternalArrayData(
3757 void* data,
3758 ExternalArrayType array_type,
3759 int length) {
3760 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3761 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3762 ENTER_V8(isolate);
3763 i::HandleScope scope(isolate);
3764 if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
3765 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3766 "length exceeds max acceptable value")) {
3767 return;
3768 }
3769 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3770 if (!Utils::ApiCheck(!self->IsJSArray(),
3771 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3772 "JSArray is not supported")) {
3773 return;
3774 }
3775 PrepareExternalArrayElements(self, data, array_type, length);
3776 }
3777
3778
HasIndexedPropertiesInExternalArrayData()3779 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3780 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3781 ON_BAILOUT(self->GetIsolate(),
3782 "v8::HasIndexedPropertiesInExternalArrayData()",
3783 return false);
3784 return self->HasExternalArrayElements();
3785 }
3786
3787
GetIndexedPropertiesExternalArrayData()3788 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3789 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3790 ON_BAILOUT(self->GetIsolate(),
3791 "v8::GetIndexedPropertiesExternalArrayData()",
3792 return NULL);
3793 if (self->HasExternalArrayElements()) {
3794 return i::ExternalArray::cast(self->elements())->external_pointer();
3795 } else {
3796 return NULL;
3797 }
3798 }
3799
3800
GetIndexedPropertiesExternalArrayDataType()3801 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3802 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3803 ON_BAILOUT(self->GetIsolate(),
3804 "v8::GetIndexedPropertiesExternalArrayDataType()",
3805 return static_cast<ExternalArrayType>(-1));
3806 switch (self->elements()->map()->instance_type()) {
3807 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \
3808 case i::EXTERNAL_##TYPE##_ARRAY_TYPE: \
3809 return kExternal##Type##Array;
3810 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
3811 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
3812 default:
3813 return static_cast<ExternalArrayType>(-1);
3814 }
3815 }
3816
3817
GetIndexedPropertiesExternalArrayDataLength()3818 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3819 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3820 ON_BAILOUT(self->GetIsolate(),
3821 "v8::GetIndexedPropertiesExternalArrayDataLength()",
3822 return 0);
3823 if (self->HasExternalArrayElements()) {
3824 return i::ExternalArray::cast(self->elements())->length();
3825 } else {
3826 return -1;
3827 }
3828 }
3829
3830
IsCallable()3831 bool v8::Object::IsCallable() {
3832 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3833 ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
3834 ENTER_V8(isolate);
3835 i::HandleScope scope(isolate);
3836 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3837 return obj->IsCallable();
3838 }
3839
3840
CallAsFunction(v8::Handle<v8::Value> recv,int argc,v8::Handle<v8::Value> argv[])3841 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
3842 int argc,
3843 v8::Handle<v8::Value> argv[]) {
3844 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3845 ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
3846 return Local<v8::Value>());
3847 LOG_API(isolate, "Object::CallAsFunction");
3848 ENTER_V8(isolate);
3849 i::Logger::TimerEventScope timer_scope(
3850 isolate, i::Logger::TimerEventScope::v8_execute);
3851 i::HandleScope scope(isolate);
3852 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3853 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3854 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3855 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3856 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
3857 if (obj->IsJSFunction()) {
3858 fun = i::Handle<i::JSFunction>::cast(obj);
3859 } else {
3860 EXCEPTION_PREAMBLE(isolate);
3861 i::Handle<i::Object> delegate;
3862 has_pending_exception = !i::Execution::TryGetFunctionDelegate(
3863 isolate, obj).ToHandle(&delegate);
3864 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3865 fun = i::Handle<i::JSFunction>::cast(delegate);
3866 recv_obj = obj;
3867 }
3868 EXCEPTION_PREAMBLE(isolate);
3869 i::Handle<i::Object> returned;
3870 has_pending_exception = !i::Execution::Call(
3871 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
3872 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
3873 return Utils::ToLocal(scope.CloseAndEscape(returned));
3874 }
3875
3876
CallAsConstructor(int argc,v8::Handle<v8::Value> argv[])3877 Local<v8::Value> Object::CallAsConstructor(int argc,
3878 v8::Handle<v8::Value> argv[]) {
3879 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3880 ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
3881 return Local<v8::Object>());
3882 LOG_API(isolate, "Object::CallAsConstructor");
3883 ENTER_V8(isolate);
3884 i::Logger::TimerEventScope timer_scope(
3885 isolate, i::Logger::TimerEventScope::v8_execute);
3886 i::HandleScope scope(isolate);
3887 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3888 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3889 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3890 if (obj->IsJSFunction()) {
3891 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
3892 EXCEPTION_PREAMBLE(isolate);
3893 i::Handle<i::Object> returned;
3894 has_pending_exception = !i::Execution::New(
3895 fun, argc, args).ToHandle(&returned);
3896 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3897 return Utils::ToLocal(scope.CloseAndEscape(
3898 i::Handle<i::JSObject>::cast(returned)));
3899 }
3900 EXCEPTION_PREAMBLE(isolate);
3901 i::Handle<i::Object> delegate;
3902 has_pending_exception = !i::Execution::TryGetConstructorDelegate(
3903 isolate, obj).ToHandle(&delegate);
3904 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
3905 if (!delegate->IsUndefined()) {
3906 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
3907 EXCEPTION_PREAMBLE(isolate);
3908 i::Handle<i::Object> returned;
3909 has_pending_exception = !i::Execution::Call(
3910 isolate, fun, obj, argc, args).ToHandle(&returned);
3911 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3912 ASSERT(!delegate->IsUndefined());
3913 return Utils::ToLocal(scope.CloseAndEscape(returned));
3914 }
3915 return Local<v8::Object>();
3916 }
3917
3918
New(Isolate * v8_isolate,FunctionCallback callback,Local<Value> data,int length)3919 Local<Function> Function::New(Isolate* v8_isolate,
3920 FunctionCallback callback,
3921 Local<Value> data,
3922 int length) {
3923 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3924 LOG_API(isolate, "Function::New");
3925 ENTER_V8(isolate);
3926 return FunctionTemplateNew(
3927 isolate, callback, data, Local<Signature>(), length, true)->
3928 GetFunction();
3929 }
3930
3931
NewInstance() const3932 Local<v8::Object> Function::NewInstance() const {
3933 return NewInstance(0, NULL);
3934 }
3935
3936
NewInstance(int argc,v8::Handle<v8::Value> argv[]) const3937 Local<v8::Object> Function::NewInstance(int argc,
3938 v8::Handle<v8::Value> argv[]) const {
3939 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3940 ON_BAILOUT(isolate, "v8::Function::NewInstance()",
3941 return Local<v8::Object>());
3942 LOG_API(isolate, "Function::NewInstance");
3943 ENTER_V8(isolate);
3944 i::Logger::TimerEventScope timer_scope(
3945 isolate, i::Logger::TimerEventScope::v8_execute);
3946 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
3947 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
3948 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3949 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3950 EXCEPTION_PREAMBLE(isolate);
3951 i::Handle<i::Object> returned;
3952 has_pending_exception = !i::Execution::New(
3953 function, argc, args).ToHandle(&returned);
3954 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3955 return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
3956 }
3957
3958
Call(v8::Handle<v8::Value> recv,int argc,v8::Handle<v8::Value> argv[])3959 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
3960 v8::Handle<v8::Value> argv[]) {
3961 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3962 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
3963 LOG_API(isolate, "Function::Call");
3964 ENTER_V8(isolate);
3965 i::Logger::TimerEventScope timer_scope(
3966 isolate, i::Logger::TimerEventScope::v8_execute);
3967 i::HandleScope scope(isolate);
3968 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
3969 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3970 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3971 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3972 EXCEPTION_PREAMBLE(isolate);
3973 i::Handle<i::Object> returned;
3974 has_pending_exception = !i::Execution::Call(
3975 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
3976 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
3977 return Utils::ToLocal(scope.CloseAndEscape(returned));
3978 }
3979
3980
SetName(v8::Handle<v8::String> name)3981 void Function::SetName(v8::Handle<v8::String> name) {
3982 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3983 ENTER_V8(isolate);
3984 USE(isolate);
3985 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3986 func->shared()->set_name(*Utils::OpenHandle(*name));
3987 }
3988
3989
GetName() const3990 Handle<Value> Function::GetName() const {
3991 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3992 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
3993 func->GetIsolate()));
3994 }
3995
3996
GetInferredName() const3997 Handle<Value> Function::GetInferredName() const {
3998 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
3999 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
4000 func->GetIsolate()));
4001 }
4002
4003
GetDisplayName() const4004 Handle<Value> Function::GetDisplayName() const {
4005 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4006 ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
4007 return ToApiHandle<Primitive>(
4008 isolate->factory()->undefined_value()));
4009 ENTER_V8(isolate);
4010 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4011 i::Handle<i::String> property_name =
4012 isolate->factory()->InternalizeOneByteString(
4013 STATIC_ASCII_VECTOR("displayName"));
4014 i::LookupResult lookup(isolate);
4015 func->LookupRealNamedProperty(property_name, &lookup);
4016 if (lookup.IsFound()) {
4017 i::Object* value = lookup.GetLazyValue();
4018 if (value && value->IsString()) {
4019 i::String* name = i::String::cast(value);
4020 if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name));
4021 }
4022 }
4023 return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
4024 }
4025
4026
GetScriptOrigin() const4027 ScriptOrigin Function::GetScriptOrigin() const {
4028 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4029 if (func->shared()->script()->IsScript()) {
4030 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4031 i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script);
4032 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
4033 v8::ScriptOrigin origin(
4034 Utils::ToLocal(scriptName),
4035 v8::Integer::New(isolate, script->line_offset()->value()),
4036 v8::Integer::New(isolate, script->column_offset()->value()));
4037 return origin;
4038 }
4039 return v8::ScriptOrigin(Handle<Value>());
4040 }
4041
4042
4043 const int Function::kLineOffsetNotFound = -1;
4044
4045
GetScriptLineNumber() const4046 int Function::GetScriptLineNumber() const {
4047 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4048 if (func->shared()->script()->IsScript()) {
4049 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4050 return i::Script::GetLineNumber(script, func->shared()->start_position());
4051 }
4052 return kLineOffsetNotFound;
4053 }
4054
4055
GetScriptColumnNumber() const4056 int Function::GetScriptColumnNumber() const {
4057 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4058 if (func->shared()->script()->IsScript()) {
4059 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4060 return i::Script::GetColumnNumber(script, func->shared()->start_position());
4061 }
4062 return kLineOffsetNotFound;
4063 }
4064
4065
IsBuiltin() const4066 bool Function::IsBuiltin() const {
4067 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4068 return func->IsBuiltin();
4069 }
4070
4071
ScriptId() const4072 int Function::ScriptId() const {
4073 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4074 if (!func->shared()->script()->IsScript()) {
4075 return v8::UnboundScript::kNoScriptId;
4076 }
4077 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4078 return script->id()->value();
4079 }
4080
4081
GetBoundFunction() const4082 Local<v8::Value> Function::GetBoundFunction() const {
4083 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4084 if (!func->shared()->bound()) {
4085 return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
4086 }
4087 i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
4088 i::FixedArray::cast(func->function_bindings()));
4089 i::Handle<i::Object> original(
4090 bound_args->get(i::JSFunction::kBoundFunctionIndex),
4091 func->GetIsolate());
4092 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
4093 }
4094
4095
Length() const4096 int String::Length() const {
4097 i::Handle<i::String> str = Utils::OpenHandle(this);
4098 return str->length();
4099 }
4100
4101
IsOneByte() const4102 bool String::IsOneByte() const {
4103 i::Handle<i::String> str = Utils::OpenHandle(this);
4104 return str->HasOnlyOneByteChars();
4105 }
4106
4107
4108 // Helpers for ContainsOnlyOneByteHelper
4109 template<size_t size> struct OneByteMask;
4110 template<> struct OneByteMask<4> {
4111 static const uint32_t value = 0xFF00FF00;
4112 };
4113 template<> struct OneByteMask<8> {
4114 static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00);
4115 };
4116 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
4117 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
Unaligned(const uint16_t * chars)4118 static inline bool Unaligned(const uint16_t* chars) {
4119 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
4120 }
4121
4122
Align(const uint16_t * chars)4123 static inline const uint16_t* Align(const uint16_t* chars) {
4124 return reinterpret_cast<uint16_t*>(
4125 reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
4126 }
4127
4128 class ContainsOnlyOneByteHelper {
4129 public:
ContainsOnlyOneByteHelper()4130 ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
Check(i::String * string)4131 bool Check(i::String* string) {
4132 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
4133 if (cons_string == NULL) return is_one_byte_;
4134 return CheckCons(cons_string);
4135 }
VisitOneByteString(const uint8_t * chars,int length)4136 void VisitOneByteString(const uint8_t* chars, int length) {
4137 // Nothing to do.
4138 }
VisitTwoByteString(const uint16_t * chars,int length)4139 void VisitTwoByteString(const uint16_t* chars, int length) {
4140 // Accumulated bits.
4141 uintptr_t acc = 0;
4142 // Align to uintptr_t.
4143 const uint16_t* end = chars + length;
4144 while (Unaligned(chars) && chars != end) {
4145 acc |= *chars++;
4146 }
4147 // Read word aligned in blocks,
4148 // checking the return value at the end of each block.
4149 const uint16_t* aligned_end = Align(end);
4150 const int increment = sizeof(uintptr_t)/sizeof(uint16_t);
4151 const int inner_loops = 16;
4152 while (chars + inner_loops*increment < aligned_end) {
4153 for (int i = 0; i < inner_loops; i++) {
4154 acc |= *reinterpret_cast<const uintptr_t*>(chars);
4155 chars += increment;
4156 }
4157 // Check for early return.
4158 if ((acc & kOneByteMask) != 0) {
4159 is_one_byte_ = false;
4160 return;
4161 }
4162 }
4163 // Read the rest.
4164 while (chars != end) {
4165 acc |= *chars++;
4166 }
4167 // Check result.
4168 if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
4169 }
4170
4171 private:
CheckCons(i::ConsString * cons_string)4172 bool CheckCons(i::ConsString* cons_string) {
4173 while (true) {
4174 // Check left side if flat.
4175 i::String* left = cons_string->first();
4176 i::ConsString* left_as_cons =
4177 i::String::VisitFlat(this, left, 0);
4178 if (!is_one_byte_) return false;
4179 // Check right side if flat.
4180 i::String* right = cons_string->second();
4181 i::ConsString* right_as_cons =
4182 i::String::VisitFlat(this, right, 0);
4183 if (!is_one_byte_) return false;
4184 // Standard recurse/iterate trick.
4185 if (left_as_cons != NULL && right_as_cons != NULL) {
4186 if (left->length() < right->length()) {
4187 CheckCons(left_as_cons);
4188 cons_string = right_as_cons;
4189 } else {
4190 CheckCons(right_as_cons);
4191 cons_string = left_as_cons;
4192 }
4193 // Check fast return.
4194 if (!is_one_byte_) return false;
4195 continue;
4196 }
4197 // Descend left in place.
4198 if (left_as_cons != NULL) {
4199 cons_string = left_as_cons;
4200 continue;
4201 }
4202 // Descend right in place.
4203 if (right_as_cons != NULL) {
4204 cons_string = right_as_cons;
4205 continue;
4206 }
4207 // Terminate.
4208 break;
4209 }
4210 return is_one_byte_;
4211 }
4212 bool is_one_byte_;
4213 DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper);
4214 };
4215
4216
ContainsOnlyOneByte() const4217 bool String::ContainsOnlyOneByte() const {
4218 i::Handle<i::String> str = Utils::OpenHandle(this);
4219 if (str->HasOnlyOneByteChars()) return true;
4220 ContainsOnlyOneByteHelper helper;
4221 return helper.Check(*str);
4222 }
4223
4224
4225 class Utf8LengthHelper : public i::AllStatic {
4226 public:
4227 enum State {
4228 kEndsWithLeadingSurrogate = 1 << 0,
4229 kStartsWithTrailingSurrogate = 1 << 1,
4230 kLeftmostEdgeIsCalculated = 1 << 2,
4231 kRightmostEdgeIsCalculated = 1 << 3,
4232 kLeftmostEdgeIsSurrogate = 1 << 4,
4233 kRightmostEdgeIsSurrogate = 1 << 5
4234 };
4235
4236 static const uint8_t kInitialState = 0;
4237
EndsWithSurrogate(uint8_t state)4238 static inline bool EndsWithSurrogate(uint8_t state) {
4239 return state & kEndsWithLeadingSurrogate;
4240 }
4241
StartsWithSurrogate(uint8_t state)4242 static inline bool StartsWithSurrogate(uint8_t state) {
4243 return state & kStartsWithTrailingSurrogate;
4244 }
4245
4246 class Visitor {
4247 public:
Visitor()4248 inline explicit Visitor()
4249 : utf8_length_(0),
4250 state_(kInitialState) {}
4251
VisitOneByteString(const uint8_t * chars,int length)4252 void VisitOneByteString(const uint8_t* chars, int length) {
4253 int utf8_length = 0;
4254 // Add in length 1 for each non-ASCII character.
4255 for (int i = 0; i < length; i++) {
4256 utf8_length += *chars++ >> 7;
4257 }
4258 // Add in length 1 for each character.
4259 utf8_length_ = utf8_length + length;
4260 state_ = kInitialState;
4261 }
4262
VisitTwoByteString(const uint16_t * chars,int length)4263 void VisitTwoByteString(const uint16_t* chars, int length) {
4264 int utf8_length = 0;
4265 int last_character = unibrow::Utf16::kNoPreviousCharacter;
4266 for (int i = 0; i < length; i++) {
4267 uint16_t c = chars[i];
4268 utf8_length += unibrow::Utf8::Length(c, last_character);
4269 last_character = c;
4270 }
4271 utf8_length_ = utf8_length;
4272 uint8_t state = 0;
4273 if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
4274 state |= kStartsWithTrailingSurrogate;
4275 }
4276 if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
4277 state |= kEndsWithLeadingSurrogate;
4278 }
4279 state_ = state;
4280 }
4281
VisitFlat(i::String * string,int * length,uint8_t * state)4282 static i::ConsString* VisitFlat(i::String* string,
4283 int* length,
4284 uint8_t* state) {
4285 Visitor visitor;
4286 i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
4287 *length = visitor.utf8_length_;
4288 *state = visitor.state_;
4289 return cons_string;
4290 }
4291
4292 private:
4293 int utf8_length_;
4294 uint8_t state_;
4295 DISALLOW_COPY_AND_ASSIGN(Visitor);
4296 };
4297
MergeLeafLeft(int * length,uint8_t * state,uint8_t leaf_state)4298 static inline void MergeLeafLeft(int* length,
4299 uint8_t* state,
4300 uint8_t leaf_state) {
4301 bool edge_surrogate = StartsWithSurrogate(leaf_state);
4302 if (!(*state & kLeftmostEdgeIsCalculated)) {
4303 ASSERT(!(*state & kLeftmostEdgeIsSurrogate));
4304 *state |= kLeftmostEdgeIsCalculated
4305 | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
4306 } else if (EndsWithSurrogate(*state) && edge_surrogate) {
4307 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4308 }
4309 if (EndsWithSurrogate(leaf_state)) {
4310 *state |= kEndsWithLeadingSurrogate;
4311 } else {
4312 *state &= ~kEndsWithLeadingSurrogate;
4313 }
4314 }
4315
MergeLeafRight(int * length,uint8_t * state,uint8_t leaf_state)4316 static inline void MergeLeafRight(int* length,
4317 uint8_t* state,
4318 uint8_t leaf_state) {
4319 bool edge_surrogate = EndsWithSurrogate(leaf_state);
4320 if (!(*state & kRightmostEdgeIsCalculated)) {
4321 ASSERT(!(*state & kRightmostEdgeIsSurrogate));
4322 *state |= (kRightmostEdgeIsCalculated
4323 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
4324 } else if (edge_surrogate && StartsWithSurrogate(*state)) {
4325 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4326 }
4327 if (StartsWithSurrogate(leaf_state)) {
4328 *state |= kStartsWithTrailingSurrogate;
4329 } else {
4330 *state &= ~kStartsWithTrailingSurrogate;
4331 }
4332 }
4333
MergeTerminal(int * length,uint8_t state,uint8_t * state_out)4334 static inline void MergeTerminal(int* length,
4335 uint8_t state,
4336 uint8_t* state_out) {
4337 ASSERT((state & kLeftmostEdgeIsCalculated) &&
4338 (state & kRightmostEdgeIsCalculated));
4339 if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
4340 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4341 }
4342 *state_out = kInitialState |
4343 (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
4344 (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
4345 }
4346
Calculate(i::ConsString * current,uint8_t * state_out)4347 static int Calculate(i::ConsString* current, uint8_t* state_out) {
4348 using namespace internal;
4349 int total_length = 0;
4350 uint8_t state = kInitialState;
4351 while (true) {
4352 i::String* left = current->first();
4353 i::String* right = current->second();
4354 uint8_t right_leaf_state;
4355 uint8_t left_leaf_state;
4356 int leaf_length;
4357 ConsString* left_as_cons =
4358 Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
4359 if (left_as_cons == NULL) {
4360 total_length += leaf_length;
4361 MergeLeafLeft(&total_length, &state, left_leaf_state);
4362 }
4363 ConsString* right_as_cons =
4364 Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
4365 if (right_as_cons == NULL) {
4366 total_length += leaf_length;
4367 MergeLeafRight(&total_length, &state, right_leaf_state);
4368 if (left_as_cons != NULL) {
4369 // 1 Leaf node. Descend in place.
4370 current = left_as_cons;
4371 continue;
4372 } else {
4373 // Terminal node.
4374 MergeTerminal(&total_length, state, state_out);
4375 return total_length;
4376 }
4377 } else if (left_as_cons == NULL) {
4378 // 1 Leaf node. Descend in place.
4379 current = right_as_cons;
4380 continue;
4381 }
4382 // Both strings are ConsStrings.
4383 // Recurse on smallest.
4384 if (left->length() < right->length()) {
4385 total_length += Calculate(left_as_cons, &left_leaf_state);
4386 MergeLeafLeft(&total_length, &state, left_leaf_state);
4387 current = right_as_cons;
4388 } else {
4389 total_length += Calculate(right_as_cons, &right_leaf_state);
4390 MergeLeafRight(&total_length, &state, right_leaf_state);
4391 current = left_as_cons;
4392 }
4393 }
4394 UNREACHABLE();
4395 return 0;
4396 }
4397
Calculate(i::ConsString * current)4398 static inline int Calculate(i::ConsString* current) {
4399 uint8_t state = kInitialState;
4400 return Calculate(current, &state);
4401 }
4402
4403 private:
4404 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
4405 };
4406
4407
Utf8Length(i::String * str,i::Isolate * isolate)4408 static int Utf8Length(i::String* str, i::Isolate* isolate) {
4409 int length = str->length();
4410 if (length == 0) return 0;
4411 uint8_t state;
4412 i::ConsString* cons_string =
4413 Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
4414 if (cons_string == NULL) return length;
4415 return Utf8LengthHelper::Calculate(cons_string);
4416 }
4417
4418
Utf8Length() const4419 int String::Utf8Length() const {
4420 i::Handle<i::String> str = Utils::OpenHandle(this);
4421 i::Isolate* isolate = str->GetIsolate();
4422 return v8::Utf8Length(*str, isolate);
4423 }
4424
4425
4426 class Utf8WriterVisitor {
4427 public:
Utf8WriterVisitor(char * buffer,int capacity,bool skip_capacity_check,bool replace_invalid_utf8)4428 Utf8WriterVisitor(
4429 char* buffer,
4430 int capacity,
4431 bool skip_capacity_check,
4432 bool replace_invalid_utf8)
4433 : early_termination_(false),
4434 last_character_(unibrow::Utf16::kNoPreviousCharacter),
4435 buffer_(buffer),
4436 start_(buffer),
4437 capacity_(capacity),
4438 skip_capacity_check_(capacity == -1 || skip_capacity_check),
4439 replace_invalid_utf8_(replace_invalid_utf8),
4440 utf16_chars_read_(0) {
4441 }
4442
WriteEndCharacter(uint16_t character,int last_character,int remaining,char * const buffer,bool replace_invalid_utf8)4443 static int WriteEndCharacter(uint16_t character,
4444 int last_character,
4445 int remaining,
4446 char* const buffer,
4447 bool replace_invalid_utf8) {
4448 using namespace unibrow;
4449 ASSERT(remaining > 0);
4450 // We can't use a local buffer here because Encode needs to modify
4451 // previous characters in the stream. We know, however, that
4452 // exactly one character will be advanced.
4453 if (Utf16::IsSurrogatePair(last_character, character)) {
4454 int written = Utf8::Encode(buffer,
4455 character,
4456 last_character,
4457 replace_invalid_utf8);
4458 ASSERT(written == 1);
4459 return written;
4460 }
4461 // Use a scratch buffer to check the required characters.
4462 char temp_buffer[Utf8::kMaxEncodedSize];
4463 // Can't encode using last_character as gcc has array bounds issues.
4464 int written = Utf8::Encode(temp_buffer,
4465 character,
4466 Utf16::kNoPreviousCharacter,
4467 replace_invalid_utf8);
4468 // Won't fit.
4469 if (written > remaining) return 0;
4470 // Copy over the character from temp_buffer.
4471 for (int j = 0; j < written; j++) {
4472 buffer[j] = temp_buffer[j];
4473 }
4474 return written;
4475 }
4476
4477 // Visit writes out a group of code units (chars) of a v8::String to the
4478 // internal buffer_. This is done in two phases. The first phase calculates a
4479 // pesimistic estimate (writable_length) on how many code units can be safely
4480 // written without exceeding the buffer capacity and without writing the last
4481 // code unit (it could be a lead surrogate). The estimated number of code
4482 // units is then written out in one go, and the reported byte usage is used
4483 // to correct the estimate. This is repeated until the estimate becomes <= 0
4484 // or all code units have been written out. The second phase writes out code
4485 // units until the buffer capacity is reached, would be exceeded by the next
4486 // unit, or all units have been written out.
4487 template<typename Char>
Visit(const Char * chars,const int length)4488 void Visit(const Char* chars, const int length) {
4489 using namespace unibrow;
4490 ASSERT(!early_termination_);
4491 if (length == 0) return;
4492 // Copy state to stack.
4493 char* buffer = buffer_;
4494 int last_character =
4495 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
4496 int i = 0;
4497 // Do a fast loop where there is no exit capacity check.
4498 while (true) {
4499 int fast_length;
4500 if (skip_capacity_check_) {
4501 fast_length = length;
4502 } else {
4503 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4504 // Need enough space to write everything but one character.
4505 STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
4506 int max_size_per_char = sizeof(Char) == 1 ? 2 : 3;
4507 int writable_length =
4508 (remaining_capacity - max_size_per_char)/max_size_per_char;
4509 // Need to drop into slow loop.
4510 if (writable_length <= 0) break;
4511 fast_length = i + writable_length;
4512 if (fast_length > length) fast_length = length;
4513 }
4514 // Write the characters to the stream.
4515 if (sizeof(Char) == 1) {
4516 for (; i < fast_length; i++) {
4517 buffer +=
4518 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
4519 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
4520 }
4521 } else {
4522 for (; i < fast_length; i++) {
4523 uint16_t character = *chars++;
4524 buffer += Utf8::Encode(buffer,
4525 character,
4526 last_character,
4527 replace_invalid_utf8_);
4528 last_character = character;
4529 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
4530 }
4531 }
4532 // Array is fully written. Exit.
4533 if (fast_length == length) {
4534 // Write state back out to object.
4535 last_character_ = last_character;
4536 buffer_ = buffer;
4537 utf16_chars_read_ += length;
4538 return;
4539 }
4540 }
4541 ASSERT(!skip_capacity_check_);
4542 // Slow loop. Must check capacity on each iteration.
4543 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4544 ASSERT(remaining_capacity >= 0);
4545 for (; i < length && remaining_capacity > 0; i++) {
4546 uint16_t character = *chars++;
4547 // remaining_capacity is <= 3 bytes at this point, so we do not write out
4548 // an umatched lead surrogate.
4549 if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) {
4550 early_termination_ = true;
4551 break;
4552 }
4553 int written = WriteEndCharacter(character,
4554 last_character,
4555 remaining_capacity,
4556 buffer,
4557 replace_invalid_utf8_);
4558 if (written == 0) {
4559 early_termination_ = true;
4560 break;
4561 }
4562 buffer += written;
4563 remaining_capacity -= written;
4564 last_character = character;
4565 }
4566 // Write state back out to object.
4567 last_character_ = last_character;
4568 buffer_ = buffer;
4569 utf16_chars_read_ += i;
4570 }
4571
IsDone()4572 inline bool IsDone() {
4573 return early_termination_;
4574 }
4575
VisitOneByteString(const uint8_t * chars,int length)4576 inline void VisitOneByteString(const uint8_t* chars, int length) {
4577 Visit(chars, length);
4578 }
4579
VisitTwoByteString(const uint16_t * chars,int length)4580 inline void VisitTwoByteString(const uint16_t* chars, int length) {
4581 Visit(chars, length);
4582 }
4583
CompleteWrite(bool write_null,int * utf16_chars_read_out)4584 int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
4585 // Write out number of utf16 characters written to the stream.
4586 if (utf16_chars_read_out != NULL) {
4587 *utf16_chars_read_out = utf16_chars_read_;
4588 }
4589 // Only null terminate if all of the string was written and there's space.
4590 if (write_null &&
4591 !early_termination_ &&
4592 (capacity_ == -1 || (buffer_ - start_) < capacity_)) {
4593 *buffer_++ = '\0';
4594 }
4595 return static_cast<int>(buffer_ - start_);
4596 }
4597
4598 private:
4599 bool early_termination_;
4600 int last_character_;
4601 char* buffer_;
4602 char* const start_;
4603 int capacity_;
4604 bool const skip_capacity_check_;
4605 bool const replace_invalid_utf8_;
4606 int utf16_chars_read_;
4607 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
4608 };
4609
4610
RecursivelySerializeToUtf8(i::String * current,Utf8WriterVisitor * writer,int recursion_budget)4611 static bool RecursivelySerializeToUtf8(i::String* current,
4612 Utf8WriterVisitor* writer,
4613 int recursion_budget) {
4614 while (!writer->IsDone()) {
4615 i::ConsString* cons_string = i::String::VisitFlat(writer, current);
4616 if (cons_string == NULL) return true; // Leaf node.
4617 if (recursion_budget <= 0) return false;
4618 // Must write the left branch first.
4619 i::String* first = cons_string->first();
4620 bool success = RecursivelySerializeToUtf8(first,
4621 writer,
4622 recursion_budget - 1);
4623 if (!success) return false;
4624 // Inline tail recurse for right branch.
4625 current = cons_string->second();
4626 }
4627 return true;
4628 }
4629
4630
WriteUtf8(char * buffer,int capacity,int * nchars_ref,int options) const4631 int String::WriteUtf8(char* buffer,
4632 int capacity,
4633 int* nchars_ref,
4634 int options) const {
4635 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4636 LOG_API(isolate, "String::WriteUtf8");
4637 ENTER_V8(isolate);
4638 i::Handle<i::String> str = Utils::OpenHandle(this);
4639 if (options & HINT_MANY_WRITES_EXPECTED) {
4640 str = i::String::Flatten(str); // Flatten the string for efficiency.
4641 }
4642 const int string_length = str->length();
4643 bool write_null = !(options & NO_NULL_TERMINATION);
4644 bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8);
4645 int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize;
4646 // First check if we can just write the string without checking capacity.
4647 if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) {
4648 Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8);
4649 const int kMaxRecursion = 100;
4650 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
4651 if (success) return writer.CompleteWrite(write_null, nchars_ref);
4652 } else if (capacity >= string_length) {
4653 // First check that the buffer is large enough.
4654 int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
4655 if (utf8_bytes <= capacity) {
4656 // ASCII fast path.
4657 if (utf8_bytes == string_length) {
4658 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
4659 if (nchars_ref != NULL) *nchars_ref = string_length;
4660 if (write_null && (utf8_bytes+1 <= capacity)) {
4661 return string_length + 1;
4662 }
4663 return string_length;
4664 }
4665 if (write_null && (utf8_bytes+1 > capacity)) {
4666 options |= NO_NULL_TERMINATION;
4667 }
4668 // Recurse once without a capacity limit.
4669 // This will get into the first branch above.
4670 // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
4671 return WriteUtf8(buffer, -1, nchars_ref, options);
4672 }
4673 }
4674 // Recursive slow path can potentially be unreasonable slow. Flatten.
4675 str = i::String::Flatten(str);
4676 Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8);
4677 i::String::VisitFlat(&writer, *str);
4678 return writer.CompleteWrite(write_null, nchars_ref);
4679 }
4680
4681
4682 template<typename CharType>
WriteHelper(const String * string,CharType * buffer,int start,int length,int options)4683 static inline int WriteHelper(const String* string,
4684 CharType* buffer,
4685 int start,
4686 int length,
4687 int options) {
4688 i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
4689 LOG_API(isolate, "String::Write");
4690 ENTER_V8(isolate);
4691 ASSERT(start >= 0 && length >= -1);
4692 i::Handle<i::String> str = Utils::OpenHandle(string);
4693 isolate->string_tracker()->RecordWrite(str);
4694 if (options & String::HINT_MANY_WRITES_EXPECTED) {
4695 // Flatten the string for efficiency. This applies whether we are
4696 // using StringCharacterStream or Get(i) to access the characters.
4697 str = i::String::Flatten(str);
4698 }
4699 int end = start + length;
4700 if ((length == -1) || (length > str->length() - start) )
4701 end = str->length();
4702 if (end < 0) return 0;
4703 i::String::WriteToFlat(*str, buffer, start, end);
4704 if (!(options & String::NO_NULL_TERMINATION) &&
4705 (length == -1 || end - start < length)) {
4706 buffer[end - start] = '\0';
4707 }
4708 return end - start;
4709 }
4710
4711
WriteOneByte(uint8_t * buffer,int start,int length,int options) const4712 int String::WriteOneByte(uint8_t* buffer,
4713 int start,
4714 int length,
4715 int options) const {
4716 return WriteHelper(this, buffer, start, length, options);
4717 }
4718
4719
Write(uint16_t * buffer,int start,int length,int options) const4720 int String::Write(uint16_t* buffer,
4721 int start,
4722 int length,
4723 int options) const {
4724 return WriteHelper(this, buffer, start, length, options);
4725 }
4726
4727
IsExternal() const4728 bool v8::String::IsExternal() const {
4729 i::Handle<i::String> str = Utils::OpenHandle(this);
4730 EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
4731 return i::StringShape(*str).IsExternalTwoByte();
4732 }
4733
4734
IsExternalAscii() const4735 bool v8::String::IsExternalAscii() const {
4736 i::Handle<i::String> str = Utils::OpenHandle(this);
4737 return i::StringShape(*str).IsExternalAscii();
4738 }
4739
4740
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const4741 void v8::String::VerifyExternalStringResource(
4742 v8::String::ExternalStringResource* value) const {
4743 i::Handle<i::String> str = Utils::OpenHandle(this);
4744 const v8::String::ExternalStringResource* expected;
4745 if (i::StringShape(*str).IsExternalTwoByte()) {
4746 const void* resource =
4747 i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4748 expected = reinterpret_cast<const ExternalStringResource*>(resource);
4749 } else {
4750 expected = NULL;
4751 }
4752 CHECK_EQ(expected, value);
4753 }
4754
VerifyExternalStringResourceBase(v8::String::ExternalStringResourceBase * value,Encoding encoding) const4755 void v8::String::VerifyExternalStringResourceBase(
4756 v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
4757 i::Handle<i::String> str = Utils::OpenHandle(this);
4758 const v8::String::ExternalStringResourceBase* expected;
4759 Encoding expectedEncoding;
4760 if (i::StringShape(*str).IsExternalAscii()) {
4761 const void* resource =
4762 i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4763 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4764 expectedEncoding = ASCII_ENCODING;
4765 } else if (i::StringShape(*str).IsExternalTwoByte()) {
4766 const void* resource =
4767 i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4768 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4769 expectedEncoding = TWO_BYTE_ENCODING;
4770 } else {
4771 expected = NULL;
4772 expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
4773 : TWO_BYTE_ENCODING;
4774 }
4775 CHECK_EQ(expected, value);
4776 CHECK_EQ(expectedEncoding, encoding);
4777 }
4778
4779 const v8::String::ExternalAsciiStringResource*
GetExternalAsciiStringResource() const4780 v8::String::GetExternalAsciiStringResource() const {
4781 i::Handle<i::String> str = Utils::OpenHandle(this);
4782 if (i::StringShape(*str).IsExternalAscii()) {
4783 const void* resource =
4784 i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4785 return reinterpret_cast<const ExternalAsciiStringResource*>(resource);
4786 } else {
4787 return NULL;
4788 }
4789 }
4790
4791
Name() const4792 Local<Value> Symbol::Name() const {
4793 i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
4794 i::Handle<i::Object> name(sym->name(), sym->GetIsolate());
4795 return Utils::ToLocal(name);
4796 }
4797
4798
Name() const4799 Local<Value> Private::Name() const {
4800 return reinterpret_cast<const Symbol*>(this)->Name();
4801 }
4802
4803
Value() const4804 double Number::Value() const {
4805 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4806 return obj->Number();
4807 }
4808
4809
Value() const4810 bool Boolean::Value() const {
4811 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4812 return obj->IsTrue();
4813 }
4814
4815
Value() const4816 int64_t Integer::Value() const {
4817 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4818 if (obj->IsSmi()) {
4819 return i::Smi::cast(*obj)->value();
4820 } else {
4821 return static_cast<int64_t>(obj->Number());
4822 }
4823 }
4824
4825
Value() const4826 int32_t Int32::Value() const {
4827 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4828 if (obj->IsSmi()) {
4829 return i::Smi::cast(*obj)->value();
4830 } else {
4831 return static_cast<int32_t>(obj->Number());
4832 }
4833 }
4834
4835
Value() const4836 uint32_t Uint32::Value() const {
4837 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4838 if (obj->IsSmi()) {
4839 return i::Smi::cast(*obj)->value();
4840 } else {
4841 return static_cast<uint32_t>(obj->Number());
4842 }
4843 }
4844
4845
InternalFieldCount()4846 int v8::Object::InternalFieldCount() {
4847 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4848 return obj->GetInternalFieldCount();
4849 }
4850
4851
InternalFieldOK(i::Handle<i::JSObject> obj,int index,const char * location)4852 static bool InternalFieldOK(i::Handle<i::JSObject> obj,
4853 int index,
4854 const char* location) {
4855 return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
4856 location,
4857 "Internal field out of bounds");
4858 }
4859
4860
SlowGetInternalField(int index)4861 Local<Value> v8::Object::SlowGetInternalField(int index) {
4862 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4863 const char* location = "v8::Object::GetInternalField()";
4864 if (!InternalFieldOK(obj, index, location)) return Local<Value>();
4865 i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
4866 return Utils::ToLocal(value);
4867 }
4868
4869
SetInternalField(int index,v8::Handle<Value> value)4870 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
4871 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4872 const char* location = "v8::Object::SetInternalField()";
4873 if (!InternalFieldOK(obj, index, location)) return;
4874 i::Handle<i::Object> val = Utils::OpenHandle(*value);
4875 obj->SetInternalField(index, *val);
4876 ASSERT_EQ(value, GetInternalField(index));
4877 }
4878
4879
SlowGetAlignedPointerFromInternalField(int index)4880 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
4881 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4882 const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
4883 if (!InternalFieldOK(obj, index, location)) return NULL;
4884 return DecodeSmiToAligned(obj->GetInternalField(index), location);
4885 }
4886
4887
SetAlignedPointerInInternalField(int index,void * value)4888 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
4889 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4890 const char* location = "v8::Object::SetAlignedPointerInInternalField()";
4891 if (!InternalFieldOK(obj, index, location)) return;
4892 obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
4893 ASSERT_EQ(value, GetAlignedPointerFromInternalField(index));
4894 }
4895
4896
ExternalValue(i::Object * obj)4897 static void* ExternalValue(i::Object* obj) {
4898 // Obscure semantics for undefined, but somehow checked in our unit tests...
4899 if (obj->IsUndefined()) return NULL;
4900 i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
4901 return i::Foreign::cast(foreign)->foreign_address();
4902 }
4903
4904
4905 // --- E n v i r o n m e n t ---
4906
4907
InitializePlatform(Platform * platform)4908 void v8::V8::InitializePlatform(Platform* platform) {
4909 #ifdef V8_USE_DEFAULT_PLATFORM
4910 FATAL("Can't override v8::Platform when using default implementation");
4911 #else
4912 i::V8::InitializePlatform(platform);
4913 #endif
4914 }
4915
4916
ShutdownPlatform()4917 void v8::V8::ShutdownPlatform() {
4918 #ifdef V8_USE_DEFAULT_PLATFORM
4919 FATAL("Can't override v8::Platform when using default implementation");
4920 #else
4921 i::V8::ShutdownPlatform();
4922 #endif
4923 }
4924
4925
Initialize()4926 bool v8::V8::Initialize() {
4927 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4928 if (isolate != NULL && isolate->IsInitialized()) {
4929 return true;
4930 }
4931 return InitializeHelper(isolate);
4932 }
4933
4934
SetEntropySource(EntropySource entropy_source)4935 void v8::V8::SetEntropySource(EntropySource entropy_source) {
4936 i::RandomNumberGenerator::SetEntropySource(entropy_source);
4937 }
4938
4939
SetReturnAddressLocationResolver(ReturnAddressLocationResolver return_address_resolver)4940 void v8::V8::SetReturnAddressLocationResolver(
4941 ReturnAddressLocationResolver return_address_resolver) {
4942 i::V8::SetReturnAddressLocationResolver(return_address_resolver);
4943 }
4944
4945
SetFunctionEntryHook(Isolate * ext_isolate,FunctionEntryHook entry_hook)4946 bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate,
4947 FunctionEntryHook entry_hook) {
4948 ASSERT(ext_isolate != NULL);
4949 ASSERT(entry_hook != NULL);
4950
4951 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate);
4952
4953 // The entry hook can only be set before the Isolate is initialized, as
4954 // otherwise the Isolate's code stubs generated at initialization won't
4955 // contain entry hooks.
4956 if (isolate->IsInitialized())
4957 return false;
4958
4959 // Setting an entry hook is a one-way operation, once set, it cannot be
4960 // changed or unset.
4961 if (isolate->function_entry_hook() != NULL)
4962 return false;
4963
4964 isolate->set_function_entry_hook(entry_hook);
4965 return true;
4966 }
4967
4968
SetJitCodeEventHandler(JitCodeEventOptions options,JitCodeEventHandler event_handler)4969 void v8::V8::SetJitCodeEventHandler(
4970 JitCodeEventOptions options, JitCodeEventHandler event_handler) {
4971 i::Isolate* isolate = i::Isolate::Current();
4972 // Ensure that logging is initialized for our isolate.
4973 isolate->InitializeLoggingAndCounters();
4974 isolate->logger()->SetCodeEventHandler(options, event_handler);
4975 }
4976
SetArrayBufferAllocator(ArrayBuffer::Allocator * allocator)4977 void v8::V8::SetArrayBufferAllocator(
4978 ArrayBuffer::Allocator* allocator) {
4979 if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
4980 "v8::V8::SetArrayBufferAllocator",
4981 "ArrayBufferAllocator might only be set once"))
4982 return;
4983 i::V8::SetArrayBufferAllocator(allocator);
4984 }
4985
4986
Dispose()4987 bool v8::V8::Dispose() {
4988 i::V8::TearDown();
4989 return true;
4990 }
4991
4992
HeapStatistics()4993 HeapStatistics::HeapStatistics(): total_heap_size_(0),
4994 total_heap_size_executable_(0),
4995 total_physical_size_(0),
4996 used_heap_size_(0),
4997 heap_size_limit_(0) { }
4998
4999
VisitExternalResources(ExternalResourceVisitor * visitor)5000 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
5001 i::Isolate* isolate = i::Isolate::Current();
5002 isolate->heap()->VisitExternalResources(visitor);
5003 }
5004
5005
5006 class VisitorAdapter : public i::ObjectVisitor {
5007 public:
VisitorAdapter(PersistentHandleVisitor * visitor)5008 explicit VisitorAdapter(PersistentHandleVisitor* visitor)
5009 : visitor_(visitor) {}
VisitPointers(i::Object ** start,i::Object ** end)5010 virtual void VisitPointers(i::Object** start, i::Object** end) {
5011 UNREACHABLE();
5012 }
VisitEmbedderReference(i::Object ** p,uint16_t class_id)5013 virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
5014 Value* value = ToApi<Value>(i::Handle<i::Object>(p));
5015 visitor_->VisitPersistentHandle(
5016 reinterpret_cast<Persistent<Value>*>(&value), class_id);
5017 }
5018 private:
5019 PersistentHandleVisitor* visitor_;
5020 };
5021
5022
VisitHandlesWithClassIds(PersistentHandleVisitor * visitor)5023 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
5024 i::Isolate* isolate = i::Isolate::Current();
5025 i::DisallowHeapAllocation no_allocation;
5026
5027 VisitorAdapter visitor_adapter(visitor);
5028 isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
5029 }
5030
5031
VisitHandlesForPartialDependence(Isolate * exported_isolate,PersistentHandleVisitor * visitor)5032 void v8::V8::VisitHandlesForPartialDependence(
5033 Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
5034 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
5035 ASSERT(isolate == i::Isolate::Current());
5036 i::DisallowHeapAllocation no_allocation;
5037
5038 VisitorAdapter visitor_adapter(visitor);
5039 isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
5040 &visitor_adapter);
5041 }
5042
5043
IdleNotification(int hint)5044 bool v8::V8::IdleNotification(int hint) {
5045 // Returning true tells the caller that it need not
5046 // continue to call IdleNotification.
5047 i::Isolate* isolate = i::Isolate::Current();
5048 if (isolate == NULL || !isolate->IsInitialized()) return true;
5049 if (!i::FLAG_use_idle_notification) return true;
5050 return isolate->heap()->IdleNotification(hint);
5051 }
5052
5053
LowMemoryNotification()5054 void v8::V8::LowMemoryNotification() {
5055 i::Isolate* isolate = i::Isolate::Current();
5056 if (isolate == NULL || !isolate->IsInitialized()) return;
5057 isolate->heap()->CollectAllAvailableGarbage("low memory notification");
5058 }
5059
5060
ContextDisposedNotification()5061 int v8::V8::ContextDisposedNotification() {
5062 i::Isolate* isolate = i::Isolate::Current();
5063 if (!isolate->IsInitialized()) return 0;
5064 return isolate->heap()->NotifyContextDisposed();
5065 }
5066
5067
InitializeICU(const char * icu_data_file)5068 bool v8::V8::InitializeICU(const char* icu_data_file) {
5069 return i::InitializeICU(icu_data_file);
5070 }
5071
5072
GetVersion()5073 const char* v8::V8::GetVersion() {
5074 return i::Version::GetVersion();
5075 }
5076
5077
CreateEnvironment(i::Isolate * isolate,v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)5078 static i::Handle<i::Context> CreateEnvironment(
5079 i::Isolate* isolate,
5080 v8::ExtensionConfiguration* extensions,
5081 v8::Handle<ObjectTemplate> global_template,
5082 v8::Handle<Value> global_object) {
5083 i::Handle<i::Context> env;
5084
5085 // Enter V8 via an ENTER_V8 scope.
5086 {
5087 ENTER_V8(isolate);
5088 v8::Handle<ObjectTemplate> proxy_template = global_template;
5089 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
5090 i::Handle<i::FunctionTemplateInfo> global_constructor;
5091
5092 if (!global_template.IsEmpty()) {
5093 // Make sure that the global_template has a constructor.
5094 global_constructor = EnsureConstructor(isolate, *global_template);
5095
5096 // Create a fresh template for the global proxy object.
5097 proxy_template = ObjectTemplate::New(
5098 reinterpret_cast<v8::Isolate*>(isolate));
5099 proxy_constructor = EnsureConstructor(isolate, *proxy_template);
5100
5101 // Set the global template to be the prototype template of
5102 // global proxy template.
5103 proxy_constructor->set_prototype_template(
5104 *Utils::OpenHandle(*global_template));
5105
5106 // Migrate security handlers from global_template to
5107 // proxy_template. Temporarily removing access check
5108 // information from the global template.
5109 if (!global_constructor->access_check_info()->IsUndefined()) {
5110 proxy_constructor->set_access_check_info(
5111 global_constructor->access_check_info());
5112 proxy_constructor->set_needs_access_check(
5113 global_constructor->needs_access_check());
5114 global_constructor->set_needs_access_check(false);
5115 global_constructor->set_access_check_info(
5116 isolate->heap()->undefined_value());
5117 }
5118 }
5119
5120 // Create the environment.
5121 env = isolate->bootstrapper()->CreateEnvironment(
5122 Utils::OpenHandle(*global_object, true),
5123 proxy_template,
5124 extensions);
5125
5126 // Restore the access check info on the global template.
5127 if (!global_template.IsEmpty()) {
5128 ASSERT(!global_constructor.is_null());
5129 ASSERT(!proxy_constructor.is_null());
5130 global_constructor->set_access_check_info(
5131 proxy_constructor->access_check_info());
5132 global_constructor->set_needs_access_check(
5133 proxy_constructor->needs_access_check());
5134 }
5135 }
5136 // Leave V8.
5137
5138 return env;
5139 }
5140
New(v8::Isolate * external_isolate,v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)5141 Local<Context> v8::Context::New(
5142 v8::Isolate* external_isolate,
5143 v8::ExtensionConfiguration* extensions,
5144 v8::Handle<ObjectTemplate> global_template,
5145 v8::Handle<Value> global_object) {
5146 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
5147 EnsureInitializedForIsolate(isolate, "v8::Context::New()");
5148 LOG_API(isolate, "Context::New");
5149 ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
5150 i::HandleScope scope(isolate);
5151 ExtensionConfiguration no_extensions;
5152 if (extensions == NULL) extensions = &no_extensions;
5153 i::Handle<i::Context> env =
5154 CreateEnvironment(isolate, extensions, global_template, global_object);
5155 if (env.is_null()) return Local<Context>();
5156 return Utils::ToLocal(scope.CloseAndEscape(env));
5157 }
5158
5159
SetSecurityToken(Handle<Value> token)5160 void v8::Context::SetSecurityToken(Handle<Value> token) {
5161 i::Isolate* isolate = i::Isolate::Current();
5162 ENTER_V8(isolate);
5163 i::Handle<i::Context> env = Utils::OpenHandle(this);
5164 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
5165 env->set_security_token(*token_handle);
5166 }
5167
5168
UseDefaultSecurityToken()5169 void v8::Context::UseDefaultSecurityToken() {
5170 i::Isolate* isolate = i::Isolate::Current();
5171 ENTER_V8(isolate);
5172 i::Handle<i::Context> env = Utils::OpenHandle(this);
5173 env->set_security_token(env->global_object());
5174 }
5175
5176
GetSecurityToken()5177 Handle<Value> v8::Context::GetSecurityToken() {
5178 i::Isolate* isolate = i::Isolate::Current();
5179 i::Handle<i::Context> env = Utils::OpenHandle(this);
5180 i::Object* security_token = env->security_token();
5181 i::Handle<i::Object> token_handle(security_token, isolate);
5182 return Utils::ToLocal(token_handle);
5183 }
5184
5185
GetIsolate()5186 v8::Isolate* Context::GetIsolate() {
5187 i::Handle<i::Context> env = Utils::OpenHandle(this);
5188 return reinterpret_cast<Isolate*>(env->GetIsolate());
5189 }
5190
5191
Global()5192 v8::Local<v8::Object> Context::Global() {
5193 i::Handle<i::Context> context = Utils::OpenHandle(this);
5194 i::Isolate* isolate = context->GetIsolate();
5195 i::Handle<i::Object> global(context->global_proxy(), isolate);
5196 // TODO(dcarney): This should always return the global proxy
5197 // but can't presently as calls to GetProtoype will return the wrong result.
5198 if (i::Handle<i::JSGlobalProxy>::cast(
5199 global)->IsDetachedFrom(context->global_object())) {
5200 global = i::Handle<i::Object>(context->global_object(), isolate);
5201 }
5202 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
5203 }
5204
5205
DetachGlobal()5206 void Context::DetachGlobal() {
5207 i::Handle<i::Context> context = Utils::OpenHandle(this);
5208 i::Isolate* isolate = context->GetIsolate();
5209 ENTER_V8(isolate);
5210 isolate->bootstrapper()->DetachGlobal(context);
5211 }
5212
5213
AllowCodeGenerationFromStrings(bool allow)5214 void Context::AllowCodeGenerationFromStrings(bool allow) {
5215 i::Handle<i::Context> context = Utils::OpenHandle(this);
5216 i::Isolate* isolate = context->GetIsolate();
5217 ENTER_V8(isolate);
5218 context->set_allow_code_gen_from_strings(
5219 allow ? isolate->heap()->true_value() : isolate->heap()->false_value());
5220 }
5221
5222
IsCodeGenerationFromStringsAllowed()5223 bool Context::IsCodeGenerationFromStringsAllowed() {
5224 i::Handle<i::Context> context = Utils::OpenHandle(this);
5225 return !context->allow_code_gen_from_strings()->IsFalse();
5226 }
5227
5228
SetErrorMessageForCodeGenerationFromStrings(Handle<String> error)5229 void Context::SetErrorMessageForCodeGenerationFromStrings(
5230 Handle<String> error) {
5231 i::Handle<i::Context> context = Utils::OpenHandle(this);
5232 i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
5233 context->set_error_message_for_code_gen_from_strings(*error_handle);
5234 }
5235
5236
NewInstance()5237 Local<v8::Object> ObjectTemplate::NewInstance() {
5238 i::Isolate* isolate = i::Isolate::Current();
5239 ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
5240 return Local<v8::Object>());
5241 LOG_API(isolate, "ObjectTemplate::NewInstance");
5242 ENTER_V8(isolate);
5243 EXCEPTION_PREAMBLE(isolate);
5244 i::Handle<i::Object> obj;
5245 has_pending_exception = !i::Execution::InstantiateObject(
5246 Utils::OpenHandle(this)).ToHandle(&obj);
5247 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
5248 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
5249 }
5250
5251
GetFunction()5252 Local<v8::Function> FunctionTemplate::GetFunction() {
5253 i::Isolate* isolate = i::Isolate::Current();
5254 ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
5255 return Local<v8::Function>());
5256 LOG_API(isolate, "FunctionTemplate::GetFunction");
5257 ENTER_V8(isolate);
5258 EXCEPTION_PREAMBLE(isolate);
5259 i::Handle<i::Object> obj;
5260 has_pending_exception = !i::Execution::InstantiateFunction(
5261 Utils::OpenHandle(this)).ToHandle(&obj);
5262 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
5263 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
5264 }
5265
5266
HasInstance(v8::Handle<v8::Value> value)5267 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
5268 ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
5269 return false);
5270 i::Object* obj = *Utils::OpenHandle(*value);
5271 return Utils::OpenHandle(this)->IsTemplateFor(obj);
5272 }
5273
5274
New(Isolate * isolate,void * value)5275 Local<External> v8::External::New(Isolate* isolate, void* value) {
5276 STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
5277 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5278 EnsureInitializedForIsolate(i_isolate, "v8::External::New()");
5279 LOG_API(i_isolate, "External::New");
5280 ENTER_V8(i_isolate);
5281 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
5282 return Utils::ExternalToLocal(external);
5283 }
5284
5285
Value() const5286 void* External::Value() const {
5287 return ExternalValue(*Utils::OpenHandle(this));
5288 }
5289
5290
5291 // anonymous namespace for string creation helper functions
5292 namespace {
5293
StringLength(const char * string)5294 inline int StringLength(const char* string) {
5295 return i::StrLength(string);
5296 }
5297
5298
StringLength(const uint8_t * string)5299 inline int StringLength(const uint8_t* string) {
5300 return i::StrLength(reinterpret_cast<const char*>(string));
5301 }
5302
5303
StringLength(const uint16_t * string)5304 inline int StringLength(const uint16_t* string) {
5305 int length = 0;
5306 while (string[length] != '\0')
5307 length++;
5308 return length;
5309 }
5310
5311
5312 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const char> string)5313 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5314 String::NewStringType type,
5315 i::Vector<const char> string) {
5316 if (type == String::kInternalizedString) {
5317 return factory->InternalizeUtf8String(string);
5318 }
5319 return factory->NewStringFromUtf8(string);
5320 }
5321
5322
5323 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const uint8_t> string)5324 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5325 String::NewStringType type,
5326 i::Vector<const uint8_t> string) {
5327 if (type == String::kInternalizedString) {
5328 return factory->InternalizeOneByteString(string);
5329 }
5330 return factory->NewStringFromOneByte(string);
5331 }
5332
5333
5334 MUST_USE_RESULT
NewString(i::Factory * factory,String::NewStringType type,i::Vector<const uint16_t> string)5335 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5336 String::NewStringType type,
5337 i::Vector<const uint16_t> string) {
5338 if (type == String::kInternalizedString) {
5339 return factory->InternalizeTwoByteString(string);
5340 }
5341 return factory->NewStringFromTwoByte(string);
5342 }
5343
5344
5345 template<typename Char>
NewString(Isolate * v8_isolate,const char * location,const char * env,const Char * data,String::NewStringType type,int length)5346 inline Local<String> NewString(Isolate* v8_isolate,
5347 const char* location,
5348 const char* env,
5349 const Char* data,
5350 String::NewStringType type,
5351 int length) {
5352 i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
5353 EnsureInitializedForIsolate(isolate, location);
5354 LOG_API(isolate, env);
5355 if (length == 0 && type != String::kUndetectableString) {
5356 return String::Empty(v8_isolate);
5357 }
5358 ENTER_V8(isolate);
5359 if (length == -1) length = StringLength(data);
5360 // We do not expect this to fail. Change this if it does.
5361 i::Handle<i::String> result = NewString(
5362 isolate->factory(),
5363 type,
5364 i::Vector<const Char>(data, length)).ToHandleChecked();
5365 if (type == String::kUndetectableString) {
5366 result->MarkAsUndetectable();
5367 }
5368 return Utils::ToLocal(result);
5369 }
5370
5371 } // anonymous namespace
5372
5373
NewFromUtf8(Isolate * isolate,const char * data,NewStringType type,int length)5374 Local<String> String::NewFromUtf8(Isolate* isolate,
5375 const char* data,
5376 NewStringType type,
5377 int length) {
5378 return NewString(isolate,
5379 "v8::String::NewFromUtf8()",
5380 "String::NewFromUtf8",
5381 data,
5382 type,
5383 length);
5384 }
5385
5386
NewFromOneByte(Isolate * isolate,const uint8_t * data,NewStringType type,int length)5387 Local<String> String::NewFromOneByte(Isolate* isolate,
5388 const uint8_t* data,
5389 NewStringType type,
5390 int length) {
5391 return NewString(isolate,
5392 "v8::String::NewFromOneByte()",
5393 "String::NewFromOneByte",
5394 data,
5395 type,
5396 length);
5397 }
5398
5399
NewFromTwoByte(Isolate * isolate,const uint16_t * data,NewStringType type,int length)5400 Local<String> String::NewFromTwoByte(Isolate* isolate,
5401 const uint16_t* data,
5402 NewStringType type,
5403 int length) {
5404 return NewString(isolate,
5405 "v8::String::NewFromTwoByte()",
5406 "String::NewFromTwoByte",
5407 data,
5408 type,
5409 length);
5410 }
5411
5412
Concat(Handle<String> left,Handle<String> right)5413 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
5414 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
5415 i::Isolate* isolate = left_string->GetIsolate();
5416 EnsureInitializedForIsolate(isolate, "v8::String::New()");
5417 LOG_API(isolate, "String::New(char)");
5418 ENTER_V8(isolate);
5419 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
5420 // We do not expect this to fail. Change this if it does.
5421 i::Handle<i::String> result = isolate->factory()->NewConsString(
5422 left_string, right_string).ToHandleChecked();
5423 return Utils::ToLocal(result);
5424 }
5425
5426
NewExternalStringHandle(i::Isolate * isolate,v8::String::ExternalStringResource * resource)5427 static i::Handle<i::String> NewExternalStringHandle(
5428 i::Isolate* isolate,
5429 v8::String::ExternalStringResource* resource) {
5430 // We do not expect this to fail. Change this if it does.
5431 return isolate->factory()->NewExternalStringFromTwoByte(
5432 resource).ToHandleChecked();
5433 }
5434
5435
NewExternalAsciiStringHandle(i::Isolate * isolate,v8::String::ExternalAsciiStringResource * resource)5436 static i::Handle<i::String> NewExternalAsciiStringHandle(
5437 i::Isolate* isolate,
5438 v8::String::ExternalAsciiStringResource* resource) {
5439 // We do not expect this to fail. Change this if it does.
5440 return isolate->factory()->NewExternalStringFromAscii(
5441 resource).ToHandleChecked();
5442 }
5443
5444
NewExternal(Isolate * isolate,v8::String::ExternalStringResource * resource)5445 Local<String> v8::String::NewExternal(
5446 Isolate* isolate,
5447 v8::String::ExternalStringResource* resource) {
5448 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5449 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5450 LOG_API(i_isolate, "String::NewExternal");
5451 ENTER_V8(i_isolate);
5452 CHECK(resource && resource->data());
5453 i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
5454 i_isolate->heap()->external_string_table()->AddString(*result);
5455 return Utils::ToLocal(result);
5456 }
5457
5458
MakeExternal(v8::String::ExternalStringResource * resource)5459 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
5460 i::Handle<i::String> obj = Utils::OpenHandle(this);
5461 i::Isolate* isolate = obj->GetIsolate();
5462 if (i::StringShape(*obj).IsExternalTwoByte()) {
5463 return false; // Already an external string.
5464 }
5465 ENTER_V8(isolate);
5466 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5467 return false;
5468 }
5469 if (isolate->heap()->IsInGCPostProcessing()) {
5470 return false;
5471 }
5472 CHECK(resource && resource->data());
5473
5474 bool result = obj->MakeExternal(resource);
5475 if (result) {
5476 ASSERT(obj->IsExternalString());
5477 isolate->heap()->external_string_table()->AddString(*obj);
5478 }
5479 return result;
5480 }
5481
5482
NewExternal(Isolate * isolate,v8::String::ExternalAsciiStringResource * resource)5483 Local<String> v8::String::NewExternal(
5484 Isolate* isolate,
5485 v8::String::ExternalAsciiStringResource* resource) {
5486 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5487 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5488 LOG_API(i_isolate, "String::NewExternal");
5489 ENTER_V8(i_isolate);
5490 CHECK(resource && resource->data());
5491 i::Handle<i::String> result =
5492 NewExternalAsciiStringHandle(i_isolate, resource);
5493 i_isolate->heap()->external_string_table()->AddString(*result);
5494 return Utils::ToLocal(result);
5495 }
5496
5497
MakeExternal(v8::String::ExternalAsciiStringResource * resource)5498 bool v8::String::MakeExternal(
5499 v8::String::ExternalAsciiStringResource* resource) {
5500 i::Handle<i::String> obj = Utils::OpenHandle(this);
5501 i::Isolate* isolate = obj->GetIsolate();
5502 if (i::StringShape(*obj).IsExternalTwoByte()) {
5503 return false; // Already an external string.
5504 }
5505 ENTER_V8(isolate);
5506 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5507 return false;
5508 }
5509 if (isolate->heap()->IsInGCPostProcessing()) {
5510 return false;
5511 }
5512 CHECK(resource && resource->data());
5513
5514 bool result = obj->MakeExternal(resource);
5515 if (result) {
5516 ASSERT(obj->IsExternalString());
5517 isolate->heap()->external_string_table()->AddString(*obj);
5518 }
5519 return result;
5520 }
5521
5522
CanMakeExternal()5523 bool v8::String::CanMakeExternal() {
5524 if (!internal::FLAG_clever_optimizations) return false;
5525 i::Handle<i::String> obj = Utils::OpenHandle(this);
5526 i::Isolate* isolate = obj->GetIsolate();
5527
5528 // TODO(yangguo): Externalizing sliced/cons strings allocates.
5529 // This rule can be removed when all code that can
5530 // trigger an access check is handlified and therefore GC safe.
5531 if (isolate->heap()->old_pointer_space()->Contains(*obj)) return false;
5532
5533 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
5534 int size = obj->Size(); // Byte size of the original string.
5535 if (size < i::ExternalString::kShortSize) return false;
5536 i::StringShape shape(*obj);
5537 return !shape.IsExternal();
5538 }
5539
5540
New(Isolate * isolate)5541 Local<v8::Object> v8::Object::New(Isolate* isolate) {
5542 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5543 EnsureInitializedForIsolate(i_isolate, "v8::Object::New()");
5544 LOG_API(i_isolate, "Object::New");
5545 ENTER_V8(i_isolate);
5546 i::Handle<i::JSObject> obj =
5547 i_isolate->factory()->NewJSObject(i_isolate->object_function());
5548 return Utils::ToLocal(obj);
5549 }
5550
5551
New(Isolate * isolate,double value)5552 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
5553 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5554 EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()");
5555 LOG_API(i_isolate, "NumberObject::New");
5556 ENTER_V8(i_isolate);
5557 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
5558 i::Handle<i::Object> obj =
5559 i::Object::ToObject(i_isolate, number).ToHandleChecked();
5560 return Utils::ToLocal(obj);
5561 }
5562
5563
ValueOf() const5564 double v8::NumberObject::ValueOf() const {
5565 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5566 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5567 i::Isolate* isolate = jsvalue->GetIsolate();
5568 LOG_API(isolate, "NumberObject::NumberValue");
5569 return jsvalue->value()->Number();
5570 }
5571
5572
New(bool value)5573 Local<v8::Value> v8::BooleanObject::New(bool value) {
5574 i::Isolate* isolate = i::Isolate::Current();
5575 EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
5576 LOG_API(isolate, "BooleanObject::New");
5577 ENTER_V8(isolate);
5578 i::Handle<i::Object> boolean(value
5579 ? isolate->heap()->true_value()
5580 : isolate->heap()->false_value(),
5581 isolate);
5582 i::Handle<i::Object> obj =
5583 i::Object::ToObject(isolate, boolean).ToHandleChecked();
5584 return Utils::ToLocal(obj);
5585 }
5586
5587
ValueOf() const5588 bool v8::BooleanObject::ValueOf() const {
5589 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5590 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5591 i::Isolate* isolate = jsvalue->GetIsolate();
5592 LOG_API(isolate, "BooleanObject::BooleanValue");
5593 return jsvalue->value()->IsTrue();
5594 }
5595
5596
New(Handle<String> value)5597 Local<v8::Value> v8::StringObject::New(Handle<String> value) {
5598 i::Handle<i::String> string = Utils::OpenHandle(*value);
5599 i::Isolate* isolate = string->GetIsolate();
5600 EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
5601 LOG_API(isolate, "StringObject::New");
5602 ENTER_V8(isolate);
5603 i::Handle<i::Object> obj =
5604 i::Object::ToObject(isolate, string).ToHandleChecked();
5605 return Utils::ToLocal(obj);
5606 }
5607
5608
ValueOf() const5609 Local<v8::String> v8::StringObject::ValueOf() const {
5610 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5611 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5612 i::Isolate* isolate = jsvalue->GetIsolate();
5613 LOG_API(isolate, "StringObject::StringValue");
5614 return Utils::ToLocal(
5615 i::Handle<i::String>(i::String::cast(jsvalue->value())));
5616 }
5617
5618
New(Isolate * isolate,Handle<Symbol> value)5619 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
5620 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5621 EnsureInitializedForIsolate(i_isolate, "v8::SymbolObject::New()");
5622 LOG_API(i_isolate, "SymbolObject::New");
5623 ENTER_V8(i_isolate);
5624 i::Handle<i::Object> obj = i::Object::ToObject(
5625 i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
5626 return Utils::ToLocal(obj);
5627 }
5628
5629
ValueOf() const5630 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
5631 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5632 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5633 i::Isolate* isolate = jsvalue->GetIsolate();
5634 LOG_API(isolate, "SymbolObject::SymbolValue");
5635 return Utils::ToLocal(
5636 i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
5637 }
5638
5639
New(Isolate * isolate,double time)5640 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
5641 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5642 EnsureInitializedForIsolate(i_isolate, "v8::Date::New()");
5643 LOG_API(i_isolate, "Date::New");
5644 if (std::isnan(time)) {
5645 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5646 time = i::OS::nan_value();
5647 }
5648 ENTER_V8(i_isolate);
5649 EXCEPTION_PREAMBLE(i_isolate);
5650 i::Handle<i::Object> obj;
5651 has_pending_exception = !i::Execution::NewDate(
5652 i_isolate, time).ToHandle(&obj);
5653 EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
5654 return Utils::ToLocal(obj);
5655 }
5656
5657
ValueOf() const5658 double v8::Date::ValueOf() const {
5659 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5660 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
5661 i::Isolate* isolate = jsdate->GetIsolate();
5662 LOG_API(isolate, "Date::NumberValue");
5663 return jsdate->value()->Number();
5664 }
5665
5666
DateTimeConfigurationChangeNotification(Isolate * isolate)5667 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
5668 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5669 if (!i_isolate->IsInitialized()) return;
5670 ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
5671 return);
5672 LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
5673 ENTER_V8(i_isolate);
5674
5675 i_isolate->date_cache()->ResetDateCache();
5676
5677 if (!i_isolate->eternal_handles()->Exists(
5678 i::EternalHandles::DATE_CACHE_VERSION)) {
5679 return;
5680 }
5681 i::Handle<i::FixedArray> date_cache_version =
5682 i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
5683 i::EternalHandles::DATE_CACHE_VERSION));
5684 ASSERT_EQ(1, date_cache_version->length());
5685 CHECK(date_cache_version->get(0)->IsSmi());
5686 date_cache_version->set(
5687 0,
5688 i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
5689 }
5690
5691
RegExpFlagsToString(RegExp::Flags flags)5692 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
5693 i::Isolate* isolate = i::Isolate::Current();
5694 uint8_t flags_buf[3];
5695 int num_flags = 0;
5696 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
5697 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
5698 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
5699 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
5700 return isolate->factory()->InternalizeOneByteString(
5701 i::Vector<const uint8_t>(flags_buf, num_flags));
5702 }
5703
5704
New(Handle<String> pattern,Flags flags)5705 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
5706 Flags flags) {
5707 i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
5708 EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
5709 LOG_API(isolate, "RegExp::New");
5710 ENTER_V8(isolate);
5711 EXCEPTION_PREAMBLE(isolate);
5712 i::Handle<i::JSRegExp> obj;
5713 has_pending_exception = !i::Execution::NewJSRegExp(
5714 Utils::OpenHandle(*pattern),
5715 RegExpFlagsToString(flags)).ToHandle(&obj);
5716 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
5717 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
5718 }
5719
5720
GetSource() const5721 Local<v8::String> v8::RegExp::GetSource() const {
5722 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5723 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
5724 }
5725
5726
5727 // Assert that the static flags cast in GetFlags is valid.
5728 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
5729 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
5730 static_cast<int>(i::JSRegExp::internal_flag))
5731 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
5732 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
5733 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
5734 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
5735 #undef REGEXP_FLAG_ASSERT_EQ
5736
GetFlags() const5737 v8::RegExp::Flags v8::RegExp::GetFlags() const {
5738 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5739 return static_cast<RegExp::Flags>(obj->GetFlags().value());
5740 }
5741
5742
New(Isolate * isolate,int length)5743 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
5744 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5745 EnsureInitializedForIsolate(i_isolate, "v8::Array::New()");
5746 LOG_API(i_isolate, "Array::New");
5747 ENTER_V8(i_isolate);
5748 int real_length = length > 0 ? length : 0;
5749 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
5750 i::Handle<i::Object> length_obj =
5751 i_isolate->factory()->NewNumberFromInt(real_length);
5752 obj->set_length(*length_obj);
5753 return Utils::ToLocal(obj);
5754 }
5755
5756
Length() const5757 uint32_t v8::Array::Length() const {
5758 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
5759 i::Object* length = obj->length();
5760 if (length->IsSmi()) {
5761 return i::Smi::cast(length)->value();
5762 } else {
5763 return static_cast<uint32_t>(length->Number());
5764 }
5765 }
5766
5767
CloneElementAt(uint32_t index)5768 Local<Object> Array::CloneElementAt(uint32_t index) {
5769 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
5770 ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
5771 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
5772 if (!self->HasFastObjectElements()) {
5773 return Local<Object>();
5774 }
5775 i::FixedArray* elms = i::FixedArray::cast(self->elements());
5776 i::Object* paragon = elms->get(index);
5777 if (!paragon->IsJSObject()) {
5778 return Local<Object>();
5779 }
5780 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5781 EXCEPTION_PREAMBLE(isolate);
5782 ENTER_V8(isolate);
5783 i::Handle<i::JSObject> result =
5784 isolate->factory()->CopyJSObject(paragon_handle);
5785 has_pending_exception = result.is_null();
5786 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5787 return Utils::ToLocal(result);
5788 }
5789
5790
IsPromise() const5791 bool Value::IsPromise() const {
5792 i::Handle<i::Object> val = Utils::OpenHandle(this);
5793 if (!val->IsJSObject()) return false;
5794 i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
5795 i::Isolate* isolate = obj->GetIsolate();
5796 LOG_API(isolate, "IsPromise");
5797 ENTER_V8(isolate);
5798 EXCEPTION_PREAMBLE(isolate);
5799 i::Handle<i::Object> argv[] = { obj };
5800 i::Handle<i::Object> b;
5801 has_pending_exception = !i::Execution::Call(
5802 isolate,
5803 handle(
5804 isolate->context()->global_object()->native_context()->is_promise()),
5805 isolate->factory()->undefined_value(),
5806 ARRAY_SIZE(argv), argv,
5807 false).ToHandle(&b);
5808 EXCEPTION_BAILOUT_CHECK(isolate, false);
5809 return b->BooleanValue();
5810 }
5811
5812
New(Isolate * v8_isolate)5813 Local<Promise::Resolver> Promise::Resolver::New(Isolate* v8_isolate) {
5814 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5815 LOG_API(isolate, "Promise::Resolver::New");
5816 ENTER_V8(isolate);
5817 EXCEPTION_PREAMBLE(isolate);
5818 i::Handle<i::Object> result;
5819 has_pending_exception = !i::Execution::Call(
5820 isolate,
5821 handle(isolate->context()->global_object()->native_context()->
5822 promise_create()),
5823 isolate->factory()->undefined_value(),
5824 0, NULL,
5825 false).ToHandle(&result);
5826 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
5827 return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
5828 }
5829
5830
GetPromise()5831 Local<Promise> Promise::Resolver::GetPromise() {
5832 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5833 return Local<Promise>::Cast(Utils::ToLocal(promise));
5834 }
5835
5836
Resolve(Handle<Value> value)5837 void Promise::Resolver::Resolve(Handle<Value> value) {
5838 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5839 i::Isolate* isolate = promise->GetIsolate();
5840 LOG_API(isolate, "Promise::Resolver::Resolve");
5841 ENTER_V8(isolate);
5842 EXCEPTION_PREAMBLE(isolate);
5843 i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5844 has_pending_exception = i::Execution::Call(
5845 isolate,
5846 handle(isolate->context()->global_object()->native_context()->
5847 promise_resolve()),
5848 isolate->factory()->undefined_value(),
5849 ARRAY_SIZE(argv), argv,
5850 false).is_null();
5851 EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5852 }
5853
5854
Reject(Handle<Value> value)5855 void Promise::Resolver::Reject(Handle<Value> value) {
5856 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5857 i::Isolate* isolate = promise->GetIsolate();
5858 LOG_API(isolate, "Promise::Resolver::Reject");
5859 ENTER_V8(isolate);
5860 EXCEPTION_PREAMBLE(isolate);
5861 i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5862 has_pending_exception = i::Execution::Call(
5863 isolate,
5864 handle(isolate->context()->global_object()->native_context()->
5865 promise_reject()),
5866 isolate->factory()->undefined_value(),
5867 ARRAY_SIZE(argv), argv,
5868 false).is_null();
5869 EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5870 }
5871
5872
Chain(Handle<Function> handler)5873 Local<Promise> Promise::Chain(Handle<Function> handler) {
5874 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5875 i::Isolate* isolate = promise->GetIsolate();
5876 LOG_API(isolate, "Promise::Chain");
5877 ENTER_V8(isolate);
5878 EXCEPTION_PREAMBLE(isolate);
5879 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5880 i::Handle<i::Object> result;
5881 has_pending_exception = !i::Execution::Call(
5882 isolate,
5883 handle(isolate->context()->global_object()->native_context()->
5884 promise_chain()),
5885 promise,
5886 ARRAY_SIZE(argv), argv,
5887 false).ToHandle(&result);
5888 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5889 return Local<Promise>::Cast(Utils::ToLocal(result));
5890 }
5891
5892
Catch(Handle<Function> handler)5893 Local<Promise> Promise::Catch(Handle<Function> handler) {
5894 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5895 i::Isolate* isolate = promise->GetIsolate();
5896 LOG_API(isolate, "Promise::Catch");
5897 ENTER_V8(isolate);
5898 EXCEPTION_PREAMBLE(isolate);
5899 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5900 i::Handle<i::Object> result;
5901 has_pending_exception = !i::Execution::Call(
5902 isolate,
5903 handle(isolate->context()->global_object()->native_context()->
5904 promise_catch()),
5905 promise,
5906 ARRAY_SIZE(argv), argv,
5907 false).ToHandle(&result);
5908 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5909 return Local<Promise>::Cast(Utils::ToLocal(result));
5910 }
5911
5912
Then(Handle<Function> handler)5913 Local<Promise> Promise::Then(Handle<Function> handler) {
5914 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5915 i::Isolate* isolate = promise->GetIsolate();
5916 LOG_API(isolate, "Promise::Then");
5917 ENTER_V8(isolate);
5918 EXCEPTION_PREAMBLE(isolate);
5919 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5920 i::Handle<i::Object> result;
5921 has_pending_exception = !i::Execution::Call(
5922 isolate,
5923 handle(isolate->context()->global_object()->native_context()->
5924 promise_then()),
5925 promise,
5926 ARRAY_SIZE(argv), argv,
5927 false).ToHandle(&result);
5928 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5929 return Local<Promise>::Cast(Utils::ToLocal(result));
5930 }
5931
5932
IsExternal() const5933 bool v8::ArrayBuffer::IsExternal() const {
5934 return Utils::OpenHandle(this)->is_external();
5935 }
5936
5937
Externalize()5938 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
5939 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5940 Utils::ApiCheck(!obj->is_external(),
5941 "v8::ArrayBuffer::Externalize",
5942 "ArrayBuffer already externalized");
5943 obj->set_is_external(true);
5944 size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
5945 Contents contents;
5946 contents.data_ = obj->backing_store();
5947 contents.byte_length_ = byte_length;
5948 return contents;
5949 }
5950
5951
Neuter()5952 void v8::ArrayBuffer::Neuter() {
5953 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5954 i::Isolate* isolate = obj->GetIsolate();
5955 Utils::ApiCheck(obj->is_external(),
5956 "v8::ArrayBuffer::Neuter",
5957 "Only externalized ArrayBuffers can be neutered");
5958 LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
5959 ENTER_V8(isolate);
5960 i::Runtime::NeuterArrayBuffer(obj);
5961 }
5962
5963
ByteLength() const5964 size_t v8::ArrayBuffer::ByteLength() const {
5965 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5966 return static_cast<size_t>(obj->byte_length()->Number());
5967 }
5968
5969
New(Isolate * isolate,size_t byte_length)5970 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
5971 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5972 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)");
5973 LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
5974 ENTER_V8(i_isolate);
5975 i::Handle<i::JSArrayBuffer> obj =
5976 i_isolate->factory()->NewJSArrayBuffer();
5977 i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
5978 return Utils::ToLocal(obj);
5979 }
5980
5981
New(Isolate * isolate,void * data,size_t byte_length)5982 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
5983 size_t byte_length) {
5984 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5985 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5986 LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5987 ENTER_V8(i_isolate);
5988 i::Handle<i::JSArrayBuffer> obj =
5989 i_isolate->factory()->NewJSArrayBuffer();
5990 i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
5991 return Utils::ToLocal(obj);
5992 }
5993
5994
Buffer()5995 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
5996 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
5997 i::Handle<i::JSArrayBuffer> buffer;
5998 if (obj->IsJSDataView()) {
5999 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
6000 ASSERT(data_view->buffer()->IsJSArrayBuffer());
6001 buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()));
6002 } else {
6003 ASSERT(obj->IsJSTypedArray());
6004 buffer = i::JSTypedArray::cast(*obj)->GetBuffer();
6005 }
6006 return Utils::ToLocal(buffer);
6007 }
6008
6009
ByteOffset()6010 size_t v8::ArrayBufferView::ByteOffset() {
6011 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6012 return static_cast<size_t>(obj->byte_offset()->Number());
6013 }
6014
6015
ByteLength()6016 size_t v8::ArrayBufferView::ByteLength() {
6017 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6018 return static_cast<size_t>(obj->byte_length()->Number());
6019 }
6020
6021
Length()6022 size_t v8::TypedArray::Length() {
6023 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
6024 return static_cast<size_t>(obj->length()->Number());
6025 }
6026
6027
SetupArrayBufferView(i::Isolate * isolate,i::Handle<i::JSArrayBufferView> obj,i::Handle<i::JSArrayBuffer> buffer,size_t byte_offset,size_t byte_length)6028 static inline void SetupArrayBufferView(
6029 i::Isolate* isolate,
6030 i::Handle<i::JSArrayBufferView> obj,
6031 i::Handle<i::JSArrayBuffer> buffer,
6032 size_t byte_offset,
6033 size_t byte_length) {
6034 ASSERT(byte_offset + byte_length <=
6035 static_cast<size_t>(buffer->byte_length()->Number()));
6036
6037 obj->set_buffer(*buffer);
6038
6039 obj->set_weak_next(buffer->weak_first_view());
6040 buffer->set_weak_first_view(*obj);
6041
6042 i::Handle<i::Object> byte_offset_object =
6043 isolate->factory()->NewNumberFromSize(byte_offset);
6044 obj->set_byte_offset(*byte_offset_object);
6045
6046 i::Handle<i::Object> byte_length_object =
6047 isolate->factory()->NewNumberFromSize(byte_length);
6048 obj->set_byte_length(*byte_length_object);
6049 }
6050
6051 template<typename ElementType,
6052 ExternalArrayType array_type,
6053 i::ElementsKind elements_kind>
NewTypedArray(i::Isolate * isolate,Handle<ArrayBuffer> array_buffer,size_t byte_offset,size_t length)6054 i::Handle<i::JSTypedArray> NewTypedArray(
6055 i::Isolate* isolate,
6056 Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
6057 i::Handle<i::JSTypedArray> obj =
6058 isolate->factory()->NewJSTypedArray(array_type);
6059 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6060
6061 ASSERT(byte_offset % sizeof(ElementType) == 0);
6062
6063 CHECK(length <= (std::numeric_limits<size_t>::max() / sizeof(ElementType)));
6064 CHECK(length <= static_cast<size_t>(i::Smi::kMaxValue));
6065 size_t byte_length = length * sizeof(ElementType);
6066 SetupArrayBufferView(
6067 isolate, obj, buffer, byte_offset, byte_length);
6068
6069 i::Handle<i::Object> length_object =
6070 isolate->factory()->NewNumberFromSize(length);
6071 obj->set_length(*length_object);
6072
6073 i::Handle<i::ExternalArray> elements =
6074 isolate->factory()->NewExternalArray(
6075 static_cast<int>(length), array_type,
6076 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
6077 i::Handle<i::Map> map =
6078 i::JSObject::GetElementsTransitionMap(obj, elements_kind);
6079 i::JSObject::SetMapAndElements(obj, map, elements);
6080 return obj;
6081 }
6082
6083
6084 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \
6085 Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer, \
6086 size_t byte_offset, size_t length) { \
6087 i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
6088 EnsureInitializedForIsolate(isolate, \
6089 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
6090 LOG_API(isolate, \
6091 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
6092 ENTER_V8(isolate); \
6093 if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue), \
6094 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)", \
6095 "length exceeds max allowed value")) { \
6096 return Local<Type##Array>(); \
6097 } \
6098 i::Handle<i::JSTypedArray> obj = \
6099 NewTypedArray<ctype, v8::kExternal##Type##Array, \
6100 i::EXTERNAL_##TYPE##_ELEMENTS>( \
6101 isolate, array_buffer, byte_offset, length); \
6102 return Utils::ToLocal##Type##Array(obj); \
6103 }
6104
6105
TYPED_ARRAYS(TYPED_ARRAY_NEW)6106 TYPED_ARRAYS(TYPED_ARRAY_NEW)
6107 #undef TYPED_ARRAY_NEW
6108
6109 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
6110 size_t byte_offset, size_t byte_length) {
6111 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6112 i::Isolate* isolate = buffer->GetIsolate();
6113 EnsureInitializedForIsolate(
6114 isolate, "v8::DataView::New(void*, size_t, size_t)");
6115 LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
6116 ENTER_V8(isolate);
6117 i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
6118 SetupArrayBufferView(
6119 isolate, obj, buffer, byte_offset, byte_length);
6120 return Utils::ToLocal(obj);
6121 }
6122
6123
New(Isolate * isolate,Local<String> name)6124 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
6125 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6126 EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
6127 LOG_API(i_isolate, "Symbol::New()");
6128 ENTER_V8(i_isolate);
6129 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6130 if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
6131 return Utils::ToLocal(result);
6132 }
6133
6134
For(Isolate * isolate,Local<String> name)6135 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
6136 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6137 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6138 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6139 i::Handle<i::String> part = i_isolate->factory()->for_string();
6140 i::Handle<i::JSObject> symbols =
6141 i::Handle<i::JSObject>::cast(
6142 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6143 i::Handle<i::Object> symbol =
6144 i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6145 if (!symbol->IsSymbol()) {
6146 ASSERT(symbol->IsUndefined());
6147 symbol = i_isolate->factory()->NewSymbol();
6148 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6149 i::JSObject::SetProperty(
6150 symbols, i_name, symbol, NONE, i::STRICT).Assert();
6151 }
6152 return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6153 }
6154
6155
ForApi(Isolate * isolate,Local<String> name)6156 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
6157 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6158 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6159 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6160 i::Handle<i::String> part = i_isolate->factory()->for_api_string();
6161 i::Handle<i::JSObject> symbols =
6162 i::Handle<i::JSObject>::cast(
6163 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6164 i::Handle<i::Object> symbol =
6165 i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6166 if (!symbol->IsSymbol()) {
6167 ASSERT(symbol->IsUndefined());
6168 symbol = i_isolate->factory()->NewSymbol();
6169 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6170 i::JSObject::SetProperty(
6171 symbols, i_name, symbol, NONE, i::STRICT).Assert();
6172 }
6173 return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6174 }
6175
6176
New(Isolate * isolate,Local<String> name)6177 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
6178 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6179 EnsureInitializedForIsolate(i_isolate, "v8::Private::New()");
6180 LOG_API(i_isolate, "Private::New()");
6181 ENTER_V8(i_isolate);
6182 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
6183 if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
6184 Local<Symbol> result = Utils::ToLocal(symbol);
6185 return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6186 }
6187
6188
ForApi(Isolate * isolate,Local<String> name)6189 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
6190 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6191 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6192 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6193 i::Handle<i::String> part = i_isolate->factory()->private_api_string();
6194 i::Handle<i::JSObject> privates =
6195 i::Handle<i::JSObject>::cast(
6196 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6197 i::Handle<i::Object> symbol =
6198 i::Object::GetPropertyOrElement(privates, i_name).ToHandleChecked();
6199 if (!symbol->IsSymbol()) {
6200 ASSERT(symbol->IsUndefined());
6201 symbol = i_isolate->factory()->NewPrivateSymbol();
6202 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6203 i::JSObject::SetProperty(
6204 privates, i_name, symbol, NONE, i::STRICT).Assert();
6205 }
6206 Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6207 return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6208 }
6209
6210
New(Isolate * isolate,double value)6211 Local<Number> v8::Number::New(Isolate* isolate, double value) {
6212 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6213 ASSERT(internal_isolate->IsInitialized());
6214 if (std::isnan(value)) {
6215 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6216 value = i::OS::nan_value();
6217 }
6218 ENTER_V8(internal_isolate);
6219 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6220 return Utils::NumberToLocal(result);
6221 }
6222
6223
New(Isolate * isolate,int32_t value)6224 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
6225 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6226 ASSERT(internal_isolate->IsInitialized());
6227 if (i::Smi::IsValid(value)) {
6228 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
6229 internal_isolate));
6230 }
6231 ENTER_V8(internal_isolate);
6232 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6233 return Utils::IntegerToLocal(result);
6234 }
6235
6236
NewFromUnsigned(Isolate * isolate,uint32_t value)6237 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
6238 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6239 ASSERT(internal_isolate->IsInitialized());
6240 bool fits_into_int32_t = (value & (1 << 31)) == 0;
6241 if (fits_into_int32_t) {
6242 return Integer::New(isolate, static_cast<int32_t>(value));
6243 }
6244 ENTER_V8(internal_isolate);
6245 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6246 return Utils::IntegerToLocal(result);
6247 }
6248
6249
AddMessageListener(MessageCallback that,Handle<Value> data)6250 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
6251 i::Isolate* isolate = i::Isolate::Current();
6252 EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
6253 ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
6254 ENTER_V8(isolate);
6255 i::HandleScope scope(isolate);
6256 NeanderArray listeners(isolate->factory()->message_listeners());
6257 NeanderObject obj(isolate, 2);
6258 obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
6259 obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
6260 : *Utils::OpenHandle(*data));
6261 listeners.add(obj.value());
6262 return true;
6263 }
6264
6265
RemoveMessageListeners(MessageCallback that)6266 void V8::RemoveMessageListeners(MessageCallback that) {
6267 i::Isolate* isolate = i::Isolate::Current();
6268 EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
6269 ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
6270 ENTER_V8(isolate);
6271 i::HandleScope scope(isolate);
6272 NeanderArray listeners(isolate->factory()->message_listeners());
6273 for (int i = 0; i < listeners.length(); i++) {
6274 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
6275
6276 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
6277 i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
6278 if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
6279 listeners.set(i, isolate->heap()->undefined_value());
6280 }
6281 }
6282 }
6283
6284
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)6285 void V8::SetCaptureStackTraceForUncaughtExceptions(
6286 bool capture,
6287 int frame_limit,
6288 StackTrace::StackTraceOptions options) {
6289 i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
6290 capture,
6291 frame_limit,
6292 options);
6293 }
6294
6295
SetCounterFunction(CounterLookupCallback callback)6296 void V8::SetCounterFunction(CounterLookupCallback callback) {
6297 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6298 // TODO(svenpanne) The Isolate should really be a parameter.
6299 if (isolate == NULL) return;
6300 isolate->stats_table()->SetCounterFunction(callback);
6301 }
6302
6303
SetCreateHistogramFunction(CreateHistogramCallback callback)6304 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6305 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6306 // TODO(svenpanne) The Isolate should really be a parameter.
6307 if (isolate == NULL) return;
6308 isolate->stats_table()->SetCreateHistogramFunction(callback);
6309 isolate->InitializeLoggingAndCounters();
6310 isolate->counters()->ResetHistograms();
6311 }
6312
6313
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)6314 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
6315 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6316 // TODO(svenpanne) The Isolate should really be a parameter.
6317 if (isolate == NULL) return;
6318 isolate->stats_table()->
6319 SetAddHistogramSampleFunction(callback);
6320 }
6321
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)6322 void V8::SetFailedAccessCheckCallbackFunction(
6323 FailedAccessCheckCallback callback) {
6324 i::Isolate* isolate = i::Isolate::Current();
6325 isolate->SetFailedAccessCheckCallback(callback);
6326 }
6327
6328
CollectAllGarbage(const char * gc_reason)6329 void Isolate::CollectAllGarbage(const char* gc_reason) {
6330 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6331 i::Heap::kNoGCFlags, gc_reason);
6332 }
6333
6334
GetHeapProfiler()6335 HeapProfiler* Isolate::GetHeapProfiler() {
6336 i::HeapProfiler* heap_profiler =
6337 reinterpret_cast<i::Isolate*>(this)->heap_profiler();
6338 return reinterpret_cast<HeapProfiler*>(heap_profiler);
6339 }
6340
6341
GetCpuProfiler()6342 CpuProfiler* Isolate::GetCpuProfiler() {
6343 i::CpuProfiler* cpu_profiler =
6344 reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
6345 return reinterpret_cast<CpuProfiler*>(cpu_profiler);
6346 }
6347
6348
InContext()6349 bool Isolate::InContext() {
6350 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6351 return isolate->context() != NULL;
6352 }
6353
6354
GetCurrentContext()6355 v8::Local<v8::Context> Isolate::GetCurrentContext() {
6356 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6357 i::Context* context = isolate->context();
6358 if (context == NULL) return Local<Context>();
6359 i::Context* native_context = context->global_object()->native_context();
6360 if (native_context == NULL) return Local<Context>();
6361 return Utils::ToLocal(i::Handle<i::Context>(native_context));
6362 }
6363
6364
GetCallingContext()6365 v8::Local<v8::Context> Isolate::GetCallingContext() {
6366 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6367 i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
6368 if (calling.is_null()) return Local<Context>();
6369 return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
6370 }
6371
6372
GetEnteredContext()6373 v8::Local<v8::Context> Isolate::GetEnteredContext() {
6374 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6375 i::Handle<i::Object> last =
6376 isolate->handle_scope_implementer()->LastEnteredContext();
6377 if (last.is_null()) return Local<Context>();
6378 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
6379 }
6380
6381
ThrowException(v8::Local<v8::Value> value)6382 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
6383 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6384 ENTER_V8(isolate);
6385 // If we're passed an empty handle, we throw an undefined exception
6386 // to deal more gracefully with out of memory situations.
6387 if (value.IsEmpty()) {
6388 isolate->ScheduleThrow(isolate->heap()->undefined_value());
6389 } else {
6390 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
6391 }
6392 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6393 }
6394
6395
SetObjectGroupId(internal::Object ** object,UniqueId id)6396 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
6397 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6398 internal_isolate->global_handles()->SetObjectGroupId(
6399 v8::internal::Handle<v8::internal::Object>(object).location(),
6400 id);
6401 }
6402
6403
SetReferenceFromGroup(UniqueId id,internal::Object ** object)6404 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
6405 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6406 internal_isolate->global_handles()->SetReferenceFromGroup(
6407 id,
6408 v8::internal::Handle<v8::internal::Object>(object).location());
6409 }
6410
6411
SetReference(internal::Object ** parent,internal::Object ** child)6412 void Isolate::SetReference(internal::Object** parent,
6413 internal::Object** child) {
6414 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6415 i::Object** parent_location =
6416 v8::internal::Handle<v8::internal::Object>(parent).location();
6417 internal_isolate->global_handles()->SetReference(
6418 reinterpret_cast<i::HeapObject**>(parent_location),
6419 v8::internal::Handle<v8::internal::Object>(child).location());
6420 }
6421
6422
AddGCPrologueCallback(GCPrologueCallback callback,GCType gc_type)6423 void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
6424 GCType gc_type) {
6425 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6426 isolate->heap()->AddGCPrologueCallback(callback, gc_type);
6427 }
6428
6429
RemoveGCPrologueCallback(GCPrologueCallback callback)6430 void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6431 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6432 isolate->heap()->RemoveGCPrologueCallback(callback);
6433 }
6434
6435
AddGCEpilogueCallback(GCEpilogueCallback callback,GCType gc_type)6436 void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
6437 GCType gc_type) {
6438 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6439 isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
6440 }
6441
6442
RemoveGCEpilogueCallback(GCEpilogueCallback callback)6443 void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6444 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6445 isolate->heap()->RemoveGCEpilogueCallback(callback);
6446 }
6447
6448
AddGCPrologueCallback(GCPrologueCallback callback,GCType gc_type)6449 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
6450 i::Isolate* isolate = i::Isolate::Current();
6451 isolate->heap()->AddGCPrologueCallback(
6452 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
6453 gc_type,
6454 false);
6455 }
6456
6457
RemoveGCPrologueCallback(GCPrologueCallback callback)6458 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6459 i::Isolate* isolate = i::Isolate::Current();
6460 isolate->heap()->RemoveGCPrologueCallback(
6461 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback));
6462 }
6463
6464
AddGCEpilogueCallback(GCEpilogueCallback callback,GCType gc_type)6465 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
6466 i::Isolate* isolate = i::Isolate::Current();
6467 isolate->heap()->AddGCEpilogueCallback(
6468 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
6469 gc_type,
6470 false);
6471 }
6472
6473
RemoveGCEpilogueCallback(GCEpilogueCallback callback)6474 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6475 i::Isolate* isolate = i::Isolate::Current();
6476 isolate->heap()->RemoveGCEpilogueCallback(
6477 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback));
6478 }
6479
6480
AddMemoryAllocationCallback(MemoryAllocationCallback callback,ObjectSpace space,AllocationAction action)6481 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
6482 ObjectSpace space,
6483 AllocationAction action) {
6484 i::Isolate* isolate = i::Isolate::Current();
6485 isolate->memory_allocator()->AddMemoryAllocationCallback(
6486 callback, space, action);
6487 }
6488
6489
RemoveMemoryAllocationCallback(MemoryAllocationCallback callback)6490 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
6491 i::Isolate* isolate = i::Isolate::Current();
6492 isolate->memory_allocator()->RemoveMemoryAllocationCallback(
6493 callback);
6494 }
6495
6496
TerminateExecution(Isolate * isolate)6497 void V8::TerminateExecution(Isolate* isolate) {
6498 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6499 i_isolate->stack_guard()->RequestTerminateExecution();
6500 }
6501
6502
IsExecutionTerminating(Isolate * isolate)6503 bool V8::IsExecutionTerminating(Isolate* isolate) {
6504 i::Isolate* i_isolate = isolate != NULL ?
6505 reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current();
6506 return IsExecutionTerminatingCheck(i_isolate);
6507 }
6508
6509
CancelTerminateExecution(Isolate * isolate)6510 void V8::CancelTerminateExecution(Isolate* isolate) {
6511 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6512 i_isolate->stack_guard()->ClearTerminateExecution();
6513 i_isolate->CancelTerminateExecution();
6514 }
6515
6516
RequestInterrupt(InterruptCallback callback,void * data)6517 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
6518 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6519 i_isolate->set_api_interrupt_callback(callback);
6520 i_isolate->set_api_interrupt_callback_data(data);
6521 i_isolate->stack_guard()->RequestApiInterrupt();
6522 }
6523
6524
ClearInterrupt()6525 void Isolate::ClearInterrupt() {
6526 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6527 i_isolate->stack_guard()->ClearApiInterrupt();
6528 i_isolate->set_api_interrupt_callback(NULL);
6529 i_isolate->set_api_interrupt_callback_data(NULL);
6530 }
6531
6532
RequestGarbageCollectionForTesting(GarbageCollectionType type)6533 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
6534 CHECK(i::FLAG_expose_gc);
6535 if (type == kMinorGarbageCollection) {
6536 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
6537 i::NEW_SPACE, "Isolate::RequestGarbageCollection",
6538 kGCCallbackFlagForced);
6539 } else {
6540 ASSERT_EQ(kFullGarbageCollection, type);
6541 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6542 i::Heap::kAbortIncrementalMarkingMask,
6543 "Isolate::RequestGarbageCollection", kGCCallbackFlagForced);
6544 }
6545 }
6546
6547
GetCurrent()6548 Isolate* Isolate::GetCurrent() {
6549 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6550 return reinterpret_cast<Isolate*>(isolate);
6551 }
6552
6553
New()6554 Isolate* Isolate::New() {
6555 i::Isolate* isolate = new i::Isolate();
6556 return reinterpret_cast<Isolate*>(isolate);
6557 }
6558
6559
Dispose()6560 void Isolate::Dispose() {
6561 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6562 if (!Utils::ApiCheck(!isolate->IsInUse(),
6563 "v8::Isolate::Dispose()",
6564 "Disposing the isolate that is entered by a thread.")) {
6565 return;
6566 }
6567 isolate->TearDown();
6568 }
6569
6570
Enter()6571 void Isolate::Enter() {
6572 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6573 isolate->Enter();
6574 }
6575
6576
Exit()6577 void Isolate::Exit() {
6578 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6579 isolate->Exit();
6580 }
6581
6582
DisallowJavascriptExecutionScope(Isolate * isolate,Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)6583 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
6584 Isolate* isolate,
6585 Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
6586 : on_failure_(on_failure) {
6587 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6588 if (on_failure_ == CRASH_ON_FAILURE) {
6589 internal_ = reinterpret_cast<void*>(
6590 new i::DisallowJavascriptExecution(i_isolate));
6591 } else {
6592 ASSERT_EQ(THROW_ON_FAILURE, on_failure);
6593 internal_ = reinterpret_cast<void*>(
6594 new i::ThrowOnJavascriptExecution(i_isolate));
6595 }
6596 }
6597
6598
~DisallowJavascriptExecutionScope()6599 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
6600 if (on_failure_ == CRASH_ON_FAILURE) {
6601 delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
6602 } else {
6603 delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
6604 }
6605 }
6606
6607
AllowJavascriptExecutionScope(Isolate * isolate)6608 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
6609 Isolate* isolate) {
6610 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6611 internal_assert_ = reinterpret_cast<void*>(
6612 new i::AllowJavascriptExecution(i_isolate));
6613 internal_throws_ = reinterpret_cast<void*>(
6614 new i::NoThrowOnJavascriptExecution(i_isolate));
6615 }
6616
6617
~AllowJavascriptExecutionScope()6618 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
6619 delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
6620 delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
6621 }
6622
6623
SuppressMicrotaskExecutionScope(Isolate * isolate)6624 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
6625 Isolate* isolate)
6626 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
6627 isolate_->handle_scope_implementer()->IncrementCallDepth();
6628 }
6629
6630
~SuppressMicrotaskExecutionScope()6631 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
6632 isolate_->handle_scope_implementer()->DecrementCallDepth();
6633 }
6634
6635
GetHeapStatistics(HeapStatistics * heap_statistics)6636 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
6637 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6638 if (!isolate->IsInitialized()) {
6639 heap_statistics->total_heap_size_ = 0;
6640 heap_statistics->total_heap_size_executable_ = 0;
6641 heap_statistics->total_physical_size_ = 0;
6642 heap_statistics->used_heap_size_ = 0;
6643 heap_statistics->heap_size_limit_ = 0;
6644 return;
6645 }
6646 i::Heap* heap = isolate->heap();
6647 heap_statistics->total_heap_size_ = heap->CommittedMemory();
6648 heap_statistics->total_heap_size_executable_ =
6649 heap->CommittedMemoryExecutable();
6650 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
6651 heap_statistics->used_heap_size_ = heap->SizeOfObjects();
6652 heap_statistics->heap_size_limit_ = heap->MaxReserved();
6653 }
6654
6655
SetEventLogger(LogEventCallback that)6656 void Isolate::SetEventLogger(LogEventCallback that) {
6657 // Do not overwrite the event logger if we want to log explicitly.
6658 if (i::FLAG_log_timer_events) return;
6659 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6660 isolate->set_event_logger(that);
6661 }
6662
6663
AddCallCompletedCallback(CallCompletedCallback callback)6664 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
6665 if (callback == NULL) return;
6666 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6667 isolate->AddCallCompletedCallback(callback);
6668 }
6669
6670
RemoveCallCompletedCallback(CallCompletedCallback callback)6671 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
6672 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6673 isolate->RemoveCallCompletedCallback(callback);
6674 }
6675
6676
RunMicrotasks()6677 void Isolate::RunMicrotasks() {
6678 reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
6679 }
6680
6681
EnqueueMicrotask(Handle<Function> microtask)6682 void Isolate::EnqueueMicrotask(Handle<Function> microtask) {
6683 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6684 isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
6685 }
6686
6687
EnqueueMicrotask(MicrotaskCallback microtask,void * data)6688 void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
6689 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6690 i::HandleScope scope(isolate);
6691 i::Handle<i::CallHandlerInfo> callback_info =
6692 i::Handle<i::CallHandlerInfo>::cast(
6693 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
6694 SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
6695 SET_FIELD_WRAPPED(callback_info, set_data, data);
6696 isolate->EnqueueMicrotask(callback_info);
6697 }
6698
6699
SetAutorunMicrotasks(bool autorun)6700 void Isolate::SetAutorunMicrotasks(bool autorun) {
6701 reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun);
6702 }
6703
6704
WillAutorunMicrotasks() const6705 bool Isolate::WillAutorunMicrotasks() const {
6706 return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks();
6707 }
6708
6709
SetCounterFunction(CounterLookupCallback callback)6710 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
6711 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6712 isolate->stats_table()->SetCounterFunction(callback);
6713 isolate->InitializeLoggingAndCounters();
6714 isolate->counters()->ResetCounters();
6715 }
6716
6717
SetCreateHistogramFunction(CreateHistogramCallback callback)6718 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6719 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6720 isolate->stats_table()->SetCreateHistogramFunction(callback);
6721 isolate->InitializeLoggingAndCounters();
6722 isolate->counters()->ResetHistograms();
6723 }
6724
6725
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)6726 void Isolate::SetAddHistogramSampleFunction(
6727 AddHistogramSampleCallback callback) {
6728 reinterpret_cast<i::Isolate*>(this)
6729 ->stats_table()
6730 ->SetAddHistogramSampleFunction(callback);
6731 }
6732
6733
Utf8Value(v8::Handle<v8::Value> obj)6734 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
6735 : str_(NULL), length_(0) {
6736 i::Isolate* isolate = i::Isolate::Current();
6737 if (obj.IsEmpty()) return;
6738 ENTER_V8(isolate);
6739 i::HandleScope scope(isolate);
6740 TryCatch try_catch;
6741 Handle<String> str = obj->ToString();
6742 if (str.IsEmpty()) return;
6743 i::Handle<i::String> i_str = Utils::OpenHandle(*str);
6744 length_ = v8::Utf8Length(*i_str, isolate);
6745 str_ = i::NewArray<char>(length_ + 1);
6746 str->WriteUtf8(str_);
6747 }
6748
6749
~Utf8Value()6750 String::Utf8Value::~Utf8Value() {
6751 i::DeleteArray(str_);
6752 }
6753
6754
Value(v8::Handle<v8::Value> obj)6755 String::Value::Value(v8::Handle<v8::Value> obj)
6756 : str_(NULL), length_(0) {
6757 i::Isolate* isolate = i::Isolate::Current();
6758 if (obj.IsEmpty()) return;
6759 ENTER_V8(isolate);
6760 i::HandleScope scope(isolate);
6761 TryCatch try_catch;
6762 Handle<String> str = obj->ToString();
6763 if (str.IsEmpty()) return;
6764 length_ = str->Length();
6765 str_ = i::NewArray<uint16_t>(length_ + 1);
6766 str->Write(str_);
6767 }
6768
6769
~Value()6770 String::Value::~Value() {
6771 i::DeleteArray(str_);
6772 }
6773
6774
RangeError(v8::Handle<v8::String> raw_message)6775 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
6776 i::Isolate* isolate = i::Isolate::Current();
6777 LOG_API(isolate, "RangeError");
6778 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
6779 ENTER_V8(isolate);
6780 i::Object* error;
6781 {
6782 i::HandleScope scope(isolate);
6783 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6784 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
6785 error = *result;
6786 }
6787 i::Handle<i::Object> result(error, isolate);
6788 return Utils::ToLocal(result);
6789 }
6790
6791
ReferenceError(v8::Handle<v8::String> raw_message)6792 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
6793 i::Isolate* isolate = i::Isolate::Current();
6794 LOG_API(isolate, "ReferenceError");
6795 ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
6796 ENTER_V8(isolate);
6797 i::Object* error;
6798 {
6799 i::HandleScope scope(isolate);
6800 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6801 i::Handle<i::Object> result =
6802 isolate->factory()->NewReferenceError(message);
6803 error = *result;
6804 }
6805 i::Handle<i::Object> result(error, isolate);
6806 return Utils::ToLocal(result);
6807 }
6808
6809
SyntaxError(v8::Handle<v8::String> raw_message)6810 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
6811 i::Isolate* isolate = i::Isolate::Current();
6812 LOG_API(isolate, "SyntaxError");
6813 ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
6814 ENTER_V8(isolate);
6815 i::Object* error;
6816 {
6817 i::HandleScope scope(isolate);
6818 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6819 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
6820 error = *result;
6821 }
6822 i::Handle<i::Object> result(error, isolate);
6823 return Utils::ToLocal(result);
6824 }
6825
6826
TypeError(v8::Handle<v8::String> raw_message)6827 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
6828 i::Isolate* isolate = i::Isolate::Current();
6829 LOG_API(isolate, "TypeError");
6830 ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
6831 ENTER_V8(isolate);
6832 i::Object* error;
6833 {
6834 i::HandleScope scope(isolate);
6835 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6836 i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
6837 error = *result;
6838 }
6839 i::Handle<i::Object> result(error, isolate);
6840 return Utils::ToLocal(result);
6841 }
6842
6843
Error(v8::Handle<v8::String> raw_message)6844 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
6845 i::Isolate* isolate = i::Isolate::Current();
6846 LOG_API(isolate, "Error");
6847 ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
6848 ENTER_V8(isolate);
6849 i::Object* error;
6850 {
6851 i::HandleScope scope(isolate);
6852 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6853 i::Handle<i::Object> result = isolate->factory()->NewError(message);
6854 error = *result;
6855 }
6856 i::Handle<i::Object> result(error, isolate);
6857 return Utils::ToLocal(result);
6858 }
6859
6860
6861 // --- D e b u g S u p p o r t ---
6862
SetDebugEventListener(EventCallback that,Handle<Value> data)6863 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
6864 i::Isolate* isolate = i::Isolate::Current();
6865 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
6866 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
6867 ENTER_V8(isolate);
6868 i::HandleScope scope(isolate);
6869 i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
6870 if (that != NULL) {
6871 foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
6872 }
6873 isolate->debug()->SetEventListener(foreign,
6874 Utils::OpenHandle(*data, true));
6875 return true;
6876 }
6877
6878
DebugBreak(Isolate * isolate)6879 void Debug::DebugBreak(Isolate* isolate) {
6880 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
6881 }
6882
6883
CancelDebugBreak(Isolate * isolate)6884 void Debug::CancelDebugBreak(Isolate* isolate) {
6885 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6886 internal_isolate->stack_guard()->ClearDebugBreak();
6887 }
6888
6889
DebugBreakForCommand(Isolate * isolate,ClientData * data)6890 void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
6891 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6892 internal_isolate->debug()->EnqueueDebugCommand(data);
6893 }
6894
6895
SetMessageHandler(v8::Debug::MessageHandler handler)6896 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
6897 i::Isolate* isolate = i::Isolate::Current();
6898 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
6899 ENTER_V8(isolate);
6900 isolate->debug()->SetMessageHandler(handler);
6901 }
6902
6903
SendCommand(Isolate * isolate,const uint16_t * command,int length,ClientData * client_data)6904 void Debug::SendCommand(Isolate* isolate,
6905 const uint16_t* command,
6906 int length,
6907 ClientData* client_data) {
6908 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6909 internal_isolate->debug()->EnqueueCommandMessage(
6910 i::Vector<const uint16_t>(command, length), client_data);
6911 }
6912
6913
Call(v8::Handle<v8::Function> fun,v8::Handle<v8::Value> data)6914 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
6915 v8::Handle<v8::Value> data) {
6916 i::Isolate* isolate = i::Isolate::Current();
6917 if (!isolate->IsInitialized()) return Local<Value>();
6918 ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
6919 ENTER_V8(isolate);
6920 i::MaybeHandle<i::Object> maybe_result;
6921 EXCEPTION_PREAMBLE(isolate);
6922 if (data.IsEmpty()) {
6923 maybe_result = isolate->debug()->Call(
6924 Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
6925 } else {
6926 maybe_result = isolate->debug()->Call(
6927 Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
6928 }
6929 i::Handle<i::Object> result;
6930 has_pending_exception = !maybe_result.ToHandle(&result);
6931 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6932 return Utils::ToLocal(result);
6933 }
6934
6935
GetMirror(v8::Handle<v8::Value> obj)6936 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
6937 i::Isolate* isolate = i::Isolate::Current();
6938 if (!isolate->IsInitialized()) return Local<Value>();
6939 ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
6940 ENTER_V8(isolate);
6941 v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
6942 i::Debug* isolate_debug = isolate->debug();
6943 EXCEPTION_PREAMBLE(isolate);
6944 has_pending_exception = !isolate_debug->Load();
6945 v8::Local<v8::Value> result;
6946 if (!has_pending_exception) {
6947 i::Handle<i::JSObject> debug(
6948 isolate_debug->debug_context()->global_object());
6949 i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
6950 STATIC_ASCII_VECTOR("MakeMirror"));
6951 i::Handle<i::Object> fun_obj =
6952 i::Object::GetProperty(debug, name).ToHandleChecked();
6953 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
6954 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
6955 const int kArgc = 1;
6956 v8::Handle<v8::Value> argv[kArgc] = { obj };
6957 result = v8_fun->Call(Utils::ToLocal(debug), kArgc, argv);
6958 has_pending_exception = result.IsEmpty();
6959 }
6960 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6961 return scope.Escape(result);
6962 }
6963
6964
ProcessDebugMessages()6965 void Debug::ProcessDebugMessages() {
6966 i::Isolate::Current()->debug()->ProcessDebugMessages(true);
6967 }
6968
6969
GetDebugContext()6970 Local<Context> Debug::GetDebugContext() {
6971 i::Isolate* isolate = i::Isolate::Current();
6972 EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
6973 ENTER_V8(isolate);
6974 return Utils::ToLocal(i::Isolate::Current()->debug()->GetDebugContext());
6975 }
6976
6977
SetLiveEditEnabled(Isolate * isolate,bool enable)6978 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
6979 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6980 internal_isolate->debug()->set_live_edit_enabled(enable);
6981 }
6982
6983
GetFunctionName() const6984 Handle<String> CpuProfileNode::GetFunctionName() const {
6985 i::Isolate* isolate = i::Isolate::Current();
6986 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6987 const i::CodeEntry* entry = node->entry();
6988 i::Handle<i::String> name =
6989 isolate->factory()->InternalizeUtf8String(entry->name());
6990 if (!entry->has_name_prefix()) {
6991 return ToApiHandle<String>(name);
6992 } else {
6993 // We do not expect this to fail. Change this if it does.
6994 i::Handle<i::String> cons = isolate->factory()->NewConsString(
6995 isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
6996 name).ToHandleChecked();
6997 return ToApiHandle<String>(cons);
6998 }
6999 }
7000
7001
GetScriptId() const7002 int CpuProfileNode::GetScriptId() const {
7003 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7004 const i::CodeEntry* entry = node->entry();
7005 return entry->script_id();
7006 }
7007
7008
GetScriptResourceName() const7009 Handle<String> CpuProfileNode::GetScriptResourceName() const {
7010 i::Isolate* isolate = i::Isolate::Current();
7011 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7012 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7013 node->entry()->resource_name()));
7014 }
7015
7016
GetLineNumber() const7017 int CpuProfileNode::GetLineNumber() const {
7018 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
7019 }
7020
7021
GetColumnNumber() const7022 int CpuProfileNode::GetColumnNumber() const {
7023 return reinterpret_cast<const i::ProfileNode*>(this)->
7024 entry()->column_number();
7025 }
7026
7027
GetBailoutReason() const7028 const char* CpuProfileNode::GetBailoutReason() const {
7029 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7030 return node->entry()->bailout_reason();
7031 }
7032
7033
GetHitCount() const7034 unsigned CpuProfileNode::GetHitCount() const {
7035 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
7036 }
7037
7038
GetCallUid() const7039 unsigned CpuProfileNode::GetCallUid() const {
7040 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
7041 }
7042
7043
GetNodeId() const7044 unsigned CpuProfileNode::GetNodeId() const {
7045 return reinterpret_cast<const i::ProfileNode*>(this)->id();
7046 }
7047
7048
GetChildrenCount() const7049 int CpuProfileNode::GetChildrenCount() const {
7050 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
7051 }
7052
7053
GetChild(int index) const7054 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
7055 const i::ProfileNode* child =
7056 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
7057 return reinterpret_cast<const CpuProfileNode*>(child);
7058 }
7059
7060
Delete()7061 void CpuProfile::Delete() {
7062 i::Isolate* isolate = i::Isolate::Current();
7063 i::CpuProfiler* profiler = isolate->cpu_profiler();
7064 ASSERT(profiler != NULL);
7065 profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
7066 }
7067
7068
GetTitle() const7069 Handle<String> CpuProfile::GetTitle() const {
7070 i::Isolate* isolate = i::Isolate::Current();
7071 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7072 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7073 profile->title()));
7074 }
7075
7076
GetTopDownRoot() const7077 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
7078 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7079 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
7080 }
7081
7082
GetSample(int index) const7083 const CpuProfileNode* CpuProfile::GetSample(int index) const {
7084 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7085 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
7086 }
7087
7088
GetSampleTimestamp(int index) const7089 int64_t CpuProfile::GetSampleTimestamp(int index) const {
7090 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7091 return (profile->sample_timestamp(index) - i::TimeTicks()).InMicroseconds();
7092 }
7093
7094
GetStartTime() const7095 int64_t CpuProfile::GetStartTime() const {
7096 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7097 return (profile->start_time() - i::TimeTicks()).InMicroseconds();
7098 }
7099
7100
GetEndTime() const7101 int64_t CpuProfile::GetEndTime() const {
7102 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7103 return (profile->end_time() - i::TimeTicks()).InMicroseconds();
7104 }
7105
7106
GetSamplesCount() const7107 int CpuProfile::GetSamplesCount() const {
7108 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
7109 }
7110
7111
SetSamplingInterval(int us)7112 void CpuProfiler::SetSamplingInterval(int us) {
7113 ASSERT(us >= 0);
7114 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
7115 i::TimeDelta::FromMicroseconds(us));
7116 }
7117
7118
StartProfiling(Handle<String> title,bool record_samples)7119 void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
7120 reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
7121 *Utils::OpenHandle(*title), record_samples);
7122 }
7123
7124
StartCpuProfiling(Handle<String> title,bool record_samples)7125 void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
7126 StartProfiling(title, record_samples);
7127 }
7128
7129
StopProfiling(Handle<String> title)7130 CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
7131 return reinterpret_cast<CpuProfile*>(
7132 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
7133 *Utils::OpenHandle(*title)));
7134 }
7135
7136
StopCpuProfiling(Handle<String> title)7137 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
7138 return StopProfiling(title);
7139 }
7140
7141
SetIdle(bool is_idle)7142 void CpuProfiler::SetIdle(bool is_idle) {
7143 i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
7144 i::StateTag state = isolate->current_vm_state();
7145 ASSERT(state == i::EXTERNAL || state == i::IDLE);
7146 if (isolate->js_entry_sp() != NULL) return;
7147 if (is_idle) {
7148 isolate->set_current_vm_state(i::IDLE);
7149 } else if (state == i::IDLE) {
7150 isolate->set_current_vm_state(i::EXTERNAL);
7151 }
7152 }
7153
7154
ToInternal(const HeapGraphEdge * edge)7155 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
7156 return const_cast<i::HeapGraphEdge*>(
7157 reinterpret_cast<const i::HeapGraphEdge*>(edge));
7158 }
7159
7160
GetType() const7161 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
7162 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
7163 }
7164
7165
GetName() const7166 Handle<Value> HeapGraphEdge::GetName() const {
7167 i::Isolate* isolate = i::Isolate::Current();
7168 i::HeapGraphEdge* edge = ToInternal(this);
7169 switch (edge->type()) {
7170 case i::HeapGraphEdge::kContextVariable:
7171 case i::HeapGraphEdge::kInternal:
7172 case i::HeapGraphEdge::kProperty:
7173 case i::HeapGraphEdge::kShortcut:
7174 case i::HeapGraphEdge::kWeak:
7175 return ToApiHandle<String>(
7176 isolate->factory()->InternalizeUtf8String(edge->name()));
7177 case i::HeapGraphEdge::kElement:
7178 case i::HeapGraphEdge::kHidden:
7179 return ToApiHandle<Number>(
7180 isolate->factory()->NewNumberFromInt(edge->index()));
7181 default: UNREACHABLE();
7182 }
7183 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
7184 }
7185
7186
GetFromNode() const7187 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
7188 const i::HeapEntry* from = ToInternal(this)->from();
7189 return reinterpret_cast<const HeapGraphNode*>(from);
7190 }
7191
7192
GetToNode() const7193 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
7194 const i::HeapEntry* to = ToInternal(this)->to();
7195 return reinterpret_cast<const HeapGraphNode*>(to);
7196 }
7197
7198
ToInternal(const HeapGraphNode * entry)7199 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
7200 return const_cast<i::HeapEntry*>(
7201 reinterpret_cast<const i::HeapEntry*>(entry));
7202 }
7203
7204
GetType() const7205 HeapGraphNode::Type HeapGraphNode::GetType() const {
7206 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
7207 }
7208
7209
GetName() const7210 Handle<String> HeapGraphNode::GetName() const {
7211 i::Isolate* isolate = i::Isolate::Current();
7212 return ToApiHandle<String>(
7213 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
7214 }
7215
7216
GetId() const7217 SnapshotObjectId HeapGraphNode::GetId() const {
7218 return ToInternal(this)->id();
7219 }
7220
7221
GetSelfSize() const7222 int HeapGraphNode::GetSelfSize() const {
7223 size_t size = ToInternal(this)->self_size();
7224 CHECK(size <= static_cast<size_t>(internal::kMaxInt));
7225 return static_cast<int>(size);
7226 }
7227
7228
GetShallowSize() const7229 size_t HeapGraphNode::GetShallowSize() const {
7230 return ToInternal(this)->self_size();
7231 }
7232
7233
GetChildrenCount() const7234 int HeapGraphNode::GetChildrenCount() const {
7235 return ToInternal(this)->children().length();
7236 }
7237
7238
GetChild(int index) const7239 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
7240 return reinterpret_cast<const HeapGraphEdge*>(
7241 ToInternal(this)->children()[index]);
7242 }
7243
7244
ToInternal(const HeapSnapshot * snapshot)7245 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
7246 return const_cast<i::HeapSnapshot*>(
7247 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
7248 }
7249
7250
Delete()7251 void HeapSnapshot::Delete() {
7252 i::Isolate* isolate = i::Isolate::Current();
7253 if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
7254 ToInternal(this)->Delete();
7255 } else {
7256 // If this is the last snapshot, clean up all accessory data as well.
7257 isolate->heap_profiler()->DeleteAllSnapshots();
7258 }
7259 }
7260
7261
GetUid() const7262 unsigned HeapSnapshot::GetUid() const {
7263 return ToInternal(this)->uid();
7264 }
7265
7266
GetTitle() const7267 Handle<String> HeapSnapshot::GetTitle() const {
7268 i::Isolate* isolate = i::Isolate::Current();
7269 return ToApiHandle<String>(
7270 isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
7271 }
7272
7273
GetRoot() const7274 const HeapGraphNode* HeapSnapshot::GetRoot() const {
7275 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
7276 }
7277
7278
GetNodeById(SnapshotObjectId id) const7279 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
7280 return reinterpret_cast<const HeapGraphNode*>(
7281 ToInternal(this)->GetEntryById(id));
7282 }
7283
7284
GetNodesCount() const7285 int HeapSnapshot::GetNodesCount() const {
7286 return ToInternal(this)->entries().length();
7287 }
7288
7289
GetNode(int index) const7290 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
7291 return reinterpret_cast<const HeapGraphNode*>(
7292 &ToInternal(this)->entries().at(index));
7293 }
7294
7295
GetMaxSnapshotJSObjectId() const7296 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
7297 return ToInternal(this)->max_snapshot_js_object_id();
7298 }
7299
7300
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const7301 void HeapSnapshot::Serialize(OutputStream* stream,
7302 HeapSnapshot::SerializationFormat format) const {
7303 Utils::ApiCheck(format == kJSON,
7304 "v8::HeapSnapshot::Serialize",
7305 "Unknown serialization format");
7306 Utils::ApiCheck(stream->GetChunkSize() > 0,
7307 "v8::HeapSnapshot::Serialize",
7308 "Invalid stream chunk size");
7309 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
7310 serializer.Serialize(stream);
7311 }
7312
7313
GetSnapshotCount()7314 int HeapProfiler::GetSnapshotCount() {
7315 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
7316 }
7317
7318
GetHeapSnapshot(int index)7319 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
7320 return reinterpret_cast<const HeapSnapshot*>(
7321 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
7322 }
7323
7324
GetObjectId(Handle<Value> value)7325 SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
7326 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
7327 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
7328 }
7329
7330
FindObjectById(SnapshotObjectId id)7331 Handle<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
7332 i::Handle<i::Object> obj =
7333 reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
7334 if (obj.is_null()) return Local<Value>();
7335 return Utils::ToLocal(obj);
7336 }
7337
7338
ClearObjectIds()7339 void HeapProfiler::ClearObjectIds() {
7340 reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
7341 }
7342
7343
TakeHeapSnapshot(Handle<String> title,ActivityControl * control,ObjectNameResolver * resolver)7344 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
7345 Handle<String> title,
7346 ActivityControl* control,
7347 ObjectNameResolver* resolver) {
7348 return reinterpret_cast<const HeapSnapshot*>(
7349 reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
7350 *Utils::OpenHandle(*title), control, resolver));
7351 }
7352
7353
StartTrackingHeapObjects(bool track_allocations)7354 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
7355 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
7356 track_allocations);
7357 }
7358
7359
StopTrackingHeapObjects()7360 void HeapProfiler::StopTrackingHeapObjects() {
7361 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
7362 }
7363
7364
GetHeapStats(OutputStream * stream)7365 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
7366 return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
7367 }
7368
7369
DeleteAllHeapSnapshots()7370 void HeapProfiler::DeleteAllHeapSnapshots() {
7371 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
7372 }
7373
7374
SetWrapperClassInfoProvider(uint16_t class_id,WrapperInfoCallback callback)7375 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
7376 WrapperInfoCallback callback) {
7377 reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
7378 callback);
7379 }
7380
7381
GetProfilerMemorySize()7382 size_t HeapProfiler::GetProfilerMemorySize() {
7383 return reinterpret_cast<i::HeapProfiler*>(this)->
7384 GetMemorySizeUsedByProfiler();
7385 }
7386
7387
SetRetainedObjectInfo(UniqueId id,RetainedObjectInfo * info)7388 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
7389 RetainedObjectInfo* info) {
7390 reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
7391 }
7392
7393
7394 v8::Testing::StressType internal::Testing::stress_type_ =
7395 v8::Testing::kStressTypeOpt;
7396
7397
SetStressRunType(Testing::StressType type)7398 void Testing::SetStressRunType(Testing::StressType type) {
7399 internal::Testing::set_stress_type(type);
7400 }
7401
7402
GetStressRuns()7403 int Testing::GetStressRuns() {
7404 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
7405 #ifdef DEBUG
7406 // In debug mode the code runs much slower so stressing will only make two
7407 // runs.
7408 return 2;
7409 #else
7410 return 5;
7411 #endif
7412 }
7413
7414
SetFlagsFromString(const char * flags)7415 static void SetFlagsFromString(const char* flags) {
7416 V8::SetFlagsFromString(flags, i::StrLength(flags));
7417 }
7418
7419
PrepareStressRun(int run)7420 void Testing::PrepareStressRun(int run) {
7421 static const char* kLazyOptimizations =
7422 "--prepare-always-opt "
7423 "--max-inlined-source-size=999999 "
7424 "--max-inlined-nodes=999999 "
7425 "--max-inlined-nodes-cumulative=999999 "
7426 "--noalways-opt";
7427 static const char* kForcedOptimizations = "--always-opt";
7428
7429 // If deoptimization stressed turn on frequent deoptimization. If no value
7430 // is spefified through --deopt-every-n-times use a default default value.
7431 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
7432 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
7433 internal::FLAG_deopt_every_n_times == 0) {
7434 SetFlagsFromString(kDeoptEvery13Times);
7435 }
7436
7437 #ifdef DEBUG
7438 // As stressing in debug mode only make two runs skip the deopt stressing
7439 // here.
7440 if (run == GetStressRuns() - 1) {
7441 SetFlagsFromString(kForcedOptimizations);
7442 } else {
7443 SetFlagsFromString(kLazyOptimizations);
7444 }
7445 #else
7446 if (run == GetStressRuns() - 1) {
7447 SetFlagsFromString(kForcedOptimizations);
7448 } else if (run != GetStressRuns() - 2) {
7449 SetFlagsFromString(kLazyOptimizations);
7450 }
7451 #endif
7452 }
7453
7454
7455 // TODO(svenpanne) Deprecate this.
DeoptimizeAll()7456 void Testing::DeoptimizeAll() {
7457 i::Isolate* isolate = i::Isolate::Current();
7458 i::HandleScope scope(isolate);
7459 internal::Deoptimizer::DeoptimizeAll(isolate);
7460 }
7461
7462
7463 namespace internal {
7464
7465
FreeThreadResources()7466 void HandleScopeImplementer::FreeThreadResources() {
7467 Free();
7468 }
7469
7470
ArchiveThread(char * storage)7471 char* HandleScopeImplementer::ArchiveThread(char* storage) {
7472 HandleScopeData* current = isolate_->handle_scope_data();
7473 handle_scope_data_ = *current;
7474 MemCopy(storage, this, sizeof(*this));
7475
7476 ResetAfterArchive();
7477 current->Initialize();
7478
7479 return storage + ArchiveSpacePerThread();
7480 }
7481
7482
ArchiveSpacePerThread()7483 int HandleScopeImplementer::ArchiveSpacePerThread() {
7484 return sizeof(HandleScopeImplementer);
7485 }
7486
7487
RestoreThread(char * storage)7488 char* HandleScopeImplementer::RestoreThread(char* storage) {
7489 MemCopy(this, storage, sizeof(*this));
7490 *isolate_->handle_scope_data() = handle_scope_data_;
7491 return storage + ArchiveSpacePerThread();
7492 }
7493
7494
IterateThis(ObjectVisitor * v)7495 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
7496 #ifdef DEBUG
7497 bool found_block_before_deferred = false;
7498 #endif
7499 // Iterate over all handles in the blocks except for the last.
7500 for (int i = blocks()->length() - 2; i >= 0; --i) {
7501 Object** block = blocks()->at(i);
7502 if (last_handle_before_deferred_block_ != NULL &&
7503 (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
7504 (last_handle_before_deferred_block_ >= block)) {
7505 v->VisitPointers(block, last_handle_before_deferred_block_);
7506 ASSERT(!found_block_before_deferred);
7507 #ifdef DEBUG
7508 found_block_before_deferred = true;
7509 #endif
7510 } else {
7511 v->VisitPointers(block, &block[kHandleBlockSize]);
7512 }
7513 }
7514
7515 ASSERT(last_handle_before_deferred_block_ == NULL ||
7516 found_block_before_deferred);
7517
7518 // Iterate over live handles in the last block (if any).
7519 if (!blocks()->is_empty()) {
7520 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
7521 }
7522
7523 List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
7524 for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) {
7525 if (context_lists[i]->is_empty()) continue;
7526 Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
7527 v->VisitPointers(start, start + context_lists[i]->length());
7528 }
7529 }
7530
7531
Iterate(ObjectVisitor * v)7532 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
7533 HandleScopeData* current = isolate_->handle_scope_data();
7534 handle_scope_data_ = *current;
7535 IterateThis(v);
7536 }
7537
7538
Iterate(ObjectVisitor * v,char * storage)7539 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
7540 HandleScopeImplementer* scope_implementer =
7541 reinterpret_cast<HandleScopeImplementer*>(storage);
7542 scope_implementer->IterateThis(v);
7543 return storage + ArchiveSpacePerThread();
7544 }
7545
7546
Detach(Object ** prev_limit)7547 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
7548 DeferredHandles* deferred =
7549 new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
7550
7551 while (!blocks_.is_empty()) {
7552 Object** block_start = blocks_.last();
7553 Object** block_limit = &block_start[kHandleBlockSize];
7554 // We should not need to check for SealHandleScope here. Assert this.
7555 ASSERT(prev_limit == block_limit ||
7556 !(block_start <= prev_limit && prev_limit <= block_limit));
7557 if (prev_limit == block_limit) break;
7558 deferred->blocks_.Add(blocks_.last());
7559 blocks_.RemoveLast();
7560 }
7561
7562 // deferred->blocks_ now contains the blocks installed on the
7563 // HandleScope stack since BeginDeferredScope was called, but in
7564 // reverse order.
7565
7566 ASSERT(prev_limit == NULL || !blocks_.is_empty());
7567
7568 ASSERT(!blocks_.is_empty() && prev_limit != NULL);
7569 ASSERT(last_handle_before_deferred_block_ != NULL);
7570 last_handle_before_deferred_block_ = NULL;
7571 return deferred;
7572 }
7573
7574
BeginDeferredScope()7575 void HandleScopeImplementer::BeginDeferredScope() {
7576 ASSERT(last_handle_before_deferred_block_ == NULL);
7577 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
7578 }
7579
7580
~DeferredHandles()7581 DeferredHandles::~DeferredHandles() {
7582 isolate_->UnlinkDeferredHandles(this);
7583
7584 for (int i = 0; i < blocks_.length(); i++) {
7585 #ifdef ENABLE_HANDLE_ZAPPING
7586 HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
7587 #endif
7588 isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
7589 }
7590 }
7591
7592
Iterate(ObjectVisitor * v)7593 void DeferredHandles::Iterate(ObjectVisitor* v) {
7594 ASSERT(!blocks_.is_empty());
7595
7596 ASSERT((first_block_limit_ >= blocks_.first()) &&
7597 (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
7598
7599 v->VisitPointers(blocks_.first(), first_block_limit_);
7600
7601 for (int i = 1; i < blocks_.length(); i++) {
7602 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
7603 }
7604 }
7605
7606
InvokeAccessorGetterCallback(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info,v8::AccessorGetterCallback getter)7607 void InvokeAccessorGetterCallback(
7608 v8::Local<v8::String> property,
7609 const v8::PropertyCallbackInfo<v8::Value>& info,
7610 v8::AccessorGetterCallback getter) {
7611 // Leaving JavaScript.
7612 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7613 Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
7614 getter));
7615 VMState<EXTERNAL> state(isolate);
7616 ExternalCallbackScope call_scope(isolate, getter_address);
7617 getter(property, info);
7618 }
7619
7620
InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info,v8::FunctionCallback callback)7621 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
7622 v8::FunctionCallback callback) {
7623 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7624 Address callback_address =
7625 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
7626 VMState<EXTERNAL> state(isolate);
7627 ExternalCallbackScope call_scope(isolate, callback_address);
7628 callback(info);
7629 }
7630
7631
7632 } } // namespace v8::internal
7633