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