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.
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/base/platform/platform.h"
17 #include "src/base/platform/time.h"
18 #include "src/base/utils/random-number-generator.h"
19 #include "src/bootstrapper.h"
20 #include "src/code-stubs.h"
21 #include "src/compiler.h"
22 #include "src/conversions-inl.h"
23 #include "src/counters.h"
24 #include "src/cpu-profiler.h"
25 #include "src/debug.h"
26 #include "src/deoptimizer.h"
27 #include "src/execution.h"
28 #include "src/global-handles.h"
29 #include "src/heap-profiler.h"
30 #include "src/heap-snapshot-generator-inl.h"
31 #include "src/icu_util.h"
32 #include "src/json-parser.h"
33 #include "src/messages.h"
34 #include "src/natives.h"
35 #include "src/parser.h"
36 #include "src/profile-generator-inl.h"
37 #include "src/property.h"
38 #include "src/property-details.h"
39 #include "src/prototype.h"
40 #include "src/runtime.h"
41 #include "src/runtime-profiler.h"
42 #include "src/scanner-character-streams.h"
43 #include "src/simulator.h"
44 #include "src/snapshot.h"
45 #include "src/unicode-inl.h"
46 #include "src/v8threads.h"
47 #include "src/version.h"
48 #include "src/vm-state-inl.h"
51 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
53 #define ENTER_V8(isolate) \
54 DCHECK((isolate)->IsInitialized()); \
55 i::VMState<i::OTHER> __state__((isolate))
59 #define ON_BAILOUT(isolate, location, code) \
60 if (IsExecutionTerminatingCheck(isolate)) { \
66 #define EXCEPTION_PREAMBLE(isolate) \
67 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \
68 DCHECK(!(isolate)->external_caught_exception()); \
69 bool has_pending_exception = false
72 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback) \
74 i::HandleScopeImplementer* handle_scope_implementer = \
75 (isolate)->handle_scope_implementer(); \
76 handle_scope_implementer->DecrementCallDepth(); \
77 if (has_pending_exception) { \
78 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \
79 (isolate)->OptionalRescheduleException(call_depth_is_zero); \
87 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value) \
88 EXCEPTION_BAILOUT_CHECK_GENERIC( \
89 isolate, value, isolate->FireCallCompletedCallback();)
92 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \
93 EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
96 // --- E x c e p t i o n B e h a v i o r ---
99 void i::FatalProcessOutOfMemory(const char* location) {
100 i::V8::FatalProcessOutOfMemory(location, false);
104 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
105 // The default fatal error handler is called and execution is stopped.
106 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
107 i::HeapStats heap_stats;
109 heap_stats.start_marker = &start_marker;
111 heap_stats.new_space_size = &new_space_size;
112 int new_space_capacity;
113 heap_stats.new_space_capacity = &new_space_capacity;
114 intptr_t old_pointer_space_size;
115 heap_stats.old_pointer_space_size = &old_pointer_space_size;
116 intptr_t old_pointer_space_capacity;
117 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
118 intptr_t old_data_space_size;
119 heap_stats.old_data_space_size = &old_data_space_size;
120 intptr_t old_data_space_capacity;
121 heap_stats.old_data_space_capacity = &old_data_space_capacity;
122 intptr_t code_space_size;
123 heap_stats.code_space_size = &code_space_size;
124 intptr_t code_space_capacity;
125 heap_stats.code_space_capacity = &code_space_capacity;
126 intptr_t map_space_size;
127 heap_stats.map_space_size = &map_space_size;
128 intptr_t map_space_capacity;
129 heap_stats.map_space_capacity = &map_space_capacity;
130 intptr_t cell_space_size;
131 heap_stats.cell_space_size = &cell_space_size;
132 intptr_t cell_space_capacity;
133 heap_stats.cell_space_capacity = &cell_space_capacity;
134 intptr_t property_cell_space_size;
135 heap_stats.property_cell_space_size = &property_cell_space_size;
136 intptr_t property_cell_space_capacity;
137 heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
138 intptr_t lo_space_size;
139 heap_stats.lo_space_size = &lo_space_size;
140 int global_handle_count;
141 heap_stats.global_handle_count = &global_handle_count;
142 int weak_global_handle_count;
143 heap_stats.weak_global_handle_count = &weak_global_handle_count;
144 int pending_global_handle_count;
145 heap_stats.pending_global_handle_count = &pending_global_handle_count;
146 int near_death_global_handle_count;
147 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
148 int free_global_handle_count;
149 heap_stats.free_global_handle_count = &free_global_handle_count;
150 intptr_t memory_allocator_size;
151 heap_stats.memory_allocator_size = &memory_allocator_size;
152 intptr_t memory_allocator_capacity;
153 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
154 int objects_per_type[LAST_TYPE + 1] = {0};
155 heap_stats.objects_per_type = objects_per_type;
156 int size_per_type[LAST_TYPE + 1] = {0};
157 heap_stats.size_per_type = size_per_type;
159 heap_stats.os_error = &os_error;
161 heap_stats.end_marker = &end_marker;
162 i::Isolate* isolate = i::Isolate::Current();
163 if (isolate->heap()->HasBeenSetUp()) {
164 // BUG(1718): Don't use the take_snapshot since we don't support
165 // HeapIterator here without doing a special GC.
166 isolate->heap()->RecordStats(&heap_stats, false);
168 Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
169 // If the fatal error handler returns, we stop execution.
170 FATAL("API fatal error handler returned after process out of memory");
174 void Utils::ReportApiFailure(const char* location, const char* message) {
175 i::Isolate* isolate = i::Isolate::Current();
176 FatalErrorCallback callback = isolate->exception_behavior();
177 if (callback == NULL) {
178 base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
182 callback(location, message);
184 isolate->SignalFatalError();
189 i::Isolate* isolate = i::Isolate::Current();
190 return isolate->IsDead();
194 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
195 if (!isolate->IsInitialized()) return false;
196 if (isolate->has_scheduled_exception()) {
197 return isolate->scheduled_exception() ==
198 isolate->heap()->termination_exception();
204 // --- S t a t i c s ---
207 static bool InitializeHelper(i::Isolate* isolate) {
208 // If the isolate has a function entry hook, it needs to re-build all its
209 // code stubs with entry hooks embedded, so let's deserialize a snapshot.
210 if (isolate == NULL || isolate->function_entry_hook() == NULL) {
211 if (i::Snapshot::Initialize())
214 return i::V8::Initialize(NULL);
218 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
219 const char* location) {
220 return (isolate != NULL && isolate->IsInitialized()) ||
221 Utils::ApiCheck(InitializeHelper(isolate),
223 "Error initializing V8");
227 StartupDataDecompressor::StartupDataDecompressor()
228 : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
229 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
235 StartupDataDecompressor::~StartupDataDecompressor() {
236 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
237 i::DeleteArray(raw_data[i]);
239 i::DeleteArray(raw_data);
243 int StartupDataDecompressor::Decompress() {
244 int compressed_data_count = V8::GetCompressedStartupDataCount();
245 StartupData* compressed_data =
246 i::NewArray<StartupData>(compressed_data_count);
247 V8::GetCompressedStartupData(compressed_data);
248 for (int i = 0; i < compressed_data_count; ++i) {
249 char* decompressed = raw_data[i] =
250 i::NewArray<char>(compressed_data[i].raw_size);
251 if (compressed_data[i].compressed_size != 0) {
252 int result = DecompressData(decompressed,
253 &compressed_data[i].raw_size,
254 compressed_data[i].data,
255 compressed_data[i].compressed_size);
256 if (result != 0) return result;
258 DCHECK_EQ(0, compressed_data[i].raw_size);
260 compressed_data[i].data = decompressed;
262 V8::SetDecompressedStartupData(compressed_data);
263 i::DeleteArray(compressed_data);
268 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() {
269 #ifdef COMPRESS_STARTUP_DATA_BZ2
270 return StartupData::kBZip2;
272 return StartupData::kUncompressed;
277 enum CompressedStartupDataItems {
281 kExperimentalLibraries,
282 kCompressedStartupDataCount
286 int V8::GetCompressedStartupDataCount() {
287 #ifdef COMPRESS_STARTUP_DATA_BZ2
288 return kCompressedStartupDataCount;
295 void V8::GetCompressedStartupData(StartupData* compressed_data) {
296 #ifdef COMPRESS_STARTUP_DATA_BZ2
297 compressed_data[kSnapshot].data =
298 reinterpret_cast<const char*>(i::Snapshot::data());
299 compressed_data[kSnapshot].compressed_size = i::Snapshot::size();
300 compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size();
302 compressed_data[kSnapshotContext].data =
303 reinterpret_cast<const char*>(i::Snapshot::context_data());
304 compressed_data[kSnapshotContext].compressed_size =
305 i::Snapshot::context_size();
306 compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size();
308 i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource();
309 compressed_data[kLibraries].data =
310 reinterpret_cast<const char*>(libraries_source.start());
311 compressed_data[kLibraries].compressed_size = libraries_source.length();
312 compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize();
314 i::Vector<const i::byte> exp_libraries_source =
315 i::ExperimentalNatives::GetScriptsSource();
316 compressed_data[kExperimentalLibraries].data =
317 reinterpret_cast<const char*>(exp_libraries_source.start());
318 compressed_data[kExperimentalLibraries].compressed_size =
319 exp_libraries_source.length();
320 compressed_data[kExperimentalLibraries].raw_size =
321 i::ExperimentalNatives::GetRawScriptsSize();
326 void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
327 #ifdef COMPRESS_STARTUP_DATA_BZ2
328 DCHECK_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size);
329 i::Snapshot::set_raw_data(
330 reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data));
332 DCHECK_EQ(i::Snapshot::context_raw_size(),
333 decompressed_data[kSnapshotContext].raw_size);
334 i::Snapshot::set_context_raw_data(
335 reinterpret_cast<const i::byte*>(
336 decompressed_data[kSnapshotContext].data));
338 DCHECK_EQ(i::Natives::GetRawScriptsSize(),
339 decompressed_data[kLibraries].raw_size);
340 i::Vector<const char> libraries_source(
341 decompressed_data[kLibraries].data,
342 decompressed_data[kLibraries].raw_size);
343 i::Natives::SetRawScriptsSource(libraries_source);
345 DCHECK_EQ(i::ExperimentalNatives::GetRawScriptsSize(),
346 decompressed_data[kExperimentalLibraries].raw_size);
347 i::Vector<const char> exp_libraries_source(
348 decompressed_data[kExperimentalLibraries].data,
349 decompressed_data[kExperimentalLibraries].raw_size);
350 i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
355 void V8::SetNativesDataBlob(StartupData* natives_blob) {
356 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
357 i::SetNativesFromFile(natives_blob);
364 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
365 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
366 i::SetSnapshotFromFile(snapshot_blob);
373 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
374 i::Isolate* isolate = i::Isolate::Current();
375 isolate->set_exception_behavior(that);
379 void V8::SetAllowCodeGenerationFromStringsCallback(
380 AllowCodeGenerationFromStringsCallback callback) {
381 i::Isolate* isolate = i::Isolate::Current();
382 isolate->set_allow_code_gen_callback(callback);
386 void V8::SetFlagsFromString(const char* str, int length) {
387 i::FlagList::SetFlagsFromString(str, length);
391 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
392 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
396 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
399 RegisteredExtension::RegisteredExtension(Extension* extension)
400 : extension_(extension) { }
403 void RegisteredExtension::Register(RegisteredExtension* that) {
404 that->next_ = first_extension_;
405 first_extension_ = that;
409 void RegisteredExtension::UnregisterAll() {
410 RegisteredExtension* re = first_extension_;
412 RegisteredExtension* next = re->next();
419 void RegisterExtension(Extension* that) {
420 RegisteredExtension* extension = new RegisteredExtension(that);
421 RegisteredExtension::Register(extension);
425 Extension::Extension(const char* name,
431 source_length_(source_length >= 0 ?
433 (source ? static_cast<int>(strlen(source)) : 0)),
434 source_(source, source_length_),
435 dep_count_(dep_count),
437 auto_enable_(false) {
438 CHECK(source != NULL || source_length_ == 0);
442 ResourceConstraints::ResourceConstraints()
443 : max_semi_space_size_(0),
444 max_old_space_size_(0),
445 max_executable_size_(0),
447 max_available_threads_(0),
448 code_range_size_(0) { }
450 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
451 uint64_t virtual_memory_limit,
452 uint32_t number_of_processors) {
454 // Android has higher physical memory requirements before raising the maximum
455 // heap size limits since it has no swap space.
456 const uint64_t low_limit = 512ul * i::MB;
457 const uint64_t medium_limit = 1ul * i::GB;
458 const uint64_t high_limit = 2ul * i::GB;
460 const uint64_t low_limit = 512ul * i::MB;
461 const uint64_t medium_limit = 768ul * i::MB;
462 const uint64_t high_limit = 1ul * i::GB;
465 if (physical_memory <= low_limit) {
466 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice);
467 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice);
468 set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice);
469 } else if (physical_memory <= medium_limit) {
470 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice);
471 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice);
472 set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice);
473 } else if (physical_memory <= high_limit) {
474 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice);
475 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice);
476 set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice);
478 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice);
479 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice);
480 set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
483 set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
485 if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
486 // Reserve no more than 1/8 of the memory for the code range, but at most
487 // kMaximalCodeRangeSize.
489 i::Min(i::kMaximalCodeRangeSize / i::MB,
490 static_cast<size_t>((virtual_memory_limit >> 3) / i::MB)));
495 bool SetResourceConstraints(Isolate* v8_isolate,
496 ResourceConstraints* constraints) {
497 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
498 int semi_space_size = constraints->max_semi_space_size();
499 int old_space_size = constraints->max_old_space_size();
500 int max_executable_size = constraints->max_executable_size();
501 size_t code_range_size = constraints->code_range_size();
502 if (semi_space_size != 0 || old_space_size != 0 ||
503 max_executable_size != 0 || code_range_size != 0) {
504 // After initialization it's too late to change Heap constraints.
505 DCHECK(!isolate->IsInitialized());
506 bool result = isolate->heap()->ConfigureHeap(semi_space_size,
510 if (!result) return false;
512 if (constraints->stack_limit() != NULL) {
513 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
514 isolate->stack_guard()->SetStackLimit(limit);
517 isolate->set_max_available_threads(constraints->max_available_threads());
522 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
523 LOG_API(isolate, "Persistent::New");
524 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
526 (*obj)->ObjectVerify();
528 return result.location();
532 i::Object** V8::CopyPersistent(i::Object** obj) {
533 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
535 (*obj)->ObjectVerify();
537 return result.location();
541 void V8::MakeWeak(i::Object** object,
543 WeakCallback weak_callback) {
544 i::GlobalHandles::MakeWeak(object, parameters, weak_callback);
548 void* V8::ClearWeak(i::Object** obj) {
549 return i::GlobalHandles::ClearWeakness(obj);
553 void V8::DisposeGlobal(i::Object** obj) {
554 i::GlobalHandles::Destroy(obj);
558 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
559 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
560 i::Object* object = *Utils::OpenHandle(value);
561 isolate->eternal_handles()->Create(isolate, object, index);
565 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
566 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
567 return Utils::ToLocal(isolate->eternal_handles()->Get(index));
571 // --- H a n d l e s ---
574 HandleScope::HandleScope(Isolate* isolate) {
579 void HandleScope::Initialize(Isolate* isolate) {
580 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
581 // We do not want to check the correct usage of the Locker class all over the
582 // place, so we do it only here: Without a HandleScope, an embedder can do
583 // almost nothing, so it is enough to check in this central place.
584 Utils::ApiCheck(!v8::Locker::IsActive() ||
585 internal_isolate->thread_manager()->IsLockedByCurrentThread(),
586 "HandleScope::HandleScope",
587 "Entering the V8 API without proper locking in place");
588 i::HandleScopeData* current = internal_isolate->handle_scope_data();
589 isolate_ = internal_isolate;
590 prev_next_ = current->next;
591 prev_limit_ = current->limit;
596 HandleScope::~HandleScope() {
597 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
601 int HandleScope::NumberOfHandles(Isolate* isolate) {
602 return i::HandleScope::NumberOfHandles(
603 reinterpret_cast<i::Isolate*>(isolate));
607 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
608 return i::HandleScope::CreateHandle(isolate, value);
612 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
614 DCHECK(heap_object->IsHeapObject());
615 return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
619 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
620 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
621 escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
622 Initialize(v8_isolate);
626 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
627 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
628 Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(),
629 "EscapeableHandleScope::Escape",
630 "Escape value set twice");
631 if (escape_value == NULL) {
632 *escape_slot_ = heap->undefined_value();
635 *escape_slot_ = *escape_value;
640 void Context::Enter() {
641 i::Handle<i::Context> env = Utils::OpenHandle(this);
642 i::Isolate* isolate = env->GetIsolate();
644 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
645 impl->EnterContext(env);
646 impl->SaveContext(isolate->context());
647 isolate->set_context(*env);
651 void Context::Exit() {
652 i::Handle<i::Context> env = Utils::OpenHandle(this);
653 i::Isolate* isolate = env->GetIsolate();
655 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
656 if (!Utils::ApiCheck(impl->LastEnteredContextWas(env),
657 "v8::Context::Exit()",
658 "Cannot exit non-entered context")) {
661 impl->LeaveContext();
662 isolate->set_context(impl->RestoreContext());
666 static void* DecodeSmiToAligned(i::Object* value, const char* location) {
667 Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
668 return reinterpret_cast<void*>(value);
672 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
673 i::Smi* smi = reinterpret_cast<i::Smi*>(value);
674 Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
679 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
682 const char* location) {
683 i::Handle<i::Context> env = Utils::OpenHandle(context);
685 Utils::ApiCheck(env->IsNativeContext(),
687 "Not a native context") &&
688 Utils::ApiCheck(index >= 0, location, "Negative index");
689 if (!ok) return i::Handle<i::FixedArray>();
690 i::Handle<i::FixedArray> data(env->embedder_data());
691 if (index < data->length()) return data;
692 if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
693 return i::Handle<i::FixedArray>();
695 int new_size = i::Max(index, data->length() << 1) + 1;
696 data = i::FixedArray::CopySize(data, new_size);
697 env->set_embedder_data(*data);
702 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
703 const char* location = "v8::Context::GetEmbedderData()";
704 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
705 if (data.is_null()) return Local<Value>();
706 i::Handle<i::Object> result(data->get(index), data->GetIsolate());
707 return Utils::ToLocal(result);
711 void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
712 const char* location = "v8::Context::SetEmbedderData()";
713 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
714 if (data.is_null()) return;
715 i::Handle<i::Object> val = Utils::OpenHandle(*value);
716 data->set(index, *val);
717 DCHECK_EQ(*Utils::OpenHandle(*value),
718 *Utils::OpenHandle(*GetEmbedderData(index)));
722 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
723 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
724 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
725 if (data.is_null()) return NULL;
726 return DecodeSmiToAligned(data->get(index), location);
730 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
731 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
732 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
733 data->set(index, EncodeAlignedAsSmi(value, location));
734 DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
738 // --- N e a n d e r ---
741 // A constructor cannot easily return an error value, therefore it is necessary
742 // to check for a dead VM with ON_BAILOUT before constructing any Neander
743 // objects. To remind you about this there is no HandleScope in the
744 // NeanderObject constructor. When you add one to the site calling the
745 // constructor you should check that you ensured the VM was not dead first.
746 NeanderObject::NeanderObject(v8::internal::Isolate* isolate, int size) {
747 EnsureInitializedForIsolate(isolate, "v8::Nowhere");
749 value_ = isolate->factory()->NewNeanderObject();
750 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
751 value_->set_elements(*elements);
755 int NeanderObject::size() {
756 return i::FixedArray::cast(value_->elements())->length();
760 NeanderArray::NeanderArray(v8::internal::Isolate* isolate) : obj_(isolate, 2) {
761 obj_.set(0, i::Smi::FromInt(0));
765 int NeanderArray::length() {
766 return i::Smi::cast(obj_.get(0))->value();
770 i::Object* NeanderArray::get(int offset) {
772 DCHECK(offset < length());
773 return obj_.get(offset + 1);
777 // This method cannot easily return an error value, therefore it is necessary
778 // to check for a dead VM with ON_BAILOUT before calling it. To remind you
779 // about this there is no HandleScope in this method. When you add one to the
780 // site calling this method you should check that you ensured the VM was not
782 void NeanderArray::add(i::Handle<i::Object> value) {
783 int length = this->length();
784 int size = obj_.size();
785 if (length == size - 1) {
786 i::Factory* factory = i::Isolate::Current()->factory();
787 i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size);
788 for (int i = 0; i < length; i++)
789 new_elms->set(i + 1, get(i));
790 obj_.value()->set_elements(*new_elms);
792 obj_.set(length + 1, *value);
793 obj_.set(0, i::Smi::FromInt(length + 1));
797 void NeanderArray::set(int index, i::Object* value) {
798 if (index < 0 || index >= this->length()) return;
799 obj_.set(index + 1, value);
803 // --- T e m p l a t e ---
806 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
807 that->set_tag(i::Smi::FromInt(type));
811 static void TemplateSet(i::Isolate* isolate,
814 v8::Handle<v8::Data>* data) {
815 i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
816 if (list->IsUndefined()) {
817 list = NeanderArray(isolate).value();
818 Utils::OpenHandle(templ)->set_property_list(*list);
820 NeanderArray array(list);
821 array.add(isolate->factory()->NewNumberFromInt(length));
822 for (int i = 0; i < length; i++) {
823 i::Handle<i::Object> value = data[i].IsEmpty() ?
824 i::Handle<i::Object>(isolate->factory()->undefined_value()) :
825 Utils::OpenHandle(*data[i]);
831 void Template::Set(v8::Handle<String> name,
832 v8::Handle<Data> value,
833 v8::PropertyAttribute attribute) {
834 i::Isolate* isolate = i::Isolate::Current();
836 i::HandleScope scope(isolate);
838 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
839 v8::Handle<v8::Data> data[kSize] = {
842 v8::Integer::New(v8_isolate, attribute)};
843 TemplateSet(isolate, this, kSize, data);
847 void Template::SetAccessorProperty(
848 v8::Local<v8::String> name,
849 v8::Local<FunctionTemplate> getter,
850 v8::Local<FunctionTemplate> setter,
851 v8::PropertyAttribute attribute,
852 v8::AccessControl access_control) {
853 // TODO(verwaest): Remove |access_control|.
854 DCHECK_EQ(v8::DEFAULT, access_control);
855 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
857 DCHECK(!name.IsEmpty());
858 DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
859 i::HandleScope scope(isolate);
861 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
862 v8::Handle<v8::Data> data[kSize] = {
866 v8::Integer::New(v8_isolate, attribute)};
867 TemplateSet(isolate, this, kSize, data);
871 // --- F u n c t i o n T e m p l a t e ---
872 static void InitializeFunctionTemplate(
873 i::Handle<i::FunctionTemplateInfo> info) {
874 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
879 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
880 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
882 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
884 if (result->IsUndefined()) {
885 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(i_isolate);
886 result = Utils::OpenHandle(*ObjectTemplate::New(isolate));
887 Utils::OpenHandle(this)->set_prototype_template(*result);
889 return ToApiHandle<ObjectTemplate>(result);
893 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
894 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
896 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
900 static Local<FunctionTemplate> FunctionTemplateNew(
902 FunctionCallback callback,
903 v8::Handle<Value> data,
904 v8::Handle<Signature> signature,
907 i::Handle<i::Struct> struct_obj =
908 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
909 i::Handle<i::FunctionTemplateInfo> obj =
910 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
911 InitializeFunctionTemplate(obj);
912 obj->set_do_not_cache(do_not_cache);
913 int next_serial_number = 0;
915 next_serial_number = isolate->next_serial_number() + 1;
916 isolate->set_next_serial_number(next_serial_number);
918 obj->set_serial_number(i::Smi::FromInt(next_serial_number));
920 if (data.IsEmpty()) {
921 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
923 Utils::ToLocal(obj)->SetCallHandler(callback, data);
925 obj->set_length(length);
926 obj->set_undetectable(false);
927 obj->set_needs_access_check(false);
928 if (!signature.IsEmpty())
929 obj->set_signature(*Utils::OpenHandle(*signature));
930 return Utils::ToLocal(obj);
933 Local<FunctionTemplate> FunctionTemplate::New(
935 FunctionCallback callback,
936 v8::Handle<Value> data,
937 v8::Handle<Signature> signature,
939 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
940 EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()");
941 LOG_API(i_isolate, "FunctionTemplate::New");
943 return FunctionTemplateNew(
944 i_isolate, callback, data, signature, length, false);
948 Local<Signature> Signature::New(Isolate* isolate,
949 Handle<FunctionTemplate> receiver, int argc,
950 Handle<FunctionTemplate> argv[]) {
951 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
952 EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()");
953 LOG_API(i_isolate, "Signature::New");
955 i::Handle<i::Struct> struct_obj =
956 i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
957 i::Handle<i::SignatureInfo> obj =
958 i::Handle<i::SignatureInfo>::cast(struct_obj);
959 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
961 i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
962 for (int i = 0; i < argc; i++) {
963 if (!argv[i].IsEmpty())
964 args->set(i, *Utils::OpenHandle(*argv[i]));
966 obj->set_args(*args);
968 return Utils::ToLocal(obj);
972 Local<AccessorSignature> AccessorSignature::New(
974 Handle<FunctionTemplate> receiver) {
975 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
979 template<typename Operation>
980 static Local<Operation> NewDescriptor(
982 const i::DeclaredAccessorDescriptorData& data,
983 Data* previous_descriptor) {
984 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
985 i::Handle<i::DeclaredAccessorDescriptor> previous =
986 i::Handle<i::DeclaredAccessorDescriptor>();
987 if (previous_descriptor != NULL) {
988 previous = Utils::OpenHandle(
989 static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
991 i::Handle<i::DeclaredAccessorDescriptor> descriptor =
992 i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
993 return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
997 Local<RawOperationDescriptor>
998 ObjectOperationDescriptor::NewInternalFieldDereference(
1000 int internal_field) {
1001 i::DeclaredAccessorDescriptorData data;
1002 data.type = i::kDescriptorObjectDereference;
1003 data.object_dereference_descriptor.internal_field = internal_field;
1004 return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
1008 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
1010 int16_t byte_offset) {
1011 i::DeclaredAccessorDescriptorData data;
1012 data.type = i::kDescriptorPointerShift;
1013 data.pointer_shift_descriptor.byte_offset = byte_offset;
1014 return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1018 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
1020 i::DeclaredAccessorDescriptorData data;
1021 data.type = i::kDescriptorReturnObject;
1022 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1026 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
1028 i::DeclaredAccessorDescriptorData data;
1029 data.type = i::kDescriptorPointerDereference;
1030 return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1034 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
1036 void* compare_value) {
1037 i::DeclaredAccessorDescriptorData data;
1038 data.type = i::kDescriptorPointerCompare;
1039 data.pointer_compare_descriptor.compare_value = compare_value;
1040 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1044 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
1046 DeclaredAccessorDescriptorDataType data_type,
1047 uint8_t bool_offset) {
1048 i::DeclaredAccessorDescriptorData data;
1049 data.type = i::kDescriptorPrimitiveValue;
1050 data.primitive_value_descriptor.data_type = data_type;
1051 data.primitive_value_descriptor.bool_offset = bool_offset;
1052 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1056 template<typename T>
1057 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
1061 RawOperationDescriptor* operation) {
1062 i::DeclaredAccessorDescriptorData data;
1063 data.type = i::kDescriptorBitmaskCompare;
1064 data.bitmask_compare_descriptor.bitmask = bitmask;
1065 data.bitmask_compare_descriptor.compare_value = compare_value;
1066 data.bitmask_compare_descriptor.size = sizeof(T);
1067 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
1071 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
1074 uint8_t compare_value) {
1075 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1079 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
1082 uint16_t compare_value) {
1083 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1087 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
1090 uint32_t compare_value) {
1091 return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1095 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
1096 Handle<FunctionTemplate> types[1] = { type };
1097 return TypeSwitch::New(1, types);
1101 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
1102 i::Isolate* isolate = i::Isolate::Current();
1103 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
1104 LOG_API(isolate, "TypeSwitch::New");
1106 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
1107 for (int i = 0; i < argc; i++)
1108 vector->set(i, *Utils::OpenHandle(*types[i]));
1109 i::Handle<i::Struct> struct_obj =
1110 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
1111 i::Handle<i::TypeSwitchInfo> obj =
1112 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
1113 obj->set_types(*vector);
1114 return Utils::ToLocal(obj);
1118 int TypeSwitch::match(v8::Handle<Value> value) {
1119 i::Isolate* isolate = i::Isolate::Current();
1120 LOG_API(isolate, "TypeSwitch::match");
1122 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
1123 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
1124 i::FixedArray* types = i::FixedArray::cast(info->types());
1125 for (int i = 0; i < types->length(); i++) {
1126 if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj))
1133 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
1134 i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
1135 (obj)->setter(*foreign); \
1139 void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1140 v8::Handle<Value> data) {
1141 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1143 i::HandleScope scope(isolate);
1144 i::Handle<i::Struct> struct_obj =
1145 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1146 i::Handle<i::CallHandlerInfo> obj =
1147 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1148 SET_FIELD_WRAPPED(obj, set_callback, callback);
1149 if (data.IsEmpty()) {
1150 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1152 obj->set_data(*Utils::OpenHandle(*data));
1153 Utils::OpenHandle(this)->set_call_code(*obj);
1157 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
1158 i::Handle<i::AccessorInfo> obj,
1159 v8::Handle<String> name,
1160 v8::AccessControl settings,
1161 v8::PropertyAttribute attributes,
1162 v8::Handle<AccessorSignature> signature) {
1163 obj->set_name(*Utils::OpenHandle(*name));
1164 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1165 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1166 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
1167 if (!signature.IsEmpty()) {
1168 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1174 template<typename Getter, typename Setter>
1175 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1176 v8::Handle<String> name,
1179 v8::Handle<Value> data,
1180 v8::AccessControl settings,
1181 v8::PropertyAttribute attributes,
1182 v8::Handle<AccessorSignature> signature) {
1183 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1184 i::Handle<i::ExecutableAccessorInfo> obj =
1185 isolate->factory()->NewExecutableAccessorInfo();
1186 SET_FIELD_WRAPPED(obj, set_getter, getter);
1187 SET_FIELD_WRAPPED(obj, set_setter, setter);
1188 if (data.IsEmpty()) {
1189 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1191 obj->set_data(*Utils::OpenHandle(*data));
1192 return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1196 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1197 v8::Handle<String> name,
1198 v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
1199 void* setter_ignored,
1201 v8::AccessControl settings,
1202 v8::PropertyAttribute attributes,
1203 v8::Handle<AccessorSignature> signature) {
1204 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1205 if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
1206 i::Handle<i::DeclaredAccessorInfo> obj =
1207 isolate->factory()->NewDeclaredAccessorInfo();
1208 obj->set_descriptor(*Utils::OpenHandle(*descriptor));
1209 return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1213 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1214 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1215 if (!Utils::ApiCheck(!handle.is_null(),
1216 "v8::FunctionTemplate::InstanceTemplate()",
1217 "Reading from empty handle")) {
1218 return Local<ObjectTemplate>();
1220 i::Isolate* isolate = handle->GetIsolate();
1222 if (handle->instance_template()->IsUndefined()) {
1223 Local<ObjectTemplate> templ =
1224 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1225 handle->set_instance_template(*Utils::OpenHandle(*templ));
1227 i::Handle<i::ObjectTemplateInfo> result(
1228 i::ObjectTemplateInfo::cast(handle->instance_template()));
1229 return Utils::ToLocal(result);
1233 void FunctionTemplate::SetLength(int length) {
1234 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1236 Utils::OpenHandle(this)->set_length(length);
1240 void FunctionTemplate::SetClassName(Handle<String> name) {
1241 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1243 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
1247 void FunctionTemplate::SetHiddenPrototype(bool value) {
1248 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1250 Utils::OpenHandle(this)->set_hidden_prototype(value);
1254 void FunctionTemplate::ReadOnlyPrototype() {
1255 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1257 Utils::OpenHandle(this)->set_read_only_prototype(true);
1261 void FunctionTemplate::RemovePrototype() {
1262 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1264 Utils::OpenHandle(this)->set_remove_prototype(true);
1268 // --- O b j e c t T e m p l a t e ---
1271 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
1272 return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
1276 Local<ObjectTemplate> ObjectTemplate::New() {
1277 return New(i::Isolate::Current(), Local<FunctionTemplate>());
1281 Local<ObjectTemplate> ObjectTemplate::New(
1282 i::Isolate* isolate,
1283 v8::Handle<FunctionTemplate> constructor) {
1284 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
1285 LOG_API(isolate, "ObjectTemplate::New");
1287 i::Handle<i::Struct> struct_obj =
1288 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1289 i::Handle<i::ObjectTemplateInfo> obj =
1290 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1291 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1292 if (!constructor.IsEmpty())
1293 obj->set_constructor(*Utils::OpenHandle(*constructor));
1294 obj->set_internal_field_count(i::Smi::FromInt(0));
1295 return Utils::ToLocal(obj);
1299 // Ensure that the object template has a constructor. If no
1300 // constructor is available we create one.
1301 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1302 i::Isolate* isolate,
1303 ObjectTemplate* object_template) {
1304 i::Object* obj = Utils::OpenHandle(object_template)->constructor();
1305 if (!obj ->IsUndefined()) {
1306 i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
1307 return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1309 Local<FunctionTemplate> templ =
1310 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1311 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1312 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1313 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1318 static inline void AddPropertyToTemplate(
1319 i::Handle<i::TemplateInfo> info,
1320 i::Handle<i::AccessorInfo> obj) {
1321 i::Isolate* isolate = info->GetIsolate();
1322 i::Handle<i::Object> list(info->property_accessors(), isolate);
1323 if (list->IsUndefined()) {
1324 list = NeanderArray(isolate).value();
1325 info->set_property_accessors(*list);
1327 NeanderArray array(list);
1332 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1333 i::Isolate* isolate,
1334 Template* template_obj) {
1335 return Utils::OpenHandle(template_obj);
1339 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor
1340 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1341 i::Isolate* isolate,
1342 ObjectTemplate* object_template) {
1343 EnsureConstructor(isolate, object_template);
1344 return Utils::OpenHandle(object_template);
1348 template<typename Setter, typename Getter, typename Data, typename Template>
1349 static bool TemplateSetAccessor(
1350 Template* template_obj,
1351 v8::Local<String> name,
1355 AccessControl settings,
1356 PropertyAttribute attribute,
1357 v8::Local<AccessorSignature> signature) {
1358 i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
1360 i::HandleScope scope(isolate);
1361 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
1362 name, getter, setter, data, settings, attribute, signature);
1363 if (obj.is_null()) return false;
1364 i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj);
1365 AddPropertyToTemplate(info, obj);
1370 bool Template::SetDeclaredAccessor(
1372 Local<DeclaredAccessorDescriptor> descriptor,
1373 PropertyAttribute attribute,
1374 Local<AccessorSignature> signature,
1375 AccessControl settings) {
1377 return TemplateSetAccessor(
1378 this, name, descriptor, null, null, settings, attribute, signature);
1382 void Template::SetNativeDataProperty(v8::Local<String> name,
1383 AccessorGetterCallback getter,
1384 AccessorSetterCallback setter,
1385 v8::Handle<Value> data,
1386 PropertyAttribute attribute,
1387 v8::Local<AccessorSignature> signature,
1388 AccessControl settings) {
1389 TemplateSetAccessor(
1390 this, name, getter, setter, data, settings, attribute, signature);
1394 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1395 AccessorGetterCallback getter,
1396 AccessorSetterCallback setter,
1397 v8::Handle<Value> data,
1398 AccessControl settings,
1399 PropertyAttribute attribute,
1400 v8::Handle<AccessorSignature> signature) {
1401 TemplateSetAccessor(
1402 this, name, getter, setter, data, settings, attribute, signature);
1406 void ObjectTemplate::SetNamedPropertyHandler(
1407 NamedPropertyGetterCallback getter,
1408 NamedPropertySetterCallback setter,
1409 NamedPropertyQueryCallback query,
1410 NamedPropertyDeleterCallback remover,
1411 NamedPropertyEnumeratorCallback enumerator,
1412 Handle<Value> data) {
1413 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1415 i::HandleScope scope(isolate);
1416 EnsureConstructor(isolate, this);
1417 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1418 Utils::OpenHandle(this)->constructor());
1419 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1420 i::Handle<i::Struct> struct_obj =
1421 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1422 i::Handle<i::InterceptorInfo> obj =
1423 i::Handle<i::InterceptorInfo>::cast(struct_obj);
1425 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1426 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1427 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1428 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1429 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1431 if (data.IsEmpty()) {
1432 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1434 obj->set_data(*Utils::OpenHandle(*data));
1435 cons->set_named_property_handler(*obj);
1439 void ObjectTemplate::MarkAsUndetectable() {
1440 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1442 i::HandleScope scope(isolate);
1443 EnsureConstructor(isolate, this);
1444 i::FunctionTemplateInfo* constructor =
1445 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1446 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1447 cons->set_undetectable(true);
1451 void ObjectTemplate::SetAccessCheckCallbacks(
1452 NamedSecurityCallback named_callback,
1453 IndexedSecurityCallback indexed_callback,
1455 bool turned_on_by_default) {
1456 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1458 i::HandleScope scope(isolate);
1459 EnsureConstructor(isolate, this);
1461 i::Handle<i::Struct> struct_info =
1462 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1463 i::Handle<i::AccessCheckInfo> info =
1464 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1466 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1467 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1469 if (data.IsEmpty()) {
1470 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1472 info->set_data(*Utils::OpenHandle(*data));
1474 i::FunctionTemplateInfo* constructor =
1475 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1476 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1477 cons->set_access_check_info(*info);
1478 cons->set_needs_access_check(turned_on_by_default);
1482 void ObjectTemplate::SetIndexedPropertyHandler(
1483 IndexedPropertyGetterCallback getter,
1484 IndexedPropertySetterCallback setter,
1485 IndexedPropertyQueryCallback query,
1486 IndexedPropertyDeleterCallback remover,
1487 IndexedPropertyEnumeratorCallback enumerator,
1488 Handle<Value> data) {
1489 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1491 i::HandleScope scope(isolate);
1492 EnsureConstructor(isolate, this);
1493 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1494 Utils::OpenHandle(this)->constructor());
1495 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1496 i::Handle<i::Struct> struct_obj =
1497 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1498 i::Handle<i::InterceptorInfo> obj =
1499 i::Handle<i::InterceptorInfo>::cast(struct_obj);
1501 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1502 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1503 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1504 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1505 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1507 if (data.IsEmpty()) {
1508 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1510 obj->set_data(*Utils::OpenHandle(*data));
1511 cons->set_indexed_property_handler(*obj);
1515 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1516 Handle<Value> data) {
1517 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1519 i::HandleScope scope(isolate);
1520 EnsureConstructor(isolate, this);
1521 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1522 Utils::OpenHandle(this)->constructor());
1523 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1524 i::Handle<i::Struct> struct_obj =
1525 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1526 i::Handle<i::CallHandlerInfo> obj =
1527 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1528 SET_FIELD_WRAPPED(obj, set_callback, callback);
1529 if (data.IsEmpty()) {
1530 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1532 obj->set_data(*Utils::OpenHandle(*data));
1533 cons->set_instance_call_handler(*obj);
1537 int ObjectTemplate::InternalFieldCount() {
1538 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1542 void ObjectTemplate::SetInternalFieldCount(int value) {
1543 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1544 if (!Utils::ApiCheck(i::Smi::IsValid(value),
1545 "v8::ObjectTemplate::SetInternalFieldCount()",
1546 "Invalid internal field count")) {
1551 // The internal field count is set by the constructor function's
1552 // construct code, so we ensure that there is a constructor
1553 // function to do the setting.
1554 EnsureConstructor(isolate, this);
1556 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1560 // --- S c r i p t s ---
1563 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1566 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
1567 BufferPolicy buffer_policy_)
1568 : data(data_), length(length_), buffer_policy(buffer_policy_) {}
1571 ScriptCompiler::CachedData::~CachedData() {
1572 if (buffer_policy == BufferOwned) {
1578 Local<Script> UnboundScript::BindToCurrentContext() {
1579 i::Handle<i::HeapObject> obj =
1580 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1581 i::Handle<i::SharedFunctionInfo>
1582 function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate());
1583 i::Handle<i::JSFunction> function =
1584 obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo(
1585 function_info, obj->GetIsolate()->global_context());
1586 return ToApiHandle<Script>(function);
1590 int UnboundScript::GetId() {
1591 i::Handle<i::HeapObject> obj =
1592 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1593 i::Isolate* isolate = obj->GetIsolate();
1594 ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1);
1595 LOG_API(isolate, "v8::UnboundScript::GetId");
1597 i::HandleScope scope(isolate);
1598 i::Handle<i::SharedFunctionInfo> function_info(
1599 i::SharedFunctionInfo::cast(*obj));
1600 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1601 return script->id()->value();
1606 int UnboundScript::GetLineNumber(int code_pos) {
1607 i::Handle<i::SharedFunctionInfo> obj =
1608 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1609 i::Isolate* isolate = obj->GetIsolate();
1610 ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1);
1611 LOG_API(isolate, "UnboundScript::GetLineNumber");
1612 if (obj->script()->IsScript()) {
1613 i::Handle<i::Script> script(i::Script::cast(obj->script()));
1614 return i::Script::GetLineNumber(script, code_pos);
1621 Handle<Value> UnboundScript::GetScriptName() {
1622 i::Handle<i::SharedFunctionInfo> obj =
1623 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1624 i::Isolate* isolate = obj->GetIsolate();
1625 ON_BAILOUT(isolate, "v8::UnboundScript::GetName()",
1626 return Handle<String>());
1627 LOG_API(isolate, "UnboundScript::GetName");
1628 if (obj->script()->IsScript()) {
1629 i::Object* name = i::Script::cast(obj->script())->name();
1630 return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
1632 return Handle<String>();
1637 Handle<Value> UnboundScript::GetSourceURL() {
1638 i::Handle<i::SharedFunctionInfo> obj =
1639 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1640 i::Isolate* isolate = obj->GetIsolate();
1641 ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceURL()",
1642 return Handle<String>());
1643 LOG_API(isolate, "UnboundScript::GetSourceURL");
1644 if (obj->script()->IsScript()) {
1645 i::Object* url = i::Script::cast(obj->script())->source_url();
1646 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1648 return Handle<String>();
1653 Handle<Value> UnboundScript::GetSourceMappingURL() {
1654 i::Handle<i::SharedFunctionInfo> obj =
1655 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1656 i::Isolate* isolate = obj->GetIsolate();
1657 ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceMappingURL()",
1658 return Handle<String>());
1659 LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
1660 if (obj->script()->IsScript()) {
1661 i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
1662 return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1664 return Handle<String>();
1669 Local<Value> Script::Run() {
1670 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
1671 // If execution is terminating, Compile(..)->Run() requires this
1673 if (obj.is_null()) return Local<Value>();
1674 i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate();
1675 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1676 LOG_API(isolate, "Script::Run");
1678 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
1679 i::HandleScope scope(isolate);
1680 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
1681 EXCEPTION_PREAMBLE(isolate);
1682 i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
1683 i::Handle<i::Object> result;
1684 has_pending_exception = !i::Execution::Call(
1685 isolate, fun, receiver, 0, NULL).ToHandle(&result);
1686 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
1687 return Utils::ToLocal(scope.CloseAndEscape(result));
1691 Local<UnboundScript> Script::GetUnboundScript() {
1692 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1693 return ToApiHandle<UnboundScript>(
1694 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()));
1698 Local<UnboundScript> ScriptCompiler::CompileUnbound(
1699 Isolate* v8_isolate,
1701 CompileOptions options) {
1702 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1703 ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
1704 return Local<UnboundScript>());
1706 // Support the old API for a transition period:
1707 // - kProduceToCache -> kProduceParserCache
1708 // - kNoCompileOptions + cached_data != NULL -> kConsumeParserCache
1709 if (options == kProduceDataToCache) {
1710 options = kProduceParserCache;
1711 } else if (options == kNoCompileOptions && source->cached_data) {
1712 options = kConsumeParserCache;
1715 i::ScriptData* script_data = NULL;
1716 if (options == kConsumeParserCache || options == kConsumeCodeCache) {
1717 DCHECK(source->cached_data);
1718 // ScriptData takes care of pointer-aligning the data.
1719 script_data = new i::ScriptData(source->cached_data->data,
1720 source->cached_data->length);
1723 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
1724 LOG_API(isolate, "ScriptCompiler::CompileUnbound");
1726 i::SharedFunctionInfo* raw_result = NULL;
1727 { i::HandleScope scope(isolate);
1728 i::Handle<i::Object> name_obj;
1729 int line_offset = 0;
1730 int column_offset = 0;
1731 bool is_shared_cross_origin = false;
1732 if (!source->resource_name.IsEmpty()) {
1733 name_obj = Utils::OpenHandle(*(source->resource_name));
1735 if (!source->resource_line_offset.IsEmpty()) {
1736 line_offset = static_cast<int>(source->resource_line_offset->Value());
1738 if (!source->resource_column_offset.IsEmpty()) {
1740 static_cast<int>(source->resource_column_offset->Value());
1742 if (!source->resource_is_shared_cross_origin.IsEmpty()) {
1743 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1744 is_shared_cross_origin =
1745 source->resource_is_shared_cross_origin == v8::True(v8_isolate);
1747 EXCEPTION_PREAMBLE(isolate);
1748 i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
1749 str, name_obj, line_offset, column_offset, is_shared_cross_origin,
1750 isolate->global_context(), NULL, &script_data, options,
1751 i::NOT_NATIVES_CODE);
1752 has_pending_exception = result.is_null();
1753 if (has_pending_exception && script_data != NULL) {
1754 // This case won't happen during normal operation; we have compiled
1755 // successfully and produced cached data, and but the second compilation
1756 // of the same source code fails.
1760 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1761 raw_result = *result;
1763 if ((options == kProduceParserCache || options == kProduceCodeCache) &&
1764 script_data != NULL) {
1765 // script_data now contains the data that was generated. source will
1766 // take the ownership.
1767 source->cached_data = new CachedData(
1768 script_data->data(), script_data->length(), CachedData::BufferOwned);
1769 script_data->ReleaseDataOwnership();
1773 i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1774 return ToApiHandle<UnboundScript>(result);
1778 Local<Script> ScriptCompiler::Compile(
1779 Isolate* v8_isolate,
1781 CompileOptions options) {
1782 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1783 ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
1784 LOG_API(isolate, "ScriptCompiler::CompiletBound()");
1786 Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
1787 if (generic.IsEmpty()) return Local<Script>();
1788 return generic->BindToCurrentContext();
1792 Local<Script> Script::Compile(v8::Handle<String> source,
1793 v8::ScriptOrigin* origin) {
1794 i::Handle<i::String> str = Utils::OpenHandle(*source);
1796 ScriptCompiler::Source script_source(source, *origin);
1797 return ScriptCompiler::Compile(
1798 reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1801 ScriptCompiler::Source script_source(source);
1802 return ScriptCompiler::Compile(
1803 reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1808 Local<Script> Script::Compile(v8::Handle<String> source,
1809 v8::Handle<String> file_name) {
1810 ScriptOrigin origin(file_name);
1811 return Compile(source, &origin);
1815 // --- E x c e p t i o n s ---
1818 v8::TryCatch::TryCatch()
1819 : isolate_(i::Isolate::Current()),
1820 next_(isolate_->try_catch_handler()),
1822 can_continue_(true),
1823 capture_message_(true),
1825 has_terminated_(false) {
1827 // Special handling for simulators which have a separate JS stack.
1828 js_stack_comparable_address_ =
1829 reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
1830 GetCurrentStackPosition()));
1831 isolate_->RegisterTryCatchHandler(this);
1835 v8::TryCatch::~TryCatch() {
1836 DCHECK(isolate_ == i::Isolate::Current());
1838 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
1839 v8::HandleScope scope(isolate);
1840 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
1841 if (HasCaught() && capture_message_) {
1842 // If an exception was caught and rethrow_ is indicated, the saved
1843 // message, script, and location need to be restored to Isolate TLS
1844 // for reuse. capture_message_ needs to be disabled so that DoThrow()
1845 // does not create a new message.
1846 isolate_->thread_local_top()->rethrowing_message_ = true;
1847 isolate_->RestorePendingMessageFromTryCatch(this);
1849 isolate_->UnregisterTryCatchHandler(this);
1850 v8::internal::SimulatorStack::UnregisterCTryCatch();
1851 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
1852 DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
1854 if (HasCaught() && isolate_->has_scheduled_exception()) {
1855 // If an exception was caught but is still scheduled because no API call
1856 // promoted it, then it is canceled to prevent it from being propagated.
1857 // Note that this will not cancel termination exceptions.
1858 isolate_->CancelScheduledExceptionFromTryCatch(this);
1860 isolate_->UnregisterTryCatchHandler(this);
1861 v8::internal::SimulatorStack::UnregisterCTryCatch();
1866 bool v8::TryCatch::HasCaught() const {
1867 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1871 bool v8::TryCatch::CanContinue() const {
1872 return can_continue_;
1876 bool v8::TryCatch::HasTerminated() const {
1877 return has_terminated_;
1881 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1882 if (!HasCaught()) return v8::Local<v8::Value>();
1884 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
1888 v8::Local<Value> v8::TryCatch::Exception() const {
1889 DCHECK(isolate_ == i::Isolate::Current());
1891 // Check for out of memory exception.
1892 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1893 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
1895 return v8::Local<Value>();
1900 v8::Local<Value> v8::TryCatch::StackTrace() const {
1901 DCHECK(isolate_ == i::Isolate::Current());
1903 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1904 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1905 i::HandleScope scope(isolate_);
1906 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
1907 i::Handle<i::String> name = isolate_->factory()->stack_string();
1908 EXCEPTION_PREAMBLE(isolate_);
1909 Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
1910 has_pending_exception = !maybe.has_value;
1911 EXCEPTION_BAILOUT_CHECK(isolate_, v8::Local<Value>());
1912 if (!maybe.value) return v8::Local<Value>();
1913 i::Handle<i::Object> value;
1914 if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
1915 return v8::Local<Value>();
1917 return v8::Utils::ToLocal(scope.CloseAndEscape(value));
1919 return v8::Local<Value>();
1924 v8::Local<v8::Message> v8::TryCatch::Message() const {
1925 DCHECK(isolate_ == i::Isolate::Current());
1926 i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
1927 DCHECK(message->IsJSMessageObject() || message->IsTheHole());
1928 if (HasCaught() && !message->IsTheHole()) {
1929 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
1931 return v8::Local<v8::Message>();
1936 void v8::TryCatch::Reset() {
1937 DCHECK(isolate_ == i::Isolate::Current());
1938 if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) {
1939 // If an exception was caught but is still scheduled because no API call
1940 // promoted it, then it is canceled to prevent it from being propagated.
1941 // Note that this will not cancel termination exceptions.
1942 isolate_->CancelScheduledExceptionFromTryCatch(this);
1948 void v8::TryCatch::ResetInternal() {
1949 i::Object* the_hole = isolate_->heap()->the_hole_value();
1950 exception_ = the_hole;
1951 message_obj_ = the_hole;
1952 message_script_ = the_hole;
1953 message_start_pos_ = 0;
1954 message_end_pos_ = 0;
1958 void v8::TryCatch::SetVerbose(bool value) {
1959 is_verbose_ = value;
1963 void v8::TryCatch::SetCaptureMessage(bool value) {
1964 capture_message_ = value;
1968 // --- M e s s a g e ---
1971 Local<String> Message::Get() const {
1972 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1973 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
1975 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
1976 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1977 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
1978 Local<String> result = Utils::ToLocal(raw_result);
1979 return scope.Escape(result);
1983 ScriptOrigin Message::GetScriptOrigin() const {
1984 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1985 i::Handle<i::JSMessageObject> message =
1986 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1987 i::Handle<i::Object> script_wraper =
1988 i::Handle<i::Object>(message->script(), isolate);
1989 i::Handle<i::JSValue> script_value =
1990 i::Handle<i::JSValue>::cast(script_wraper);
1991 i::Handle<i::Script> script(i::Script::cast(script_value->value()));
1992 i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script));
1993 v8::Isolate* v8_isolate =
1994 reinterpret_cast<v8::Isolate*>(script->GetIsolate());
1995 v8::ScriptOrigin origin(
1996 Utils::ToLocal(scriptName),
1997 v8::Integer::New(v8_isolate, script->line_offset()->value()),
1998 v8::Integer::New(v8_isolate, script->column_offset()->value()),
2000 v8::Integer::New(v8_isolate, script->id()->value()));
2005 v8::Handle<Value> Message::GetScriptResourceName() const {
2006 return GetScriptOrigin().ResourceName();
2010 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
2011 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2013 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2014 i::Handle<i::JSMessageObject> message =
2015 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2016 i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
2017 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
2018 i::Handle<i::JSArray> stackTrace =
2019 i::Handle<i::JSArray>::cast(stackFramesObj);
2020 return scope.Escape(Utils::StackTraceToLocal(stackTrace));
2024 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2026 i::Handle<i::Object> recv,
2028 i::Handle<i::Object> argv[]) {
2029 i::Isolate* isolate = i::Isolate::Current();
2030 i::Handle<i::Object> object_fun =
2031 i::Object::GetProperty(
2032 isolate, isolate->js_builtins_object(), name).ToHandleChecked();
2033 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
2034 return i::Execution::Call(isolate, fun, recv, argc, argv);
2038 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2040 i::Handle<i::Object> data) {
2041 i::Handle<i::Object> argv[] = { data };
2042 return CallV8HeapFunction(name,
2043 i::Isolate::Current()->js_builtins_object(),
2049 int Message::GetLineNumber() const {
2050 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2051 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
2053 i::HandleScope scope(isolate);
2055 EXCEPTION_PREAMBLE(isolate);
2056 i::Handle<i::Object> result;
2057 has_pending_exception = !CallV8HeapFunction(
2058 "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result);
2059 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2060 return static_cast<int>(result->Number());
2064 int Message::GetStartPosition() const {
2065 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2067 i::HandleScope scope(isolate);
2068 i::Handle<i::JSMessageObject> message =
2069 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2070 return message->start_position();
2074 int Message::GetEndPosition() const {
2075 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2077 i::HandleScope scope(isolate);
2078 i::Handle<i::JSMessageObject> message =
2079 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2080 return message->end_position();
2084 int Message::GetStartColumn() const {
2085 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2086 ON_BAILOUT(isolate, "v8::Message::GetStartColumn()", return kNoColumnInfo);
2088 i::HandleScope scope(isolate);
2089 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2090 EXCEPTION_PREAMBLE(isolate);
2091 i::Handle<i::Object> start_col_obj;
2092 has_pending_exception = !CallV8HeapFunction(
2093 "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2094 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2095 return static_cast<int>(start_col_obj->Number());
2099 int Message::GetEndColumn() const {
2100 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2101 ON_BAILOUT(isolate, "v8::Message::GetEndColumn()", return kNoColumnInfo);
2103 i::HandleScope scope(isolate);
2104 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2105 EXCEPTION_PREAMBLE(isolate);
2106 i::Handle<i::Object> start_col_obj;
2107 has_pending_exception = !CallV8HeapFunction(
2108 "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2109 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2110 i::Handle<i::JSMessageObject> message =
2111 i::Handle<i::JSMessageObject>::cast(data_obj);
2112 int start = message->start_position();
2113 int end = message->end_position();
2114 return static_cast<int>(start_col_obj->Number()) + (end - start);
2118 bool Message::IsSharedCrossOrigin() const {
2119 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2121 i::HandleScope scope(isolate);
2122 i::Handle<i::JSMessageObject> message =
2123 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2124 i::Handle<i::JSValue> script =
2125 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2127 return i::Script::cast(script->value())->is_shared_cross_origin();
2131 Local<String> Message::GetSourceLine() const {
2132 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2133 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
2135 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2136 EXCEPTION_PREAMBLE(isolate);
2137 i::Handle<i::Object> result;
2138 has_pending_exception = !CallV8HeapFunction(
2139 "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result);
2140 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
2141 if (result->IsString()) {
2142 return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
2144 return Local<String>();
2149 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
2150 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2151 ENTER_V8(i_isolate);
2152 i_isolate->PrintCurrentStackTrace(out);
2156 // --- S t a c k T r a c e ---
2158 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
2159 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2161 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2162 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
2163 i::Handle<i::Object> obj =
2164 i::Object::GetElement(isolate, self, index).ToHandleChecked();
2165 i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
2166 return scope.Escape(Utils::StackFrameToLocal(jsobj));
2170 int StackTrace::GetFrameCount() const {
2171 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2173 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2177 Local<Array> StackTrace::AsArray() {
2178 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2180 return Utils::ToLocal(Utils::OpenHandle(this));
2184 Local<StackTrace> StackTrace::CurrentStackTrace(
2187 StackTraceOptions options) {
2188 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2189 ENTER_V8(i_isolate);
2190 // TODO(dcarney): remove when ScriptDebugServer is fixed.
2191 options = static_cast<StackTraceOptions>(
2192 static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins);
2193 i::Handle<i::JSArray> stackTrace =
2194 i_isolate->CaptureCurrentStackTrace(frame_limit, options);
2195 return Utils::StackTraceToLocal(stackTrace);
2199 // --- S t a c k F r a m e ---
2201 static int getIntProperty(const StackFrame* f, const char* propertyName,
2203 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2205 i::HandleScope scope(isolate);
2206 i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2207 i::Handle<i::Object> obj =
2208 i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2209 return obj->IsSmi() ? i::Smi::cast(*obj)->value() : defaultValue;
2213 int StackFrame::GetLineNumber() const {
2214 return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo);
2218 int StackFrame::GetColumn() const {
2219 return getIntProperty(this, "column", Message::kNoColumnInfo);
2223 int StackFrame::GetScriptId() const {
2224 return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo);
2228 static Local<String> getStringProperty(const StackFrame* f,
2229 const char* propertyName) {
2230 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2232 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2233 i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2234 i::Handle<i::Object> obj =
2235 i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2236 return obj->IsString()
2237 ? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
2242 Local<String> StackFrame::GetScriptName() const {
2243 return getStringProperty(this, "scriptName");
2247 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2248 return getStringProperty(this, "scriptNameOrSourceURL");
2252 Local<String> StackFrame::GetFunctionName() const {
2253 return getStringProperty(this, "functionName");
2257 static bool getBoolProperty(const StackFrame* f, const char* propertyName) {
2258 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2260 i::HandleScope scope(isolate);
2261 i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2262 i::Handle<i::Object> obj =
2263 i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2264 return obj->IsTrue();
2267 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }
2270 bool StackFrame::IsConstructor() const {
2271 return getBoolProperty(this, "isConstructor");
2277 Local<Value> JSON::Parse(Local<String> json_string) {
2278 i::Handle<i::String> string = Utils::OpenHandle(*json_string);
2279 i::Isolate* isolate = string->GetIsolate();
2280 EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
2282 i::HandleScope scope(isolate);
2283 i::Handle<i::String> source = i::String::Flatten(string);
2284 EXCEPTION_PREAMBLE(isolate);
2285 i::MaybeHandle<i::Object> maybe_result =
2286 source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
2287 : i::JsonParser<false>::Parse(source);
2288 i::Handle<i::Object> result;
2289 has_pending_exception = !maybe_result.ToHandle(&result);
2290 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2291 return Utils::ToLocal(
2292 i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
2298 bool Value::FullIsUndefined() const {
2299 bool result = Utils::OpenHandle(this)->IsUndefined();
2300 DCHECK_EQ(result, QuickIsUndefined());
2305 bool Value::FullIsNull() const {
2306 bool result = Utils::OpenHandle(this)->IsNull();
2307 DCHECK_EQ(result, QuickIsNull());
2312 bool Value::IsTrue() const {
2313 return Utils::OpenHandle(this)->IsTrue();
2317 bool Value::IsFalse() const {
2318 return Utils::OpenHandle(this)->IsFalse();
2322 bool Value::IsFunction() const {
2323 return Utils::OpenHandle(this)->IsJSFunction();
2327 bool Value::FullIsString() const {
2328 bool result = Utils::OpenHandle(this)->IsString();
2329 DCHECK_EQ(result, QuickIsString());
2334 bool Value::IsSymbol() const {
2335 return Utils::OpenHandle(this)->IsSymbol();
2339 bool Value::IsArray() const {
2340 return Utils::OpenHandle(this)->IsJSArray();
2344 bool Value::IsArrayBuffer() const {
2345 return Utils::OpenHandle(this)->IsJSArrayBuffer();
2349 bool Value::IsArrayBufferView() const {
2350 return Utils::OpenHandle(this)->IsJSArrayBufferView();
2354 bool Value::IsTypedArray() const {
2355 return Utils::OpenHandle(this)->IsJSTypedArray();
2359 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \
2360 bool Value::Is##Type##Array() const { \
2361 i::Handle<i::Object> obj = Utils::OpenHandle(this); \
2362 return obj->IsJSTypedArray() && \
2363 i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array; \
2366 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
2368 #undef VALUE_IS_TYPED_ARRAY
2371 bool Value::IsDataView() const {
2372 return Utils::OpenHandle(this)->IsJSDataView();
2376 bool Value::IsObject() const {
2377 return Utils::OpenHandle(this)->IsJSObject();
2381 bool Value::IsNumber() const {
2382 return Utils::OpenHandle(this)->IsNumber();
2386 bool Value::IsBoolean() const {
2387 return Utils::OpenHandle(this)->IsBoolean();
2391 bool Value::IsExternal() const {
2392 return Utils::OpenHandle(this)->IsExternal();
2396 bool Value::IsInt32() const {
2397 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2398 if (obj->IsSmi()) return true;
2399 if (obj->IsNumber()) {
2400 return i::IsInt32Double(obj->Number());
2406 bool Value::IsUint32() const {
2407 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2408 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2409 if (obj->IsNumber()) {
2410 double value = obj->Number();
2411 return !i::IsMinusZero(value) &&
2413 value <= i::kMaxUInt32 &&
2414 value == i::FastUI2D(i::FastD2UI(value));
2420 bool Value::IsDate() const {
2421 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2422 if (!obj->IsHeapObject()) return false;
2423 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2424 return obj->HasSpecificClassOf(isolate->heap()->Date_string());
2428 bool Value::IsStringObject() const {
2429 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2430 if (!obj->IsHeapObject()) return false;
2431 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2432 return obj->HasSpecificClassOf(isolate->heap()->String_string());
2436 bool Value::IsSymbolObject() const {
2437 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2438 if (!obj->IsHeapObject()) return false;
2439 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2440 return obj->HasSpecificClassOf(isolate->heap()->Symbol_string());
2444 bool Value::IsNumberObject() const {
2445 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2446 if (!obj->IsHeapObject()) return false;
2447 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2448 return obj->HasSpecificClassOf(isolate->heap()->Number_string());
2452 static bool CheckConstructor(i::Isolate* isolate,
2453 i::Handle<i::JSObject> obj,
2454 const char* class_name) {
2455 i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
2456 if (!constr->IsJSFunction()) return false;
2457 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
2458 return func->shared()->native() && constr.is_identical_to(
2459 i::Object::GetProperty(isolate,
2460 isolate->js_builtins_object(),
2461 class_name).ToHandleChecked());
2465 bool Value::IsNativeError() const {
2466 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2467 if (obj->IsJSObject()) {
2468 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
2469 i::Isolate* isolate = js_obj->GetIsolate();
2470 return CheckConstructor(isolate, js_obj, "$Error") ||
2471 CheckConstructor(isolate, js_obj, "$EvalError") ||
2472 CheckConstructor(isolate, js_obj, "$RangeError") ||
2473 CheckConstructor(isolate, js_obj, "$ReferenceError") ||
2474 CheckConstructor(isolate, js_obj, "$SyntaxError") ||
2475 CheckConstructor(isolate, js_obj, "$TypeError") ||
2476 CheckConstructor(isolate, js_obj, "$URIError");
2483 bool Value::IsBooleanObject() const {
2484 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2485 if (!obj->IsHeapObject()) return false;
2486 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2487 return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
2491 bool Value::IsRegExp() const {
2492 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2493 return obj->IsJSRegExp();
2497 Local<String> Value::ToString() const {
2498 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2499 i::Handle<i::Object> str;
2500 if (obj->IsString()) {
2503 i::Isolate* isolate = i::Isolate::Current();
2504 LOG_API(isolate, "ToString");
2506 EXCEPTION_PREAMBLE(isolate);
2507 has_pending_exception = !i::Execution::ToString(
2508 isolate, obj).ToHandle(&str);
2509 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2511 return ToApiHandle<String>(str);
2515 Local<String> Value::ToDetailString() const {
2516 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2517 i::Handle<i::Object> str;
2518 if (obj->IsString()) {
2521 i::Isolate* isolate = i::Isolate::Current();
2522 LOG_API(isolate, "ToDetailString");
2524 EXCEPTION_PREAMBLE(isolate);
2525 has_pending_exception = !i::Execution::ToDetailString(
2526 isolate, obj).ToHandle(&str);
2527 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2529 return ToApiHandle<String>(str);
2533 Local<v8::Object> Value::ToObject() const {
2534 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2535 i::Handle<i::Object> val;
2536 if (obj->IsJSObject()) {
2539 i::Isolate* isolate = i::Isolate::Current();
2540 LOG_API(isolate, "ToObject");
2542 EXCEPTION_PREAMBLE(isolate);
2543 has_pending_exception = !i::Execution::ToObject(
2544 isolate, obj).ToHandle(&val);
2545 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2547 return ToApiHandle<Object>(val);
2551 Local<Boolean> Value::ToBoolean() const {
2552 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2553 if (obj->IsBoolean()) {
2554 return ToApiHandle<Boolean>(obj);
2556 i::Isolate* isolate = i::Isolate::Current();
2557 LOG_API(isolate, "ToBoolean");
2559 i::Handle<i::Object> val =
2560 isolate->factory()->ToBoolean(obj->BooleanValue());
2561 return ToApiHandle<Boolean>(val);
2566 Local<Number> Value::ToNumber() const {
2567 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2568 i::Handle<i::Object> num;
2569 if (obj->IsNumber()) {
2572 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2573 LOG_API(isolate, "ToNumber");
2575 EXCEPTION_PREAMBLE(isolate);
2576 has_pending_exception = !i::Execution::ToNumber(
2577 isolate, obj).ToHandle(&num);
2578 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2580 return ToApiHandle<Number>(num);
2584 Local<Integer> Value::ToInteger() const {
2585 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2586 i::Handle<i::Object> num;
2590 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2591 LOG_API(isolate, "ToInteger");
2593 EXCEPTION_PREAMBLE(isolate);
2594 has_pending_exception = !i::Execution::ToInteger(
2595 isolate, obj).ToHandle(&num);
2596 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2598 return ToApiHandle<Integer>(num);
2602 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
2603 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
2604 Utils::ApiCheck(isolate != NULL &&
2605 isolate->IsInitialized() &&
2607 "v8::internal::Internals::CheckInitialized()",
2608 "Isolate is not initialized or V8 has died");
2612 void External::CheckCast(v8::Value* that) {
2613 Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
2614 "v8::External::Cast()",
2615 "Could not convert to external");
2619 void v8::Object::CheckCast(Value* that) {
2620 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2621 Utils::ApiCheck(obj->IsJSObject(),
2622 "v8::Object::Cast()",
2623 "Could not convert to object");
2627 void v8::Function::CheckCast(Value* that) {
2628 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2629 Utils::ApiCheck(obj->IsJSFunction(),
2630 "v8::Function::Cast()",
2631 "Could not convert to function");
2635 void v8::String::CheckCast(v8::Value* that) {
2636 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2637 Utils::ApiCheck(obj->IsString(),
2638 "v8::String::Cast()",
2639 "Could not convert to string");
2643 void v8::Symbol::CheckCast(v8::Value* that) {
2644 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2645 Utils::ApiCheck(obj->IsSymbol(),
2646 "v8::Symbol::Cast()",
2647 "Could not convert to symbol");
2651 void v8::Number::CheckCast(v8::Value* that) {
2652 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2653 Utils::ApiCheck(obj->IsNumber(),
2654 "v8::Number::Cast()",
2655 "Could not convert to number");
2659 void v8::Integer::CheckCast(v8::Value* that) {
2660 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2661 Utils::ApiCheck(obj->IsNumber(),
2662 "v8::Integer::Cast()",
2663 "Could not convert to number");
2667 void v8::Array::CheckCast(Value* that) {
2668 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2669 Utils::ApiCheck(obj->IsJSArray(),
2670 "v8::Array::Cast()",
2671 "Could not convert to array");
2675 void v8::Promise::CheckCast(Value* that) {
2676 Utils::ApiCheck(that->IsPromise(),
2677 "v8::Promise::Cast()",
2678 "Could not convert to promise");
2682 void v8::Promise::Resolver::CheckCast(Value* that) {
2683 Utils::ApiCheck(that->IsPromise(),
2684 "v8::Promise::Resolver::Cast()",
2685 "Could not convert to promise resolver");
2689 void v8::ArrayBuffer::CheckCast(Value* that) {
2690 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2691 Utils::ApiCheck(obj->IsJSArrayBuffer(),
2692 "v8::ArrayBuffer::Cast()",
2693 "Could not convert to ArrayBuffer");
2697 void v8::ArrayBufferView::CheckCast(Value* that) {
2698 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2699 Utils::ApiCheck(obj->IsJSArrayBufferView(),
2700 "v8::ArrayBufferView::Cast()",
2701 "Could not convert to ArrayBufferView");
2705 void v8::TypedArray::CheckCast(Value* that) {
2706 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2707 Utils::ApiCheck(obj->IsJSTypedArray(),
2708 "v8::TypedArray::Cast()",
2709 "Could not convert to TypedArray");
2713 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size) \
2714 void v8::Type##Array::CheckCast(Value* that) { \
2715 i::Handle<i::Object> obj = Utils::OpenHandle(that); \
2716 Utils::ApiCheck(obj->IsJSTypedArray() && \
2717 i::JSTypedArray::cast(*obj)->type() == \
2718 kExternal##Type##Array, \
2719 "v8::" #Type "Array::Cast()", \
2720 "Could not convert to " #Type "Array"); \
2724 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
2726 #undef CHECK_TYPED_ARRAY_CAST
2729 void v8::DataView::CheckCast(Value* that) {
2730 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2731 Utils::ApiCheck(obj->IsJSDataView(),
2732 "v8::DataView::Cast()",
2733 "Could not convert to DataView");
2737 void v8::Date::CheckCast(v8::Value* that) {
2738 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2739 i::Isolate* isolate = NULL;
2740 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2741 Utils::ApiCheck(isolate != NULL &&
2742 obj->HasSpecificClassOf(isolate->heap()->Date_string()),
2744 "Could not convert to date");
2748 void v8::StringObject::CheckCast(v8::Value* that) {
2749 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2750 i::Isolate* isolate = NULL;
2751 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2752 Utils::ApiCheck(isolate != NULL &&
2753 obj->HasSpecificClassOf(isolate->heap()->String_string()),
2754 "v8::StringObject::Cast()",
2755 "Could not convert to StringObject");
2759 void v8::SymbolObject::CheckCast(v8::Value* that) {
2760 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2761 i::Isolate* isolate = NULL;
2762 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2763 Utils::ApiCheck(isolate != NULL &&
2764 obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
2765 "v8::SymbolObject::Cast()",
2766 "Could not convert to SymbolObject");
2770 void v8::NumberObject::CheckCast(v8::Value* that) {
2771 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2772 i::Isolate* isolate = NULL;
2773 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2774 Utils::ApiCheck(isolate != NULL &&
2775 obj->HasSpecificClassOf(isolate->heap()->Number_string()),
2776 "v8::NumberObject::Cast()",
2777 "Could not convert to NumberObject");
2781 void v8::BooleanObject::CheckCast(v8::Value* that) {
2782 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2783 i::Isolate* isolate = NULL;
2784 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2785 Utils::ApiCheck(isolate != NULL &&
2786 obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
2787 "v8::BooleanObject::Cast()",
2788 "Could not convert to BooleanObject");
2792 void v8::RegExp::CheckCast(v8::Value* that) {
2793 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2794 Utils::ApiCheck(obj->IsJSRegExp(),
2795 "v8::RegExp::Cast()",
2796 "Could not convert to regular expression");
2800 bool Value::BooleanValue() const {
2801 return Utils::OpenHandle(this)->BooleanValue();
2805 double Value::NumberValue() const {
2806 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2807 i::Handle<i::Object> num;
2808 if (obj->IsNumber()) {
2811 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2812 LOG_API(isolate, "NumberValue");
2814 EXCEPTION_PREAMBLE(isolate);
2815 has_pending_exception = !i::Execution::ToNumber(
2816 isolate, obj).ToHandle(&num);
2817 EXCEPTION_BAILOUT_CHECK(isolate, base::OS::nan_value());
2819 return num->Number();
2823 int64_t Value::IntegerValue() const {
2824 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2825 i::Handle<i::Object> num;
2826 if (obj->IsNumber()) {
2829 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2830 LOG_API(isolate, "IntegerValue");
2832 EXCEPTION_PREAMBLE(isolate);
2833 has_pending_exception = !i::Execution::ToInteger(
2834 isolate, obj).ToHandle(&num);
2835 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2838 return i::Smi::cast(*num)->value();
2840 return static_cast<int64_t>(num->Number());
2845 Local<Int32> Value::ToInt32() const {
2846 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2847 i::Handle<i::Object> num;
2851 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2852 LOG_API(isolate, "ToInt32");
2854 EXCEPTION_PREAMBLE(isolate);
2855 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2856 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2858 return ToApiHandle<Int32>(num);
2862 Local<Uint32> Value::ToUint32() const {
2863 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2864 i::Handle<i::Object> num;
2868 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2869 LOG_API(isolate, "ToUInt32");
2871 EXCEPTION_PREAMBLE(isolate);
2872 has_pending_exception = !i::Execution::ToUint32(
2873 isolate, obj).ToHandle(&num);
2874 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2876 return ToApiHandle<Uint32>(num);
2880 Local<Uint32> Value::ToArrayIndex() const {
2881 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2883 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2884 return Local<Uint32>();
2886 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2887 LOG_API(isolate, "ToArrayIndex");
2889 EXCEPTION_PREAMBLE(isolate);
2890 i::Handle<i::Object> string_obj;
2891 has_pending_exception = !i::Execution::ToString(
2892 isolate, obj).ToHandle(&string_obj);
2893 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2894 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2896 if (str->AsArrayIndex(&index)) {
2897 i::Handle<i::Object> value;
2898 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2899 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
2901 value = isolate->factory()->NewNumber(index);
2903 return Utils::Uint32ToLocal(value);
2905 return Local<Uint32>();
2909 int32_t Value::Int32Value() const {
2910 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2912 return i::Smi::cast(*obj)->value();
2914 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2915 LOG_API(isolate, "Int32Value (slow)");
2917 EXCEPTION_PREAMBLE(isolate);
2918 i::Handle<i::Object> num;
2919 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2920 EXCEPTION_BAILOUT_CHECK(isolate, 0);
2922 return i::Smi::cast(*num)->value();
2924 return static_cast<int32_t>(num->Number());
2930 bool Value::Equals(Handle<Value> that) const {
2931 i::Isolate* isolate = i::Isolate::Current();
2932 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2933 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2934 "v8::Value::Equals()",
2935 "Reading from empty handle")) {
2938 LOG_API(isolate, "Equals");
2940 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2941 // If both obj and other are JSObjects, we'd better compare by identity
2942 // immediately when going into JS builtin. The reason is Invoke
2943 // would overwrite global object receiver with global proxy.
2944 if (obj->IsJSObject() && other->IsJSObject()) {
2945 return *obj == *other;
2947 i::Handle<i::Object> args[] = { other };
2948 EXCEPTION_PREAMBLE(isolate);
2949 i::Handle<i::Object> result;
2950 has_pending_exception = !CallV8HeapFunction(
2951 "EQUALS", obj, ARRAY_SIZE(args), args).ToHandle(&result);
2952 EXCEPTION_BAILOUT_CHECK(isolate, false);
2953 return *result == i::Smi::FromInt(i::EQUAL);
2957 bool Value::StrictEquals(Handle<Value> that) const {
2958 i::Isolate* isolate = i::Isolate::Current();
2959 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2960 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2961 "v8::Value::StrictEquals()",
2962 "Reading from empty handle")) {
2965 LOG_API(isolate, "StrictEquals");
2966 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2967 // Must check HeapNumber first, since NaN !== NaN.
2968 if (obj->IsHeapNumber()) {
2969 if (!other->IsNumber()) return false;
2970 double x = obj->Number();
2971 double y = other->Number();
2972 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2973 return x == y && !std::isnan(x) && !std::isnan(y);
2974 } else if (*obj == *other) { // Also covers Booleans.
2976 } else if (obj->IsSmi()) {
2977 return other->IsNumber() && obj->Number() == other->Number();
2978 } else if (obj->IsString()) {
2979 return other->IsString() &&
2980 i::String::Equals(i::Handle<i::String>::cast(obj),
2981 i::Handle<i::String>::cast(other));
2982 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2983 return other->IsUndefined() || other->IsUndetectableObject();
2990 bool Value::SameValue(Handle<Value> that) const {
2991 i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2992 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2993 "v8::Value::SameValue()",
2994 "Reading from empty handle")) {
2997 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2998 return obj->SameValue(*other);
3002 uint32_t Value::Uint32Value() const {
3003 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3005 return i::Smi::cast(*obj)->value();
3007 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
3008 LOG_API(isolate, "Uint32Value");
3010 EXCEPTION_PREAMBLE(isolate);
3011 i::Handle<i::Object> num;
3012 has_pending_exception = !i::Execution::ToUint32(
3013 isolate, obj).ToHandle(&num);
3014 EXCEPTION_BAILOUT_CHECK(isolate, 0);
3016 return i::Smi::cast(*num)->value();
3018 return static_cast<uint32_t>(num->Number());
3024 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value) {
3025 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3026 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3028 i::HandleScope scope(isolate);
3029 i::Handle<i::Object> self = Utils::OpenHandle(this);
3030 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3031 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3032 EXCEPTION_PREAMBLE(isolate);
3033 has_pending_exception =
3034 i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
3035 i::SLOPPY).is_null();
3036 EXCEPTION_BAILOUT_CHECK(isolate, false);
3041 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
3042 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3043 ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3045 i::HandleScope scope(isolate);
3046 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3047 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3048 EXCEPTION_PREAMBLE(isolate);
3049 has_pending_exception = i::JSObject::SetElement(
3050 self, index, value_obj, NONE, i::SLOPPY).is_null();
3051 EXCEPTION_BAILOUT_CHECK(isolate, false);
3056 bool v8::Object::ForceSet(v8::Handle<Value> key,
3057 v8::Handle<Value> value,
3058 v8::PropertyAttribute attribs) {
3059 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3060 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
3062 i::HandleScope scope(isolate);
3063 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3064 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3065 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3066 EXCEPTION_PREAMBLE(isolate);
3067 has_pending_exception = i::Runtime::DefineObjectProperty(
3071 static_cast<PropertyAttributes>(attribs)).is_null();
3072 EXCEPTION_BAILOUT_CHECK(isolate, false);
3077 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
3078 return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
3083 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
3084 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3085 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
3087 i::HandleScope scope(isolate);
3088 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3089 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3091 // When deleting a property on the global object using ForceDelete
3092 // deoptimize all functions as optimized code does not check for the hole
3093 // value with DontDelete properties. We have to deoptimize all contexts
3094 // because of possible cross-context inlined functions.
3095 if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
3096 i::Deoptimizer::DeoptimizeAll(isolate);
3099 EXCEPTION_PREAMBLE(isolate);
3100 i::Handle<i::Object> obj;
3101 has_pending_exception = !i::Runtime::DeleteObjectProperty(
3102 isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
3103 EXCEPTION_BAILOUT_CHECK(isolate, false);
3104 return obj->IsTrue();
3108 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
3109 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3110 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3112 i::Handle<i::Object> self = Utils::OpenHandle(this);
3113 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3114 EXCEPTION_PREAMBLE(isolate);
3115 i::Handle<i::Object> result;
3116 has_pending_exception =
3117 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
3118 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3119 return Utils::ToLocal(result);
3123 Local<Value> v8::Object::Get(uint32_t index) {
3124 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3125 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3127 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3128 EXCEPTION_PREAMBLE(isolate);
3129 i::Handle<i::Object> result;
3130 has_pending_exception =
3131 !i::Object::GetElement(isolate, self, index).ToHandle(&result);
3132 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3133 return Utils::ToLocal(result);
3137 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) {
3138 return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3142 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
3143 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3144 ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()",
3145 return static_cast<PropertyAttribute>(NONE));
3147 i::HandleScope scope(isolate);
3148 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3149 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3150 if (!key_obj->IsName()) {
3151 EXCEPTION_PREAMBLE(isolate);
3152 has_pending_exception = !i::Execution::ToString(
3153 isolate, key_obj).ToHandle(&key_obj);
3154 EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3156 i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
3157 EXCEPTION_PREAMBLE(isolate);
3158 Maybe<PropertyAttributes> result =
3159 i::JSReceiver::GetPropertyAttributes(self, key_name);
3160 has_pending_exception = !result.has_value;
3161 EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3162 if (result.value == ABSENT) return static_cast<PropertyAttribute>(NONE);
3163 return static_cast<PropertyAttribute>(result.value);
3167 Local<Value> v8::Object::GetOwnPropertyDescriptor(Local<String> key) {
3168 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3169 ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyDescriptor()",
3170 return Local<Value>());
3172 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3173 i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
3174 i::Handle<i::Object> args[] = { obj, key_name };
3175 EXCEPTION_PREAMBLE(isolate);
3176 i::Handle<i::Object> result;
3177 has_pending_exception = !CallV8HeapFunction(
3178 "ObjectGetOwnPropertyDescriptor",
3179 isolate->factory()->undefined_value(),
3181 args).ToHandle(&result);
3182 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3183 return Utils::ToLocal(result);
3187 Local<Value> v8::Object::GetPrototype() {
3188 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3189 ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
3191 i::Handle<i::Object> self = Utils::OpenHandle(this);
3192 i::PrototypeIterator iter(isolate, self);
3193 return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
3197 bool v8::Object::SetPrototype(Handle<Value> value) {
3198 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3199 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
3201 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3202 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3203 // We do not allow exceptions thrown while setting the prototype
3204 // to propagate outside.
3206 EXCEPTION_PREAMBLE(isolate);
3207 i::MaybeHandle<i::Object> result =
3208 i::JSObject::SetPrototype(self, value_obj, false);
3209 has_pending_exception = result.is_null();
3210 EXCEPTION_BAILOUT_CHECK(isolate, false);
3215 Local<Object> v8::Object::FindInstanceInPrototypeChain(
3216 v8::Handle<FunctionTemplate> tmpl) {
3217 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3219 "v8::Object::FindInstanceInPrototypeChain()",
3220 return Local<v8::Object>());
3222 i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this),
3223 i::PrototypeIterator::START_AT_RECEIVER);
3224 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
3225 while (!tmpl_info->IsTemplateFor(iter.GetCurrent())) {
3227 if (iter.IsAtEnd()) {
3228 return Local<Object>();
3231 return Utils::ToLocal(
3232 i::handle(i::JSObject::cast(iter.GetCurrent()), isolate));
3236 Local<Array> v8::Object::GetPropertyNames() {
3237 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3238 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
3239 return Local<v8::Array>());
3241 i::HandleScope scope(isolate);
3242 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3243 EXCEPTION_PREAMBLE(isolate);
3244 i::Handle<i::FixedArray> value;
3245 has_pending_exception = !i::JSReceiver::GetKeys(
3246 self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value);
3247 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3248 // Because we use caching to speed up enumeration it is important
3249 // to never change the result of the basic enumeration function so
3250 // we clone the result.
3251 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3252 i::Handle<i::JSArray> result =
3253 isolate->factory()->NewJSArrayWithElements(elms);
3254 return Utils::ToLocal(scope.CloseAndEscape(result));
3258 Local<Array> v8::Object::GetOwnPropertyNames() {
3259 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3260 ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
3261 return Local<v8::Array>());
3263 i::HandleScope scope(isolate);
3264 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3265 EXCEPTION_PREAMBLE(isolate);
3266 i::Handle<i::FixedArray> value;
3267 has_pending_exception = !i::JSReceiver::GetKeys(
3268 self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
3269 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3270 // Because we use caching to speed up enumeration it is important
3271 // to never change the result of the basic enumeration function so
3272 // we clone the result.
3273 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3274 i::Handle<i::JSArray> result =
3275 isolate->factory()->NewJSArrayWithElements(elms);
3276 return Utils::ToLocal(scope.CloseAndEscape(result));
3280 Local<String> v8::Object::ObjectProtoToString() {
3281 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
3282 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
3283 ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()",
3284 return Local<v8::String>());
3285 ENTER_V8(i_isolate);
3286 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3288 i::Handle<i::Object> name(self->class_name(), i_isolate);
3290 // Native implementation of Object.prototype.toString (v8natives.js):
3291 // var c = %_ClassOf(this);
3292 // if (c === 'Arguments') c = 'Object';
3293 // return "[object " + c + "]";
3295 if (!name->IsString()) {
3296 return v8::String::NewFromUtf8(isolate, "[object ]");
3298 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
3299 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) {
3300 return v8::String::NewFromUtf8(isolate, "[object Object]");
3302 const char* prefix = "[object ";
3303 Local<String> str = Utils::ToLocal(class_name);
3304 const char* postfix = "]";
3306 int prefix_len = i::StrLength(prefix);
3307 int str_len = str->Utf8Length();
3308 int postfix_len = i::StrLength(postfix);
3310 int buf_len = prefix_len + str_len + postfix_len;
3311 i::ScopedVector<char> buf(buf_len);
3314 char* ptr = buf.start();
3315 i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
3318 // Write real content.
3319 str->WriteUtf8(ptr, str_len);
3323 i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
3325 // Copy the buffer into a heap-allocated string and return it.
3326 Local<String> result = v8::String::NewFromUtf8(
3327 isolate, buf.start(), String::kNormalString, buf_len);
3334 Local<String> v8::Object::GetConstructorName() {
3335 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3336 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
3337 return Local<v8::String>());
3339 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3340 i::Handle<i::String> name(self->constructor_name());
3341 return Utils::ToLocal(name);
3345 bool v8::Object::Delete(v8::Handle<Value> key) {
3346 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3347 ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
3349 i::HandleScope scope(isolate);
3350 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3351 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3352 EXCEPTION_PREAMBLE(isolate);
3353 i::Handle<i::Object> obj;
3354 has_pending_exception = !i::Runtime::DeleteObjectProperty(
3355 isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
3356 EXCEPTION_BAILOUT_CHECK(isolate, false);
3357 return obj->IsTrue();
3361 bool v8::Object::DeletePrivate(v8::Handle<Private> key) {
3362 return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3366 bool v8::Object::Has(v8::Handle<Value> key) {
3367 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3368 ON_BAILOUT(isolate, "v8::Object::Has()", return false);
3370 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
3371 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3372 EXCEPTION_PREAMBLE(isolate);
3373 i::Handle<i::Object> obj;
3374 has_pending_exception = !i::Runtime::HasObjectProperty(
3375 isolate, self, key_obj).ToHandle(&obj);
3376 EXCEPTION_BAILOUT_CHECK(isolate, false);
3377 return obj->IsTrue();
3381 bool v8::Object::HasPrivate(v8::Handle<Private> key) {
3382 // TODO(rossberg): this should use HasOwnProperty, but we'd need to
3383 // generalise that to a (noy yet existant) Name argument first.
3384 return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3388 bool v8::Object::Delete(uint32_t index) {
3389 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3390 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
3393 HandleScope scope(reinterpret_cast<Isolate*>(isolate));
3394 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3396 EXCEPTION_PREAMBLE(isolate);
3397 i::Handle<i::Object> obj;
3398 has_pending_exception =
3399 !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj);
3400 EXCEPTION_BAILOUT_CHECK(isolate, false);
3401 return obj->IsTrue();
3405 bool v8::Object::Has(uint32_t index) {
3406 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3407 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
3408 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3409 EXCEPTION_PREAMBLE(isolate);
3410 Maybe<bool> maybe = i::JSReceiver::HasElement(self, index);
3411 has_pending_exception = !maybe.has_value;
3412 EXCEPTION_BAILOUT_CHECK(isolate, false);
3417 template<typename Setter, typename Getter, typename Data>
3418 static inline bool ObjectSetAccessor(Object* obj,
3419 Handle<String> name,
3423 AccessControl settings,
3424 PropertyAttribute attributes) {
3425 i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
3426 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
3428 i::HandleScope scope(isolate);
3429 v8::Handle<AccessorSignature> signature;
3430 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
3431 name, getter, setter, data, settings, attributes, signature);
3432 if (info.is_null()) return false;
3433 bool fast = Utils::OpenHandle(obj)->HasFastProperties();
3434 i::Handle<i::Object> result;
3435 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3437 i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
3439 if (result->IsUndefined()) return false;
3440 if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
3445 bool Object::SetAccessor(Handle<String> name,
3446 AccessorGetterCallback getter,
3447 AccessorSetterCallback setter,
3448 v8::Handle<Value> data,
3449 AccessControl settings,
3450 PropertyAttribute attributes) {
3451 return ObjectSetAccessor(
3452 this, name, getter, setter, data, settings, attributes);
3456 bool Object::SetDeclaredAccessor(Local<String> name,
3457 Local<DeclaredAccessorDescriptor> descriptor,
3458 PropertyAttribute attributes,
3459 AccessControl settings) {
3461 return ObjectSetAccessor(
3462 this, name, descriptor, null, null, settings, attributes);
3466 void Object::SetAccessorProperty(Local<String> name,
3467 Local<Function> getter,
3468 Handle<Function> setter,
3469 PropertyAttribute attribute,
3470 AccessControl settings) {
3471 // TODO(verwaest): Remove |settings|.
3472 DCHECK_EQ(v8::DEFAULT, settings);
3473 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3474 ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return);
3476 i::HandleScope scope(isolate);
3477 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
3478 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
3479 if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
3480 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this),
3481 v8::Utils::OpenHandle(*name),
3484 static_cast<PropertyAttributes>(attribute));
3488 bool v8::Object::HasOwnProperty(Handle<String> key) {
3489 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3490 ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
3492 EXCEPTION_PREAMBLE(isolate);
3493 Maybe<bool> maybe = i::JSReceiver::HasOwnProperty(Utils::OpenHandle(this),
3494 Utils::OpenHandle(*key));
3495 has_pending_exception = !maybe.has_value;
3496 EXCEPTION_BAILOUT_CHECK(isolate, false);
3501 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
3502 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3503 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
3505 EXCEPTION_PREAMBLE(isolate);
3506 Maybe<bool> maybe = i::JSObject::HasRealNamedProperty(
3507 Utils::OpenHandle(this), Utils::OpenHandle(*key));
3508 has_pending_exception = !maybe.has_value;
3509 EXCEPTION_BAILOUT_CHECK(isolate, false);
3514 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
3515 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3516 ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
3518 EXCEPTION_PREAMBLE(isolate);
3520 i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
3521 has_pending_exception = !maybe.has_value;
3522 EXCEPTION_BAILOUT_CHECK(isolate, false);
3527 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
3528 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3530 "v8::Object::HasRealNamedCallbackProperty()",
3533 EXCEPTION_PREAMBLE(isolate);
3534 Maybe<bool> maybe = i::JSObject::HasRealNamedCallbackProperty(
3535 Utils::OpenHandle(this), Utils::OpenHandle(*key));
3536 has_pending_exception = !maybe.has_value;
3537 EXCEPTION_BAILOUT_CHECK(isolate, false);
3542 bool v8::Object::HasNamedLookupInterceptor() {
3543 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3544 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
3546 return Utils::OpenHandle(this)->HasNamedInterceptor();
3550 bool v8::Object::HasIndexedLookupInterceptor() {
3551 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3552 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
3554 return Utils::OpenHandle(this)->HasIndexedInterceptor();
3558 static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
3559 i::Handle<i::JSObject> receiver,
3560 i::Handle<i::String> name,
3561 i::LookupResult* lookup) {
3562 if (!lookup->IsProperty()) {
3563 // No real property was found.
3564 return Local<Value>();
3567 // If the property being looked up is a callback, it can throw
3569 EXCEPTION_PREAMBLE(isolate);
3570 i::LookupIterator it(
3571 receiver, name, i::Handle<i::JSReceiver>(lookup->holder(), isolate),
3572 i::LookupIterator::SKIP_INTERCEPTOR);
3573 i::Handle<i::Object> result;
3574 has_pending_exception = !i::Object::GetProperty(&it).ToHandle(&result);
3575 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3577 return Utils::ToLocal(result);
3581 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
3582 Handle<String> key) {
3583 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3585 "v8::Object::GetRealNamedPropertyInPrototypeChain()",
3586 return Local<Value>());
3588 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3589 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3590 i::LookupResult lookup(isolate);
3591 self_obj->LookupRealNamedPropertyInPrototypes(key_obj, &lookup);
3592 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3596 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
3597 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3598 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
3599 return Local<Value>());
3601 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3602 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3603 i::LookupResult lookup(isolate);
3604 self_obj->LookupRealNamedProperty(key_obj, &lookup);
3605 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3609 // Turns on access checks by copying the map and setting the check flag.
3610 // Because the object gets a new map, existing inline cache caching
3611 // the old map of this object will fail.
3612 void v8::Object::TurnOnAccessCheck() {
3613 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3614 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
3616 i::HandleScope scope(isolate);
3617 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3619 // When turning on access checks for a global object deoptimize all functions
3620 // as optimized code does not always handle access checks.
3621 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
3623 i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
3624 new_map->set_is_access_check_needed(true);
3625 i::JSObject::MigrateToMap(obj, new_map);
3629 bool v8::Object::IsDirty() {
3630 return Utils::OpenHandle(this)->IsDirty();
3634 Local<v8::Object> v8::Object::Clone() {
3635 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3636 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
3638 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3639 EXCEPTION_PREAMBLE(isolate);
3640 i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
3641 has_pending_exception = result.is_null();
3642 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3643 return Utils::ToLocal(result);
3647 Local<v8::Context> v8::Object::CreationContext() {
3648 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3650 "v8::Object::CreationContext()", return Local<v8::Context>());
3652 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3653 i::Context* context = self->GetCreationContext();
3654 return Utils::ToLocal(i::Handle<i::Context>(context));
3658 int v8::Object::GetIdentityHash() {
3659 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3660 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
3662 i::HandleScope scope(isolate);
3663 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3664 return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
3668 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
3669 v8::Handle<v8::Value> value) {
3670 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3671 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
3672 if (value.IsEmpty()) return DeleteHiddenValue(key);
3674 i::HandleScope scope(isolate);
3675 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3676 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3677 i::Handle<i::String> key_string =
3678 isolate->factory()->InternalizeString(key_obj);
3679 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3680 i::Handle<i::Object> result =
3681 i::JSObject::SetHiddenProperty(self, key_string, value_obj);
3682 return *result == *self;
3686 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
3687 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3688 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
3689 return Local<v8::Value>());
3691 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3692 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3693 i::Handle<i::String> key_string =
3694 isolate->factory()->InternalizeString(key_obj);
3695 i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate);
3696 if (result->IsTheHole()) return v8::Local<v8::Value>();
3697 return Utils::ToLocal(result);
3701 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3702 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3703 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3705 i::HandleScope scope(isolate);
3706 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3707 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3708 i::Handle<i::String> key_string =
3709 isolate->factory()->InternalizeString(key_obj);
3710 i::JSObject::DeleteHiddenProperty(self, key_string);
3717 static i::ElementsKind GetElementsKindFromExternalArrayType(
3718 ExternalArrayType array_type) {
3719 switch (array_type) {
3720 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \
3721 case kExternal##Type##Array: \
3722 return i::EXTERNAL_##TYPE##_ELEMENTS;
3724 TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND)
3725 #undef ARRAY_TYPE_TO_ELEMENTS_KIND
3728 return i::DICTIONARY_ELEMENTS;
3732 void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3734 ExternalArrayType array_type,
3736 i::Isolate* isolate = object->GetIsolate();
3737 i::Handle<i::ExternalArray> array =
3738 isolate->factory()->NewExternalArray(length, array_type, data);
3740 i::Handle<i::Map> external_array_map =
3741 i::JSObject::GetElementsTransitionMap(
3743 GetElementsKindFromExternalArrayType(array_type));
3745 i::JSObject::SetMapAndElements(object, external_array_map, array);
3751 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3752 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3753 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3755 i::HandleScope scope(isolate);
3756 if (!Utils::ApiCheck(length >= 0 &&
3757 length <= i::ExternalUint8ClampedArray::kMaxLength,
3758 "v8::Object::SetIndexedPropertiesToPixelData()",
3759 "length exceeds max acceptable value")) {
3762 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3763 if (!Utils::ApiCheck(!self->IsJSArray(),
3764 "v8::Object::SetIndexedPropertiesToPixelData()",
3765 "JSArray is not supported")) {
3768 PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length);
3772 bool v8::Object::HasIndexedPropertiesInPixelData() {
3773 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3774 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3776 return self->HasExternalUint8ClampedElements();
3780 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3781 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3782 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3784 if (self->HasExternalUint8ClampedElements()) {
3785 return i::ExternalUint8ClampedArray::cast(self->elements())->
3786 external_uint8_clamped_pointer();
3793 int v8::Object::GetIndexedPropertiesPixelDataLength() {
3794 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3795 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3797 if (self->HasExternalUint8ClampedElements()) {
3798 return i::ExternalUint8ClampedArray::cast(self->elements())->length();
3805 void v8::Object::SetIndexedPropertiesToExternalArrayData(
3807 ExternalArrayType array_type,
3809 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3810 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3812 i::HandleScope scope(isolate);
3813 if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
3814 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3815 "length exceeds max acceptable value")) {
3818 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3819 if (!Utils::ApiCheck(!self->IsJSArray(),
3820 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3821 "JSArray is not supported")) {
3824 PrepareExternalArrayElements(self, data, array_type, length);
3828 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3829 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3830 ON_BAILOUT(self->GetIsolate(),
3831 "v8::HasIndexedPropertiesInExternalArrayData()",
3833 return self->HasExternalArrayElements();
3837 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3838 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3839 ON_BAILOUT(self->GetIsolate(),
3840 "v8::GetIndexedPropertiesExternalArrayData()",
3842 if (self->HasExternalArrayElements()) {
3843 return i::ExternalArray::cast(self->elements())->external_pointer();
3850 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3851 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3852 ON_BAILOUT(self->GetIsolate(),
3853 "v8::GetIndexedPropertiesExternalArrayDataType()",
3854 return static_cast<ExternalArrayType>(-1));
3855 switch (self->elements()->map()->instance_type()) {
3856 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \
3857 case i::EXTERNAL_##TYPE##_ARRAY_TYPE: \
3858 return kExternal##Type##Array;
3859 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
3860 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
3862 return static_cast<ExternalArrayType>(-1);
3867 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3868 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3869 ON_BAILOUT(self->GetIsolate(),
3870 "v8::GetIndexedPropertiesExternalArrayDataLength()",
3872 if (self->HasExternalArrayElements()) {
3873 return i::ExternalArray::cast(self->elements())->length();
3880 bool v8::Object::IsCallable() {
3881 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3882 ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
3884 i::HandleScope scope(isolate);
3885 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3886 return obj->IsCallable();
3890 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
3892 v8::Handle<v8::Value> argv[]) {
3893 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3894 ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
3895 return Local<v8::Value>());
3896 LOG_API(isolate, "Object::CallAsFunction");
3898 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3899 i::HandleScope scope(isolate);
3900 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3901 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3902 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3903 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3904 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
3905 if (obj->IsJSFunction()) {
3906 fun = i::Handle<i::JSFunction>::cast(obj);
3908 EXCEPTION_PREAMBLE(isolate);
3909 i::Handle<i::Object> delegate;
3910 has_pending_exception = !i::Execution::TryGetFunctionDelegate(
3911 isolate, obj).ToHandle(&delegate);
3912 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3913 fun = i::Handle<i::JSFunction>::cast(delegate);
3916 EXCEPTION_PREAMBLE(isolate);
3917 i::Handle<i::Object> returned;
3918 has_pending_exception = !i::Execution::Call(
3919 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
3920 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
3921 return Utils::ToLocal(scope.CloseAndEscape(returned));
3925 Local<v8::Value> Object::CallAsConstructor(int argc,
3926 v8::Handle<v8::Value> argv[]) {
3927 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3928 ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
3929 return Local<v8::Object>());
3930 LOG_API(isolate, "Object::CallAsConstructor");
3932 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3933 i::HandleScope scope(isolate);
3934 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3935 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3936 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3937 if (obj->IsJSFunction()) {
3938 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
3939 EXCEPTION_PREAMBLE(isolate);
3940 i::Handle<i::Object> returned;
3941 has_pending_exception = !i::Execution::New(
3942 fun, argc, args).ToHandle(&returned);
3943 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3944 return Utils::ToLocal(scope.CloseAndEscape(
3945 i::Handle<i::JSObject>::cast(returned)));
3947 EXCEPTION_PREAMBLE(isolate);
3948 i::Handle<i::Object> delegate;
3949 has_pending_exception = !i::Execution::TryGetConstructorDelegate(
3950 isolate, obj).ToHandle(&delegate);
3951 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
3952 if (!delegate->IsUndefined()) {
3953 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
3954 EXCEPTION_PREAMBLE(isolate);
3955 i::Handle<i::Object> returned;
3956 has_pending_exception = !i::Execution::Call(
3957 isolate, fun, obj, argc, args).ToHandle(&returned);
3958 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3959 DCHECK(!delegate->IsUndefined());
3960 return Utils::ToLocal(scope.CloseAndEscape(returned));
3962 return Local<v8::Object>();
3966 Local<Function> Function::New(Isolate* v8_isolate,
3967 FunctionCallback callback,
3970 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3971 LOG_API(isolate, "Function::New");
3973 return FunctionTemplateNew(
3974 isolate, callback, data, Local<Signature>(), length, true)->
3979 Local<v8::Object> Function::NewInstance() const {
3980 return NewInstance(0, NULL);
3984 Local<v8::Object> Function::NewInstance(int argc,
3985 v8::Handle<v8::Value> argv[]) const {
3986 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3987 ON_BAILOUT(isolate, "v8::Function::NewInstance()",
3988 return Local<v8::Object>());
3989 LOG_API(isolate, "Function::NewInstance");
3991 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3992 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
3993 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
3994 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3995 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3996 EXCEPTION_PREAMBLE(isolate);
3997 i::Handle<i::Object> returned;
3998 has_pending_exception = !i::Execution::New(
3999 function, argc, args).ToHandle(&returned);
4000 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4001 return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
4005 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
4006 v8::Handle<v8::Value> argv[]) {
4007 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4008 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
4009 LOG_API(isolate, "Function::Call");
4011 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
4012 i::HandleScope scope(isolate);
4013 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
4014 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
4015 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4016 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4017 EXCEPTION_PREAMBLE(isolate);
4018 i::Handle<i::Object> returned;
4019 has_pending_exception = !i::Execution::Call(
4020 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
4021 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
4022 return Utils::ToLocal(scope.CloseAndEscape(returned));
4026 void Function::SetName(v8::Handle<v8::String> name) {
4027 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4030 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4031 func->shared()->set_name(*Utils::OpenHandle(*name));
4035 Handle<Value> Function::GetName() const {
4036 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4037 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
4038 func->GetIsolate()));
4042 Handle<Value> Function::GetInferredName() const {
4043 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4044 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
4045 func->GetIsolate()));
4049 Handle<Value> Function::GetDisplayName() const {
4050 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4051 ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
4052 return ToApiHandle<Primitive>(
4053 isolate->factory()->undefined_value()));
4055 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4056 i::Handle<i::String> property_name =
4057 isolate->factory()->InternalizeOneByteString(
4058 STATIC_ASCII_VECTOR("displayName"));
4059 i::LookupResult lookup(isolate);
4060 func->LookupRealNamedProperty(property_name, &lookup);
4061 if (lookup.IsFound()) {
4062 i::Object* value = lookup.GetLazyValue();
4063 if (value && value->IsString()) {
4064 i::String* name = i::String::cast(value);
4065 if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name));
4068 return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
4072 ScriptOrigin Function::GetScriptOrigin() const {
4073 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4074 if (func->shared()->script()->IsScript()) {
4075 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4076 i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script);
4077 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
4078 v8::ScriptOrigin origin(
4079 Utils::ToLocal(scriptName),
4080 v8::Integer::New(isolate, script->line_offset()->value()),
4081 v8::Integer::New(isolate, script->column_offset()->value()));
4084 return v8::ScriptOrigin(Handle<Value>());
4088 const int Function::kLineOffsetNotFound = -1;
4091 int Function::GetScriptLineNumber() const {
4092 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4093 if (func->shared()->script()->IsScript()) {
4094 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4095 return i::Script::GetLineNumber(script, func->shared()->start_position());
4097 return kLineOffsetNotFound;
4101 int Function::GetScriptColumnNumber() const {
4102 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4103 if (func->shared()->script()->IsScript()) {
4104 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4105 return i::Script::GetColumnNumber(script, func->shared()->start_position());
4107 return kLineOffsetNotFound;
4111 bool Function::IsBuiltin() const {
4112 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4113 return func->IsBuiltin();
4117 int Function::ScriptId() const {
4118 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4119 if (!func->shared()->script()->IsScript()) {
4120 return v8::UnboundScript::kNoScriptId;
4122 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4123 return script->id()->value();
4127 Local<v8::Value> Function::GetBoundFunction() const {
4128 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4129 if (!func->shared()->bound()) {
4130 return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
4132 i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
4133 i::FixedArray::cast(func->function_bindings()));
4134 i::Handle<i::Object> original(
4135 bound_args->get(i::JSFunction::kBoundFunctionIndex),
4136 func->GetIsolate());
4137 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
4141 int String::Length() const {
4142 i::Handle<i::String> str = Utils::OpenHandle(this);
4143 return str->length();
4147 bool String::IsOneByte() const {
4148 i::Handle<i::String> str = Utils::OpenHandle(this);
4149 return str->HasOnlyOneByteChars();
4153 // Helpers for ContainsOnlyOneByteHelper
4154 template<size_t size> struct OneByteMask;
4155 template<> struct OneByteMask<4> {
4156 static const uint32_t value = 0xFF00FF00;
4158 template<> struct OneByteMask<8> {
4159 static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00);
4161 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
4162 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
4163 static inline bool Unaligned(const uint16_t* chars) {
4164 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
4168 static inline const uint16_t* Align(const uint16_t* chars) {
4169 return reinterpret_cast<uint16_t*>(
4170 reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
4173 class ContainsOnlyOneByteHelper {
4175 ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
4176 bool Check(i::String* string) {
4177 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
4178 if (cons_string == NULL) return is_one_byte_;
4179 return CheckCons(cons_string);
4181 void VisitOneByteString(const uint8_t* chars, int length) {
4184 void VisitTwoByteString(const uint16_t* chars, int length) {
4185 // Accumulated bits.
4187 // Align to uintptr_t.
4188 const uint16_t* end = chars + length;
4189 while (Unaligned(chars) && chars != end) {
4192 // Read word aligned in blocks,
4193 // checking the return value at the end of each block.
4194 const uint16_t* aligned_end = Align(end);
4195 const int increment = sizeof(uintptr_t)/sizeof(uint16_t);
4196 const int inner_loops = 16;
4197 while (chars + inner_loops*increment < aligned_end) {
4198 for (int i = 0; i < inner_loops; i++) {
4199 acc |= *reinterpret_cast<const uintptr_t*>(chars);
4202 // Check for early return.
4203 if ((acc & kOneByteMask) != 0) {
4204 is_one_byte_ = false;
4209 while (chars != end) {
4213 if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
4217 bool CheckCons(i::ConsString* cons_string) {
4219 // Check left side if flat.
4220 i::String* left = cons_string->first();
4221 i::ConsString* left_as_cons =
4222 i::String::VisitFlat(this, left, 0);
4223 if (!is_one_byte_) return false;
4224 // Check right side if flat.
4225 i::String* right = cons_string->second();
4226 i::ConsString* right_as_cons =
4227 i::String::VisitFlat(this, right, 0);
4228 if (!is_one_byte_) return false;
4229 // Standard recurse/iterate trick.
4230 if (left_as_cons != NULL && right_as_cons != NULL) {
4231 if (left->length() < right->length()) {
4232 CheckCons(left_as_cons);
4233 cons_string = right_as_cons;
4235 CheckCons(right_as_cons);
4236 cons_string = left_as_cons;
4238 // Check fast return.
4239 if (!is_one_byte_) return false;
4242 // Descend left in place.
4243 if (left_as_cons != NULL) {
4244 cons_string = left_as_cons;
4247 // Descend right in place.
4248 if (right_as_cons != NULL) {
4249 cons_string = right_as_cons;
4255 return is_one_byte_;
4258 DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper);
4262 bool String::ContainsOnlyOneByte() const {
4263 i::Handle<i::String> str = Utils::OpenHandle(this);
4264 if (str->HasOnlyOneByteChars()) return true;
4265 ContainsOnlyOneByteHelper helper;
4266 return helper.Check(*str);
4270 class Utf8LengthHelper : public i::AllStatic {
4273 kEndsWithLeadingSurrogate = 1 << 0,
4274 kStartsWithTrailingSurrogate = 1 << 1,
4275 kLeftmostEdgeIsCalculated = 1 << 2,
4276 kRightmostEdgeIsCalculated = 1 << 3,
4277 kLeftmostEdgeIsSurrogate = 1 << 4,
4278 kRightmostEdgeIsSurrogate = 1 << 5
4281 static const uint8_t kInitialState = 0;
4283 static inline bool EndsWithSurrogate(uint8_t state) {
4284 return state & kEndsWithLeadingSurrogate;
4287 static inline bool StartsWithSurrogate(uint8_t state) {
4288 return state & kStartsWithTrailingSurrogate;
4293 Visitor() : utf8_length_(0), state_(kInitialState) {}
4295 void VisitOneByteString(const uint8_t* chars, int length) {
4296 int utf8_length = 0;
4297 // Add in length 1 for each non-ASCII character.
4298 for (int i = 0; i < length; i++) {
4299 utf8_length += *chars++ >> 7;
4301 // Add in length 1 for each character.
4302 utf8_length_ = utf8_length + length;
4303 state_ = kInitialState;
4306 void VisitTwoByteString(const uint16_t* chars, int length) {
4307 int utf8_length = 0;
4308 int last_character = unibrow::Utf16::kNoPreviousCharacter;
4309 for (int i = 0; i < length; i++) {
4310 uint16_t c = chars[i];
4311 utf8_length += unibrow::Utf8::Length(c, last_character);
4314 utf8_length_ = utf8_length;
4316 if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
4317 state |= kStartsWithTrailingSurrogate;
4319 if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
4320 state |= kEndsWithLeadingSurrogate;
4325 static i::ConsString* VisitFlat(i::String* string,
4329 i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
4330 *length = visitor.utf8_length_;
4331 *state = visitor.state_;
4338 DISALLOW_COPY_AND_ASSIGN(Visitor);
4341 static inline void MergeLeafLeft(int* length,
4343 uint8_t leaf_state) {
4344 bool edge_surrogate = StartsWithSurrogate(leaf_state);
4345 if (!(*state & kLeftmostEdgeIsCalculated)) {
4346 DCHECK(!(*state & kLeftmostEdgeIsSurrogate));
4347 *state |= kLeftmostEdgeIsCalculated
4348 | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
4349 } else if (EndsWithSurrogate(*state) && edge_surrogate) {
4350 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4352 if (EndsWithSurrogate(leaf_state)) {
4353 *state |= kEndsWithLeadingSurrogate;
4355 *state &= ~kEndsWithLeadingSurrogate;
4359 static inline void MergeLeafRight(int* length,
4361 uint8_t leaf_state) {
4362 bool edge_surrogate = EndsWithSurrogate(leaf_state);
4363 if (!(*state & kRightmostEdgeIsCalculated)) {
4364 DCHECK(!(*state & kRightmostEdgeIsSurrogate));
4365 *state |= (kRightmostEdgeIsCalculated
4366 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
4367 } else if (edge_surrogate && StartsWithSurrogate(*state)) {
4368 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4370 if (StartsWithSurrogate(leaf_state)) {
4371 *state |= kStartsWithTrailingSurrogate;
4373 *state &= ~kStartsWithTrailingSurrogate;
4377 static inline void MergeTerminal(int* length,
4379 uint8_t* state_out) {
4380 DCHECK((state & kLeftmostEdgeIsCalculated) &&
4381 (state & kRightmostEdgeIsCalculated));
4382 if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
4383 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4385 *state_out = kInitialState |
4386 (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
4387 (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
4390 static int Calculate(i::ConsString* current, uint8_t* state_out) {
4391 using namespace internal;
4392 int total_length = 0;
4393 uint8_t state = kInitialState;
4395 i::String* left = current->first();
4396 i::String* right = current->second();
4397 uint8_t right_leaf_state;
4398 uint8_t left_leaf_state;
4400 ConsString* left_as_cons =
4401 Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
4402 if (left_as_cons == NULL) {
4403 total_length += leaf_length;
4404 MergeLeafLeft(&total_length, &state, left_leaf_state);
4406 ConsString* right_as_cons =
4407 Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
4408 if (right_as_cons == NULL) {
4409 total_length += leaf_length;
4410 MergeLeafRight(&total_length, &state, right_leaf_state);
4411 if (left_as_cons != NULL) {
4412 // 1 Leaf node. Descend in place.
4413 current = left_as_cons;
4417 MergeTerminal(&total_length, state, state_out);
4418 return total_length;
4420 } else if (left_as_cons == NULL) {
4421 // 1 Leaf node. Descend in place.
4422 current = right_as_cons;
4425 // Both strings are ConsStrings.
4426 // Recurse on smallest.
4427 if (left->length() < right->length()) {
4428 total_length += Calculate(left_as_cons, &left_leaf_state);
4429 MergeLeafLeft(&total_length, &state, left_leaf_state);
4430 current = right_as_cons;
4432 total_length += Calculate(right_as_cons, &right_leaf_state);
4433 MergeLeafRight(&total_length, &state, right_leaf_state);
4434 current = left_as_cons;
4441 static inline int Calculate(i::ConsString* current) {
4442 uint8_t state = kInitialState;
4443 return Calculate(current, &state);
4447 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
4451 static int Utf8Length(i::String* str, i::Isolate* isolate) {
4452 int length = str->length();
4453 if (length == 0) return 0;
4455 i::ConsString* cons_string =
4456 Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
4457 if (cons_string == NULL) return length;
4458 return Utf8LengthHelper::Calculate(cons_string);
4462 int String::Utf8Length() const {
4463 i::Handle<i::String> str = Utils::OpenHandle(this);
4464 i::Isolate* isolate = str->GetIsolate();
4465 return v8::Utf8Length(*str, isolate);
4469 class Utf8WriterVisitor {
4474 bool skip_capacity_check,
4475 bool replace_invalid_utf8)
4476 : early_termination_(false),
4477 last_character_(unibrow::Utf16::kNoPreviousCharacter),
4480 capacity_(capacity),
4481 skip_capacity_check_(capacity == -1 || skip_capacity_check),
4482 replace_invalid_utf8_(replace_invalid_utf8),
4483 utf16_chars_read_(0) {
4486 static int WriteEndCharacter(uint16_t character,
4490 bool replace_invalid_utf8) {
4491 using namespace unibrow;
4492 DCHECK(remaining > 0);
4493 // We can't use a local buffer here because Encode needs to modify
4494 // previous characters in the stream. We know, however, that
4495 // exactly one character will be advanced.
4496 if (Utf16::IsSurrogatePair(last_character, character)) {
4497 int written = Utf8::Encode(buffer,
4500 replace_invalid_utf8);
4501 DCHECK(written == 1);
4504 // Use a scratch buffer to check the required characters.
4505 char temp_buffer[Utf8::kMaxEncodedSize];
4506 // Can't encode using last_character as gcc has array bounds issues.
4507 int written = Utf8::Encode(temp_buffer,
4509 Utf16::kNoPreviousCharacter,
4510 replace_invalid_utf8);
4512 if (written > remaining) return 0;
4513 // Copy over the character from temp_buffer.
4514 for (int j = 0; j < written; j++) {
4515 buffer[j] = temp_buffer[j];
4520 // Visit writes out a group of code units (chars) of a v8::String to the
4521 // internal buffer_. This is done in two phases. The first phase calculates a
4522 // pesimistic estimate (writable_length) on how many code units can be safely
4523 // written without exceeding the buffer capacity and without writing the last
4524 // code unit (it could be a lead surrogate). The estimated number of code
4525 // units is then written out in one go, and the reported byte usage is used
4526 // to correct the estimate. This is repeated until the estimate becomes <= 0
4527 // or all code units have been written out. The second phase writes out code
4528 // units until the buffer capacity is reached, would be exceeded by the next
4529 // unit, or all units have been written out.
4530 template<typename Char>
4531 void Visit(const Char* chars, const int length) {
4532 using namespace unibrow;
4533 DCHECK(!early_termination_);
4534 if (length == 0) return;
4535 // Copy state to stack.
4536 char* buffer = buffer_;
4537 int last_character =
4538 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
4540 // Do a fast loop where there is no exit capacity check.
4543 if (skip_capacity_check_) {
4544 fast_length = length;
4546 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4547 // Need enough space to write everything but one character.
4548 STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
4549 int max_size_per_char = sizeof(Char) == 1 ? 2 : 3;
4550 int writable_length =
4551 (remaining_capacity - max_size_per_char)/max_size_per_char;
4552 // Need to drop into slow loop.
4553 if (writable_length <= 0) break;
4554 fast_length = i + writable_length;
4555 if (fast_length > length) fast_length = length;
4557 // Write the characters to the stream.
4558 if (sizeof(Char) == 1) {
4559 for (; i < fast_length; i++) {
4561 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
4562 DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4565 for (; i < fast_length; i++) {
4566 uint16_t character = *chars++;
4567 buffer += Utf8::Encode(buffer,
4570 replace_invalid_utf8_);
4571 last_character = character;
4572 DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4575 // Array is fully written. Exit.
4576 if (fast_length == length) {
4577 // Write state back out to object.
4578 last_character_ = last_character;
4580 utf16_chars_read_ += length;
4584 DCHECK(!skip_capacity_check_);
4585 // Slow loop. Must check capacity on each iteration.
4586 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4587 DCHECK(remaining_capacity >= 0);
4588 for (; i < length && remaining_capacity > 0; i++) {
4589 uint16_t character = *chars++;
4590 // remaining_capacity is <= 3 bytes at this point, so we do not write out
4591 // an umatched lead surrogate.
4592 if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) {
4593 early_termination_ = true;
4596 int written = WriteEndCharacter(character,
4600 replace_invalid_utf8_);
4602 early_termination_ = true;
4606 remaining_capacity -= written;
4607 last_character = character;
4609 // Write state back out to object.
4610 last_character_ = last_character;
4612 utf16_chars_read_ += i;
4615 inline bool IsDone() {
4616 return early_termination_;
4619 inline void VisitOneByteString(const uint8_t* chars, int length) {
4620 Visit(chars, length);
4623 inline void VisitTwoByteString(const uint16_t* chars, int length) {
4624 Visit(chars, length);
4627 int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
4628 // Write out number of utf16 characters written to the stream.
4629 if (utf16_chars_read_out != NULL) {
4630 *utf16_chars_read_out = utf16_chars_read_;
4632 // Only null terminate if all of the string was written and there's space.
4634 !early_termination_ &&
4635 (capacity_ == -1 || (buffer_ - start_) < capacity_)) {
4638 return static_cast<int>(buffer_ - start_);
4642 bool early_termination_;
4643 int last_character_;
4647 bool const skip_capacity_check_;
4648 bool const replace_invalid_utf8_;
4649 int utf16_chars_read_;
4650 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
4654 static bool RecursivelySerializeToUtf8(i::String* current,
4655 Utf8WriterVisitor* writer,
4656 int recursion_budget) {
4657 while (!writer->IsDone()) {
4658 i::ConsString* cons_string = i::String::VisitFlat(writer, current);
4659 if (cons_string == NULL) return true; // Leaf node.
4660 if (recursion_budget <= 0) return false;
4661 // Must write the left branch first.
4662 i::String* first = cons_string->first();
4663 bool success = RecursivelySerializeToUtf8(first,
4665 recursion_budget - 1);
4666 if (!success) return false;
4667 // Inline tail recurse for right branch.
4668 current = cons_string->second();
4674 int String::WriteUtf8(char* buffer,
4677 int options) const {
4678 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4679 LOG_API(isolate, "String::WriteUtf8");
4681 i::Handle<i::String> str = Utils::OpenHandle(this);
4682 if (options & HINT_MANY_WRITES_EXPECTED) {
4683 str = i::String::Flatten(str); // Flatten the string for efficiency.
4685 const int string_length = str->length();
4686 bool write_null = !(options & NO_NULL_TERMINATION);
4687 bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8);
4688 int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize;
4689 // First check if we can just write the string without checking capacity.
4690 if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) {
4691 Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8);
4692 const int kMaxRecursion = 100;
4693 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
4694 if (success) return writer.CompleteWrite(write_null, nchars_ref);
4695 } else if (capacity >= string_length) {
4696 // First check that the buffer is large enough.
4697 int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
4698 if (utf8_bytes <= capacity) {
4700 if (utf8_bytes == string_length) {
4701 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
4702 if (nchars_ref != NULL) *nchars_ref = string_length;
4703 if (write_null && (utf8_bytes+1 <= capacity)) {
4704 return string_length + 1;
4706 return string_length;
4708 if (write_null && (utf8_bytes+1 > capacity)) {
4709 options |= NO_NULL_TERMINATION;
4711 // Recurse once without a capacity limit.
4712 // This will get into the first branch above.
4713 // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
4714 return WriteUtf8(buffer, -1, nchars_ref, options);
4717 // Recursive slow path can potentially be unreasonable slow. Flatten.
4718 str = i::String::Flatten(str);
4719 Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8);
4720 i::String::VisitFlat(&writer, *str);
4721 return writer.CompleteWrite(write_null, nchars_ref);
4725 template<typename CharType>
4726 static inline int WriteHelper(const String* string,
4731 i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
4732 LOG_API(isolate, "String::Write");
4734 DCHECK(start >= 0 && length >= -1);
4735 i::Handle<i::String> str = Utils::OpenHandle(string);
4736 isolate->string_tracker()->RecordWrite(str);
4737 if (options & String::HINT_MANY_WRITES_EXPECTED) {
4738 // Flatten the string for efficiency. This applies whether we are
4739 // using StringCharacterStream or Get(i) to access the characters.
4740 str = i::String::Flatten(str);
4742 int end = start + length;
4743 if ((length == -1) || (length > str->length() - start) )
4744 end = str->length();
4745 if (end < 0) return 0;
4746 i::String::WriteToFlat(*str, buffer, start, end);
4747 if (!(options & String::NO_NULL_TERMINATION) &&
4748 (length == -1 || end - start < length)) {
4749 buffer[end - start] = '\0';
4755 int String::WriteOneByte(uint8_t* buffer,
4758 int options) const {
4759 return WriteHelper(this, buffer, start, length, options);
4763 int String::Write(uint16_t* buffer,
4766 int options) const {
4767 return WriteHelper(this, buffer, start, length, options);
4771 bool v8::String::IsExternal() const {
4772 i::Handle<i::String> str = Utils::OpenHandle(this);
4773 EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
4774 return i::StringShape(*str).IsExternalTwoByte();
4778 bool v8::String::IsExternalAscii() const {
4779 i::Handle<i::String> str = Utils::OpenHandle(this);
4780 return i::StringShape(*str).IsExternalAscii();
4784 void v8::String::VerifyExternalStringResource(
4785 v8::String::ExternalStringResource* value) const {
4786 i::Handle<i::String> str = Utils::OpenHandle(this);
4787 const v8::String::ExternalStringResource* expected;
4788 if (i::StringShape(*str).IsExternalTwoByte()) {
4789 const void* resource =
4790 i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4791 expected = reinterpret_cast<const ExternalStringResource*>(resource);
4795 CHECK_EQ(expected, value);
4798 void v8::String::VerifyExternalStringResourceBase(
4799 v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
4800 i::Handle<i::String> str = Utils::OpenHandle(this);
4801 const v8::String::ExternalStringResourceBase* expected;
4802 Encoding expectedEncoding;
4803 if (i::StringShape(*str).IsExternalAscii()) {
4804 const void* resource =
4805 i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4806 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4807 expectedEncoding = ASCII_ENCODING;
4808 } else if (i::StringShape(*str).IsExternalTwoByte()) {
4809 const void* resource =
4810 i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4811 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4812 expectedEncoding = TWO_BYTE_ENCODING;
4815 expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
4816 : TWO_BYTE_ENCODING;
4818 CHECK_EQ(expected, value);
4819 CHECK_EQ(expectedEncoding, encoding);
4822 const v8::String::ExternalAsciiStringResource*
4823 v8::String::GetExternalAsciiStringResource() const {
4824 i::Handle<i::String> str = Utils::OpenHandle(this);
4825 if (i::StringShape(*str).IsExternalAscii()) {
4826 const void* resource =
4827 i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4828 return reinterpret_cast<const ExternalAsciiStringResource*>(resource);
4835 Local<Value> Symbol::Name() const {
4836 i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
4837 i::Handle<i::Object> name(sym->name(), sym->GetIsolate());
4838 return Utils::ToLocal(name);
4842 Local<Value> Private::Name() const {
4843 return reinterpret_cast<const Symbol*>(this)->Name();
4847 double Number::Value() const {
4848 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4849 return obj->Number();
4853 bool Boolean::Value() const {
4854 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4855 return obj->IsTrue();
4859 int64_t Integer::Value() const {
4860 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4862 return i::Smi::cast(*obj)->value();
4864 return static_cast<int64_t>(obj->Number());
4869 int32_t Int32::Value() const {
4870 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4872 return i::Smi::cast(*obj)->value();
4874 return static_cast<int32_t>(obj->Number());
4879 uint32_t Uint32::Value() const {
4880 i::Handle<i::Object> obj = Utils::OpenHandle(this);
4882 return i::Smi::cast(*obj)->value();
4884 return static_cast<uint32_t>(obj->Number());
4889 int v8::Object::InternalFieldCount() {
4890 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4891 return obj->GetInternalFieldCount();
4895 static bool InternalFieldOK(i::Handle<i::JSObject> obj,
4897 const char* location) {
4898 return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
4900 "Internal field out of bounds");
4904 Local<Value> v8::Object::SlowGetInternalField(int index) {
4905 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4906 const char* location = "v8::Object::GetInternalField()";
4907 if (!InternalFieldOK(obj, index, location)) return Local<Value>();
4908 i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
4909 return Utils::ToLocal(value);
4913 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
4914 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4915 const char* location = "v8::Object::SetInternalField()";
4916 if (!InternalFieldOK(obj, index, location)) return;
4917 i::Handle<i::Object> val = Utils::OpenHandle(*value);
4918 obj->SetInternalField(index, *val);
4919 DCHECK_EQ(value, GetInternalField(index));
4923 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
4924 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4925 const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
4926 if (!InternalFieldOK(obj, index, location)) return NULL;
4927 return DecodeSmiToAligned(obj->GetInternalField(index), location);
4931 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
4932 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4933 const char* location = "v8::Object::SetAlignedPointerInInternalField()";
4934 if (!InternalFieldOK(obj, index, location)) return;
4935 obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
4936 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
4940 static void* ExternalValue(i::Object* obj) {
4941 // Obscure semantics for undefined, but somehow checked in our unit tests...
4942 if (obj->IsUndefined()) return NULL;
4943 i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
4944 return i::Foreign::cast(foreign)->foreign_address();
4948 // --- E n v i r o n m e n t ---
4951 void v8::V8::InitializePlatform(Platform* platform) {
4952 i::V8::InitializePlatform(platform);
4956 void v8::V8::ShutdownPlatform() {
4957 i::V8::ShutdownPlatform();
4961 bool v8::V8::Initialize() {
4962 i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4963 if (isolate != NULL && isolate->IsInitialized()) {
4966 return InitializeHelper(isolate);
4970 void v8::V8::SetEntropySource(EntropySource entropy_source) {
4971 base::RandomNumberGenerator::SetEntropySource(entropy_source);
4975 void v8::V8::SetReturnAddressLocationResolver(
4976 ReturnAddressLocationResolver return_address_resolver) {
4977 i::V8::SetReturnAddressLocationResolver(return_address_resolver);
4981 bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate,
4982 FunctionEntryHook entry_hook) {
4983 DCHECK(ext_isolate != NULL);
4984 DCHECK(entry_hook != NULL);
4986 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate);
4988 // The entry hook can only be set before the Isolate is initialized, as
4989 // otherwise the Isolate's code stubs generated at initialization won't
4990 // contain entry hooks.
4991 if (isolate->IsInitialized())
4994 // Setting an entry hook is a one-way operation, once set, it cannot be
4995 // changed or unset.
4996 if (isolate->function_entry_hook() != NULL)
4999 isolate->set_function_entry_hook(entry_hook);
5004 void v8::V8::SetJitCodeEventHandler(
5005 JitCodeEventOptions options, JitCodeEventHandler event_handler) {
5006 i::Isolate* isolate = i::Isolate::Current();
5007 // Ensure that logging is initialized for our isolate.
5008 isolate->InitializeLoggingAndCounters();
5009 isolate->logger()->SetCodeEventHandler(options, event_handler);
5012 void v8::V8::SetArrayBufferAllocator(
5013 ArrayBuffer::Allocator* allocator) {
5014 if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
5015 "v8::V8::SetArrayBufferAllocator",
5016 "ArrayBufferAllocator might only be set once"))
5018 i::V8::SetArrayBufferAllocator(allocator);
5022 bool v8::V8::Dispose() {
5028 HeapStatistics::HeapStatistics(): total_heap_size_(0),
5029 total_heap_size_executable_(0),
5030 total_physical_size_(0),
5032 heap_size_limit_(0) { }
5035 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
5036 i::Isolate* isolate = i::Isolate::Current();
5037 isolate->heap()->VisitExternalResources(visitor);
5041 class VisitorAdapter : public i::ObjectVisitor {
5043 explicit VisitorAdapter(PersistentHandleVisitor* visitor)
5044 : visitor_(visitor) {}
5045 virtual void VisitPointers(i::Object** start, i::Object** end) {
5048 virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
5049 Value* value = ToApi<Value>(i::Handle<i::Object>(p));
5050 visitor_->VisitPersistentHandle(
5051 reinterpret_cast<Persistent<Value>*>(&value), class_id);
5054 PersistentHandleVisitor* visitor_;
5058 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
5059 i::Isolate* isolate = i::Isolate::Current();
5060 i::DisallowHeapAllocation no_allocation;
5062 VisitorAdapter visitor_adapter(visitor);
5063 isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
5067 void v8::V8::VisitHandlesForPartialDependence(
5068 Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
5069 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
5070 DCHECK(isolate == i::Isolate::Current());
5071 i::DisallowHeapAllocation no_allocation;
5073 VisitorAdapter visitor_adapter(visitor);
5074 isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
5079 bool v8::V8::InitializeICU(const char* icu_data_file) {
5080 return i::InitializeICU(icu_data_file);
5084 const char* v8::V8::GetVersion() {
5085 return i::Version::GetVersion();
5089 static i::Handle<i::Context> CreateEnvironment(
5090 i::Isolate* isolate,
5091 v8::ExtensionConfiguration* extensions,
5092 v8::Handle<ObjectTemplate> global_template,
5093 v8::Handle<Value> maybe_global_proxy) {
5094 i::Handle<i::Context> env;
5096 // Enter V8 via an ENTER_V8 scope.
5099 v8::Handle<ObjectTemplate> proxy_template = global_template;
5100 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
5101 i::Handle<i::FunctionTemplateInfo> global_constructor;
5103 if (!global_template.IsEmpty()) {
5104 // Make sure that the global_template has a constructor.
5105 global_constructor = EnsureConstructor(isolate, *global_template);
5107 // Create a fresh template for the global proxy object.
5108 proxy_template = ObjectTemplate::New(
5109 reinterpret_cast<v8::Isolate*>(isolate));
5110 proxy_constructor = EnsureConstructor(isolate, *proxy_template);
5112 // Set the global template to be the prototype template of
5113 // global proxy template.
5114 proxy_constructor->set_prototype_template(
5115 *Utils::OpenHandle(*global_template));
5117 // Migrate security handlers from global_template to
5118 // proxy_template. Temporarily removing access check
5119 // information from the global template.
5120 if (!global_constructor->access_check_info()->IsUndefined()) {
5121 proxy_constructor->set_access_check_info(
5122 global_constructor->access_check_info());
5123 proxy_constructor->set_needs_access_check(
5124 global_constructor->needs_access_check());
5125 global_constructor->set_needs_access_check(false);
5126 global_constructor->set_access_check_info(
5127 isolate->heap()->undefined_value());
5131 i::Handle<i::Object> proxy = Utils::OpenHandle(*maybe_global_proxy, true);
5132 i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
5133 if (!proxy.is_null()) {
5134 maybe_proxy = i::Handle<i::JSGlobalProxy>::cast(proxy);
5136 // Create the environment.
5137 env = isolate->bootstrapper()->CreateEnvironment(
5138 maybe_proxy, proxy_template, extensions);
5140 // Restore the access check info on the global template.
5141 if (!global_template.IsEmpty()) {
5142 DCHECK(!global_constructor.is_null());
5143 DCHECK(!proxy_constructor.is_null());
5144 global_constructor->set_access_check_info(
5145 proxy_constructor->access_check_info());
5146 global_constructor->set_needs_access_check(
5147 proxy_constructor->needs_access_check());
5155 Local<Context> v8::Context::New(
5156 v8::Isolate* external_isolate,
5157 v8::ExtensionConfiguration* extensions,
5158 v8::Handle<ObjectTemplate> global_template,
5159 v8::Handle<Value> global_object) {
5160 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
5161 EnsureInitializedForIsolate(isolate, "v8::Context::New()");
5162 LOG_API(isolate, "Context::New");
5163 ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
5164 i::HandleScope scope(isolate);
5165 ExtensionConfiguration no_extensions;
5166 if (extensions == NULL) extensions = &no_extensions;
5167 i::Handle<i::Context> env =
5168 CreateEnvironment(isolate, extensions, global_template, global_object);
5169 if (env.is_null()) return Local<Context>();
5170 return Utils::ToLocal(scope.CloseAndEscape(env));
5174 void v8::Context::SetSecurityToken(Handle<Value> token) {
5175 i::Isolate* isolate = i::Isolate::Current();
5177 i::Handle<i::Context> env = Utils::OpenHandle(this);
5178 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
5179 env->set_security_token(*token_handle);
5183 void v8::Context::UseDefaultSecurityToken() {
5184 i::Isolate* isolate = i::Isolate::Current();
5186 i::Handle<i::Context> env = Utils::OpenHandle(this);
5187 env->set_security_token(env->global_object());
5191 Handle<Value> v8::Context::GetSecurityToken() {
5192 i::Isolate* isolate = i::Isolate::Current();
5193 i::Handle<i::Context> env = Utils::OpenHandle(this);
5194 i::Object* security_token = env->security_token();
5195 i::Handle<i::Object> token_handle(security_token, isolate);
5196 return Utils::ToLocal(token_handle);
5200 v8::Isolate* Context::GetIsolate() {
5201 i::Handle<i::Context> env = Utils::OpenHandle(this);
5202 return reinterpret_cast<Isolate*>(env->GetIsolate());
5206 v8::Local<v8::Object> Context::Global() {
5207 i::Handle<i::Context> context = Utils::OpenHandle(this);
5208 i::Isolate* isolate = context->GetIsolate();
5209 i::Handle<i::Object> global(context->global_proxy(), isolate);
5210 // TODO(dcarney): This should always return the global proxy
5211 // but can't presently as calls to GetProtoype will return the wrong result.
5212 if (i::Handle<i::JSGlobalProxy>::cast(
5213 global)->IsDetachedFrom(context->global_object())) {
5214 global = i::Handle<i::Object>(context->global_object(), isolate);
5216 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
5220 void Context::DetachGlobal() {
5221 i::Handle<i::Context> context = Utils::OpenHandle(this);
5222 i::Isolate* isolate = context->GetIsolate();
5224 isolate->bootstrapper()->DetachGlobal(context);
5228 void Context::AllowCodeGenerationFromStrings(bool allow) {
5229 i::Handle<i::Context> context = Utils::OpenHandle(this);
5230 i::Isolate* isolate = context->GetIsolate();
5232 context->set_allow_code_gen_from_strings(
5233 allow ? isolate->heap()->true_value() : isolate->heap()->false_value());
5237 bool Context::IsCodeGenerationFromStringsAllowed() {
5238 i::Handle<i::Context> context = Utils::OpenHandle(this);
5239 return !context->allow_code_gen_from_strings()->IsFalse();
5243 void Context::SetErrorMessageForCodeGenerationFromStrings(
5244 Handle<String> error) {
5245 i::Handle<i::Context> context = Utils::OpenHandle(this);
5246 i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
5247 context->set_error_message_for_code_gen_from_strings(*error_handle);
5251 Local<v8::Object> ObjectTemplate::NewInstance() {
5252 i::Isolate* isolate = i::Isolate::Current();
5253 ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
5254 return Local<v8::Object>());
5255 LOG_API(isolate, "ObjectTemplate::NewInstance");
5257 EXCEPTION_PREAMBLE(isolate);
5258 i::Handle<i::Object> obj;
5259 has_pending_exception = !i::Execution::InstantiateObject(
5260 Utils::OpenHandle(this)).ToHandle(&obj);
5261 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
5262 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
5266 Local<v8::Function> FunctionTemplate::GetFunction() {
5267 i::Isolate* isolate = i::Isolate::Current();
5268 ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
5269 return Local<v8::Function>());
5270 LOG_API(isolate, "FunctionTemplate::GetFunction");
5272 EXCEPTION_PREAMBLE(isolate);
5273 i::Handle<i::Object> obj;
5274 has_pending_exception = !i::Execution::InstantiateFunction(
5275 Utils::OpenHandle(this)).ToHandle(&obj);
5276 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
5277 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
5281 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
5282 ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
5284 i::Object* obj = *Utils::OpenHandle(*value);
5285 return Utils::OpenHandle(this)->IsTemplateFor(obj);
5289 Local<External> v8::External::New(Isolate* isolate, void* value) {
5290 STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
5291 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5292 EnsureInitializedForIsolate(i_isolate, "v8::External::New()");
5293 LOG_API(i_isolate, "External::New");
5294 ENTER_V8(i_isolate);
5295 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
5296 return Utils::ExternalToLocal(external);
5300 void* External::Value() const {
5301 return ExternalValue(*Utils::OpenHandle(this));
5305 // anonymous namespace for string creation helper functions
5308 inline int StringLength(const char* string) {
5309 return i::StrLength(string);
5313 inline int StringLength(const uint8_t* string) {
5314 return i::StrLength(reinterpret_cast<const char*>(string));
5318 inline int StringLength(const uint16_t* string) {
5320 while (string[length] != '\0')
5327 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5328 String::NewStringType type,
5329 i::Vector<const char> string) {
5330 if (type == String::kInternalizedString) {
5331 return factory->InternalizeUtf8String(string);
5333 return factory->NewStringFromUtf8(string);
5338 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5339 String::NewStringType type,
5340 i::Vector<const uint8_t> string) {
5341 if (type == String::kInternalizedString) {
5342 return factory->InternalizeOneByteString(string);
5344 return factory->NewStringFromOneByte(string);
5349 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5350 String::NewStringType type,
5351 i::Vector<const uint16_t> string) {
5352 if (type == String::kInternalizedString) {
5353 return factory->InternalizeTwoByteString(string);
5355 return factory->NewStringFromTwoByte(string);
5359 template<typename Char>
5360 inline Local<String> NewString(Isolate* v8_isolate,
5361 const char* location,
5364 String::NewStringType type,
5366 i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
5367 EnsureInitializedForIsolate(isolate, location);
5368 LOG_API(isolate, env);
5369 if (length == 0 && type != String::kUndetectableString) {
5370 return String::Empty(v8_isolate);
5373 if (length == -1) length = StringLength(data);
5374 // We do not expect this to fail. Change this if it does.
5375 i::Handle<i::String> result = NewString(
5378 i::Vector<const Char>(data, length)).ToHandleChecked();
5379 if (type == String::kUndetectableString) {
5380 result->MarkAsUndetectable();
5382 return Utils::ToLocal(result);
5385 } // anonymous namespace
5388 Local<String> String::NewFromUtf8(Isolate* isolate,
5392 return NewString(isolate,
5393 "v8::String::NewFromUtf8()",
5394 "String::NewFromUtf8",
5401 Local<String> String::NewFromOneByte(Isolate* isolate,
5402 const uint8_t* data,
5405 return NewString(isolate,
5406 "v8::String::NewFromOneByte()",
5407 "String::NewFromOneByte",
5414 Local<String> String::NewFromTwoByte(Isolate* isolate,
5415 const uint16_t* data,
5418 return NewString(isolate,
5419 "v8::String::NewFromTwoByte()",
5420 "String::NewFromTwoByte",
5427 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
5428 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
5429 i::Isolate* isolate = left_string->GetIsolate();
5430 EnsureInitializedForIsolate(isolate, "v8::String::New()");
5431 LOG_API(isolate, "String::New(char)");
5433 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
5434 // We do not expect this to fail. Change this if it does.
5435 i::Handle<i::String> result = isolate->factory()->NewConsString(
5436 left_string, right_string).ToHandleChecked();
5437 return Utils::ToLocal(result);
5441 static i::Handle<i::String> NewExternalStringHandle(
5442 i::Isolate* isolate,
5443 v8::String::ExternalStringResource* resource) {
5444 // We do not expect this to fail. Change this if it does.
5445 return isolate->factory()->NewExternalStringFromTwoByte(
5446 resource).ToHandleChecked();
5450 static i::Handle<i::String> NewExternalAsciiStringHandle(
5451 i::Isolate* isolate,
5452 v8::String::ExternalAsciiStringResource* resource) {
5453 // We do not expect this to fail. Change this if it does.
5454 return isolate->factory()->NewExternalStringFromAscii(
5455 resource).ToHandleChecked();
5459 Local<String> v8::String::NewExternal(
5461 v8::String::ExternalStringResource* resource) {
5462 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5463 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5464 LOG_API(i_isolate, "String::NewExternal");
5465 ENTER_V8(i_isolate);
5466 CHECK(resource && resource->data());
5467 i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
5468 i_isolate->heap()->external_string_table()->AddString(*result);
5469 return Utils::ToLocal(result);
5473 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
5474 i::Handle<i::String> obj = Utils::OpenHandle(this);
5475 i::Isolate* isolate = obj->GetIsolate();
5476 if (i::StringShape(*obj).IsExternal()) {
5477 return false; // Already an external string.
5480 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5483 if (isolate->heap()->IsInGCPostProcessing()) {
5486 CHECK(resource && resource->data());
5488 bool result = obj->MakeExternal(resource);
5489 // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5490 DCHECK(!CanMakeExternal() || result);
5492 DCHECK(obj->IsExternalString());
5493 isolate->heap()->external_string_table()->AddString(*obj);
5499 Local<String> v8::String::NewExternal(
5501 v8::String::ExternalAsciiStringResource* resource) {
5502 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5503 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5504 LOG_API(i_isolate, "String::NewExternal");
5505 ENTER_V8(i_isolate);
5506 CHECK(resource && resource->data());
5507 i::Handle<i::String> result =
5508 NewExternalAsciiStringHandle(i_isolate, resource);
5509 i_isolate->heap()->external_string_table()->AddString(*result);
5510 return Utils::ToLocal(result);
5514 bool v8::String::MakeExternal(
5515 v8::String::ExternalAsciiStringResource* resource) {
5516 i::Handle<i::String> obj = Utils::OpenHandle(this);
5517 i::Isolate* isolate = obj->GetIsolate();
5518 if (i::StringShape(*obj).IsExternal()) {
5519 return false; // Already an external string.
5522 if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5525 if (isolate->heap()->IsInGCPostProcessing()) {
5528 CHECK(resource && resource->data());
5530 bool result = obj->MakeExternal(resource);
5531 // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5532 DCHECK(!CanMakeExternal() || result);
5534 DCHECK(obj->IsExternalString());
5535 isolate->heap()->external_string_table()->AddString(*obj);
5541 bool v8::String::CanMakeExternal() {
5542 if (!internal::FLAG_clever_optimizations) return false;
5543 i::Handle<i::String> obj = Utils::OpenHandle(this);
5544 i::Isolate* isolate = obj->GetIsolate();
5546 // TODO(yangguo): Externalizing sliced/cons strings allocates.
5547 // This rule can be removed when all code that can
5548 // trigger an access check is handlified and therefore GC safe.
5549 if (isolate->heap()->old_pointer_space()->Contains(*obj)) return false;
5551 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
5552 int size = obj->Size(); // Byte size of the original string.
5553 if (size < i::ExternalString::kShortSize) return false;
5554 i::StringShape shape(*obj);
5555 return !shape.IsExternal();
5559 Local<v8::Object> v8::Object::New(Isolate* isolate) {
5560 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5561 EnsureInitializedForIsolate(i_isolate, "v8::Object::New()");
5562 LOG_API(i_isolate, "Object::New");
5563 ENTER_V8(i_isolate);
5564 i::Handle<i::JSObject> obj =
5565 i_isolate->factory()->NewJSObject(i_isolate->object_function());
5566 return Utils::ToLocal(obj);
5570 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
5571 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5572 EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()");
5573 LOG_API(i_isolate, "NumberObject::New");
5574 ENTER_V8(i_isolate);
5575 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
5576 i::Handle<i::Object> obj =
5577 i::Object::ToObject(i_isolate, number).ToHandleChecked();
5578 return Utils::ToLocal(obj);
5582 double v8::NumberObject::ValueOf() const {
5583 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5584 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5585 i::Isolate* isolate = jsvalue->GetIsolate();
5586 LOG_API(isolate, "NumberObject::NumberValue");
5587 return jsvalue->value()->Number();
5591 Local<v8::Value> v8::BooleanObject::New(bool value) {
5592 i::Isolate* isolate = i::Isolate::Current();
5593 EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
5594 LOG_API(isolate, "BooleanObject::New");
5596 i::Handle<i::Object> boolean(value
5597 ? isolate->heap()->true_value()
5598 : isolate->heap()->false_value(),
5600 i::Handle<i::Object> obj =
5601 i::Object::ToObject(isolate, boolean).ToHandleChecked();
5602 return Utils::ToLocal(obj);
5606 bool v8::BooleanObject::ValueOf() const {
5607 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5608 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5609 i::Isolate* isolate = jsvalue->GetIsolate();
5610 LOG_API(isolate, "BooleanObject::BooleanValue");
5611 return jsvalue->value()->IsTrue();
5615 Local<v8::Value> v8::StringObject::New(Handle<String> value) {
5616 i::Handle<i::String> string = Utils::OpenHandle(*value);
5617 i::Isolate* isolate = string->GetIsolate();
5618 EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
5619 LOG_API(isolate, "StringObject::New");
5621 i::Handle<i::Object> obj =
5622 i::Object::ToObject(isolate, string).ToHandleChecked();
5623 return Utils::ToLocal(obj);
5627 Local<v8::String> v8::StringObject::ValueOf() const {
5628 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5629 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5630 i::Isolate* isolate = jsvalue->GetIsolate();
5631 LOG_API(isolate, "StringObject::StringValue");
5632 return Utils::ToLocal(
5633 i::Handle<i::String>(i::String::cast(jsvalue->value())));
5637 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
5638 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5639 EnsureInitializedForIsolate(i_isolate, "v8::SymbolObject::New()");
5640 LOG_API(i_isolate, "SymbolObject::New");
5641 ENTER_V8(i_isolate);
5642 i::Handle<i::Object> obj = i::Object::ToObject(
5643 i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
5644 return Utils::ToLocal(obj);
5648 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
5649 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5650 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5651 i::Isolate* isolate = jsvalue->GetIsolate();
5652 LOG_API(isolate, "SymbolObject::SymbolValue");
5653 return Utils::ToLocal(
5654 i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
5658 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
5659 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5660 EnsureInitializedForIsolate(i_isolate, "v8::Date::New()");
5661 LOG_API(i_isolate, "Date::New");
5662 if (std::isnan(time)) {
5663 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5664 time = base::OS::nan_value();
5666 ENTER_V8(i_isolate);
5667 EXCEPTION_PREAMBLE(i_isolate);
5668 i::Handle<i::Object> obj;
5669 has_pending_exception = !i::Execution::NewDate(
5670 i_isolate, time).ToHandle(&obj);
5671 EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
5672 return Utils::ToLocal(obj);
5676 double v8::Date::ValueOf() const {
5677 i::Handle<i::Object> obj = Utils::OpenHandle(this);
5678 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
5679 i::Isolate* isolate = jsdate->GetIsolate();
5680 LOG_API(isolate, "Date::NumberValue");
5681 return jsdate->value()->Number();
5685 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
5686 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5687 if (!i_isolate->IsInitialized()) return;
5688 ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
5690 LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
5691 ENTER_V8(i_isolate);
5693 i_isolate->date_cache()->ResetDateCache();
5695 if (!i_isolate->eternal_handles()->Exists(
5696 i::EternalHandles::DATE_CACHE_VERSION)) {
5699 i::Handle<i::FixedArray> date_cache_version =
5700 i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
5701 i::EternalHandles::DATE_CACHE_VERSION));
5702 DCHECK_EQ(1, date_cache_version->length());
5703 CHECK(date_cache_version->get(0)->IsSmi());
5704 date_cache_version->set(
5706 i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
5710 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
5711 i::Isolate* isolate = i::Isolate::Current();
5712 uint8_t flags_buf[3];
5714 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
5715 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
5716 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
5717 DCHECK(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
5718 return isolate->factory()->InternalizeOneByteString(
5719 i::Vector<const uint8_t>(flags_buf, num_flags));
5723 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
5725 i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
5726 EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
5727 LOG_API(isolate, "RegExp::New");
5729 EXCEPTION_PREAMBLE(isolate);
5730 i::Handle<i::JSRegExp> obj;
5731 has_pending_exception = !i::Execution::NewJSRegExp(
5732 Utils::OpenHandle(*pattern),
5733 RegExpFlagsToString(flags)).ToHandle(&obj);
5734 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
5735 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
5739 Local<v8::String> v8::RegExp::GetSource() const {
5740 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5741 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
5745 // Assert that the static flags cast in GetFlags is valid.
5746 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
5747 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
5748 static_cast<int>(i::JSRegExp::internal_flag))
5749 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
5750 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
5751 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
5752 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
5753 #undef REGEXP_FLAG_ASSERT_EQ
5755 v8::RegExp::Flags v8::RegExp::GetFlags() const {
5756 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5757 return static_cast<RegExp::Flags>(obj->GetFlags().value());
5761 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
5762 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5763 EnsureInitializedForIsolate(i_isolate, "v8::Array::New()");
5764 LOG_API(i_isolate, "Array::New");
5765 ENTER_V8(i_isolate);
5766 int real_length = length > 0 ? length : 0;
5767 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
5768 i::Handle<i::Object> length_obj =
5769 i_isolate->factory()->NewNumberFromInt(real_length);
5770 obj->set_length(*length_obj);
5771 return Utils::ToLocal(obj);
5775 uint32_t v8::Array::Length() const {
5776 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
5777 i::Object* length = obj->length();
5778 if (length->IsSmi()) {
5779 return i::Smi::cast(length)->value();
5781 return static_cast<uint32_t>(length->Number());
5786 Local<Object> Array::CloneElementAt(uint32_t index) {
5787 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
5788 ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
5789 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
5790 if (!self->HasFastObjectElements()) {
5791 return Local<Object>();
5793 i::FixedArray* elms = i::FixedArray::cast(self->elements());
5794 i::Object* paragon = elms->get(index);
5795 if (!paragon->IsJSObject()) {
5796 return Local<Object>();
5798 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5799 EXCEPTION_PREAMBLE(isolate);
5801 i::Handle<i::JSObject> result =
5802 isolate->factory()->CopyJSObject(paragon_handle);
5803 has_pending_exception = result.is_null();
5804 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5805 return Utils::ToLocal(result);
5809 bool Value::IsPromise() const {
5810 i::Handle<i::Object> val = Utils::OpenHandle(this);
5811 if (!val->IsJSObject()) return false;
5812 i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
5813 i::Isolate* isolate = obj->GetIsolate();
5814 LOG_API(isolate, "IsPromise");
5816 EXCEPTION_PREAMBLE(isolate);
5817 i::Handle<i::Object> argv[] = { obj };
5818 i::Handle<i::Object> b;
5819 has_pending_exception = !i::Execution::Call(
5821 isolate->is_promise(),
5822 isolate->factory()->undefined_value(),
5823 ARRAY_SIZE(argv), argv,
5824 false).ToHandle(&b);
5825 EXCEPTION_BAILOUT_CHECK(isolate, false);
5826 return b->BooleanValue();
5830 Local<Promise::Resolver> Promise::Resolver::New(Isolate* v8_isolate) {
5831 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5832 LOG_API(isolate, "Promise::Resolver::New");
5834 EXCEPTION_PREAMBLE(isolate);
5835 i::Handle<i::Object> result;
5836 has_pending_exception = !i::Execution::Call(
5838 isolate->promise_create(),
5839 isolate->factory()->undefined_value(),
5841 false).ToHandle(&result);
5842 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
5843 return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
5847 Local<Promise> Promise::Resolver::GetPromise() {
5848 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5849 return Local<Promise>::Cast(Utils::ToLocal(promise));
5853 void Promise::Resolver::Resolve(Handle<Value> value) {
5854 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5855 i::Isolate* isolate = promise->GetIsolate();
5856 LOG_API(isolate, "Promise::Resolver::Resolve");
5858 EXCEPTION_PREAMBLE(isolate);
5859 i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5860 has_pending_exception = i::Execution::Call(
5862 isolate->promise_resolve(),
5863 isolate->factory()->undefined_value(),
5864 ARRAY_SIZE(argv), argv,
5866 EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5870 void Promise::Resolver::Reject(Handle<Value> value) {
5871 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5872 i::Isolate* isolate = promise->GetIsolate();
5873 LOG_API(isolate, "Promise::Resolver::Reject");
5875 EXCEPTION_PREAMBLE(isolate);
5876 i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5877 has_pending_exception = i::Execution::Call(
5879 isolate->promise_reject(),
5880 isolate->factory()->undefined_value(),
5881 ARRAY_SIZE(argv), argv,
5883 EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5887 Local<Promise> Promise::Chain(Handle<Function> handler) {
5888 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5889 i::Isolate* isolate = promise->GetIsolate();
5890 LOG_API(isolate, "Promise::Chain");
5892 EXCEPTION_PREAMBLE(isolate);
5893 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5894 i::Handle<i::Object> result;
5895 has_pending_exception = !i::Execution::Call(
5897 isolate->promise_chain(),
5899 ARRAY_SIZE(argv), argv,
5900 false).ToHandle(&result);
5901 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5902 return Local<Promise>::Cast(Utils::ToLocal(result));
5906 Local<Promise> Promise::Catch(Handle<Function> handler) {
5907 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5908 i::Isolate* isolate = promise->GetIsolate();
5909 LOG_API(isolate, "Promise::Catch");
5911 EXCEPTION_PREAMBLE(isolate);
5912 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5913 i::Handle<i::Object> result;
5914 has_pending_exception = !i::Execution::Call(
5916 isolate->promise_catch(),
5918 ARRAY_SIZE(argv), argv,
5919 false).ToHandle(&result);
5920 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5921 return Local<Promise>::Cast(Utils::ToLocal(result));
5925 Local<Promise> Promise::Then(Handle<Function> handler) {
5926 i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5927 i::Isolate* isolate = promise->GetIsolate();
5928 LOG_API(isolate, "Promise::Then");
5930 EXCEPTION_PREAMBLE(isolate);
5931 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5932 i::Handle<i::Object> result;
5933 has_pending_exception = !i::Execution::Call(
5935 isolate->promise_then(),
5937 ARRAY_SIZE(argv), argv,
5938 false).ToHandle(&result);
5939 EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5940 return Local<Promise>::Cast(Utils::ToLocal(result));
5944 bool v8::ArrayBuffer::IsExternal() const {
5945 return Utils::OpenHandle(this)->is_external();
5949 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
5950 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5951 Utils::ApiCheck(!obj->is_external(),
5952 "v8::ArrayBuffer::Externalize",
5953 "ArrayBuffer already externalized");
5954 obj->set_is_external(true);
5955 size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
5957 contents.data_ = obj->backing_store();
5958 contents.byte_length_ = byte_length;
5963 void v8::ArrayBuffer::Neuter() {
5964 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5965 i::Isolate* isolate = obj->GetIsolate();
5966 Utils::ApiCheck(obj->is_external(),
5967 "v8::ArrayBuffer::Neuter",
5968 "Only externalized ArrayBuffers can be neutered");
5969 LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
5971 i::Runtime::NeuterArrayBuffer(obj);
5975 size_t v8::ArrayBuffer::ByteLength() const {
5976 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5977 return static_cast<size_t>(obj->byte_length()->Number());
5981 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
5982 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5983 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)");
5984 LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
5985 ENTER_V8(i_isolate);
5986 i::Handle<i::JSArrayBuffer> obj =
5987 i_isolate->factory()->NewJSArrayBuffer();
5988 i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
5989 return Utils::ToLocal(obj);
5993 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
5994 size_t byte_length) {
5995 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5996 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5997 LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5998 ENTER_V8(i_isolate);
5999 i::Handle<i::JSArrayBuffer> obj =
6000 i_isolate->factory()->NewJSArrayBuffer();
6001 i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
6002 return Utils::ToLocal(obj);
6006 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
6007 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6008 i::Handle<i::JSArrayBuffer> buffer;
6009 if (obj->IsJSDataView()) {
6010 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
6011 DCHECK(data_view->buffer()->IsJSArrayBuffer());
6012 buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()));
6014 DCHECK(obj->IsJSTypedArray());
6015 buffer = i::JSTypedArray::cast(*obj)->GetBuffer();
6017 return Utils::ToLocal(buffer);
6021 size_t v8::ArrayBufferView::ByteOffset() {
6022 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6023 return static_cast<size_t>(obj->byte_offset()->Number());
6027 size_t v8::ArrayBufferView::ByteLength() {
6028 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6029 return static_cast<size_t>(obj->byte_length()->Number());
6033 size_t v8::TypedArray::Length() {
6034 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
6035 return static_cast<size_t>(obj->length()->Number());
6039 static inline void SetupArrayBufferView(
6040 i::Isolate* isolate,
6041 i::Handle<i::JSArrayBufferView> obj,
6042 i::Handle<i::JSArrayBuffer> buffer,
6044 size_t byte_length) {
6045 DCHECK(byte_offset + byte_length <=
6046 static_cast<size_t>(buffer->byte_length()->Number()));
6048 obj->set_buffer(*buffer);
6050 obj->set_weak_next(buffer->weak_first_view());
6051 buffer->set_weak_first_view(*obj);
6053 i::Handle<i::Object> byte_offset_object =
6054 isolate->factory()->NewNumberFromSize(byte_offset);
6055 obj->set_byte_offset(*byte_offset_object);
6057 i::Handle<i::Object> byte_length_object =
6058 isolate->factory()->NewNumberFromSize(byte_length);
6059 obj->set_byte_length(*byte_length_object);
6062 template<typename ElementType,
6063 ExternalArrayType array_type,
6064 i::ElementsKind elements_kind>
6065 i::Handle<i::JSTypedArray> NewTypedArray(
6066 i::Isolate* isolate,
6067 Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
6068 i::Handle<i::JSTypedArray> obj =
6069 isolate->factory()->NewJSTypedArray(array_type);
6070 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6072 DCHECK(byte_offset % sizeof(ElementType) == 0);
6074 CHECK(length <= (std::numeric_limits<size_t>::max() / sizeof(ElementType)));
6075 CHECK(length <= static_cast<size_t>(i::Smi::kMaxValue));
6076 size_t byte_length = length * sizeof(ElementType);
6077 SetupArrayBufferView(
6078 isolate, obj, buffer, byte_offset, byte_length);
6080 i::Handle<i::Object> length_object =
6081 isolate->factory()->NewNumberFromSize(length);
6082 obj->set_length(*length_object);
6084 i::Handle<i::ExternalArray> elements =
6085 isolate->factory()->NewExternalArray(
6086 static_cast<int>(length), array_type,
6087 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
6088 i::Handle<i::Map> map =
6089 i::JSObject::GetElementsTransitionMap(obj, elements_kind);
6090 i::JSObject::SetMapAndElements(obj, map, elements);
6095 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \
6096 Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer, \
6097 size_t byte_offset, size_t length) { \
6098 i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
6099 EnsureInitializedForIsolate(isolate, \
6100 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
6102 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)"); \
6103 ENTER_V8(isolate); \
6104 if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue), \
6105 "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)", \
6106 "length exceeds max allowed value")) { \
6107 return Local<Type##Array>(); \
6109 i::Handle<i::JSTypedArray> obj = \
6110 NewTypedArray<ctype, v8::kExternal##Type##Array, \
6111 i::EXTERNAL_##TYPE##_ELEMENTS>( \
6112 isolate, array_buffer, byte_offset, length); \
6113 return Utils::ToLocal##Type##Array(obj); \
6117 TYPED_ARRAYS(TYPED_ARRAY_NEW)
6118 #undef TYPED_ARRAY_NEW
6120 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
6121 size_t byte_offset, size_t byte_length) {
6122 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6123 i::Isolate* isolate = buffer->GetIsolate();
6124 EnsureInitializedForIsolate(
6125 isolate, "v8::DataView::New(void*, size_t, size_t)");
6126 LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
6128 i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
6129 SetupArrayBufferView(
6130 isolate, obj, buffer, byte_offset, byte_length);
6131 return Utils::ToLocal(obj);
6135 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
6136 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6137 EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
6138 LOG_API(i_isolate, "Symbol::New()");
6139 ENTER_V8(i_isolate);
6140 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6141 if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
6142 return Utils::ToLocal(result);
6146 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
6147 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6148 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6149 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6150 i::Handle<i::String> part = i_isolate->factory()->for_string();
6151 i::Handle<i::JSObject> symbols =
6152 i::Handle<i::JSObject>::cast(
6153 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6154 i::Handle<i::Object> symbol =
6155 i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6156 if (!symbol->IsSymbol()) {
6157 DCHECK(symbol->IsUndefined());
6158 symbol = i_isolate->factory()->NewSymbol();
6159 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6160 i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
6162 return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6166 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
6167 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6168 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6169 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6170 i::Handle<i::String> part = i_isolate->factory()->for_api_string();
6171 i::Handle<i::JSObject> symbols =
6172 i::Handle<i::JSObject>::cast(
6173 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6174 i::Handle<i::Object> symbol =
6175 i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6176 if (!symbol->IsSymbol()) {
6177 DCHECK(symbol->IsUndefined());
6178 symbol = i_isolate->factory()->NewSymbol();
6179 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6180 i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
6182 return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6186 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
6187 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6188 EnsureInitializedForIsolate(i_isolate, "v8::Private::New()");
6189 LOG_API(i_isolate, "Private::New()");
6190 ENTER_V8(i_isolate);
6191 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
6192 if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
6193 Local<Symbol> result = Utils::ToLocal(symbol);
6194 return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6198 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
6199 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6200 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6201 i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6202 i::Handle<i::String> part = i_isolate->factory()->private_api_string();
6203 i::Handle<i::JSObject> privates =
6204 i::Handle<i::JSObject>::cast(
6205 i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6206 i::Handle<i::Object> symbol =
6207 i::Object::GetPropertyOrElement(privates, i_name).ToHandleChecked();
6208 if (!symbol->IsSymbol()) {
6209 DCHECK(symbol->IsUndefined());
6210 symbol = i_isolate->factory()->NewPrivateSymbol();
6211 i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6212 i::JSObject::SetProperty(privates, i_name, symbol, i::STRICT).Assert();
6214 Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6215 return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6219 Local<Number> v8::Number::New(Isolate* isolate, double value) {
6220 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6221 DCHECK(internal_isolate->IsInitialized());
6222 if (std::isnan(value)) {
6223 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6224 value = base::OS::nan_value();
6226 ENTER_V8(internal_isolate);
6227 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6228 return Utils::NumberToLocal(result);
6232 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
6233 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6234 DCHECK(internal_isolate->IsInitialized());
6235 if (i::Smi::IsValid(value)) {
6236 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
6239 ENTER_V8(internal_isolate);
6240 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6241 return Utils::IntegerToLocal(result);
6245 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
6246 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6247 DCHECK(internal_isolate->IsInitialized());
6248 bool fits_into_int32_t = (value & (1 << 31)) == 0;
6249 if (fits_into_int32_t) {
6250 return Integer::New(isolate, static_cast<int32_t>(value));
6252 ENTER_V8(internal_isolate);
6253 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6254 return Utils::IntegerToLocal(result);
6258 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
6259 i::Isolate* isolate = i::Isolate::Current();
6260 EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
6261 ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
6263 i::HandleScope scope(isolate);
6264 NeanderArray listeners(isolate->factory()->message_listeners());
6265 NeanderObject obj(isolate, 2);
6266 obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
6267 obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
6268 : *Utils::OpenHandle(*data));
6269 listeners.add(obj.value());
6274 void V8::RemoveMessageListeners(MessageCallback that) {
6275 i::Isolate* isolate = i::Isolate::Current();
6276 EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
6277 ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
6279 i::HandleScope scope(isolate);
6280 NeanderArray listeners(isolate->factory()->message_listeners());
6281 for (int i = 0; i < listeners.length(); i++) {
6282 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
6284 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
6285 i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
6286 if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
6287 listeners.set(i, isolate->heap()->undefined_value());
6293 void V8::SetCaptureStackTraceForUncaughtExceptions(
6296 StackTrace::StackTraceOptions options) {
6297 i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
6304 void V8::SetFailedAccessCheckCallbackFunction(
6305 FailedAccessCheckCallback callback) {
6306 i::Isolate* isolate = i::Isolate::Current();
6307 isolate->SetFailedAccessCheckCallback(callback);
6311 void Isolate::CollectAllGarbage(const char* gc_reason) {
6312 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6313 i::Heap::kNoGCFlags, gc_reason);
6317 HeapProfiler* Isolate::GetHeapProfiler() {
6318 i::HeapProfiler* heap_profiler =
6319 reinterpret_cast<i::Isolate*>(this)->heap_profiler();
6320 return reinterpret_cast<HeapProfiler*>(heap_profiler);
6324 CpuProfiler* Isolate::GetCpuProfiler() {
6325 i::CpuProfiler* cpu_profiler =
6326 reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
6327 return reinterpret_cast<CpuProfiler*>(cpu_profiler);
6331 bool Isolate::InContext() {
6332 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6333 return isolate->context() != NULL;
6337 v8::Local<v8::Context> Isolate::GetCurrentContext() {
6338 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6339 i::Context* context = isolate->context();
6340 if (context == NULL) return Local<Context>();
6341 i::Context* native_context = context->native_context();
6342 if (native_context == NULL) return Local<Context>();
6343 return Utils::ToLocal(i::Handle<i::Context>(native_context));
6347 v8::Local<v8::Context> Isolate::GetCallingContext() {
6348 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6349 i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
6350 if (calling.is_null()) return Local<Context>();
6351 return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
6355 v8::Local<v8::Context> Isolate::GetEnteredContext() {
6356 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6357 i::Handle<i::Object> last =
6358 isolate->handle_scope_implementer()->LastEnteredContext();
6359 if (last.is_null()) return Local<Context>();
6360 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
6364 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
6365 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6367 // If we're passed an empty handle, we throw an undefined exception
6368 // to deal more gracefully with out of memory situations.
6369 if (value.IsEmpty()) {
6370 isolate->ScheduleThrow(isolate->heap()->undefined_value());
6372 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
6374 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6378 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
6379 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6380 internal_isolate->global_handles()->SetObjectGroupId(
6381 v8::internal::Handle<v8::internal::Object>(object).location(),
6386 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
6387 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6388 internal_isolate->global_handles()->SetReferenceFromGroup(
6390 v8::internal::Handle<v8::internal::Object>(object).location());
6394 void Isolate::SetReference(internal::Object** parent,
6395 internal::Object** child) {
6396 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6397 i::Object** parent_location =
6398 v8::internal::Handle<v8::internal::Object>(parent).location();
6399 internal_isolate->global_handles()->SetReference(
6400 reinterpret_cast<i::HeapObject**>(parent_location),
6401 v8::internal::Handle<v8::internal::Object>(child).location());
6405 void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
6407 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6408 isolate->heap()->AddGCPrologueCallback(callback, gc_type);
6412 void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6413 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6414 isolate->heap()->RemoveGCPrologueCallback(callback);
6418 void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
6420 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6421 isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
6425 void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6426 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6427 isolate->heap()->RemoveGCEpilogueCallback(callback);
6431 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
6432 i::Isolate* isolate = i::Isolate::Current();
6433 isolate->heap()->AddGCPrologueCallback(
6434 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
6440 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6441 i::Isolate* isolate = i::Isolate::Current();
6442 isolate->heap()->RemoveGCPrologueCallback(
6443 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback));
6447 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
6448 i::Isolate* isolate = i::Isolate::Current();
6449 isolate->heap()->AddGCEpilogueCallback(
6450 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
6456 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6457 i::Isolate* isolate = i::Isolate::Current();
6458 isolate->heap()->RemoveGCEpilogueCallback(
6459 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback));
6463 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
6465 AllocationAction action) {
6466 i::Isolate* isolate = i::Isolate::Current();
6467 isolate->memory_allocator()->AddMemoryAllocationCallback(
6468 callback, space, action);
6472 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
6473 i::Isolate* isolate = i::Isolate::Current();
6474 isolate->memory_allocator()->RemoveMemoryAllocationCallback(
6479 void V8::TerminateExecution(Isolate* isolate) {
6480 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6481 i_isolate->stack_guard()->RequestTerminateExecution();
6485 bool V8::IsExecutionTerminating(Isolate* isolate) {
6486 i::Isolate* i_isolate = isolate != NULL ?
6487 reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current();
6488 return IsExecutionTerminatingCheck(i_isolate);
6492 void V8::CancelTerminateExecution(Isolate* isolate) {
6493 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6494 i_isolate->stack_guard()->ClearTerminateExecution();
6495 i_isolate->CancelTerminateExecution();
6499 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
6500 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6501 i_isolate->set_api_interrupt_callback(callback);
6502 i_isolate->set_api_interrupt_callback_data(data);
6503 i_isolate->stack_guard()->RequestApiInterrupt();
6507 void Isolate::ClearInterrupt() {
6508 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6509 i_isolate->stack_guard()->ClearApiInterrupt();
6510 i_isolate->set_api_interrupt_callback(NULL);
6511 i_isolate->set_api_interrupt_callback_data(NULL);
6515 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
6516 CHECK(i::FLAG_expose_gc);
6517 if (type == kMinorGarbageCollection) {
6518 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
6519 i::NEW_SPACE, "Isolate::RequestGarbageCollection",
6520 kGCCallbackFlagForced);
6522 DCHECK_EQ(kFullGarbageCollection, type);
6523 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6524 i::Heap::kAbortIncrementalMarkingMask,
6525 "Isolate::RequestGarbageCollection", kGCCallbackFlagForced);
6530 Isolate* Isolate::GetCurrent() {
6531 i::Isolate* isolate = i::Isolate::Current();
6532 return reinterpret_cast<Isolate*>(isolate);
6536 Isolate* Isolate::New() {
6537 i::Isolate* isolate = new i::Isolate();
6538 return reinterpret_cast<Isolate*>(isolate);
6542 void Isolate::Dispose() {
6543 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6544 if (!Utils::ApiCheck(!isolate->IsInUse(),
6545 "v8::Isolate::Dispose()",
6546 "Disposing the isolate that is entered by a thread.")) {
6549 isolate->TearDown();
6553 void Isolate::Enter() {
6554 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6559 void Isolate::Exit() {
6560 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6565 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
6567 Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
6568 : on_failure_(on_failure) {
6569 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6570 if (on_failure_ == CRASH_ON_FAILURE) {
6571 internal_ = reinterpret_cast<void*>(
6572 new i::DisallowJavascriptExecution(i_isolate));
6574 DCHECK_EQ(THROW_ON_FAILURE, on_failure);
6575 internal_ = reinterpret_cast<void*>(
6576 new i::ThrowOnJavascriptExecution(i_isolate));
6581 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
6582 if (on_failure_ == CRASH_ON_FAILURE) {
6583 delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
6585 delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
6590 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
6592 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6593 internal_assert_ = reinterpret_cast<void*>(
6594 new i::AllowJavascriptExecution(i_isolate));
6595 internal_throws_ = reinterpret_cast<void*>(
6596 new i::NoThrowOnJavascriptExecution(i_isolate));
6600 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
6601 delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
6602 delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
6606 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
6608 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
6609 isolate_->handle_scope_implementer()->IncrementCallDepth();
6613 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
6614 isolate_->handle_scope_implementer()->DecrementCallDepth();
6618 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
6619 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6620 if (!isolate->IsInitialized()) {
6621 heap_statistics->total_heap_size_ = 0;
6622 heap_statistics->total_heap_size_executable_ = 0;
6623 heap_statistics->total_physical_size_ = 0;
6624 heap_statistics->used_heap_size_ = 0;
6625 heap_statistics->heap_size_limit_ = 0;
6628 i::Heap* heap = isolate->heap();
6629 heap_statistics->total_heap_size_ = heap->CommittedMemory();
6630 heap_statistics->total_heap_size_executable_ =
6631 heap->CommittedMemoryExecutable();
6632 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
6633 heap_statistics->used_heap_size_ = heap->SizeOfObjects();
6634 heap_statistics->heap_size_limit_ = heap->MaxReserved();
6638 void Isolate::SetEventLogger(LogEventCallback that) {
6639 // Do not overwrite the event logger if we want to log explicitly.
6640 if (i::FLAG_log_timer_events) return;
6641 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6642 isolate->set_event_logger(that);
6646 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
6647 if (callback == NULL) return;
6648 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6649 isolate->AddCallCompletedCallback(callback);
6653 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
6654 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6655 isolate->RemoveCallCompletedCallback(callback);
6659 void Isolate::RunMicrotasks() {
6660 reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
6664 void Isolate::EnqueueMicrotask(Handle<Function> microtask) {
6665 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6666 isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
6670 void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
6671 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6672 i::HandleScope scope(isolate);
6673 i::Handle<i::CallHandlerInfo> callback_info =
6674 i::Handle<i::CallHandlerInfo>::cast(
6675 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
6676 SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
6677 SET_FIELD_WRAPPED(callback_info, set_data, data);
6678 isolate->EnqueueMicrotask(callback_info);
6682 void Isolate::SetAutorunMicrotasks(bool autorun) {
6683 reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun);
6687 bool Isolate::WillAutorunMicrotasks() const {
6688 return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks();
6692 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
6693 reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
6697 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
6698 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6699 isolate->stats_table()->SetCounterFunction(callback);
6700 isolate->InitializeLoggingAndCounters();
6701 isolate->counters()->ResetCounters();
6705 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6706 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6707 isolate->stats_table()->SetCreateHistogramFunction(callback);
6708 isolate->InitializeLoggingAndCounters();
6709 isolate->counters()->ResetHistograms();
6713 void Isolate::SetAddHistogramSampleFunction(
6714 AddHistogramSampleCallback callback) {
6715 reinterpret_cast<i::Isolate*>(this)
6717 ->SetAddHistogramSampleFunction(callback);
6721 bool v8::Isolate::IdleNotification(int idle_time_in_ms) {
6722 // Returning true tells the caller that it need not
6723 // continue to call IdleNotification.
6724 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6725 if (!i::FLAG_use_idle_notification) return true;
6726 return isolate->heap()->IdleNotification(idle_time_in_ms);
6730 void v8::Isolate::LowMemoryNotification() {
6731 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6733 i::HistogramTimerScope idle_notification_scope(
6734 isolate->counters()->gc_low_memory_notification());
6735 isolate->heap()->CollectAllAvailableGarbage("low memory notification");
6740 int v8::Isolate::ContextDisposedNotification() {
6741 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6742 return isolate->heap()->NotifyContextDisposed();
6746 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
6747 : str_(NULL), length_(0) {
6748 i::Isolate* isolate = i::Isolate::Current();
6749 if (obj.IsEmpty()) return;
6751 i::HandleScope scope(isolate);
6753 Handle<String> str = obj->ToString();
6754 if (str.IsEmpty()) return;
6755 i::Handle<i::String> i_str = Utils::OpenHandle(*str);
6756 length_ = v8::Utf8Length(*i_str, isolate);
6757 str_ = i::NewArray<char>(length_ + 1);
6758 str->WriteUtf8(str_);
6762 String::Utf8Value::~Utf8Value() {
6763 i::DeleteArray(str_);
6767 String::Value::Value(v8::Handle<v8::Value> obj)
6768 : str_(NULL), length_(0) {
6769 i::Isolate* isolate = i::Isolate::Current();
6770 if (obj.IsEmpty()) return;
6772 i::HandleScope scope(isolate);
6774 Handle<String> str = obj->ToString();
6775 if (str.IsEmpty()) return;
6776 length_ = str->Length();
6777 str_ = i::NewArray<uint16_t>(length_ + 1);
6782 String::Value::~Value() {
6783 i::DeleteArray(str_);
6787 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
6788 i::Isolate* isolate = i::Isolate::Current();
6789 LOG_API(isolate, "RangeError");
6790 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
6794 i::HandleScope scope(isolate);
6795 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6796 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
6799 i::Handle<i::Object> result(error, isolate);
6800 return Utils::ToLocal(result);
6804 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
6805 i::Isolate* isolate = i::Isolate::Current();
6806 LOG_API(isolate, "ReferenceError");
6807 ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
6811 i::HandleScope scope(isolate);
6812 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6813 i::Handle<i::Object> result =
6814 isolate->factory()->NewReferenceError(message);
6817 i::Handle<i::Object> result(error, isolate);
6818 return Utils::ToLocal(result);
6822 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
6823 i::Isolate* isolate = i::Isolate::Current();
6824 LOG_API(isolate, "SyntaxError");
6825 ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
6829 i::HandleScope scope(isolate);
6830 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6831 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
6834 i::Handle<i::Object> result(error, isolate);
6835 return Utils::ToLocal(result);
6839 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
6840 i::Isolate* isolate = i::Isolate::Current();
6841 LOG_API(isolate, "TypeError");
6842 ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
6846 i::HandleScope scope(isolate);
6847 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6848 i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
6851 i::Handle<i::Object> result(error, isolate);
6852 return Utils::ToLocal(result);
6856 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
6857 i::Isolate* isolate = i::Isolate::Current();
6858 LOG_API(isolate, "Error");
6859 ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
6863 i::HandleScope scope(isolate);
6864 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6865 i::Handle<i::Object> result = isolate->factory()->NewError(message);
6868 i::Handle<i::Object> result(error, isolate);
6869 return Utils::ToLocal(result);
6873 // --- D e b u g S u p p o r t ---
6875 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
6876 i::Isolate* isolate = i::Isolate::Current();
6877 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
6878 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
6880 i::HandleScope scope(isolate);
6881 i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
6883 foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
6885 isolate->debug()->SetEventListener(foreign,
6886 Utils::OpenHandle(*data, true));
6891 void Debug::DebugBreak(Isolate* isolate) {
6892 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
6896 void Debug::CancelDebugBreak(Isolate* isolate) {
6897 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6898 internal_isolate->stack_guard()->ClearDebugBreak();
6902 void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
6903 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6904 internal_isolate->debug()->EnqueueDebugCommand(data);
6908 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
6909 i::Isolate* isolate = i::Isolate::Current();
6910 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
6912 isolate->debug()->SetMessageHandler(handler);
6916 void Debug::SendCommand(Isolate* isolate,
6917 const uint16_t* command,
6919 ClientData* client_data) {
6920 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6921 internal_isolate->debug()->EnqueueCommandMessage(
6922 i::Vector<const uint16_t>(command, length), client_data);
6926 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
6927 v8::Handle<v8::Value> data) {
6928 i::Isolate* isolate = i::Isolate::Current();
6929 if (!isolate->IsInitialized()) return Local<Value>();
6930 ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
6932 i::MaybeHandle<i::Object> maybe_result;
6933 EXCEPTION_PREAMBLE(isolate);
6934 if (data.IsEmpty()) {
6935 maybe_result = isolate->debug()->Call(
6936 Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
6938 maybe_result = isolate->debug()->Call(
6939 Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
6941 i::Handle<i::Object> result;
6942 has_pending_exception = !maybe_result.ToHandle(&result);
6943 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6944 return Utils::ToLocal(result);
6948 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
6949 i::Isolate* isolate = i::Isolate::Current();
6950 if (!isolate->IsInitialized()) return Local<Value>();
6951 ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
6953 v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
6954 i::Debug* isolate_debug = isolate->debug();
6955 EXCEPTION_PREAMBLE(isolate);
6956 has_pending_exception = !isolate_debug->Load();
6957 v8::Local<v8::Value> result;
6958 if (!has_pending_exception) {
6959 i::Handle<i::JSObject> debug(
6960 isolate_debug->debug_context()->global_object());
6961 i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
6962 STATIC_ASCII_VECTOR("MakeMirror"));
6963 i::Handle<i::Object> fun_obj =
6964 i::Object::GetProperty(debug, name).ToHandleChecked();
6965 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
6966 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
6967 const int kArgc = 1;
6968 v8::Handle<v8::Value> argv[kArgc] = { obj };
6969 result = v8_fun->Call(Utils::ToLocal(debug), kArgc, argv);
6970 has_pending_exception = result.IsEmpty();
6972 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6973 return scope.Escape(result);
6977 void Debug::ProcessDebugMessages() {
6978 i::Isolate::Current()->debug()->ProcessDebugMessages(true);
6982 Local<Context> Debug::GetDebugContext() {
6983 i::Isolate* isolate = i::Isolate::Current();
6984 EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
6986 return Utils::ToLocal(i::Isolate::Current()->debug()->GetDebugContext());
6990 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
6991 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6992 internal_isolate->debug()->set_live_edit_enabled(enable);
6996 Handle<String> CpuProfileNode::GetFunctionName() const {
6997 i::Isolate* isolate = i::Isolate::Current();
6998 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6999 const i::CodeEntry* entry = node->entry();
7000 i::Handle<i::String> name =
7001 isolate->factory()->InternalizeUtf8String(entry->name());
7002 if (!entry->has_name_prefix()) {
7003 return ToApiHandle<String>(name);
7005 // We do not expect this to fail. Change this if it does.
7006 i::Handle<i::String> cons = isolate->factory()->NewConsString(
7007 isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
7008 name).ToHandleChecked();
7009 return ToApiHandle<String>(cons);
7014 int CpuProfileNode::GetScriptId() const {
7015 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7016 const i::CodeEntry* entry = node->entry();
7017 return entry->script_id();
7021 Handle<String> CpuProfileNode::GetScriptResourceName() const {
7022 i::Isolate* isolate = i::Isolate::Current();
7023 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7024 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7025 node->entry()->resource_name()));
7029 int CpuProfileNode::GetLineNumber() const {
7030 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
7034 int CpuProfileNode::GetColumnNumber() const {
7035 return reinterpret_cast<const i::ProfileNode*>(this)->
7036 entry()->column_number();
7040 unsigned int CpuProfileNode::GetHitLineCount() const {
7041 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7042 return node->GetHitLineCount();
7046 bool CpuProfileNode::GetLineTicks(LineTick* entries,
7047 unsigned int length) const {
7048 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7049 return node->GetLineTicks(entries, length);
7053 const char* CpuProfileNode::GetBailoutReason() const {
7054 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7055 return node->entry()->bailout_reason();
7059 unsigned CpuProfileNode::GetHitCount() const {
7060 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
7064 unsigned CpuProfileNode::GetCallUid() const {
7065 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
7069 unsigned CpuProfileNode::GetNodeId() const {
7070 return reinterpret_cast<const i::ProfileNode*>(this)->id();
7074 int CpuProfileNode::GetChildrenCount() const {
7075 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
7079 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
7080 const i::ProfileNode* child =
7081 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
7082 return reinterpret_cast<const CpuProfileNode*>(child);
7086 void CpuProfile::Delete() {
7087 i::Isolate* isolate = i::Isolate::Current();
7088 i::CpuProfiler* profiler = isolate->cpu_profiler();
7089 DCHECK(profiler != NULL);
7090 profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
7094 Handle<String> CpuProfile::GetTitle() const {
7095 i::Isolate* isolate = i::Isolate::Current();
7096 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7097 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7102 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
7103 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7104 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
7108 const CpuProfileNode* CpuProfile::GetSample(int index) const {
7109 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7110 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
7114 int64_t CpuProfile::GetSampleTimestamp(int index) const {
7115 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7116 return (profile->sample_timestamp(index) - base::TimeTicks())
7121 int64_t CpuProfile::GetStartTime() const {
7122 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7123 return (profile->start_time() - base::TimeTicks()).InMicroseconds();
7127 int64_t CpuProfile::GetEndTime() const {
7128 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7129 return (profile->end_time() - base::TimeTicks()).InMicroseconds();
7133 int CpuProfile::GetSamplesCount() const {
7134 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
7138 void CpuProfiler::SetSamplingInterval(int us) {
7140 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
7141 base::TimeDelta::FromMicroseconds(us));
7145 void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
7146 reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
7147 *Utils::OpenHandle(*title), record_samples);
7151 void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
7152 StartProfiling(title, record_samples);
7156 CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
7157 return reinterpret_cast<CpuProfile*>(
7158 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
7159 *Utils::OpenHandle(*title)));
7163 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
7164 return StopProfiling(title);
7168 void CpuProfiler::SetIdle(bool is_idle) {
7169 i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
7170 i::StateTag state = isolate->current_vm_state();
7171 DCHECK(state == i::EXTERNAL || state == i::IDLE);
7172 if (isolate->js_entry_sp() != NULL) return;
7174 isolate->set_current_vm_state(i::IDLE);
7175 } else if (state == i::IDLE) {
7176 isolate->set_current_vm_state(i::EXTERNAL);
7181 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
7182 return const_cast<i::HeapGraphEdge*>(
7183 reinterpret_cast<const i::HeapGraphEdge*>(edge));
7187 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
7188 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
7192 Handle<Value> HeapGraphEdge::GetName() const {
7193 i::Isolate* isolate = i::Isolate::Current();
7194 i::HeapGraphEdge* edge = ToInternal(this);
7195 switch (edge->type()) {
7196 case i::HeapGraphEdge::kContextVariable:
7197 case i::HeapGraphEdge::kInternal:
7198 case i::HeapGraphEdge::kProperty:
7199 case i::HeapGraphEdge::kShortcut:
7200 case i::HeapGraphEdge::kWeak:
7201 return ToApiHandle<String>(
7202 isolate->factory()->InternalizeUtf8String(edge->name()));
7203 case i::HeapGraphEdge::kElement:
7204 case i::HeapGraphEdge::kHidden:
7205 return ToApiHandle<Number>(
7206 isolate->factory()->NewNumberFromInt(edge->index()));
7207 default: UNREACHABLE();
7209 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
7213 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
7214 const i::HeapEntry* from = ToInternal(this)->from();
7215 return reinterpret_cast<const HeapGraphNode*>(from);
7219 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
7220 const i::HeapEntry* to = ToInternal(this)->to();
7221 return reinterpret_cast<const HeapGraphNode*>(to);
7225 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
7226 return const_cast<i::HeapEntry*>(
7227 reinterpret_cast<const i::HeapEntry*>(entry));
7231 HeapGraphNode::Type HeapGraphNode::GetType() const {
7232 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
7236 Handle<String> HeapGraphNode::GetName() const {
7237 i::Isolate* isolate = i::Isolate::Current();
7238 return ToApiHandle<String>(
7239 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
7243 SnapshotObjectId HeapGraphNode::GetId() const {
7244 return ToInternal(this)->id();
7248 int HeapGraphNode::GetSelfSize() const {
7249 size_t size = ToInternal(this)->self_size();
7250 CHECK(size <= static_cast<size_t>(internal::kMaxInt));
7251 return static_cast<int>(size);
7255 size_t HeapGraphNode::GetShallowSize() const {
7256 return ToInternal(this)->self_size();
7260 int HeapGraphNode::GetChildrenCount() const {
7261 return ToInternal(this)->children().length();
7265 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
7266 return reinterpret_cast<const HeapGraphEdge*>(
7267 ToInternal(this)->children()[index]);
7271 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
7272 return const_cast<i::HeapSnapshot*>(
7273 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
7277 void HeapSnapshot::Delete() {
7278 i::Isolate* isolate = i::Isolate::Current();
7279 if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
7280 ToInternal(this)->Delete();
7282 // If this is the last snapshot, clean up all accessory data as well.
7283 isolate->heap_profiler()->DeleteAllSnapshots();
7288 unsigned HeapSnapshot::GetUid() const {
7289 return ToInternal(this)->uid();
7293 Handle<String> HeapSnapshot::GetTitle() const {
7294 i::Isolate* isolate = i::Isolate::Current();
7295 return ToApiHandle<String>(
7296 isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
7300 const HeapGraphNode* HeapSnapshot::GetRoot() const {
7301 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
7305 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
7306 return reinterpret_cast<const HeapGraphNode*>(
7307 ToInternal(this)->GetEntryById(id));
7311 int HeapSnapshot::GetNodesCount() const {
7312 return ToInternal(this)->entries().length();
7316 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
7317 return reinterpret_cast<const HeapGraphNode*>(
7318 &ToInternal(this)->entries().at(index));
7322 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
7323 return ToInternal(this)->max_snapshot_js_object_id();
7327 void HeapSnapshot::Serialize(OutputStream* stream,
7328 HeapSnapshot::SerializationFormat format) const {
7329 Utils::ApiCheck(format == kJSON,
7330 "v8::HeapSnapshot::Serialize",
7331 "Unknown serialization format");
7332 Utils::ApiCheck(stream->GetChunkSize() > 0,
7333 "v8::HeapSnapshot::Serialize",
7334 "Invalid stream chunk size");
7335 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
7336 serializer.Serialize(stream);
7340 int HeapProfiler::GetSnapshotCount() {
7341 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
7345 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
7346 return reinterpret_cast<const HeapSnapshot*>(
7347 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
7351 SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
7352 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
7353 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
7357 Handle<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
7358 i::Handle<i::Object> obj =
7359 reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
7360 if (obj.is_null()) return Local<Value>();
7361 return Utils::ToLocal(obj);
7365 void HeapProfiler::ClearObjectIds() {
7366 reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
7370 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
7371 Handle<String> title,
7372 ActivityControl* control,
7373 ObjectNameResolver* resolver) {
7374 return reinterpret_cast<const HeapSnapshot*>(
7375 reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
7376 *Utils::OpenHandle(*title), control, resolver));
7380 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
7381 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
7386 void HeapProfiler::StopTrackingHeapObjects() {
7387 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
7391 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
7392 return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
7396 void HeapProfiler::DeleteAllHeapSnapshots() {
7397 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
7401 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
7402 WrapperInfoCallback callback) {
7403 reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
7408 size_t HeapProfiler::GetProfilerMemorySize() {
7409 return reinterpret_cast<i::HeapProfiler*>(this)->
7410 GetMemorySizeUsedByProfiler();
7414 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
7415 RetainedObjectInfo* info) {
7416 reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
7420 v8::Testing::StressType internal::Testing::stress_type_ =
7421 v8::Testing::kStressTypeOpt;
7424 void Testing::SetStressRunType(Testing::StressType type) {
7425 internal::Testing::set_stress_type(type);
7429 int Testing::GetStressRuns() {
7430 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
7432 // In debug mode the code runs much slower so stressing will only make two
7441 static void SetFlagsFromString(const char* flags) {
7442 V8::SetFlagsFromString(flags, i::StrLength(flags));
7446 void Testing::PrepareStressRun(int run) {
7447 static const char* kLazyOptimizations =
7448 "--prepare-always-opt "
7449 "--max-inlined-source-size=999999 "
7450 "--max-inlined-nodes=999999 "
7451 "--max-inlined-nodes-cumulative=999999 "
7453 static const char* kForcedOptimizations = "--always-opt";
7455 // If deoptimization stressed turn on frequent deoptimization. If no value
7456 // is spefified through --deopt-every-n-times use a default default value.
7457 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
7458 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
7459 internal::FLAG_deopt_every_n_times == 0) {
7460 SetFlagsFromString(kDeoptEvery13Times);
7464 // As stressing in debug mode only make two runs skip the deopt stressing
7466 if (run == GetStressRuns() - 1) {
7467 SetFlagsFromString(kForcedOptimizations);
7469 SetFlagsFromString(kLazyOptimizations);
7472 if (run == GetStressRuns() - 1) {
7473 SetFlagsFromString(kForcedOptimizations);
7474 } else if (run != GetStressRuns() - 2) {
7475 SetFlagsFromString(kLazyOptimizations);
7481 // TODO(svenpanne) Deprecate this.
7482 void Testing::DeoptimizeAll() {
7483 i::Isolate* isolate = i::Isolate::Current();
7484 i::HandleScope scope(isolate);
7485 internal::Deoptimizer::DeoptimizeAll(isolate);
7489 namespace internal {
7492 void HandleScopeImplementer::FreeThreadResources() {
7497 char* HandleScopeImplementer::ArchiveThread(char* storage) {
7498 HandleScopeData* current = isolate_->handle_scope_data();
7499 handle_scope_data_ = *current;
7500 MemCopy(storage, this, sizeof(*this));
7502 ResetAfterArchive();
7503 current->Initialize();
7505 return storage + ArchiveSpacePerThread();
7509 int HandleScopeImplementer::ArchiveSpacePerThread() {
7510 return sizeof(HandleScopeImplementer);
7514 char* HandleScopeImplementer::RestoreThread(char* storage) {
7515 MemCopy(this, storage, sizeof(*this));
7516 *isolate_->handle_scope_data() = handle_scope_data_;
7517 return storage + ArchiveSpacePerThread();
7521 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
7523 bool found_block_before_deferred = false;
7525 // Iterate over all handles in the blocks except for the last.
7526 for (int i = blocks()->length() - 2; i >= 0; --i) {
7527 Object** block = blocks()->at(i);
7528 if (last_handle_before_deferred_block_ != NULL &&
7529 (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
7530 (last_handle_before_deferred_block_ >= block)) {
7531 v->VisitPointers(block, last_handle_before_deferred_block_);
7532 DCHECK(!found_block_before_deferred);
7534 found_block_before_deferred = true;
7537 v->VisitPointers(block, &block[kHandleBlockSize]);
7541 DCHECK(last_handle_before_deferred_block_ == NULL ||
7542 found_block_before_deferred);
7544 // Iterate over live handles in the last block (if any).
7545 if (!blocks()->is_empty()) {
7546 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
7549 List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
7550 for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) {
7551 if (context_lists[i]->is_empty()) continue;
7552 Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
7553 v->VisitPointers(start, start + context_lists[i]->length());
7558 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
7559 HandleScopeData* current = isolate_->handle_scope_data();
7560 handle_scope_data_ = *current;
7565 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
7566 HandleScopeImplementer* scope_implementer =
7567 reinterpret_cast<HandleScopeImplementer*>(storage);
7568 scope_implementer->IterateThis(v);
7569 return storage + ArchiveSpacePerThread();
7573 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
7574 DeferredHandles* deferred =
7575 new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
7577 while (!blocks_.is_empty()) {
7578 Object** block_start = blocks_.last();
7579 Object** block_limit = &block_start[kHandleBlockSize];
7580 // We should not need to check for SealHandleScope here. Assert this.
7581 DCHECK(prev_limit == block_limit ||
7582 !(block_start <= prev_limit && prev_limit <= block_limit));
7583 if (prev_limit == block_limit) break;
7584 deferred->blocks_.Add(blocks_.last());
7585 blocks_.RemoveLast();
7588 // deferred->blocks_ now contains the blocks installed on the
7589 // HandleScope stack since BeginDeferredScope was called, but in
7592 DCHECK(prev_limit == NULL || !blocks_.is_empty());
7594 DCHECK(!blocks_.is_empty() && prev_limit != NULL);
7595 DCHECK(last_handle_before_deferred_block_ != NULL);
7596 last_handle_before_deferred_block_ = NULL;
7601 void HandleScopeImplementer::BeginDeferredScope() {
7602 DCHECK(last_handle_before_deferred_block_ == NULL);
7603 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
7607 DeferredHandles::~DeferredHandles() {
7608 isolate_->UnlinkDeferredHandles(this);
7610 for (int i = 0; i < blocks_.length(); i++) {
7611 #ifdef ENABLE_HANDLE_ZAPPING
7612 HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
7614 isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
7619 void DeferredHandles::Iterate(ObjectVisitor* v) {
7620 DCHECK(!blocks_.is_empty());
7622 DCHECK((first_block_limit_ >= blocks_.first()) &&
7623 (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
7625 v->VisitPointers(blocks_.first(), first_block_limit_);
7627 for (int i = 1; i < blocks_.length(); i++) {
7628 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
7633 void InvokeAccessorGetterCallback(
7634 v8::Local<v8::String> property,
7635 const v8::PropertyCallbackInfo<v8::Value>& info,
7636 v8::AccessorGetterCallback getter) {
7637 // Leaving JavaScript.
7638 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7639 Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
7641 VMState<EXTERNAL> state(isolate);
7642 ExternalCallbackScope call_scope(isolate, getter_address);
7643 getter(property, info);
7647 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
7648 v8::FunctionCallback callback) {
7649 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7650 Address callback_address =
7651 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
7652 VMState<EXTERNAL> state(isolate);
7653 ExternalCallbackScope call_scope(isolate, callback_address);
7658 } } // namespace v8::internal