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