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