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