1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/api.h" 6 7 #include <string.h> // For memcpy, strlen. 8 #ifdef V8_USE_ADDRESS_SANITIZER 9 #include <sanitizer/asan_interface.h> 10 #endif // V8_USE_ADDRESS_SANITIZER 11 #include <cmath> // For isnan. 12 #include "include/v8-debug.h" 13 #include "include/v8-profiler.h" 14 #include "include/v8-testing.h" 15 #include "src/assert-scope.h" 16 #include "src/bootstrapper.h" 17 #include "src/code-stubs.h" 18 #include "src/compiler.h" 19 #include "src/conversions-inl.h" 20 #include "src/counters.h" 21 #include "src/cpu-profiler.h" 22 #include "src/debug.h" 23 #include "src/deoptimizer.h" 24 #include "src/execution.h" 25 #include "src/global-handles.h" 26 #include "src/heap-profiler.h" 27 #include "src/heap-snapshot-generator-inl.h" 28 #include "src/icu_util.h" 29 #include "src/json-parser.h" 30 #include "src/messages.h" 31 #ifdef COMPRESS_STARTUP_DATA_BZ2 32 #include "src/natives.h" 33 #endif 34 #include "src/parser.h" 35 #include "src/platform.h" 36 #include "src/platform/time.h" 37 #include "src/profile-generator-inl.h" 38 #include "src/property-details.h" 39 #include "src/property.h" 40 #include "src/runtime.h" 41 #include "src/runtime-profiler.h" 42 #include "src/scanner-character-streams.h" 43 #include "src/simulator.h" 44 #include "src/snapshot.h" 45 #include "src/unicode-inl.h" 46 #include "src/utils/random-number-generator.h" 47 #include "src/v8threads.h" 48 #include "src/version.h" 49 #include "src/vm-state-inl.h" 50 51 52 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) 53 54 #define ENTER_V8(isolate) \ 55 ASSERT((isolate)->IsInitialized()); \ 56 i::VMState<i::OTHER> __state__((isolate)) 57 58 namespace v8 { 59 60 #define ON_BAILOUT(isolate, location, code) \ 61 if (IsExecutionTerminatingCheck(isolate)) { \ 62 code; \ 63 UNREACHABLE(); \ 64 } 65 66 67 #define EXCEPTION_PREAMBLE(isolate) \ 68 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \ 69 ASSERT(!(isolate)->external_caught_exception()); \ 70 bool has_pending_exception = false 71 72 73 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback) \ 74 do { \ 75 i::HandleScopeImplementer* handle_scope_implementer = \ 76 (isolate)->handle_scope_implementer(); \ 77 handle_scope_implementer->DecrementCallDepth(); \ 78 if (has_pending_exception) { \ 79 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \ 80 (isolate)->OptionalRescheduleException(call_depth_is_zero); \ 81 do_callback \ 82 return value; \ 83 } \ 84 do_callback \ 85 } while (false) 86 87 88 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value) \ 89 EXCEPTION_BAILOUT_CHECK_GENERIC( \ 90 isolate, value, isolate->FireCallCompletedCallback();) 91 92 93 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \ 94 EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;) 95 96 97 // --- E x c e p t i o n B e h a v i o r --- 98 99 100 void i::FatalProcessOutOfMemory(const char* location) { 101 i::V8::FatalProcessOutOfMemory(location, false); 102 } 103 104 105 // When V8 cannot allocated memory FatalProcessOutOfMemory is called. 106 // The default fatal error handler is called and execution is stopped. 107 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { 108 i::HeapStats heap_stats; 109 int start_marker; 110 heap_stats.start_marker = &start_marker; 111 int new_space_size; 112 heap_stats.new_space_size = &new_space_size; 113 int new_space_capacity; 114 heap_stats.new_space_capacity = &new_space_capacity; 115 intptr_t old_pointer_space_size; 116 heap_stats.old_pointer_space_size = &old_pointer_space_size; 117 intptr_t old_pointer_space_capacity; 118 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity; 119 intptr_t old_data_space_size; 120 heap_stats.old_data_space_size = &old_data_space_size; 121 intptr_t old_data_space_capacity; 122 heap_stats.old_data_space_capacity = &old_data_space_capacity; 123 intptr_t code_space_size; 124 heap_stats.code_space_size = &code_space_size; 125 intptr_t code_space_capacity; 126 heap_stats.code_space_capacity = &code_space_capacity; 127 intptr_t map_space_size; 128 heap_stats.map_space_size = &map_space_size; 129 intptr_t map_space_capacity; 130 heap_stats.map_space_capacity = &map_space_capacity; 131 intptr_t cell_space_size; 132 heap_stats.cell_space_size = &cell_space_size; 133 intptr_t cell_space_capacity; 134 heap_stats.cell_space_capacity = &cell_space_capacity; 135 intptr_t property_cell_space_size; 136 heap_stats.property_cell_space_size = &property_cell_space_size; 137 intptr_t property_cell_space_capacity; 138 heap_stats.property_cell_space_capacity = &property_cell_space_capacity; 139 intptr_t lo_space_size; 140 heap_stats.lo_space_size = &lo_space_size; 141 int global_handle_count; 142 heap_stats.global_handle_count = &global_handle_count; 143 int weak_global_handle_count; 144 heap_stats.weak_global_handle_count = &weak_global_handle_count; 145 int pending_global_handle_count; 146 heap_stats.pending_global_handle_count = &pending_global_handle_count; 147 int near_death_global_handle_count; 148 heap_stats.near_death_global_handle_count = &near_death_global_handle_count; 149 int free_global_handle_count; 150 heap_stats.free_global_handle_count = &free_global_handle_count; 151 intptr_t memory_allocator_size; 152 heap_stats.memory_allocator_size = &memory_allocator_size; 153 intptr_t memory_allocator_capacity; 154 heap_stats.memory_allocator_capacity = &memory_allocator_capacity; 155 int objects_per_type[LAST_TYPE + 1] = {0}; 156 heap_stats.objects_per_type = objects_per_type; 157 int size_per_type[LAST_TYPE + 1] = {0}; 158 heap_stats.size_per_type = size_per_type; 159 int os_error; 160 heap_stats.os_error = &os_error; 161 int end_marker; 162 heap_stats.end_marker = &end_marker; 163 i::Isolate* isolate = i::Isolate::Current(); 164 if (isolate->heap()->HasBeenSetUp()) { 165 // BUG(1718): Don't use the take_snapshot since we don't support 166 // HeapIterator here without doing a special GC. 167 isolate->heap()->RecordStats(&heap_stats, false); 168 } 169 Utils::ApiCheck(false, location, "Allocation failed - process out of memory"); 170 // If the fatal error handler returns, we stop execution. 171 FATAL("API fatal error handler returned after process out of memory"); 172 } 173 174 175 void Utils::ReportApiFailure(const char* location, const char* message) { 176 i::Isolate* isolate = i::Isolate::Current(); 177 FatalErrorCallback callback = isolate->exception_behavior(); 178 if (callback == NULL) { 179 i::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", 180 location, message); 181 i::OS::Abort(); 182 } else { 183 callback(location, message); 184 } 185 isolate->SignalFatalError(); 186 } 187 188 189 bool V8::IsDead() { 190 i::Isolate* isolate = i::Isolate::Current(); 191 return isolate->IsDead(); 192 } 193 194 195 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { 196 if (!isolate->IsInitialized()) return false; 197 if (isolate->has_scheduled_exception()) { 198 return isolate->scheduled_exception() == 199 isolate->heap()->termination_exception(); 200 } 201 return false; 202 } 203 204 205 // --- S t a t i c s --- 206 207 208 static bool InitializeHelper(i::Isolate* isolate) { 209 // If the isolate has a function entry hook, it needs to re-build all its 210 // code stubs with entry hooks embedded, so let's deserialize a snapshot. 211 if (isolate == NULL || isolate->function_entry_hook() == NULL) { 212 if (i::Snapshot::Initialize()) 213 return true; 214 } 215 return i::V8::Initialize(NULL); 216 } 217 218 219 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate, 220 const char* location) { 221 return (isolate != NULL && isolate->IsInitialized()) || 222 Utils::ApiCheck(InitializeHelper(isolate), 223 location, 224 "Error initializing V8"); 225 } 226 227 228 StartupDataDecompressor::StartupDataDecompressor() 229 : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) { 230 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) { 231 raw_data[i] = NULL; 232 } 233 } 234 235 236 StartupDataDecompressor::~StartupDataDecompressor() { 237 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) { 238 i::DeleteArray(raw_data[i]); 239 } 240 i::DeleteArray(raw_data); 241 } 242 243 244 int StartupDataDecompressor::Decompress() { 245 int compressed_data_count = V8::GetCompressedStartupDataCount(); 246 StartupData* compressed_data = 247 i::NewArray<StartupData>(compressed_data_count); 248 V8::GetCompressedStartupData(compressed_data); 249 for (int i = 0; i < compressed_data_count; ++i) { 250 char* decompressed = raw_data[i] = 251 i::NewArray<char>(compressed_data[i].raw_size); 252 if (compressed_data[i].compressed_size != 0) { 253 int result = DecompressData(decompressed, 254 &compressed_data[i].raw_size, 255 compressed_data[i].data, 256 compressed_data[i].compressed_size); 257 if (result != 0) return result; 258 } else { 259 ASSERT_EQ(0, compressed_data[i].raw_size); 260 } 261 compressed_data[i].data = decompressed; 262 } 263 V8::SetDecompressedStartupData(compressed_data); 264 i::DeleteArray(compressed_data); 265 return 0; 266 } 267 268 269 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() { 270 #ifdef COMPRESS_STARTUP_DATA_BZ2 271 return StartupData::kBZip2; 272 #else 273 return StartupData::kUncompressed; 274 #endif 275 } 276 277 278 enum CompressedStartupDataItems { 279 kSnapshot = 0, 280 kSnapshotContext, 281 kLibraries, 282 kExperimentalLibraries, 283 kCompressedStartupDataCount 284 }; 285 286 287 int V8::GetCompressedStartupDataCount() { 288 #ifdef COMPRESS_STARTUP_DATA_BZ2 289 return kCompressedStartupDataCount; 290 #else 291 return 0; 292 #endif 293 } 294 295 296 void V8::GetCompressedStartupData(StartupData* compressed_data) { 297 #ifdef COMPRESS_STARTUP_DATA_BZ2 298 compressed_data[kSnapshot].data = 299 reinterpret_cast<const char*>(i::Snapshot::data()); 300 compressed_data[kSnapshot].compressed_size = i::Snapshot::size(); 301 compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size(); 302 303 compressed_data[kSnapshotContext].data = 304 reinterpret_cast<const char*>(i::Snapshot::context_data()); 305 compressed_data[kSnapshotContext].compressed_size = 306 i::Snapshot::context_size(); 307 compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size(); 308 309 i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource(); 310 compressed_data[kLibraries].data = 311 reinterpret_cast<const char*>(libraries_source.start()); 312 compressed_data[kLibraries].compressed_size = libraries_source.length(); 313 compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize(); 314 315 i::Vector<const i::byte> exp_libraries_source = 316 i::ExperimentalNatives::GetScriptsSource(); 317 compressed_data[kExperimentalLibraries].data = 318 reinterpret_cast<const char*>(exp_libraries_source.start()); 319 compressed_data[kExperimentalLibraries].compressed_size = 320 exp_libraries_source.length(); 321 compressed_data[kExperimentalLibraries].raw_size = 322 i::ExperimentalNatives::GetRawScriptsSize(); 323 #endif 324 } 325 326 327 void V8::SetDecompressedStartupData(StartupData* decompressed_data) { 328 #ifdef COMPRESS_STARTUP_DATA_BZ2 329 ASSERT_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size); 330 i::Snapshot::set_raw_data( 331 reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data)); 332 333 ASSERT_EQ(i::Snapshot::context_raw_size(), 334 decompressed_data[kSnapshotContext].raw_size); 335 i::Snapshot::set_context_raw_data( 336 reinterpret_cast<const i::byte*>( 337 decompressed_data[kSnapshotContext].data)); 338 339 ASSERT_EQ(i::Natives::GetRawScriptsSize(), 340 decompressed_data[kLibraries].raw_size); 341 i::Vector<const char> libraries_source( 342 decompressed_data[kLibraries].data, 343 decompressed_data[kLibraries].raw_size); 344 i::Natives::SetRawScriptsSource(libraries_source); 345 346 ASSERT_EQ(i::ExperimentalNatives::GetRawScriptsSize(), 347 decompressed_data[kExperimentalLibraries].raw_size); 348 i::Vector<const char> exp_libraries_source( 349 decompressed_data[kExperimentalLibraries].data, 350 decompressed_data[kExperimentalLibraries].raw_size); 351 i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source); 352 #endif 353 } 354 355 356 void V8::SetFatalErrorHandler(FatalErrorCallback that) { 357 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 358 isolate->set_exception_behavior(that); 359 } 360 361 362 void V8::SetAllowCodeGenerationFromStringsCallback( 363 AllowCodeGenerationFromStringsCallback callback) { 364 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 365 isolate->set_allow_code_gen_callback(callback); 366 } 367 368 369 void V8::SetFlagsFromString(const char* str, int length) { 370 i::FlagList::SetFlagsFromString(str, length); 371 } 372 373 374 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 375 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 376 } 377 378 379 RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 380 381 382 RegisteredExtension::RegisteredExtension(Extension* extension) 383 : extension_(extension) { } 384 385 386 void RegisteredExtension::Register(RegisteredExtension* that) { 387 that->next_ = first_extension_; 388 first_extension_ = that; 389 } 390 391 392 void RegisteredExtension::UnregisterAll() { 393 RegisteredExtension* re = first_extension_; 394 while (re != NULL) { 395 RegisteredExtension* next = re->next(); 396 delete re; 397 re = next; 398 } 399 } 400 401 402 void RegisterExtension(Extension* that) { 403 RegisteredExtension* extension = new RegisteredExtension(that); 404 RegisteredExtension::Register(extension); 405 } 406 407 408 Extension::Extension(const char* name, 409 const char* source, 410 int dep_count, 411 const char** deps, 412 int source_length) 413 : name_(name), 414 source_length_(source_length >= 0 ? 415 source_length : 416 (source ? static_cast<int>(strlen(source)) : 0)), 417 source_(source, source_length_), 418 dep_count_(dep_count), 419 deps_(deps), 420 auto_enable_(false) { 421 CHECK(source != NULL || source_length_ == 0); 422 } 423 424 425 ResourceConstraints::ResourceConstraints() 426 : max_semi_space_size_(0), 427 max_old_space_size_(0), 428 max_executable_size_(0), 429 stack_limit_(NULL), 430 max_available_threads_(0), 431 code_range_size_(0) { } 432 433 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory, 434 uint64_t virtual_memory_limit, 435 uint32_t number_of_processors) { 436 #if V8_OS_ANDROID 437 // Android has higher physical memory requirements before raising the maximum 438 // heap size limits since it has no swap space. 439 const uint64_t low_limit = 512ul * i::MB; 440 const uint64_t medium_limit = 1ul * i::GB; 441 const uint64_t high_limit = 2ul * i::GB; 442 #else 443 const uint64_t low_limit = 512ul * i::MB; 444 const uint64_t medium_limit = 768ul * i::MB; 445 const uint64_t high_limit = 1ul * i::GB; 446 #endif 447 448 if (physical_memory <= low_limit) { 449 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice); 450 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice); 451 set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice); 452 } else if (physical_memory <= medium_limit) { 453 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice); 454 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice); 455 set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice); 456 } else if (physical_memory <= high_limit) { 457 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice); 458 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice); 459 set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice); 460 } else { 461 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice); 462 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice); 463 set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice); 464 } 465 466 set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u)); 467 468 if (virtual_memory_limit > 0 && i::kRequiresCodeRange) { 469 // Reserve no more than 1/8 of the memory for the code range, but at most 470 // kMaximalCodeRangeSize. 471 set_code_range_size( 472 i::Min(i::kMaximalCodeRangeSize / i::MB, 473 static_cast<size_t>((virtual_memory_limit >> 3) / i::MB))); 474 } 475 } 476 477 478 bool SetResourceConstraints(Isolate* v8_isolate, 479 ResourceConstraints* constraints) { 480 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 481 int semi_space_size = constraints->max_semi_space_size(); 482 int old_space_size = constraints->max_old_space_size(); 483 int max_executable_size = constraints->max_executable_size(); 484 size_t code_range_size = constraints->code_range_size(); 485 if (semi_space_size != 0 || old_space_size != 0 || 486 max_executable_size != 0 || code_range_size != 0) { 487 // After initialization it's too late to change Heap constraints. 488 ASSERT(!isolate->IsInitialized()); 489 bool result = isolate->heap()->ConfigureHeap(semi_space_size, 490 old_space_size, 491 max_executable_size, 492 code_range_size); 493 if (!result) return false; 494 } 495 if (constraints->stack_limit() != NULL) { 496 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit()); 497 isolate->stack_guard()->SetStackLimit(limit); 498 } 499 500 isolate->set_max_available_threads(constraints->max_available_threads()); 501 return true; 502 } 503 504 505 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) { 506 LOG_API(isolate, "Persistent::New"); 507 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj); 508 #ifdef DEBUG 509 (*obj)->ObjectVerify(); 510 #endif // DEBUG 511 return result.location(); 512 } 513 514 515 i::Object** V8::CopyPersistent(i::Object** obj) { 516 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj); 517 #ifdef DEBUG 518 (*obj)->ObjectVerify(); 519 #endif // DEBUG 520 return result.location(); 521 } 522 523 524 void V8::MakeWeak(i::Object** object, 525 void* parameters, 526 WeakCallback weak_callback) { 527 i::GlobalHandles::MakeWeak(object, parameters, weak_callback); 528 } 529 530 531 void* V8::ClearWeak(i::Object** obj) { 532 return i::GlobalHandles::ClearWeakness(obj); 533 } 534 535 536 void V8::DisposeGlobal(i::Object** obj) { 537 i::GlobalHandles::Destroy(obj); 538 } 539 540 541 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) { 542 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 543 i::Object* object = *Utils::OpenHandle(value); 544 isolate->eternal_handles()->Create(isolate, object, index); 545 } 546 547 548 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) { 549 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 550 return Utils::ToLocal(isolate->eternal_handles()->Get(index)); 551 } 552 553 554 // --- H a n d l e s --- 555 556 557 HandleScope::HandleScope(Isolate* isolate) { 558 Initialize(isolate); 559 } 560 561 562 void HandleScope::Initialize(Isolate* isolate) { 563 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 564 // We do not want to check the correct usage of the Locker class all over the 565 // place, so we do it only here: Without a HandleScope, an embedder can do 566 // almost nothing, so it is enough to check in this central place. 567 Utils::ApiCheck(!v8::Locker::IsActive() || 568 internal_isolate->thread_manager()->IsLockedByCurrentThread(), 569 "HandleScope::HandleScope", 570 "Entering the V8 API without proper locking in place"); 571 i::HandleScopeData* current = internal_isolate->handle_scope_data(); 572 isolate_ = internal_isolate; 573 prev_next_ = current->next; 574 prev_limit_ = current->limit; 575 current->level++; 576 } 577 578 579 HandleScope::~HandleScope() { 580 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_); 581 } 582 583 584 int HandleScope::NumberOfHandles(Isolate* isolate) { 585 return i::HandleScope::NumberOfHandles( 586 reinterpret_cast<i::Isolate*>(isolate)); 587 } 588 589 590 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) { 591 return i::HandleScope::CreateHandle(isolate, value); 592 } 593 594 595 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object, 596 i::Object* value) { 597 ASSERT(heap_object->IsHeapObject()); 598 return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value); 599 } 600 601 602 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) { 603 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 604 escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value()); 605 Initialize(v8_isolate); 606 } 607 608 609 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) { 610 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap(); 611 Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(), 612 "EscapeableHandleScope::Escape", 613 "Escape value set twice"); 614 if (escape_value == NULL) { 615 *escape_slot_ = heap->undefined_value(); 616 return NULL; 617 } 618 *escape_slot_ = *escape_value; 619 return escape_slot_; 620 } 621 622 623 void Context::Enter() { 624 i::Handle<i::Context> env = Utils::OpenHandle(this); 625 i::Isolate* isolate = env->GetIsolate(); 626 ENTER_V8(isolate); 627 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 628 impl->EnterContext(env); 629 impl->SaveContext(isolate->context()); 630 isolate->set_context(*env); 631 } 632 633 634 void Context::Exit() { 635 i::Handle<i::Context> env = Utils::OpenHandle(this); 636 i::Isolate* isolate = env->GetIsolate(); 637 ENTER_V8(isolate); 638 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 639 if (!Utils::ApiCheck(impl->LastEnteredContextWas(env), 640 "v8::Context::Exit()", 641 "Cannot exit non-entered context")) { 642 return; 643 } 644 impl->LeaveContext(); 645 isolate->set_context(impl->RestoreContext()); 646 } 647 648 649 static void* DecodeSmiToAligned(i::Object* value, const char* location) { 650 Utils::ApiCheck(value->IsSmi(), location, "Not a Smi"); 651 return reinterpret_cast<void*>(value); 652 } 653 654 655 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) { 656 i::Smi* smi = reinterpret_cast<i::Smi*>(value); 657 Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned"); 658 return smi; 659 } 660 661 662 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context, 663 int index, 664 bool can_grow, 665 const char* location) { 666 i::Handle<i::Context> env = Utils::OpenHandle(context); 667 bool ok = 668 Utils::ApiCheck(env->IsNativeContext(), 669 location, 670 "Not a native context") && 671 Utils::ApiCheck(index >= 0, location, "Negative index"); 672 if (!ok) return i::Handle<i::FixedArray>(); 673 i::Handle<i::FixedArray> data(env->embedder_data()); 674 if (index < data->length()) return data; 675 if (!Utils::ApiCheck(can_grow, location, "Index too large")) { 676 return i::Handle<i::FixedArray>(); 677 } 678 int new_size = i::Max(index, data->length() << 1) + 1; 679 data = i::FixedArray::CopySize(data, new_size); 680 env->set_embedder_data(*data); 681 return data; 682 } 683 684 685 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) { 686 const char* location = "v8::Context::GetEmbedderData()"; 687 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 688 if (data.is_null()) return Local<Value>(); 689 i::Handle<i::Object> result(data->get(index), data->GetIsolate()); 690 return Utils::ToLocal(result); 691 } 692 693 694 void Context::SetEmbedderData(int index, v8::Handle<Value> value) { 695 const char* location = "v8::Context::SetEmbedderData()"; 696 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 697 if (data.is_null()) return; 698 i::Handle<i::Object> val = Utils::OpenHandle(*value); 699 data->set(index, *val); 700 ASSERT_EQ(*Utils::OpenHandle(*value), 701 *Utils::OpenHandle(*GetEmbedderData(index))); 702 } 703 704 705 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) { 706 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()"; 707 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 708 if (data.is_null()) return NULL; 709 return DecodeSmiToAligned(data->get(index), location); 710 } 711 712 713 void Context::SetAlignedPointerInEmbedderData(int index, void* value) { 714 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()"; 715 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 716 data->set(index, EncodeAlignedAsSmi(value, location)); 717 ASSERT_EQ(value, GetAlignedPointerFromEmbedderData(index)); 718 } 719 720 721 // --- N e a n d e r --- 722 723 724 // A constructor cannot easily return an error value, therefore it is necessary 725 // to check for a dead VM with ON_BAILOUT before constructing any Neander 726 // objects. To remind you about this there is no HandleScope in the 727 // NeanderObject constructor. When you add one to the site calling the 728 // constructor you should check that you ensured the VM was not dead first. 729 NeanderObject::NeanderObject(v8::internal::Isolate* isolate, int size) { 730 EnsureInitializedForIsolate(isolate, "v8::Nowhere"); 731 ENTER_V8(isolate); 732 value_ = isolate->factory()->NewNeanderObject(); 733 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size); 734 value_->set_elements(*elements); 735 } 736 737 738 int NeanderObject::size() { 739 return i::FixedArray::cast(value_->elements())->length(); 740 } 741 742 743 NeanderArray::NeanderArray(v8::internal::Isolate* isolate) : obj_(isolate, 2) { 744 obj_.set(0, i::Smi::FromInt(0)); 745 } 746 747 748 int NeanderArray::length() { 749 return i::Smi::cast(obj_.get(0))->value(); 750 } 751 752 753 i::Object* NeanderArray::get(int offset) { 754 ASSERT(0 <= offset); 755 ASSERT(offset < length()); 756 return obj_.get(offset + 1); 757 } 758 759 760 // This method cannot easily return an error value, therefore it is necessary 761 // to check for a dead VM with ON_BAILOUT before calling it. To remind you 762 // about this there is no HandleScope in this method. When you add one to the 763 // site calling this method you should check that you ensured the VM was not 764 // dead first. 765 void NeanderArray::add(i::Handle<i::Object> value) { 766 int length = this->length(); 767 int size = obj_.size(); 768 if (length == size - 1) { 769 i::Factory* factory = i::Isolate::Current()->factory(); 770 i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size); 771 for (int i = 0; i < length; i++) 772 new_elms->set(i + 1, get(i)); 773 obj_.value()->set_elements(*new_elms); 774 } 775 obj_.set(length + 1, *value); 776 obj_.set(0, i::Smi::FromInt(length + 1)); 777 } 778 779 780 void NeanderArray::set(int index, i::Object* value) { 781 if (index < 0 || index >= this->length()) return; 782 obj_.set(index + 1, value); 783 } 784 785 786 // --- T e m p l a t e --- 787 788 789 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) { 790 that->set_tag(i::Smi::FromInt(type)); 791 } 792 793 794 static void TemplateSet(i::Isolate* isolate, 795 v8::Template* templ, 796 int length, 797 v8::Handle<v8::Data>* data) { 798 i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate); 799 if (list->IsUndefined()) { 800 list = NeanderArray(isolate).value(); 801 Utils::OpenHandle(templ)->set_property_list(*list); 802 } 803 NeanderArray array(list); 804 array.add(isolate->factory()->NewNumberFromInt(length)); 805 for (int i = 0; i < length; i++) { 806 i::Handle<i::Object> value = data[i].IsEmpty() ? 807 i::Handle<i::Object>(isolate->factory()->undefined_value()) : 808 Utils::OpenHandle(*data[i]); 809 array.add(value); 810 } 811 } 812 813 814 void Template::Set(v8::Handle<String> name, 815 v8::Handle<Data> value, 816 v8::PropertyAttribute attribute) { 817 i::Isolate* isolate = i::Isolate::Current(); 818 ENTER_V8(isolate); 819 i::HandleScope scope(isolate); 820 const int kSize = 3; 821 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 822 v8::Handle<v8::Data> data[kSize] = { 823 name, 824 value, 825 v8::Integer::New(v8_isolate, attribute)}; 826 TemplateSet(isolate, this, kSize, data); 827 } 828 829 830 void Template::SetAccessorProperty( 831 v8::Local<v8::String> name, 832 v8::Local<FunctionTemplate> getter, 833 v8::Local<FunctionTemplate> setter, 834 v8::PropertyAttribute attribute, 835 v8::AccessControl access_control) { 836 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 837 ENTER_V8(isolate); 838 ASSERT(!name.IsEmpty()); 839 ASSERT(!getter.IsEmpty() || !setter.IsEmpty()); 840 i::HandleScope scope(isolate); 841 const int kSize = 5; 842 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 843 v8::Handle<v8::Data> data[kSize] = { 844 name, 845 getter, 846 setter, 847 v8::Integer::New(v8_isolate, attribute), 848 v8::Integer::New(v8_isolate, access_control)}; 849 TemplateSet(isolate, this, kSize, data); 850 } 851 852 853 // --- F u n c t i o n T e m p l a t e --- 854 static void InitializeFunctionTemplate( 855 i::Handle<i::FunctionTemplateInfo> info) { 856 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE)); 857 info->set_flag(0); 858 } 859 860 861 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { 862 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 863 ENTER_V8(i_isolate); 864 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(), 865 i_isolate); 866 if (result->IsUndefined()) { 867 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(i_isolate); 868 result = Utils::OpenHandle(*ObjectTemplate::New(isolate)); 869 Utils::OpenHandle(this)->set_prototype_template(*result); 870 } 871 return ToApiHandle<ObjectTemplate>(result); 872 } 873 874 875 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) { 876 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 877 ENTER_V8(isolate); 878 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value)); 879 } 880 881 882 static Local<FunctionTemplate> FunctionTemplateNew( 883 i::Isolate* isolate, 884 FunctionCallback callback, 885 v8::Handle<Value> data, 886 v8::Handle<Signature> signature, 887 int length, 888 bool do_not_cache) { 889 i::Handle<i::Struct> struct_obj = 890 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE); 891 i::Handle<i::FunctionTemplateInfo> obj = 892 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj); 893 InitializeFunctionTemplate(obj); 894 obj->set_do_not_cache(do_not_cache); 895 int next_serial_number = 0; 896 if (!do_not_cache) { 897 next_serial_number = isolate->next_serial_number() + 1; 898 isolate->set_next_serial_number(next_serial_number); 899 } 900 obj->set_serial_number(i::Smi::FromInt(next_serial_number)); 901 if (callback != 0) { 902 if (data.IsEmpty()) { 903 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 904 } 905 Utils::ToLocal(obj)->SetCallHandler(callback, data); 906 } 907 obj->set_length(length); 908 obj->set_undetectable(false); 909 obj->set_needs_access_check(false); 910 if (!signature.IsEmpty()) 911 obj->set_signature(*Utils::OpenHandle(*signature)); 912 return Utils::ToLocal(obj); 913 } 914 915 Local<FunctionTemplate> FunctionTemplate::New( 916 Isolate* isolate, 917 FunctionCallback callback, 918 v8::Handle<Value> data, 919 v8::Handle<Signature> signature, 920 int length) { 921 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 922 EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()"); 923 LOG_API(i_isolate, "FunctionTemplate::New"); 924 ENTER_V8(i_isolate); 925 return FunctionTemplateNew( 926 i_isolate, callback, data, signature, length, false); 927 } 928 929 930 Local<Signature> Signature::New(Isolate* isolate, 931 Handle<FunctionTemplate> receiver, int argc, 932 Handle<FunctionTemplate> argv[]) { 933 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 934 EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()"); 935 LOG_API(i_isolate, "Signature::New"); 936 ENTER_V8(i_isolate); 937 i::Handle<i::Struct> struct_obj = 938 i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE); 939 i::Handle<i::SignatureInfo> obj = 940 i::Handle<i::SignatureInfo>::cast(struct_obj); 941 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver)); 942 if (argc > 0) { 943 i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc); 944 for (int i = 0; i < argc; i++) { 945 if (!argv[i].IsEmpty()) 946 args->set(i, *Utils::OpenHandle(*argv[i])); 947 } 948 obj->set_args(*args); 949 } 950 return Utils::ToLocal(obj); 951 } 952 953 954 Local<AccessorSignature> AccessorSignature::New( 955 Isolate* isolate, 956 Handle<FunctionTemplate> receiver) { 957 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); 958 } 959 960 961 template<typename Operation> 962 static Local<Operation> NewDescriptor( 963 Isolate* isolate, 964 const i::DeclaredAccessorDescriptorData& data, 965 Data* previous_descriptor) { 966 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 967 i::Handle<i::DeclaredAccessorDescriptor> previous = 968 i::Handle<i::DeclaredAccessorDescriptor>(); 969 if (previous_descriptor != NULL) { 970 previous = Utils::OpenHandle( 971 static_cast<DeclaredAccessorDescriptor*>(previous_descriptor)); 972 } 973 i::Handle<i::DeclaredAccessorDescriptor> descriptor = 974 i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous); 975 return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor); 976 } 977 978 979 Local<RawOperationDescriptor> 980 ObjectOperationDescriptor::NewInternalFieldDereference( 981 Isolate* isolate, 982 int internal_field) { 983 i::DeclaredAccessorDescriptorData data; 984 data.type = i::kDescriptorObjectDereference; 985 data.object_dereference_descriptor.internal_field = internal_field; 986 return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL); 987 } 988 989 990 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift( 991 Isolate* isolate, 992 int16_t byte_offset) { 993 i::DeclaredAccessorDescriptorData data; 994 data.type = i::kDescriptorPointerShift; 995 data.pointer_shift_descriptor.byte_offset = byte_offset; 996 return NewDescriptor<RawOperationDescriptor>(isolate, data, this); 997 } 998 999 1000 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference( 1001 Isolate* isolate) { 1002 i::DeclaredAccessorDescriptorData data; 1003 data.type = i::kDescriptorReturnObject; 1004 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1005 } 1006 1007 1008 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference( 1009 Isolate* isolate) { 1010 i::DeclaredAccessorDescriptorData data; 1011 data.type = i::kDescriptorPointerDereference; 1012 return NewDescriptor<RawOperationDescriptor>(isolate, data, this); 1013 } 1014 1015 1016 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare( 1017 Isolate* isolate, 1018 void* compare_value) { 1019 i::DeclaredAccessorDescriptorData data; 1020 data.type = i::kDescriptorPointerCompare; 1021 data.pointer_compare_descriptor.compare_value = compare_value; 1022 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1023 } 1024 1025 1026 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue( 1027 Isolate* isolate, 1028 DeclaredAccessorDescriptorDataType data_type, 1029 uint8_t bool_offset) { 1030 i::DeclaredAccessorDescriptorData data; 1031 data.type = i::kDescriptorPrimitiveValue; 1032 data.primitive_value_descriptor.data_type = data_type; 1033 data.primitive_value_descriptor.bool_offset = bool_offset; 1034 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1035 } 1036 1037 1038 template<typename T> 1039 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare( 1040 Isolate* isolate, 1041 T bitmask, 1042 T compare_value, 1043 RawOperationDescriptor* operation) { 1044 i::DeclaredAccessorDescriptorData data; 1045 data.type = i::kDescriptorBitmaskCompare; 1046 data.bitmask_compare_descriptor.bitmask = bitmask; 1047 data.bitmask_compare_descriptor.compare_value = compare_value; 1048 data.bitmask_compare_descriptor.size = sizeof(T); 1049 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation); 1050 } 1051 1052 1053 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8( 1054 Isolate* isolate, 1055 uint8_t bitmask, 1056 uint8_t compare_value) { 1057 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1058 } 1059 1060 1061 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16( 1062 Isolate* isolate, 1063 uint16_t bitmask, 1064 uint16_t compare_value) { 1065 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1066 } 1067 1068 1069 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32( 1070 Isolate* isolate, 1071 uint32_t bitmask, 1072 uint32_t compare_value) { 1073 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1074 } 1075 1076 1077 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) { 1078 Handle<FunctionTemplate> types[1] = { type }; 1079 return TypeSwitch::New(1, types); 1080 } 1081 1082 1083 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) { 1084 i::Isolate* isolate = i::Isolate::Current(); 1085 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()"); 1086 LOG_API(isolate, "TypeSwitch::New"); 1087 ENTER_V8(isolate); 1088 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc); 1089 for (int i = 0; i < argc; i++) 1090 vector->set(i, *Utils::OpenHandle(*types[i])); 1091 i::Handle<i::Struct> struct_obj = 1092 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE); 1093 i::Handle<i::TypeSwitchInfo> obj = 1094 i::Handle<i::TypeSwitchInfo>::cast(struct_obj); 1095 obj->set_types(*vector); 1096 return Utils::ToLocal(obj); 1097 } 1098 1099 1100 int TypeSwitch::match(v8::Handle<Value> value) { 1101 i::Isolate* isolate = i::Isolate::Current(); 1102 LOG_API(isolate, "TypeSwitch::match"); 1103 USE(isolate); 1104 i::Handle<i::Object> obj = Utils::OpenHandle(*value); 1105 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this); 1106 i::FixedArray* types = i::FixedArray::cast(info->types()); 1107 for (int i = 0; i < types->length(); i++) { 1108 if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj)) 1109 return i + 1; 1110 } 1111 return 0; 1112 } 1113 1114 1115 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ 1116 i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \ 1117 (obj)->setter(*foreign); \ 1118 } while (false) 1119 1120 1121 void FunctionTemplate::SetCallHandler(FunctionCallback callback, 1122 v8::Handle<Value> data) { 1123 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1124 ENTER_V8(isolate); 1125 i::HandleScope scope(isolate); 1126 i::Handle<i::Struct> struct_obj = 1127 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1128 i::Handle<i::CallHandlerInfo> obj = 1129 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1130 SET_FIELD_WRAPPED(obj, set_callback, callback); 1131 if (data.IsEmpty()) { 1132 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1133 } 1134 obj->set_data(*Utils::OpenHandle(*data)); 1135 Utils::OpenHandle(this)->set_call_code(*obj); 1136 } 1137 1138 1139 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties( 1140 i::Handle<i::AccessorInfo> obj, 1141 v8::Handle<String> name, 1142 v8::AccessControl settings, 1143 v8::PropertyAttribute attributes, 1144 v8::Handle<AccessorSignature> signature) { 1145 obj->set_name(*Utils::OpenHandle(*name)); 1146 if (settings & ALL_CAN_READ) obj->set_all_can_read(true); 1147 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); 1148 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes)); 1149 if (!signature.IsEmpty()) { 1150 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature)); 1151 } 1152 return obj; 1153 } 1154 1155 1156 template<typename Getter, typename Setter> 1157 static i::Handle<i::AccessorInfo> MakeAccessorInfo( 1158 v8::Handle<String> name, 1159 Getter getter, 1160 Setter setter, 1161 v8::Handle<Value> data, 1162 v8::AccessControl settings, 1163 v8::PropertyAttribute attributes, 1164 v8::Handle<AccessorSignature> signature) { 1165 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate(); 1166 i::Handle<i::ExecutableAccessorInfo> obj = 1167 isolate->factory()->NewExecutableAccessorInfo(); 1168 SET_FIELD_WRAPPED(obj, set_getter, getter); 1169 SET_FIELD_WRAPPED(obj, set_setter, setter); 1170 if (data.IsEmpty()) { 1171 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1172 } 1173 obj->set_data(*Utils::OpenHandle(*data)); 1174 return SetAccessorInfoProperties(obj, name, settings, attributes, signature); 1175 } 1176 1177 1178 static i::Handle<i::AccessorInfo> MakeAccessorInfo( 1179 v8::Handle<String> name, 1180 v8::Handle<v8::DeclaredAccessorDescriptor> descriptor, 1181 void* setter_ignored, 1182 void* data_ignored, 1183 v8::AccessControl settings, 1184 v8::PropertyAttribute attributes, 1185 v8::Handle<AccessorSignature> signature) { 1186 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate(); 1187 if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>(); 1188 i::Handle<i::DeclaredAccessorInfo> obj = 1189 isolate->factory()->NewDeclaredAccessorInfo(); 1190 obj->set_descriptor(*Utils::OpenHandle(*descriptor)); 1191 return SetAccessorInfoProperties(obj, name, settings, attributes, signature); 1192 } 1193 1194 1195 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { 1196 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true); 1197 if (!Utils::ApiCheck(!handle.is_null(), 1198 "v8::FunctionTemplate::InstanceTemplate()", 1199 "Reading from empty handle")) { 1200 return Local<ObjectTemplate>(); 1201 } 1202 i::Isolate* isolate = handle->GetIsolate(); 1203 ENTER_V8(isolate); 1204 if (handle->instance_template()->IsUndefined()) { 1205 Local<ObjectTemplate> templ = 1206 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle)); 1207 handle->set_instance_template(*Utils::OpenHandle(*templ)); 1208 } 1209 i::Handle<i::ObjectTemplateInfo> result( 1210 i::ObjectTemplateInfo::cast(handle->instance_template())); 1211 return Utils::ToLocal(result); 1212 } 1213 1214 1215 void FunctionTemplate::SetLength(int length) { 1216 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1217 ENTER_V8(isolate); 1218 Utils::OpenHandle(this)->set_length(length); 1219 } 1220 1221 1222 void FunctionTemplate::SetClassName(Handle<String> name) { 1223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1224 ENTER_V8(isolate); 1225 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name)); 1226 } 1227 1228 1229 void FunctionTemplate::SetHiddenPrototype(bool value) { 1230 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1231 ENTER_V8(isolate); 1232 Utils::OpenHandle(this)->set_hidden_prototype(value); 1233 } 1234 1235 1236 void FunctionTemplate::ReadOnlyPrototype() { 1237 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1238 ENTER_V8(isolate); 1239 Utils::OpenHandle(this)->set_read_only_prototype(true); 1240 } 1241 1242 1243 void FunctionTemplate::RemovePrototype() { 1244 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1245 ENTER_V8(isolate); 1246 Utils::OpenHandle(this)->set_remove_prototype(true); 1247 } 1248 1249 1250 // --- O b j e c t T e m p l a t e --- 1251 1252 1253 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) { 1254 return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>()); 1255 } 1256 1257 1258 Local<ObjectTemplate> ObjectTemplate::New() { 1259 return New(i::Isolate::Current(), Local<FunctionTemplate>()); 1260 } 1261 1262 1263 Local<ObjectTemplate> ObjectTemplate::New( 1264 i::Isolate* isolate, 1265 v8::Handle<FunctionTemplate> constructor) { 1266 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()"); 1267 LOG_API(isolate, "ObjectTemplate::New"); 1268 ENTER_V8(isolate); 1269 i::Handle<i::Struct> struct_obj = 1270 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE); 1271 i::Handle<i::ObjectTemplateInfo> obj = 1272 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj); 1273 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); 1274 if (!constructor.IsEmpty()) 1275 obj->set_constructor(*Utils::OpenHandle(*constructor)); 1276 obj->set_internal_field_count(i::Smi::FromInt(0)); 1277 return Utils::ToLocal(obj); 1278 } 1279 1280 1281 // Ensure that the object template has a constructor. If no 1282 // constructor is available we create one. 1283 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor( 1284 i::Isolate* isolate, 1285 ObjectTemplate* object_template) { 1286 i::Object* obj = Utils::OpenHandle(object_template)->constructor(); 1287 if (!obj ->IsUndefined()) { 1288 i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj); 1289 return i::Handle<i::FunctionTemplateInfo>(info, isolate); 1290 } 1291 Local<FunctionTemplate> templ = 1292 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate)); 1293 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ); 1294 constructor->set_instance_template(*Utils::OpenHandle(object_template)); 1295 Utils::OpenHandle(object_template)->set_constructor(*constructor); 1296 return constructor; 1297 } 1298 1299 1300 static inline void AddPropertyToTemplate( 1301 i::Handle<i::TemplateInfo> info, 1302 i::Handle<i::AccessorInfo> obj) { 1303 i::Isolate* isolate = info->GetIsolate(); 1304 i::Handle<i::Object> list(info->property_accessors(), isolate); 1305 if (list->IsUndefined()) { 1306 list = NeanderArray(isolate).value(); 1307 info->set_property_accessors(*list); 1308 } 1309 NeanderArray array(list); 1310 array.add(obj); 1311 } 1312 1313 1314 static inline i::Handle<i::TemplateInfo> GetTemplateInfo( 1315 i::Isolate* isolate, 1316 Template* template_obj) { 1317 return Utils::OpenHandle(template_obj); 1318 } 1319 1320 1321 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor 1322 static inline i::Handle<i::TemplateInfo> GetTemplateInfo( 1323 i::Isolate* isolate, 1324 ObjectTemplate* object_template) { 1325 EnsureConstructor(isolate, object_template); 1326 return Utils::OpenHandle(object_template); 1327 } 1328 1329 1330 template<typename Setter, typename Getter, typename Data, typename Template> 1331 static bool TemplateSetAccessor( 1332 Template* template_obj, 1333 v8::Local<String> name, 1334 Getter getter, 1335 Setter setter, 1336 Data data, 1337 AccessControl settings, 1338 PropertyAttribute attribute, 1339 v8::Local<AccessorSignature> signature) { 1340 i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate(); 1341 ENTER_V8(isolate); 1342 i::HandleScope scope(isolate); 1343 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo( 1344 name, getter, setter, data, settings, attribute, signature); 1345 if (obj.is_null()) return false; 1346 i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj); 1347 AddPropertyToTemplate(info, obj); 1348 return true; 1349 } 1350 1351 1352 bool Template::SetDeclaredAccessor( 1353 Local<String> name, 1354 Local<DeclaredAccessorDescriptor> descriptor, 1355 PropertyAttribute attribute, 1356 Local<AccessorSignature> signature, 1357 AccessControl settings) { 1358 void* null = NULL; 1359 return TemplateSetAccessor( 1360 this, name, descriptor, null, null, settings, attribute, signature); 1361 } 1362 1363 1364 void Template::SetNativeDataProperty(v8::Local<String> name, 1365 AccessorGetterCallback getter, 1366 AccessorSetterCallback setter, 1367 v8::Handle<Value> data, 1368 PropertyAttribute attribute, 1369 v8::Local<AccessorSignature> signature, 1370 AccessControl settings) { 1371 TemplateSetAccessor( 1372 this, name, getter, setter, data, settings, attribute, signature); 1373 } 1374 1375 1376 void ObjectTemplate::SetAccessor(v8::Handle<String> name, 1377 AccessorGetterCallback getter, 1378 AccessorSetterCallback setter, 1379 v8::Handle<Value> data, 1380 AccessControl settings, 1381 PropertyAttribute attribute, 1382 v8::Handle<AccessorSignature> signature) { 1383 TemplateSetAccessor( 1384 this, name, getter, setter, data, settings, attribute, signature); 1385 } 1386 1387 1388 void ObjectTemplate::SetNamedPropertyHandler( 1389 NamedPropertyGetterCallback getter, 1390 NamedPropertySetterCallback setter, 1391 NamedPropertyQueryCallback query, 1392 NamedPropertyDeleterCallback remover, 1393 NamedPropertyEnumeratorCallback enumerator, 1394 Handle<Value> data) { 1395 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1396 ENTER_V8(isolate); 1397 i::HandleScope scope(isolate); 1398 EnsureConstructor(isolate, this); 1399 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1400 Utils::OpenHandle(this)->constructor()); 1401 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1402 i::Handle<i::Struct> struct_obj = 1403 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 1404 i::Handle<i::InterceptorInfo> obj = 1405 i::Handle<i::InterceptorInfo>::cast(struct_obj); 1406 1407 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1408 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1409 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1410 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1411 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1412 1413 if (data.IsEmpty()) { 1414 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1415 } 1416 obj->set_data(*Utils::OpenHandle(*data)); 1417 cons->set_named_property_handler(*obj); 1418 } 1419 1420 1421 void ObjectTemplate::MarkAsUndetectable() { 1422 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1423 ENTER_V8(isolate); 1424 i::HandleScope scope(isolate); 1425 EnsureConstructor(isolate, this); 1426 i::FunctionTemplateInfo* constructor = 1427 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1428 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1429 cons->set_undetectable(true); 1430 } 1431 1432 1433 void ObjectTemplate::SetAccessCheckCallbacks( 1434 NamedSecurityCallback named_callback, 1435 IndexedSecurityCallback indexed_callback, 1436 Handle<Value> data, 1437 bool turned_on_by_default) { 1438 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1439 ENTER_V8(isolate); 1440 i::HandleScope scope(isolate); 1441 EnsureConstructor(isolate, this); 1442 1443 i::Handle<i::Struct> struct_info = 1444 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE); 1445 i::Handle<i::AccessCheckInfo> info = 1446 i::Handle<i::AccessCheckInfo>::cast(struct_info); 1447 1448 SET_FIELD_WRAPPED(info, set_named_callback, named_callback); 1449 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback); 1450 1451 if (data.IsEmpty()) { 1452 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1453 } 1454 info->set_data(*Utils::OpenHandle(*data)); 1455 1456 i::FunctionTemplateInfo* constructor = 1457 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1458 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1459 cons->set_access_check_info(*info); 1460 cons->set_needs_access_check(turned_on_by_default); 1461 } 1462 1463 1464 void ObjectTemplate::SetIndexedPropertyHandler( 1465 IndexedPropertyGetterCallback getter, 1466 IndexedPropertySetterCallback setter, 1467 IndexedPropertyQueryCallback query, 1468 IndexedPropertyDeleterCallback remover, 1469 IndexedPropertyEnumeratorCallback enumerator, 1470 Handle<Value> data) { 1471 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1472 ENTER_V8(isolate); 1473 i::HandleScope scope(isolate); 1474 EnsureConstructor(isolate, this); 1475 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1476 Utils::OpenHandle(this)->constructor()); 1477 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1478 i::Handle<i::Struct> struct_obj = 1479 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 1480 i::Handle<i::InterceptorInfo> obj = 1481 i::Handle<i::InterceptorInfo>::cast(struct_obj); 1482 1483 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1484 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1485 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1486 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1487 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1488 1489 if (data.IsEmpty()) { 1490 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1491 } 1492 obj->set_data(*Utils::OpenHandle(*data)); 1493 cons->set_indexed_property_handler(*obj); 1494 } 1495 1496 1497 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, 1498 Handle<Value> data) { 1499 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1500 ENTER_V8(isolate); 1501 i::HandleScope scope(isolate); 1502 EnsureConstructor(isolate, this); 1503 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1504 Utils::OpenHandle(this)->constructor()); 1505 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1506 i::Handle<i::Struct> struct_obj = 1507 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1508 i::Handle<i::CallHandlerInfo> obj = 1509 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1510 SET_FIELD_WRAPPED(obj, set_callback, callback); 1511 if (data.IsEmpty()) { 1512 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1513 } 1514 obj->set_data(*Utils::OpenHandle(*data)); 1515 cons->set_instance_call_handler(*obj); 1516 } 1517 1518 1519 int ObjectTemplate::InternalFieldCount() { 1520 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value(); 1521 } 1522 1523 1524 void ObjectTemplate::SetInternalFieldCount(int value) { 1525 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1526 if (!Utils::ApiCheck(i::Smi::IsValid(value), 1527 "v8::ObjectTemplate::SetInternalFieldCount()", 1528 "Invalid internal field count")) { 1529 return; 1530 } 1531 ENTER_V8(isolate); 1532 if (value > 0) { 1533 // The internal field count is set by the constructor function's 1534 // construct code, so we ensure that there is a constructor 1535 // function to do the setting. 1536 EnsureConstructor(isolate, this); 1537 } 1538 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value)); 1539 } 1540 1541 1542 // --- S c r i p t s --- 1543 1544 1545 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a 1546 // JSFunction. 1547 1548 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_, 1549 BufferPolicy buffer_policy_) 1550 : data(data_), length(length_), buffer_policy(buffer_policy_) {} 1551 1552 1553 ScriptCompiler::CachedData::~CachedData() { 1554 if (buffer_policy == BufferOwned) { 1555 delete[] data; 1556 } 1557 } 1558 1559 1560 Local<Script> UnboundScript::BindToCurrentContext() { 1561 i::Handle<i::HeapObject> obj = 1562 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1563 i::Handle<i::SharedFunctionInfo> 1564 function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate()); 1565 i::Handle<i::JSFunction> function = 1566 obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo( 1567 function_info, obj->GetIsolate()->global_context()); 1568 return ToApiHandle<Script>(function); 1569 } 1570 1571 1572 int UnboundScript::GetId() { 1573 i::Handle<i::HeapObject> obj = 1574 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1575 i::Isolate* isolate = obj->GetIsolate(); 1576 ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1); 1577 LOG_API(isolate, "v8::UnboundScript::GetId"); 1578 { 1579 i::HandleScope scope(isolate); 1580 i::Handle<i::SharedFunctionInfo> function_info( 1581 i::SharedFunctionInfo::cast(*obj)); 1582 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1583 return script->id()->value(); 1584 } 1585 } 1586 1587 1588 int UnboundScript::GetLineNumber(int code_pos) { 1589 i::Handle<i::SharedFunctionInfo> obj = 1590 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 1591 i::Isolate* isolate = obj->GetIsolate(); 1592 ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1); 1593 LOG_API(isolate, "UnboundScript::GetLineNumber"); 1594 if (obj->script()->IsScript()) { 1595 i::Handle<i::Script> script(i::Script::cast(obj->script())); 1596 return i::Script::GetLineNumber(script, code_pos); 1597 } else { 1598 return -1; 1599 } 1600 } 1601 1602 1603 Handle<Value> UnboundScript::GetScriptName() { 1604 i::Handle<i::SharedFunctionInfo> obj = 1605 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 1606 i::Isolate* isolate = obj->GetIsolate(); 1607 ON_BAILOUT(isolate, "v8::UnboundScript::GetName()", 1608 return Handle<String>()); 1609 LOG_API(isolate, "UnboundScript::GetName"); 1610 if (obj->script()->IsScript()) { 1611 i::Object* name = i::Script::cast(obj->script())->name(); 1612 return Utils::ToLocal(i::Handle<i::Object>(name, isolate)); 1613 } else { 1614 return Handle<String>(); 1615 } 1616 } 1617 1618 1619 Local<Value> Script::Run() { 1620 i::Handle<i::Object> obj = Utils::OpenHandle(this, true); 1621 // If execution is terminating, Compile(..)->Run() requires this 1622 // check. 1623 if (obj.is_null()) return Local<Value>(); 1624 i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate(); 1625 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); 1626 LOG_API(isolate, "Script::Run"); 1627 ENTER_V8(isolate); 1628 i::Logger::TimerEventScope timer_scope( 1629 isolate, i::Logger::TimerEventScope::v8_execute); 1630 i::HandleScope scope(isolate); 1631 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); 1632 EXCEPTION_PREAMBLE(isolate); 1633 i::Handle<i::Object> receiver( 1634 isolate->context()->global_proxy(), isolate); 1635 i::Handle<i::Object> result; 1636 has_pending_exception = !i::Execution::Call( 1637 isolate, fun, receiver, 0, NULL).ToHandle(&result); 1638 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>()); 1639 return Utils::ToLocal(scope.CloseAndEscape(result)); 1640 } 1641 1642 1643 Local<UnboundScript> Script::GetUnboundScript() { 1644 i::Handle<i::Object> obj = Utils::OpenHandle(this); 1645 return ToApiHandle<UnboundScript>( 1646 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared())); 1647 } 1648 1649 1650 Local<UnboundScript> ScriptCompiler::CompileUnbound( 1651 Isolate* v8_isolate, 1652 Source* source, 1653 CompileOptions options) { 1654 i::ScriptData* script_data_impl = NULL; 1655 i::CachedDataMode cached_data_mode = i::NO_CACHED_DATA; 1656 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 1657 ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()", 1658 return Local<UnboundScript>()); 1659 if (options & kProduceDataToCache) { 1660 cached_data_mode = i::PRODUCE_CACHED_DATA; 1661 ASSERT(source->cached_data == NULL); 1662 if (source->cached_data) { 1663 // Asked to produce cached data even though there is some already -> not 1664 // good. Fail the compilation. 1665 EXCEPTION_PREAMBLE(isolate); 1666 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError( 1667 "invalid_cached_data", isolate->factory()->NewJSArray(0)); 1668 isolate->Throw(*result); 1669 isolate->ReportPendingMessages(); 1670 has_pending_exception = true; 1671 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>()); 1672 } 1673 } else if (source->cached_data) { 1674 cached_data_mode = i::CONSUME_CACHED_DATA; 1675 // ScriptData takes care of aligning, in case the data is not aligned 1676 // correctly. 1677 script_data_impl = i::ScriptData::New( 1678 reinterpret_cast<const char*>(source->cached_data->data), 1679 source->cached_data->length); 1680 // If the cached data is not valid, fail the compilation. 1681 if (script_data_impl == NULL || !script_data_impl->SanityCheck()) { 1682 EXCEPTION_PREAMBLE(isolate); 1683 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError( 1684 "invalid_cached_data", isolate->factory()->NewJSArray(0)); 1685 isolate->Throw(*result); 1686 isolate->ReportPendingMessages(); 1687 delete script_data_impl; 1688 has_pending_exception = true; 1689 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>()); 1690 } 1691 } 1692 1693 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string)); 1694 LOG_API(isolate, "ScriptCompiler::CompileUnbound"); 1695 ENTER_V8(isolate); 1696 i::SharedFunctionInfo* raw_result = NULL; 1697 { i::HandleScope scope(isolate); 1698 i::Handle<i::Object> name_obj; 1699 int line_offset = 0; 1700 int column_offset = 0; 1701 bool is_shared_cross_origin = false; 1702 if (!source->resource_name.IsEmpty()) { 1703 name_obj = Utils::OpenHandle(*(source->resource_name)); 1704 } 1705 if (!source->resource_line_offset.IsEmpty()) { 1706 line_offset = static_cast<int>(source->resource_line_offset->Value()); 1707 } 1708 if (!source->resource_column_offset.IsEmpty()) { 1709 column_offset = 1710 static_cast<int>(source->resource_column_offset->Value()); 1711 } 1712 if (!source->resource_is_shared_cross_origin.IsEmpty()) { 1713 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 1714 is_shared_cross_origin = 1715 source->resource_is_shared_cross_origin == v8::True(v8_isolate); 1716 } 1717 EXCEPTION_PREAMBLE(isolate); 1718 i::Handle<i::SharedFunctionInfo> result = 1719 i::Compiler::CompileScript(str, 1720 name_obj, 1721 line_offset, 1722 column_offset, 1723 is_shared_cross_origin, 1724 isolate->global_context(), 1725 NULL, 1726 &script_data_impl, 1727 cached_data_mode, 1728 i::NOT_NATIVES_CODE); 1729 has_pending_exception = result.is_null(); 1730 if (has_pending_exception && cached_data_mode == i::CONSUME_CACHED_DATA) { 1731 // This case won't happen during normal operation; we have compiled 1732 // successfully and produced cached data, and but the second compilation 1733 // of the same source code fails. 1734 delete script_data_impl; 1735 script_data_impl = NULL; 1736 } 1737 EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>()); 1738 raw_result = *result; 1739 if ((options & kProduceDataToCache) && script_data_impl != NULL) { 1740 // script_data_impl now contains the data that was generated. source will 1741 // take the ownership. 1742 source->cached_data = new CachedData( 1743 reinterpret_cast<const uint8_t*>(script_data_impl->Data()), 1744 script_data_impl->Length(), CachedData::BufferOwned); 1745 script_data_impl->owns_store_ = false; 1746 } 1747 delete script_data_impl; 1748 } 1749 i::Handle<i::SharedFunctionInfo> result(raw_result, isolate); 1750 return ToApiHandle<UnboundScript>(result); 1751 } 1752 1753 1754 Local<Script> ScriptCompiler::Compile( 1755 Isolate* v8_isolate, 1756 Source* source, 1757 CompileOptions options) { 1758 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 1759 ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>()); 1760 LOG_API(isolate, "ScriptCompiler::CompiletBound()"); 1761 ENTER_V8(isolate); 1762 Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options); 1763 if (generic.IsEmpty()) return Local<Script>(); 1764 return generic->BindToCurrentContext(); 1765 } 1766 1767 1768 Local<Script> Script::Compile(v8::Handle<String> source, 1769 v8::ScriptOrigin* origin) { 1770 i::Handle<i::String> str = Utils::OpenHandle(*source); 1771 if (origin) { 1772 ScriptCompiler::Source script_source(source, *origin); 1773 return ScriptCompiler::Compile( 1774 reinterpret_cast<v8::Isolate*>(str->GetIsolate()), 1775 &script_source); 1776 } 1777 ScriptCompiler::Source script_source(source); 1778 return ScriptCompiler::Compile( 1779 reinterpret_cast<v8::Isolate*>(str->GetIsolate()), 1780 &script_source); 1781 } 1782 1783 1784 Local<Script> Script::Compile(v8::Handle<String> source, 1785 v8::Handle<String> file_name) { 1786 ScriptOrigin origin(file_name); 1787 return Compile(source, &origin); 1788 } 1789 1790 1791 // --- E x c e p t i o n s --- 1792 1793 1794 v8::TryCatch::TryCatch() 1795 : isolate_(i::Isolate::Current()), 1796 next_(isolate_->try_catch_handler()), 1797 is_verbose_(false), 1798 can_continue_(true), 1799 capture_message_(true), 1800 rethrow_(false), 1801 has_terminated_(false) { 1802 Reset(); 1803 js_stack_comparable_address_ = this; 1804 #ifdef V8_USE_ADDRESS_SANITIZER 1805 void* asan_fake_stack_handle = __asan_get_current_fake_stack(); 1806 if (asan_fake_stack_handle != NULL) { 1807 js_stack_comparable_address_ = __asan_addr_is_in_fake_stack( 1808 asan_fake_stack_handle, js_stack_comparable_address_, NULL, NULL); 1809 CHECK(js_stack_comparable_address_ != NULL); 1810 } 1811 #endif 1812 // Special handling for simulators which have a separate JS stack. 1813 js_stack_comparable_address_ = reinterpret_cast<void*>( 1814 v8::internal::SimulatorStack::RegisterCTryCatch( 1815 reinterpret_cast<uintptr_t>(js_stack_comparable_address_))); 1816 isolate_->RegisterTryCatchHandler(this); 1817 } 1818 1819 1820 v8::TryCatch::~TryCatch() { 1821 ASSERT(isolate_ == i::Isolate::Current()); 1822 if (rethrow_) { 1823 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_); 1824 v8::HandleScope scope(isolate); 1825 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception()); 1826 if (HasCaught() && capture_message_) { 1827 // If an exception was caught and rethrow_ is indicated, the saved 1828 // message, script, and location need to be restored to Isolate TLS 1829 // for reuse. capture_message_ needs to be disabled so that DoThrow() 1830 // does not create a new message. 1831 isolate_->thread_local_top()->rethrowing_message_ = true; 1832 isolate_->RestorePendingMessageFromTryCatch(this); 1833 } 1834 isolate_->UnregisterTryCatchHandler(this); 1835 v8::internal::SimulatorStack::UnregisterCTryCatch(); 1836 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc); 1837 ASSERT(!isolate_->thread_local_top()->rethrowing_message_); 1838 } else { 1839 isolate_->UnregisterTryCatchHandler(this); 1840 v8::internal::SimulatorStack::UnregisterCTryCatch(); 1841 } 1842 } 1843 1844 1845 bool v8::TryCatch::HasCaught() const { 1846 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(); 1847 } 1848 1849 1850 bool v8::TryCatch::CanContinue() const { 1851 return can_continue_; 1852 } 1853 1854 1855 bool v8::TryCatch::HasTerminated() const { 1856 return has_terminated_; 1857 } 1858 1859 1860 v8::Handle<v8::Value> v8::TryCatch::ReThrow() { 1861 if (!HasCaught()) return v8::Local<v8::Value>(); 1862 rethrow_ = true; 1863 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_)); 1864 } 1865 1866 1867 v8::Local<Value> v8::TryCatch::Exception() const { 1868 ASSERT(isolate_ == i::Isolate::Current()); 1869 if (HasCaught()) { 1870 // Check for out of memory exception. 1871 i::Object* exception = reinterpret_cast<i::Object*>(exception_); 1872 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_)); 1873 } else { 1874 return v8::Local<Value>(); 1875 } 1876 } 1877 1878 1879 v8::Local<Value> v8::TryCatch::StackTrace() const { 1880 ASSERT(isolate_ == i::Isolate::Current()); 1881 if (HasCaught()) { 1882 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_); 1883 if (!raw_obj->IsJSObject()) return v8::Local<Value>(); 1884 i::HandleScope scope(isolate_); 1885 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_); 1886 i::Handle<i::String> name = isolate_->factory()->stack_string(); 1887 if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>(); 1888 i::Handle<i::Object> value; 1889 if (!i::Object::GetProperty(obj, name).ToHandle(&value)) { 1890 return v8::Local<Value>(); 1891 } 1892 return v8::Utils::ToLocal(scope.CloseAndEscape(value)); 1893 } else { 1894 return v8::Local<Value>(); 1895 } 1896 } 1897 1898 1899 v8::Local<v8::Message> v8::TryCatch::Message() const { 1900 ASSERT(isolate_ == i::Isolate::Current()); 1901 i::Object* message = reinterpret_cast<i::Object*>(message_obj_); 1902 ASSERT(message->IsJSMessageObject() || message->IsTheHole()); 1903 if (HasCaught() && !message->IsTheHole()) { 1904 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_)); 1905 } else { 1906 return v8::Local<v8::Message>(); 1907 } 1908 } 1909 1910 1911 void v8::TryCatch::Reset() { 1912 ASSERT(isolate_ == i::Isolate::Current()); 1913 i::Object* the_hole = isolate_->heap()->the_hole_value(); 1914 exception_ = the_hole; 1915 message_obj_ = the_hole; 1916 message_script_ = the_hole; 1917 message_start_pos_ = 0; 1918 message_end_pos_ = 0; 1919 } 1920 1921 1922 void v8::TryCatch::SetVerbose(bool value) { 1923 is_verbose_ = value; 1924 } 1925 1926 1927 void v8::TryCatch::SetCaptureMessage(bool value) { 1928 capture_message_ = value; 1929 } 1930 1931 1932 // --- M e s s a g e --- 1933 1934 1935 Local<String> Message::Get() const { 1936 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1937 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>()); 1938 ENTER_V8(isolate); 1939 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 1940 i::Handle<i::Object> obj = Utils::OpenHandle(this); 1941 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj); 1942 Local<String> result = Utils::ToLocal(raw_result); 1943 return scope.Escape(result); 1944 } 1945 1946 1947 v8::Handle<Value> Message::GetScriptResourceName() const { 1948 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1949 ENTER_V8(isolate); 1950 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 1951 i::Handle<i::JSMessageObject> message = 1952 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1953 // Return this.script.name. 1954 i::Handle<i::JSValue> script = 1955 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(), 1956 isolate)); 1957 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name(), 1958 isolate); 1959 return scope.Escape(Utils::ToLocal(resource_name)); 1960 } 1961 1962 1963 v8::Handle<v8::StackTrace> Message::GetStackTrace() const { 1964 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1965 ENTER_V8(isolate); 1966 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 1967 i::Handle<i::JSMessageObject> message = 1968 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1969 i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate); 1970 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>(); 1971 i::Handle<i::JSArray> stackTrace = 1972 i::Handle<i::JSArray>::cast(stackFramesObj); 1973 return scope.Escape(Utils::StackTraceToLocal(stackTrace)); 1974 } 1975 1976 1977 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction( 1978 const char* name, 1979 i::Handle<i::Object> recv, 1980 int argc, 1981 i::Handle<i::Object> argv[]) { 1982 i::Isolate* isolate = i::Isolate::Current(); 1983 i::Handle<i::Object> object_fun = 1984 i::Object::GetProperty( 1985 isolate, isolate->js_builtins_object(), name).ToHandleChecked(); 1986 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun); 1987 return i::Execution::Call(isolate, fun, recv, argc, argv); 1988 } 1989 1990 1991 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction( 1992 const char* name, 1993 i::Handle<i::Object> data) { 1994 i::Handle<i::Object> argv[] = { data }; 1995 return CallV8HeapFunction(name, 1996 i::Isolate::Current()->js_builtins_object(), 1997 ARRAY_SIZE(argv), 1998 argv); 1999 } 2000 2001 2002 int Message::GetLineNumber() const { 2003 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2004 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo); 2005 ENTER_V8(isolate); 2006 i::HandleScope scope(isolate); 2007 2008 EXCEPTION_PREAMBLE(isolate); 2009 i::Handle<i::Object> result; 2010 has_pending_exception = !CallV8HeapFunction( 2011 "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result); 2012 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2013 return static_cast<int>(result->Number()); 2014 } 2015 2016 2017 int Message::GetStartPosition() const { 2018 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2019 ENTER_V8(isolate); 2020 i::HandleScope scope(isolate); 2021 i::Handle<i::JSMessageObject> message = 2022 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2023 return message->start_position(); 2024 } 2025 2026 2027 int Message::GetEndPosition() const { 2028 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2029 ENTER_V8(isolate); 2030 i::HandleScope scope(isolate); 2031 i::Handle<i::JSMessageObject> message = 2032 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2033 return message->end_position(); 2034 } 2035 2036 2037 int Message::GetStartColumn() const { 2038 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2039 ENTER_V8(isolate); 2040 i::HandleScope scope(isolate); 2041 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 2042 EXCEPTION_PREAMBLE(isolate); 2043 i::Handle<i::Object> start_col_obj; 2044 has_pending_exception = !CallV8HeapFunction( 2045 "GetPositionInLine", data_obj).ToHandle(&start_col_obj); 2046 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2047 return static_cast<int>(start_col_obj->Number()); 2048 } 2049 2050 2051 int Message::GetEndColumn() const { 2052 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2053 ENTER_V8(isolate); 2054 i::HandleScope scope(isolate); 2055 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 2056 EXCEPTION_PREAMBLE(isolate); 2057 i::Handle<i::Object> start_col_obj; 2058 has_pending_exception = !CallV8HeapFunction( 2059 "GetPositionInLine", data_obj).ToHandle(&start_col_obj); 2060 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2061 i::Handle<i::JSMessageObject> message = 2062 i::Handle<i::JSMessageObject>::cast(data_obj); 2063 int start = message->start_position(); 2064 int end = message->end_position(); 2065 return static_cast<int>(start_col_obj->Number()) + (end - start); 2066 } 2067 2068 2069 bool Message::IsSharedCrossOrigin() const { 2070 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2071 ENTER_V8(isolate); 2072 i::HandleScope scope(isolate); 2073 i::Handle<i::JSMessageObject> message = 2074 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2075 i::Handle<i::JSValue> script = 2076 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(), 2077 isolate)); 2078 return i::Script::cast(script->value())->is_shared_cross_origin(); 2079 } 2080 2081 2082 Local<String> Message::GetSourceLine() const { 2083 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2084 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>()); 2085 ENTER_V8(isolate); 2086 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2087 EXCEPTION_PREAMBLE(isolate); 2088 i::Handle<i::Object> result; 2089 has_pending_exception = !CallV8HeapFunction( 2090 "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result); 2091 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>()); 2092 if (result->IsString()) { 2093 return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result))); 2094 } else { 2095 return Local<String>(); 2096 } 2097 } 2098 2099 2100 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) { 2101 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2102 ENTER_V8(i_isolate); 2103 i_isolate->PrintCurrentStackTrace(out); 2104 } 2105 2106 2107 // --- S t a c k T r a c e --- 2108 2109 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const { 2110 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2111 ENTER_V8(isolate); 2112 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2113 i::Handle<i::JSArray> self = Utils::OpenHandle(this); 2114 i::Handle<i::Object> obj = 2115 i::Object::GetElement(isolate, self, index).ToHandleChecked(); 2116 i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj); 2117 return scope.Escape(Utils::StackFrameToLocal(jsobj)); 2118 } 2119 2120 2121 int StackTrace::GetFrameCount() const { 2122 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2123 ENTER_V8(isolate); 2124 return i::Smi::cast(Utils::OpenHandle(this)->length())->value(); 2125 } 2126 2127 2128 Local<Array> StackTrace::AsArray() { 2129 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2130 ENTER_V8(isolate); 2131 return Utils::ToLocal(Utils::OpenHandle(this)); 2132 } 2133 2134 2135 Local<StackTrace> StackTrace::CurrentStackTrace( 2136 Isolate* isolate, 2137 int frame_limit, 2138 StackTraceOptions options) { 2139 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2140 ENTER_V8(i_isolate); 2141 // TODO(dcarney): remove when ScriptDebugServer is fixed. 2142 options = static_cast<StackTraceOptions>( 2143 static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins); 2144 i::Handle<i::JSArray> stackTrace = 2145 i_isolate->CaptureCurrentStackTrace(frame_limit, options); 2146 return Utils::StackTraceToLocal(stackTrace); 2147 } 2148 2149 2150 // --- S t a c k F r a m e --- 2151 2152 int StackFrame::GetLineNumber() const { 2153 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2154 ENTER_V8(isolate); 2155 i::HandleScope scope(isolate); 2156 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2157 i::Handle<i::Object> line = i::Object::GetProperty( 2158 isolate, self, "lineNumber").ToHandleChecked(); 2159 if (!line->IsSmi()) { 2160 return Message::kNoLineNumberInfo; 2161 } 2162 return i::Smi::cast(*line)->value(); 2163 } 2164 2165 2166 int StackFrame::GetColumn() const { 2167 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2168 ENTER_V8(isolate); 2169 i::HandleScope scope(isolate); 2170 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2171 i::Handle<i::Object> column = i::Object::GetProperty( 2172 isolate, self, "column").ToHandleChecked(); 2173 if (!column->IsSmi()) { 2174 return Message::kNoColumnInfo; 2175 } 2176 return i::Smi::cast(*column)->value(); 2177 } 2178 2179 2180 int StackFrame::GetScriptId() const { 2181 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2182 ENTER_V8(isolate); 2183 i::HandleScope scope(isolate); 2184 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2185 i::Handle<i::Object> scriptId = i::Object::GetProperty( 2186 isolate, self, "scriptId").ToHandleChecked(); 2187 if (!scriptId->IsSmi()) { 2188 return Message::kNoScriptIdInfo; 2189 } 2190 return i::Smi::cast(*scriptId)->value(); 2191 } 2192 2193 2194 Local<String> StackFrame::GetScriptName() const { 2195 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2196 ENTER_V8(isolate); 2197 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2198 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2199 i::Handle<i::Object> name = i::Object::GetProperty( 2200 isolate, self, "scriptName").ToHandleChecked(); 2201 if (!name->IsString()) { 2202 return Local<String>(); 2203 } 2204 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2205 } 2206 2207 2208 Local<String> StackFrame::GetScriptNameOrSourceURL() const { 2209 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2210 ENTER_V8(isolate); 2211 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2212 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2213 i::Handle<i::Object> name = i::Object::GetProperty( 2214 isolate, self, "scriptNameOrSourceURL").ToHandleChecked(); 2215 if (!name->IsString()) { 2216 return Local<String>(); 2217 } 2218 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2219 } 2220 2221 2222 Local<String> StackFrame::GetFunctionName() const { 2223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2224 ENTER_V8(isolate); 2225 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2226 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2227 i::Handle<i::Object> name = i::Object::GetProperty( 2228 isolate, self, "functionName").ToHandleChecked(); 2229 if (!name->IsString()) { 2230 return Local<String>(); 2231 } 2232 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2233 } 2234 2235 2236 bool StackFrame::IsEval() const { 2237 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2238 ENTER_V8(isolate); 2239 i::HandleScope scope(isolate); 2240 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2241 i::Handle<i::Object> is_eval = i::Object::GetProperty( 2242 isolate, self, "isEval").ToHandleChecked(); 2243 return is_eval->IsTrue(); 2244 } 2245 2246 2247 bool StackFrame::IsConstructor() const { 2248 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2249 ENTER_V8(isolate); 2250 i::HandleScope scope(isolate); 2251 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2252 i::Handle<i::Object> is_constructor = i::Object::GetProperty( 2253 isolate, self, "isConstructor").ToHandleChecked(); 2254 return is_constructor->IsTrue(); 2255 } 2256 2257 2258 // --- J S O N --- 2259 2260 Local<Value> JSON::Parse(Local<String> json_string) { 2261 i::Handle<i::String> string = Utils::OpenHandle(*json_string); 2262 i::Isolate* isolate = string->GetIsolate(); 2263 EnsureInitializedForIsolate(isolate, "v8::JSON::Parse"); 2264 ENTER_V8(isolate); 2265 i::HandleScope scope(isolate); 2266 i::Handle<i::String> source = i::String::Flatten(string); 2267 EXCEPTION_PREAMBLE(isolate); 2268 i::MaybeHandle<i::Object> maybe_result = 2269 source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source) 2270 : i::JsonParser<false>::Parse(source); 2271 i::Handle<i::Object> result; 2272 has_pending_exception = !maybe_result.ToHandle(&result); 2273 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 2274 return Utils::ToLocal( 2275 i::Handle<i::Object>::cast(scope.CloseAndEscape(result))); 2276 } 2277 2278 2279 // --- D a t a --- 2280 2281 bool Value::FullIsUndefined() const { 2282 bool result = Utils::OpenHandle(this)->IsUndefined(); 2283 ASSERT_EQ(result, QuickIsUndefined()); 2284 return result; 2285 } 2286 2287 2288 bool Value::FullIsNull() const { 2289 bool result = Utils::OpenHandle(this)->IsNull(); 2290 ASSERT_EQ(result, QuickIsNull()); 2291 return result; 2292 } 2293 2294 2295 bool Value::IsTrue() const { 2296 return Utils::OpenHandle(this)->IsTrue(); 2297 } 2298 2299 2300 bool Value::IsFalse() const { 2301 return Utils::OpenHandle(this)->IsFalse(); 2302 } 2303 2304 2305 bool Value::IsFunction() const { 2306 return Utils::OpenHandle(this)->IsJSFunction(); 2307 } 2308 2309 2310 bool Value::FullIsString() const { 2311 bool result = Utils::OpenHandle(this)->IsString(); 2312 ASSERT_EQ(result, QuickIsString()); 2313 return result; 2314 } 2315 2316 2317 bool Value::IsSymbol() const { 2318 return Utils::OpenHandle(this)->IsSymbol(); 2319 } 2320 2321 2322 bool Value::IsArray() const { 2323 return Utils::OpenHandle(this)->IsJSArray(); 2324 } 2325 2326 2327 bool Value::IsArrayBuffer() const { 2328 return Utils::OpenHandle(this)->IsJSArrayBuffer(); 2329 } 2330 2331 2332 bool Value::IsArrayBufferView() const { 2333 return Utils::OpenHandle(this)->IsJSArrayBufferView(); 2334 } 2335 2336 2337 bool Value::IsTypedArray() const { 2338 return Utils::OpenHandle(this)->IsJSTypedArray(); 2339 } 2340 2341 2342 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 2343 bool Value::Is##Type##Array() const { \ 2344 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ 2345 return obj->IsJSTypedArray() && \ 2346 i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array; \ 2347 } 2348 2349 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY) 2350 2351 #undef VALUE_IS_TYPED_ARRAY 2352 2353 2354 bool Value::IsDataView() const { 2355 return Utils::OpenHandle(this)->IsJSDataView(); 2356 } 2357 2358 2359 bool Value::IsObject() const { 2360 return Utils::OpenHandle(this)->IsJSObject(); 2361 } 2362 2363 2364 bool Value::IsNumber() const { 2365 return Utils::OpenHandle(this)->IsNumber(); 2366 } 2367 2368 2369 bool Value::IsBoolean() const { 2370 return Utils::OpenHandle(this)->IsBoolean(); 2371 } 2372 2373 2374 bool Value::IsExternal() const { 2375 return Utils::OpenHandle(this)->IsExternal(); 2376 } 2377 2378 2379 bool Value::IsInt32() const { 2380 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2381 if (obj->IsSmi()) return true; 2382 if (obj->IsNumber()) { 2383 return i::IsInt32Double(obj->Number()); 2384 } 2385 return false; 2386 } 2387 2388 2389 bool Value::IsUint32() const { 2390 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2391 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0; 2392 if (obj->IsNumber()) { 2393 double value = obj->Number(); 2394 return !i::IsMinusZero(value) && 2395 value >= 0 && 2396 value <= i::kMaxUInt32 && 2397 value == i::FastUI2D(i::FastD2UI(value)); 2398 } 2399 return false; 2400 } 2401 2402 2403 bool Value::IsDate() const { 2404 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2405 if (!obj->IsHeapObject()) return false; 2406 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2407 return obj->HasSpecificClassOf(isolate->heap()->Date_string()); 2408 } 2409 2410 2411 bool Value::IsStringObject() const { 2412 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2413 if (!obj->IsHeapObject()) return false; 2414 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2415 return obj->HasSpecificClassOf(isolate->heap()->String_string()); 2416 } 2417 2418 2419 bool Value::IsSymbolObject() const { 2420 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2421 if (!obj->IsHeapObject()) return false; 2422 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2423 return obj->HasSpecificClassOf(isolate->heap()->Symbol_string()); 2424 } 2425 2426 2427 bool Value::IsNumberObject() const { 2428 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2429 if (!obj->IsHeapObject()) return false; 2430 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2431 return obj->HasSpecificClassOf(isolate->heap()->Number_string()); 2432 } 2433 2434 2435 static bool CheckConstructor(i::Isolate* isolate, 2436 i::Handle<i::JSObject> obj, 2437 const char* class_name) { 2438 i::Handle<i::Object> constr(obj->map()->constructor(), isolate); 2439 if (!constr->IsJSFunction()) return false; 2440 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr); 2441 return func->shared()->native() && constr.is_identical_to( 2442 i::Object::GetProperty(isolate, 2443 isolate->js_builtins_object(), 2444 class_name).ToHandleChecked()); 2445 } 2446 2447 2448 bool Value::IsNativeError() const { 2449 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2450 if (obj->IsJSObject()) { 2451 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj)); 2452 i::Isolate* isolate = js_obj->GetIsolate(); 2453 return CheckConstructor(isolate, js_obj, "$Error") || 2454 CheckConstructor(isolate, js_obj, "$EvalError") || 2455 CheckConstructor(isolate, js_obj, "$RangeError") || 2456 CheckConstructor(isolate, js_obj, "$ReferenceError") || 2457 CheckConstructor(isolate, js_obj, "$SyntaxError") || 2458 CheckConstructor(isolate, js_obj, "$TypeError") || 2459 CheckConstructor(isolate, js_obj, "$URIError"); 2460 } else { 2461 return false; 2462 } 2463 } 2464 2465 2466 bool Value::IsBooleanObject() const { 2467 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2468 if (!obj->IsHeapObject()) return false; 2469 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2470 return obj->HasSpecificClassOf(isolate->heap()->Boolean_string()); 2471 } 2472 2473 2474 bool Value::IsRegExp() const { 2475 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2476 return obj->IsJSRegExp(); 2477 } 2478 2479 2480 Local<String> Value::ToString() const { 2481 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2482 i::Handle<i::Object> str; 2483 if (obj->IsString()) { 2484 str = obj; 2485 } else { 2486 i::Isolate* isolate = i::Isolate::Current(); 2487 LOG_API(isolate, "ToString"); 2488 ENTER_V8(isolate); 2489 EXCEPTION_PREAMBLE(isolate); 2490 has_pending_exception = !i::Execution::ToString( 2491 isolate, obj).ToHandle(&str); 2492 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2493 } 2494 return ToApiHandle<String>(str); 2495 } 2496 2497 2498 Local<String> Value::ToDetailString() const { 2499 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2500 i::Handle<i::Object> str; 2501 if (obj->IsString()) { 2502 str = obj; 2503 } else { 2504 i::Isolate* isolate = i::Isolate::Current(); 2505 LOG_API(isolate, "ToDetailString"); 2506 ENTER_V8(isolate); 2507 EXCEPTION_PREAMBLE(isolate); 2508 has_pending_exception = !i::Execution::ToDetailString( 2509 isolate, obj).ToHandle(&str); 2510 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2511 } 2512 return ToApiHandle<String>(str); 2513 } 2514 2515 2516 Local<v8::Object> Value::ToObject() const { 2517 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2518 i::Handle<i::Object> val; 2519 if (obj->IsJSObject()) { 2520 val = obj; 2521 } else { 2522 i::Isolate* isolate = i::Isolate::Current(); 2523 LOG_API(isolate, "ToObject"); 2524 ENTER_V8(isolate); 2525 EXCEPTION_PREAMBLE(isolate); 2526 has_pending_exception = !i::Execution::ToObject( 2527 isolate, obj).ToHandle(&val); 2528 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 2529 } 2530 return ToApiHandle<Object>(val); 2531 } 2532 2533 2534 Local<Boolean> Value::ToBoolean() const { 2535 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2536 if (obj->IsBoolean()) { 2537 return ToApiHandle<Boolean>(obj); 2538 } else { 2539 i::Isolate* isolate = i::Isolate::Current(); 2540 LOG_API(isolate, "ToBoolean"); 2541 ENTER_V8(isolate); 2542 i::Handle<i::Object> val = 2543 isolate->factory()->ToBoolean(obj->BooleanValue()); 2544 return ToApiHandle<Boolean>(val); 2545 } 2546 } 2547 2548 2549 Local<Number> Value::ToNumber() const { 2550 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2551 i::Handle<i::Object> num; 2552 if (obj->IsNumber()) { 2553 num = obj; 2554 } else { 2555 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2556 LOG_API(isolate, "ToNumber"); 2557 ENTER_V8(isolate); 2558 EXCEPTION_PREAMBLE(isolate); 2559 has_pending_exception = !i::Execution::ToNumber( 2560 isolate, obj).ToHandle(&num); 2561 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>()); 2562 } 2563 return ToApiHandle<Number>(num); 2564 } 2565 2566 2567 Local<Integer> Value::ToInteger() const { 2568 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2569 i::Handle<i::Object> num; 2570 if (obj->IsSmi()) { 2571 num = obj; 2572 } else { 2573 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2574 LOG_API(isolate, "ToInteger"); 2575 ENTER_V8(isolate); 2576 EXCEPTION_PREAMBLE(isolate); 2577 has_pending_exception = !i::Execution::ToInteger( 2578 isolate, obj).ToHandle(&num); 2579 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>()); 2580 } 2581 return ToApiHandle<Integer>(num); 2582 } 2583 2584 2585 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { 2586 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 2587 Utils::ApiCheck(isolate != NULL && 2588 isolate->IsInitialized() && 2589 !isolate->IsDead(), 2590 "v8::internal::Internals::CheckInitialized()", 2591 "Isolate is not initialized or V8 has died"); 2592 } 2593 2594 2595 void External::CheckCast(v8::Value* that) { 2596 Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(), 2597 "v8::External::Cast()", 2598 "Could not convert to external"); 2599 } 2600 2601 2602 void v8::Object::CheckCast(Value* that) { 2603 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2604 Utils::ApiCheck(obj->IsJSObject(), 2605 "v8::Object::Cast()", 2606 "Could not convert to object"); 2607 } 2608 2609 2610 void v8::Function::CheckCast(Value* that) { 2611 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2612 Utils::ApiCheck(obj->IsJSFunction(), 2613 "v8::Function::Cast()", 2614 "Could not convert to function"); 2615 } 2616 2617 2618 void v8::String::CheckCast(v8::Value* that) { 2619 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2620 Utils::ApiCheck(obj->IsString(), 2621 "v8::String::Cast()", 2622 "Could not convert to string"); 2623 } 2624 2625 2626 void v8::Symbol::CheckCast(v8::Value* that) { 2627 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2628 Utils::ApiCheck(obj->IsSymbol(), 2629 "v8::Symbol::Cast()", 2630 "Could not convert to symbol"); 2631 } 2632 2633 2634 void v8::Number::CheckCast(v8::Value* that) { 2635 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2636 Utils::ApiCheck(obj->IsNumber(), 2637 "v8::Number::Cast()", 2638 "Could not convert to number"); 2639 } 2640 2641 2642 void v8::Integer::CheckCast(v8::Value* that) { 2643 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2644 Utils::ApiCheck(obj->IsNumber(), 2645 "v8::Integer::Cast()", 2646 "Could not convert to number"); 2647 } 2648 2649 2650 void v8::Array::CheckCast(Value* that) { 2651 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2652 Utils::ApiCheck(obj->IsJSArray(), 2653 "v8::Array::Cast()", 2654 "Could not convert to array"); 2655 } 2656 2657 2658 void v8::Promise::CheckCast(Value* that) { 2659 Utils::ApiCheck(that->IsPromise(), 2660 "v8::Promise::Cast()", 2661 "Could not convert to promise"); 2662 } 2663 2664 2665 void v8::Promise::Resolver::CheckCast(Value* that) { 2666 Utils::ApiCheck(that->IsPromise(), 2667 "v8::Promise::Resolver::Cast()", 2668 "Could not convert to promise resolver"); 2669 } 2670 2671 2672 void v8::ArrayBuffer::CheckCast(Value* that) { 2673 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2674 Utils::ApiCheck(obj->IsJSArrayBuffer(), 2675 "v8::ArrayBuffer::Cast()", 2676 "Could not convert to ArrayBuffer"); 2677 } 2678 2679 2680 void v8::ArrayBufferView::CheckCast(Value* that) { 2681 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2682 Utils::ApiCheck(obj->IsJSArrayBufferView(), 2683 "v8::ArrayBufferView::Cast()", 2684 "Could not convert to ArrayBufferView"); 2685 } 2686 2687 2688 void v8::TypedArray::CheckCast(Value* that) { 2689 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2690 Utils::ApiCheck(obj->IsJSTypedArray(), 2691 "v8::TypedArray::Cast()", 2692 "Could not convert to TypedArray"); 2693 } 2694 2695 2696 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size) \ 2697 void v8::Type##Array::CheckCast(Value* that) { \ 2698 i::Handle<i::Object> obj = Utils::OpenHandle(that); \ 2699 Utils::ApiCheck(obj->IsJSTypedArray() && \ 2700 i::JSTypedArray::cast(*obj)->type() == \ 2701 kExternal##Type##Array, \ 2702 "v8::" #Type "Array::Cast()", \ 2703 "Could not convert to " #Type "Array"); \ 2704 } 2705 2706 2707 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST) 2708 2709 #undef CHECK_TYPED_ARRAY_CAST 2710 2711 2712 void v8::DataView::CheckCast(Value* that) { 2713 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2714 Utils::ApiCheck(obj->IsJSDataView(), 2715 "v8::DataView::Cast()", 2716 "Could not convert to DataView"); 2717 } 2718 2719 2720 void v8::Date::CheckCast(v8::Value* that) { 2721 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2722 i::Isolate* isolate = NULL; 2723 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2724 Utils::ApiCheck(isolate != NULL && 2725 obj->HasSpecificClassOf(isolate->heap()->Date_string()), 2726 "v8::Date::Cast()", 2727 "Could not convert to date"); 2728 } 2729 2730 2731 void v8::StringObject::CheckCast(v8::Value* that) { 2732 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2733 i::Isolate* isolate = NULL; 2734 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2735 Utils::ApiCheck(isolate != NULL && 2736 obj->HasSpecificClassOf(isolate->heap()->String_string()), 2737 "v8::StringObject::Cast()", 2738 "Could not convert to StringObject"); 2739 } 2740 2741 2742 void v8::SymbolObject::CheckCast(v8::Value* that) { 2743 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2744 i::Isolate* isolate = NULL; 2745 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2746 Utils::ApiCheck(isolate != NULL && 2747 obj->HasSpecificClassOf(isolate->heap()->Symbol_string()), 2748 "v8::SymbolObject::Cast()", 2749 "Could not convert to SymbolObject"); 2750 } 2751 2752 2753 void v8::NumberObject::CheckCast(v8::Value* that) { 2754 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2755 i::Isolate* isolate = NULL; 2756 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2757 Utils::ApiCheck(isolate != NULL && 2758 obj->HasSpecificClassOf(isolate->heap()->Number_string()), 2759 "v8::NumberObject::Cast()", 2760 "Could not convert to NumberObject"); 2761 } 2762 2763 2764 void v8::BooleanObject::CheckCast(v8::Value* that) { 2765 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2766 i::Isolate* isolate = NULL; 2767 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2768 Utils::ApiCheck(isolate != NULL && 2769 obj->HasSpecificClassOf(isolate->heap()->Boolean_string()), 2770 "v8::BooleanObject::Cast()", 2771 "Could not convert to BooleanObject"); 2772 } 2773 2774 2775 void v8::RegExp::CheckCast(v8::Value* that) { 2776 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2777 Utils::ApiCheck(obj->IsJSRegExp(), 2778 "v8::RegExp::Cast()", 2779 "Could not convert to regular expression"); 2780 } 2781 2782 2783 bool Value::BooleanValue() const { 2784 return Utils::OpenHandle(this)->BooleanValue(); 2785 } 2786 2787 2788 double Value::NumberValue() const { 2789 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2790 i::Handle<i::Object> num; 2791 if (obj->IsNumber()) { 2792 num = obj; 2793 } else { 2794 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2795 LOG_API(isolate, "NumberValue"); 2796 ENTER_V8(isolate); 2797 EXCEPTION_PREAMBLE(isolate); 2798 has_pending_exception = !i::Execution::ToNumber( 2799 isolate, obj).ToHandle(&num); 2800 EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value()); 2801 } 2802 return num->Number(); 2803 } 2804 2805 2806 int64_t Value::IntegerValue() const { 2807 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2808 i::Handle<i::Object> num; 2809 if (obj->IsNumber()) { 2810 num = obj; 2811 } else { 2812 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2813 LOG_API(isolate, "IntegerValue"); 2814 ENTER_V8(isolate); 2815 EXCEPTION_PREAMBLE(isolate); 2816 has_pending_exception = !i::Execution::ToInteger( 2817 isolate, obj).ToHandle(&num); 2818 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2819 } 2820 if (num->IsSmi()) { 2821 return i::Smi::cast(*num)->value(); 2822 } else { 2823 return static_cast<int64_t>(num->Number()); 2824 } 2825 } 2826 2827 2828 Local<Int32> Value::ToInt32() const { 2829 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2830 i::Handle<i::Object> num; 2831 if (obj->IsSmi()) { 2832 num = obj; 2833 } else { 2834 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2835 LOG_API(isolate, "ToInt32"); 2836 ENTER_V8(isolate); 2837 EXCEPTION_PREAMBLE(isolate); 2838 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num); 2839 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>()); 2840 } 2841 return ToApiHandle<Int32>(num); 2842 } 2843 2844 2845 Local<Uint32> Value::ToUint32() const { 2846 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2847 i::Handle<i::Object> num; 2848 if (obj->IsSmi()) { 2849 num = obj; 2850 } else { 2851 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2852 LOG_API(isolate, "ToUInt32"); 2853 ENTER_V8(isolate); 2854 EXCEPTION_PREAMBLE(isolate); 2855 has_pending_exception = !i::Execution::ToUint32( 2856 isolate, obj).ToHandle(&num); 2857 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 2858 } 2859 return ToApiHandle<Uint32>(num); 2860 } 2861 2862 2863 Local<Uint32> Value::ToArrayIndex() const { 2864 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2865 if (obj->IsSmi()) { 2866 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj); 2867 return Local<Uint32>(); 2868 } 2869 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2870 LOG_API(isolate, "ToArrayIndex"); 2871 ENTER_V8(isolate); 2872 EXCEPTION_PREAMBLE(isolate); 2873 i::Handle<i::Object> string_obj; 2874 has_pending_exception = !i::Execution::ToString( 2875 isolate, obj).ToHandle(&string_obj); 2876 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 2877 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj); 2878 uint32_t index; 2879 if (str->AsArrayIndex(&index)) { 2880 i::Handle<i::Object> value; 2881 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) { 2882 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate); 2883 } else { 2884 value = isolate->factory()->NewNumber(index); 2885 } 2886 return Utils::Uint32ToLocal(value); 2887 } 2888 return Local<Uint32>(); 2889 } 2890 2891 2892 int32_t Value::Int32Value() const { 2893 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2894 if (obj->IsSmi()) { 2895 return i::Smi::cast(*obj)->value(); 2896 } else { 2897 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2898 LOG_API(isolate, "Int32Value (slow)"); 2899 ENTER_V8(isolate); 2900 EXCEPTION_PREAMBLE(isolate); 2901 i::Handle<i::Object> num; 2902 has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num); 2903 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2904 if (num->IsSmi()) { 2905 return i::Smi::cast(*num)->value(); 2906 } else { 2907 return static_cast<int32_t>(num->Number()); 2908 } 2909 } 2910 } 2911 2912 2913 bool Value::Equals(Handle<Value> that) const { 2914 i::Isolate* isolate = i::Isolate::Current(); 2915 i::Handle<i::Object> obj = Utils::OpenHandle(this, true); 2916 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(), 2917 "v8::Value::Equals()", 2918 "Reading from empty handle")) { 2919 return false; 2920 } 2921 LOG_API(isolate, "Equals"); 2922 ENTER_V8(isolate); 2923 i::Handle<i::Object> other = Utils::OpenHandle(*that); 2924 // If both obj and other are JSObjects, we'd better compare by identity 2925 // immediately when going into JS builtin. The reason is Invoke 2926 // would overwrite global object receiver with global proxy. 2927 if (obj->IsJSObject() && other->IsJSObject()) { 2928 return *obj == *other; 2929 } 2930 i::Handle<i::Object> args[] = { other }; 2931 EXCEPTION_PREAMBLE(isolate); 2932 i::Handle<i::Object> result; 2933 has_pending_exception = !CallV8HeapFunction( 2934 "EQUALS", obj, ARRAY_SIZE(args), args).ToHandle(&result); 2935 EXCEPTION_BAILOUT_CHECK(isolate, false); 2936 return *result == i::Smi::FromInt(i::EQUAL); 2937 } 2938 2939 2940 bool Value::StrictEquals(Handle<Value> that) const { 2941 i::Isolate* isolate = i::Isolate::Current(); 2942 i::Handle<i::Object> obj = Utils::OpenHandle(this, true); 2943 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(), 2944 "v8::Value::StrictEquals()", 2945 "Reading from empty handle")) { 2946 return false; 2947 } 2948 LOG_API(isolate, "StrictEquals"); 2949 i::Handle<i::Object> other = Utils::OpenHandle(*that); 2950 // Must check HeapNumber first, since NaN !== NaN. 2951 if (obj->IsHeapNumber()) { 2952 if (!other->IsNumber()) return false; 2953 double x = obj->Number(); 2954 double y = other->Number(); 2955 // Must check explicitly for NaN:s on Windows, but -0 works fine. 2956 return x == y && !std::isnan(x) && !std::isnan(y); 2957 } else if (*obj == *other) { // Also covers Booleans. 2958 return true; 2959 } else if (obj->IsSmi()) { 2960 return other->IsNumber() && obj->Number() == other->Number(); 2961 } else if (obj->IsString()) { 2962 return other->IsString() && 2963 i::String::Equals(i::Handle<i::String>::cast(obj), 2964 i::Handle<i::String>::cast(other)); 2965 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) { 2966 return other->IsUndefined() || other->IsUndetectableObject(); 2967 } else { 2968 return false; 2969 } 2970 } 2971 2972 2973 bool Value::SameValue(Handle<Value> that) const { 2974 i::Handle<i::Object> obj = Utils::OpenHandle(this, true); 2975 if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(), 2976 "v8::Value::SameValue()", 2977 "Reading from empty handle")) { 2978 return false; 2979 } 2980 i::Handle<i::Object> other = Utils::OpenHandle(*that); 2981 return obj->SameValue(*other); 2982 } 2983 2984 2985 uint32_t Value::Uint32Value() const { 2986 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2987 if (obj->IsSmi()) { 2988 return i::Smi::cast(*obj)->value(); 2989 } else { 2990 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); 2991 LOG_API(isolate, "Uint32Value"); 2992 ENTER_V8(isolate); 2993 EXCEPTION_PREAMBLE(isolate); 2994 i::Handle<i::Object> num; 2995 has_pending_exception = !i::Execution::ToUint32( 2996 isolate, obj).ToHandle(&num); 2997 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2998 if (num->IsSmi()) { 2999 return i::Smi::cast(*num)->value(); 3000 } else { 3001 return static_cast<uint32_t>(num->Number()); 3002 } 3003 } 3004 } 3005 3006 3007 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value, 3008 v8::PropertyAttribute attribs) { 3009 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3010 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 3011 ENTER_V8(isolate); 3012 i::HandleScope scope(isolate); 3013 i::Handle<i::Object> self = Utils::OpenHandle(this); 3014 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3015 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3016 EXCEPTION_PREAMBLE(isolate); 3017 has_pending_exception = i::Runtime::SetObjectProperty( 3018 isolate, 3019 self, 3020 key_obj, 3021 value_obj, 3022 static_cast<PropertyAttributes>(attribs), 3023 i::SLOPPY).is_null(); 3024 EXCEPTION_BAILOUT_CHECK(isolate, false); 3025 return true; 3026 } 3027 3028 3029 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) { 3030 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3031 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 3032 ENTER_V8(isolate); 3033 i::HandleScope scope(isolate); 3034 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3035 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3036 EXCEPTION_PREAMBLE(isolate); 3037 has_pending_exception = i::JSObject::SetElement( 3038 self, index, value_obj, NONE, i::SLOPPY).is_null(); 3039 EXCEPTION_BAILOUT_CHECK(isolate, false); 3040 return true; 3041 } 3042 3043 3044 bool v8::Object::ForceSet(v8::Handle<Value> key, 3045 v8::Handle<Value> value, 3046 v8::PropertyAttribute attribs) { 3047 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3048 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false); 3049 ENTER_V8(isolate); 3050 i::HandleScope scope(isolate); 3051 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3052 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3053 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3054 EXCEPTION_PREAMBLE(isolate); 3055 has_pending_exception = i::Runtime::ForceSetObjectProperty( 3056 self, 3057 key_obj, 3058 value_obj, 3059 static_cast<PropertyAttributes>(attribs)).is_null(); 3060 EXCEPTION_BAILOUT_CHECK(isolate, false); 3061 return true; 3062 } 3063 3064 3065 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) { 3066 return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)), 3067 value, DontEnum); 3068 } 3069 3070 3071 bool v8::Object::ForceDelete(v8::Handle<Value> key) { 3072 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3073 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false); 3074 ENTER_V8(isolate); 3075 i::HandleScope scope(isolate); 3076 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3077 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3078 3079 // When deleting a property on the global object using ForceDelete 3080 // deoptimize all functions as optimized code does not check for the hole 3081 // value with DontDelete properties. We have to deoptimize all contexts 3082 // because of possible cross-context inlined functions. 3083 if (self->IsJSGlobalProxy() || self->IsGlobalObject()) { 3084 i::Deoptimizer::DeoptimizeAll(isolate); 3085 } 3086 3087 EXCEPTION_PREAMBLE(isolate); 3088 i::Handle<i::Object> obj; 3089 has_pending_exception = !i::Runtime::DeleteObjectProperty( 3090 isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj); 3091 EXCEPTION_BAILOUT_CHECK(isolate, false); 3092 return obj->IsTrue(); 3093 } 3094 3095 3096 Local<Value> v8::Object::Get(v8::Handle<Value> key) { 3097 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3098 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 3099 ENTER_V8(isolate); 3100 i::Handle<i::Object> self = Utils::OpenHandle(this); 3101 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3102 EXCEPTION_PREAMBLE(isolate); 3103 i::Handle<i::Object> result; 3104 has_pending_exception = 3105 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result); 3106 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3107 return Utils::ToLocal(result); 3108 } 3109 3110 3111 Local<Value> v8::Object::Get(uint32_t index) { 3112 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3113 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 3114 ENTER_V8(isolate); 3115 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3116 EXCEPTION_PREAMBLE(isolate); 3117 i::Handle<i::Object> result; 3118 has_pending_exception = 3119 !i::Object::GetElement(isolate, self, index).ToHandle(&result); 3120 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3121 return Utils::ToLocal(result); 3122 } 3123 3124 3125 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) { 3126 return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3127 } 3128 3129 3130 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) { 3131 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3132 ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()", 3133 return static_cast<PropertyAttribute>(NONE)); 3134 ENTER_V8(isolate); 3135 i::HandleScope scope(isolate); 3136 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3137 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3138 if (!key_obj->IsName()) { 3139 EXCEPTION_PREAMBLE(isolate); 3140 has_pending_exception = !i::Execution::ToString( 3141 isolate, key_obj).ToHandle(&key_obj); 3142 EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE)); 3143 } 3144 i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj); 3145 PropertyAttributes result = 3146 i::JSReceiver::GetPropertyAttributes(self, key_name); 3147 if (result == ABSENT) return static_cast<PropertyAttribute>(NONE); 3148 return static_cast<PropertyAttribute>(result); 3149 } 3150 3151 3152 Local<Value> v8::Object::GetPrototype() { 3153 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3154 ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>()); 3155 ENTER_V8(isolate); 3156 i::Handle<i::Object> self = Utils::OpenHandle(this); 3157 i::Handle<i::Object> result(self->GetPrototype(isolate), isolate); 3158 return Utils::ToLocal(result); 3159 } 3160 3161 3162 bool v8::Object::SetPrototype(Handle<Value> value) { 3163 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3164 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false); 3165 ENTER_V8(isolate); 3166 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3167 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3168 // We do not allow exceptions thrown while setting the prototype 3169 // to propagate outside. 3170 TryCatch try_catch; 3171 EXCEPTION_PREAMBLE(isolate); 3172 i::MaybeHandle<i::Object> result = i::JSObject::SetPrototype( 3173 self, value_obj); 3174 has_pending_exception = result.is_null(); 3175 EXCEPTION_BAILOUT_CHECK(isolate, false); 3176 return true; 3177 } 3178 3179 3180 Local<Object> v8::Object::FindInstanceInPrototypeChain( 3181 v8::Handle<FunctionTemplate> tmpl) { 3182 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3183 ON_BAILOUT(isolate, 3184 "v8::Object::FindInstanceInPrototypeChain()", 3185 return Local<v8::Object>()); 3186 ENTER_V8(isolate); 3187 i::JSObject* object = *Utils::OpenHandle(this); 3188 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); 3189 while (!tmpl_info->IsTemplateFor(object)) { 3190 i::Object* prototype = object->GetPrototype(); 3191 if (!prototype->IsJSObject()) return Local<Object>(); 3192 object = i::JSObject::cast(prototype); 3193 } 3194 return Utils::ToLocal(i::Handle<i::JSObject>(object)); 3195 } 3196 3197 3198 Local<Array> v8::Object::GetPropertyNames() { 3199 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3200 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()", 3201 return Local<v8::Array>()); 3202 ENTER_V8(isolate); 3203 i::HandleScope scope(isolate); 3204 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3205 EXCEPTION_PREAMBLE(isolate); 3206 i::Handle<i::FixedArray> value; 3207 has_pending_exception = !i::JSReceiver::GetKeys( 3208 self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value); 3209 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>()); 3210 // Because we use caching to speed up enumeration it is important 3211 // to never change the result of the basic enumeration function so 3212 // we clone the result. 3213 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value); 3214 i::Handle<i::JSArray> result = 3215 isolate->factory()->NewJSArrayWithElements(elms); 3216 return Utils::ToLocal(scope.CloseAndEscape(result)); 3217 } 3218 3219 3220 Local<Array> v8::Object::GetOwnPropertyNames() { 3221 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3222 ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()", 3223 return Local<v8::Array>()); 3224 ENTER_V8(isolate); 3225 i::HandleScope scope(isolate); 3226 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3227 EXCEPTION_PREAMBLE(isolate); 3228 i::Handle<i::FixedArray> value; 3229 has_pending_exception = !i::JSReceiver::GetKeys( 3230 self, i::JSReceiver::OWN_ONLY).ToHandle(&value); 3231 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>()); 3232 // Because we use caching to speed up enumeration it is important 3233 // to never change the result of the basic enumeration function so 3234 // we clone the result. 3235 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value); 3236 i::Handle<i::JSArray> result = 3237 isolate->factory()->NewJSArrayWithElements(elms); 3238 return Utils::ToLocal(scope.CloseAndEscape(result)); 3239 } 3240 3241 3242 Local<String> v8::Object::ObjectProtoToString() { 3243 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 3244 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); 3245 ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()", 3246 return Local<v8::String>()); 3247 ENTER_V8(i_isolate); 3248 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3249 3250 i::Handle<i::Object> name(self->class_name(), i_isolate); 3251 3252 // Native implementation of Object.prototype.toString (v8natives.js): 3253 // var c = %_ClassOf(this); 3254 // if (c === 'Arguments') c = 'Object'; 3255 // return "[object " + c + "]"; 3256 3257 if (!name->IsString()) { 3258 return v8::String::NewFromUtf8(isolate, "[object ]"); 3259 } else { 3260 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name); 3261 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) { 3262 return v8::String::NewFromUtf8(isolate, "[object Object]"); 3263 } else { 3264 const char* prefix = "[object "; 3265 Local<String> str = Utils::ToLocal(class_name); 3266 const char* postfix = "]"; 3267 3268 int prefix_len = i::StrLength(prefix); 3269 int str_len = str->Utf8Length(); 3270 int postfix_len = i::StrLength(postfix); 3271 3272 int buf_len = prefix_len + str_len + postfix_len; 3273 i::ScopedVector<char> buf(buf_len); 3274 3275 // Write prefix. 3276 char* ptr = buf.start(); 3277 i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize); 3278 ptr += prefix_len; 3279 3280 // Write real content. 3281 str->WriteUtf8(ptr, str_len); 3282 ptr += str_len; 3283 3284 // Write postfix. 3285 i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize); 3286 3287 // Copy the buffer into a heap-allocated string and return it. 3288 Local<String> result = v8::String::NewFromUtf8( 3289 isolate, buf.start(), String::kNormalString, buf_len); 3290 return result; 3291 } 3292 } 3293 } 3294 3295 3296 Local<Value> v8::Object::GetConstructor() { 3297 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3298 ON_BAILOUT(isolate, "v8::Object::GetConstructor()", 3299 return Local<v8::Function>()); 3300 ENTER_V8(isolate); 3301 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3302 i::Handle<i::Object> constructor(self->GetConstructor(), isolate); 3303 return Utils::ToLocal(constructor); 3304 } 3305 3306 3307 Local<String> v8::Object::GetConstructorName() { 3308 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3309 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()", 3310 return Local<v8::String>()); 3311 ENTER_V8(isolate); 3312 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3313 i::Handle<i::String> name(self->constructor_name()); 3314 return Utils::ToLocal(name); 3315 } 3316 3317 3318 bool v8::Object::Delete(v8::Handle<Value> key) { 3319 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3320 ON_BAILOUT(isolate, "v8::Object::Delete()", return false); 3321 ENTER_V8(isolate); 3322 i::HandleScope scope(isolate); 3323 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3324 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3325 EXCEPTION_PREAMBLE(isolate); 3326 i::Handle<i::Object> obj; 3327 has_pending_exception = !i::Runtime::DeleteObjectProperty( 3328 isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj); 3329 EXCEPTION_BAILOUT_CHECK(isolate, false); 3330 return obj->IsTrue(); 3331 } 3332 3333 3334 bool v8::Object::DeletePrivate(v8::Handle<Private> key) { 3335 return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3336 } 3337 3338 3339 bool v8::Object::Has(v8::Handle<Value> key) { 3340 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3341 ON_BAILOUT(isolate, "v8::Object::Has()", return false); 3342 ENTER_V8(isolate); 3343 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 3344 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3345 EXCEPTION_PREAMBLE(isolate); 3346 i::Handle<i::Object> obj; 3347 has_pending_exception = !i::Runtime::HasObjectProperty( 3348 isolate, self, key_obj).ToHandle(&obj); 3349 EXCEPTION_BAILOUT_CHECK(isolate, false); 3350 return obj->IsTrue(); 3351 } 3352 3353 3354 bool v8::Object::HasPrivate(v8::Handle<Private> key) { 3355 // TODO(rossberg): this should use HasOwnProperty, but we'd need to 3356 // generalise that to a (noy yet existant) Name argument first. 3357 return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3358 } 3359 3360 3361 bool v8::Object::Delete(uint32_t index) { 3362 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3363 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()", 3364 return false); 3365 ENTER_V8(isolate); 3366 HandleScope scope(reinterpret_cast<Isolate*>(isolate)); 3367 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3368 3369 EXCEPTION_PREAMBLE(isolate); 3370 i::Handle<i::Object> obj; 3371 has_pending_exception = 3372 !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj); 3373 EXCEPTION_BAILOUT_CHECK(isolate, false); 3374 return obj->IsTrue(); 3375 } 3376 3377 3378 bool v8::Object::Has(uint32_t index) { 3379 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3380 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false); 3381 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3382 return i::JSReceiver::HasElement(self, index); 3383 } 3384 3385 3386 template<typename Setter, typename Getter, typename Data> 3387 static inline bool ObjectSetAccessor(Object* obj, 3388 Handle<String> name, 3389 Setter getter, 3390 Getter setter, 3391 Data data, 3392 AccessControl settings, 3393 PropertyAttribute attributes) { 3394 i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate(); 3395 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false); 3396 ENTER_V8(isolate); 3397 i::HandleScope scope(isolate); 3398 v8::Handle<AccessorSignature> signature; 3399 i::Handle<i::AccessorInfo> info = MakeAccessorInfo( 3400 name, getter, setter, data, settings, attributes, signature); 3401 if (info.is_null()) return false; 3402 bool fast = Utils::OpenHandle(obj)->HasFastProperties(); 3403 i::Handle<i::Object> result; 3404 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 3405 isolate, result, 3406 i::JSObject::SetAccessor(Utils::OpenHandle(obj), info), 3407 false); 3408 if (result->IsUndefined()) return false; 3409 if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0); 3410 return true; 3411 } 3412 3413 3414 bool Object::SetAccessor(Handle<String> name, 3415 AccessorGetterCallback getter, 3416 AccessorSetterCallback setter, 3417 v8::Handle<Value> data, 3418 AccessControl settings, 3419 PropertyAttribute attributes) { 3420 return ObjectSetAccessor( 3421 this, name, getter, setter, data, settings, attributes); 3422 } 3423 3424 3425 bool Object::SetDeclaredAccessor(Local<String> name, 3426 Local<DeclaredAccessorDescriptor> descriptor, 3427 PropertyAttribute attributes, 3428 AccessControl settings) { 3429 void* null = NULL; 3430 return ObjectSetAccessor( 3431 this, name, descriptor, null, null, settings, attributes); 3432 } 3433 3434 3435 void Object::SetAccessorProperty(Local<String> name, 3436 Local<Function> getter, 3437 Handle<Function> setter, 3438 PropertyAttribute attribute, 3439 AccessControl settings) { 3440 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3441 ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return); 3442 ENTER_V8(isolate); 3443 i::HandleScope scope(isolate); 3444 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter); 3445 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true); 3446 if (setter_i.is_null()) setter_i = isolate->factory()->null_value(); 3447 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this), 3448 v8::Utils::OpenHandle(*name), 3449 getter_i, 3450 setter_i, 3451 static_cast<PropertyAttributes>(attribute), 3452 settings); 3453 } 3454 3455 3456 bool v8::Object::HasOwnProperty(Handle<String> key) { 3457 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3458 ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()", 3459 return false); 3460 return i::JSReceiver::HasOwnProperty( 3461 Utils::OpenHandle(this), Utils::OpenHandle(*key)); 3462 } 3463 3464 3465 bool v8::Object::HasRealNamedProperty(Handle<String> key) { 3466 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3467 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()", 3468 return false); 3469 return i::JSObject::HasRealNamedProperty(Utils::OpenHandle(this), 3470 Utils::OpenHandle(*key)); 3471 } 3472 3473 3474 bool v8::Object::HasRealIndexedProperty(uint32_t index) { 3475 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3476 ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()", 3477 return false); 3478 return i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index); 3479 } 3480 3481 3482 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) { 3483 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3484 ON_BAILOUT(isolate, 3485 "v8::Object::HasRealNamedCallbackProperty()", 3486 return false); 3487 ENTER_V8(isolate); 3488 return i::JSObject::HasRealNamedCallbackProperty(Utils::OpenHandle(this), 3489 Utils::OpenHandle(*key)); 3490 } 3491 3492 3493 bool v8::Object::HasNamedLookupInterceptor() { 3494 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3495 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()", 3496 return false); 3497 return Utils::OpenHandle(this)->HasNamedInterceptor(); 3498 } 3499 3500 3501 bool v8::Object::HasIndexedLookupInterceptor() { 3502 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3503 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()", 3504 return false); 3505 return Utils::OpenHandle(this)->HasIndexedInterceptor(); 3506 } 3507 3508 3509 static Local<Value> GetPropertyByLookup(i::Isolate* isolate, 3510 i::Handle<i::JSObject> receiver, 3511 i::Handle<i::String> name, 3512 i::LookupResult* lookup) { 3513 if (!lookup->IsProperty()) { 3514 // No real property was found. 3515 return Local<Value>(); 3516 } 3517 3518 // If the property being looked up is a callback, it can throw 3519 // an exception. 3520 EXCEPTION_PREAMBLE(isolate); 3521 i::LookupIterator it( 3522 receiver, name, i::Handle<i::JSReceiver>(lookup->holder(), isolate), 3523 i::LookupIterator::SKIP_INTERCEPTOR); 3524 i::Handle<i::Object> result; 3525 has_pending_exception = !i::Object::GetProperty(&it).ToHandle(&result); 3526 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3527 3528 return Utils::ToLocal(result); 3529 } 3530 3531 3532 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( 3533 Handle<String> key) { 3534 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3535 ON_BAILOUT(isolate, 3536 "v8::Object::GetRealNamedPropertyInPrototypeChain()", 3537 return Local<Value>()); 3538 ENTER_V8(isolate); 3539 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 3540 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3541 i::LookupResult lookup(isolate); 3542 self_obj->LookupRealNamedPropertyInPrototypes(key_obj, &lookup); 3543 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 3544 } 3545 3546 3547 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { 3548 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3549 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()", 3550 return Local<Value>()); 3551 ENTER_V8(isolate); 3552 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 3553 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3554 i::LookupResult lookup(isolate); 3555 self_obj->LookupRealNamedProperty(key_obj, &lookup); 3556 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 3557 } 3558 3559 3560 // Turns on access checks by copying the map and setting the check flag. 3561 // Because the object gets a new map, existing inline cache caching 3562 // the old map of this object will fail. 3563 void v8::Object::TurnOnAccessCheck() { 3564 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3565 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return); 3566 ENTER_V8(isolate); 3567 i::HandleScope scope(isolate); 3568 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3569 3570 // When turning on access checks for a global object deoptimize all functions 3571 // as optimized code does not always handle access checks. 3572 i::Deoptimizer::DeoptimizeGlobalObject(*obj); 3573 3574 i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map())); 3575 new_map->set_is_access_check_needed(true); 3576 obj->set_map(*new_map); 3577 } 3578 3579 3580 bool v8::Object::IsDirty() { 3581 return Utils::OpenHandle(this)->IsDirty(); 3582 } 3583 3584 3585 Local<v8::Object> v8::Object::Clone() { 3586 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3587 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>()); 3588 ENTER_V8(isolate); 3589 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3590 EXCEPTION_PREAMBLE(isolate); 3591 i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self); 3592 has_pending_exception = result.is_null(); 3593 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 3594 return Utils::ToLocal(result); 3595 } 3596 3597 3598 Local<v8::Context> v8::Object::CreationContext() { 3599 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3600 ON_BAILOUT(isolate, 3601 "v8::Object::CreationContext()", return Local<v8::Context>()); 3602 ENTER_V8(isolate); 3603 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3604 i::Context* context = self->GetCreationContext(); 3605 return Utils::ToLocal(i::Handle<i::Context>(context)); 3606 } 3607 3608 3609 int v8::Object::GetIdentityHash() { 3610 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3611 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0); 3612 ENTER_V8(isolate); 3613 i::HandleScope scope(isolate); 3614 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3615 return i::JSReceiver::GetOrCreateIdentityHash(self)->value(); 3616 } 3617 3618 3619 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, 3620 v8::Handle<v8::Value> value) { 3621 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3622 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false); 3623 if (value.IsEmpty()) return DeleteHiddenValue(key); 3624 ENTER_V8(isolate); 3625 i::HandleScope scope(isolate); 3626 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3627 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3628 i::Handle<i::String> key_string = 3629 isolate->factory()->InternalizeString(key_obj); 3630 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3631 i::Handle<i::Object> result = 3632 i::JSObject::SetHiddenProperty(self, key_string, value_obj); 3633 return *result == *self; 3634 } 3635 3636 3637 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { 3638 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3639 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()", 3640 return Local<v8::Value>()); 3641 ENTER_V8(isolate); 3642 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3643 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3644 i::Handle<i::String> key_string = 3645 isolate->factory()->InternalizeString(key_obj); 3646 i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate); 3647 if (result->IsTheHole()) return v8::Local<v8::Value>(); 3648 return Utils::ToLocal(result); 3649 } 3650 3651 3652 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { 3653 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3654 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false); 3655 ENTER_V8(isolate); 3656 i::HandleScope scope(isolate); 3657 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3658 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3659 i::Handle<i::String> key_string = 3660 isolate->factory()->InternalizeString(key_obj); 3661 i::JSObject::DeleteHiddenProperty(self, key_string); 3662 return true; 3663 } 3664 3665 3666 namespace { 3667 3668 static i::ElementsKind GetElementsKindFromExternalArrayType( 3669 ExternalArrayType array_type) { 3670 switch (array_type) { 3671 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size) \ 3672 case kExternal##Type##Array: \ 3673 return i::EXTERNAL_##TYPE##_ELEMENTS; 3674 3675 TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND) 3676 #undef ARRAY_TYPE_TO_ELEMENTS_KIND 3677 } 3678 UNREACHABLE(); 3679 return i::DICTIONARY_ELEMENTS; 3680 } 3681 3682 3683 void PrepareExternalArrayElements(i::Handle<i::JSObject> object, 3684 void* data, 3685 ExternalArrayType array_type, 3686 int length) { 3687 i::Isolate* isolate = object->GetIsolate(); 3688 i::Handle<i::ExternalArray> array = 3689 isolate->factory()->NewExternalArray(length, array_type, data); 3690 3691 i::Handle<i::Map> external_array_map = 3692 i::JSObject::GetElementsTransitionMap( 3693 object, 3694 GetElementsKindFromExternalArrayType(array_type)); 3695 3696 i::JSObject::SetMapAndElements(object, external_array_map, array); 3697 } 3698 3699 } // namespace 3700 3701 3702 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { 3703 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3704 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); 3705 ENTER_V8(isolate); 3706 i::HandleScope scope(isolate); 3707 if (!Utils::ApiCheck(length >= 0 && 3708 length <= i::ExternalUint8ClampedArray::kMaxLength, 3709 "v8::Object::SetIndexedPropertiesToPixelData()", 3710 "length exceeds max acceptable value")) { 3711 return; 3712 } 3713 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3714 if (!Utils::ApiCheck(!self->IsJSArray(), 3715 "v8::Object::SetIndexedPropertiesToPixelData()", 3716 "JSArray is not supported")) { 3717 return; 3718 } 3719 PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length); 3720 } 3721 3722 3723 bool v8::Object::HasIndexedPropertiesInPixelData() { 3724 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3725 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()", 3726 return false); 3727 return self->HasExternalUint8ClampedElements(); 3728 } 3729 3730 3731 uint8_t* v8::Object::GetIndexedPropertiesPixelData() { 3732 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3733 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()", 3734 return NULL); 3735 if (self->HasExternalUint8ClampedElements()) { 3736 return i::ExternalUint8ClampedArray::cast(self->elements())-> 3737 external_uint8_clamped_pointer(); 3738 } else { 3739 return NULL; 3740 } 3741 } 3742 3743 3744 int v8::Object::GetIndexedPropertiesPixelDataLength() { 3745 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3746 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()", 3747 return -1); 3748 if (self->HasExternalUint8ClampedElements()) { 3749 return i::ExternalUint8ClampedArray::cast(self->elements())->length(); 3750 } else { 3751 return -1; 3752 } 3753 } 3754 3755 3756 void v8::Object::SetIndexedPropertiesToExternalArrayData( 3757 void* data, 3758 ExternalArrayType array_type, 3759 int length) { 3760 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3761 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return); 3762 ENTER_V8(isolate); 3763 i::HandleScope scope(isolate); 3764 if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength, 3765 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3766 "length exceeds max acceptable value")) { 3767 return; 3768 } 3769 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3770 if (!Utils::ApiCheck(!self->IsJSArray(), 3771 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3772 "JSArray is not supported")) { 3773 return; 3774 } 3775 PrepareExternalArrayElements(self, data, array_type, length); 3776 } 3777 3778 3779 bool v8::Object::HasIndexedPropertiesInExternalArrayData() { 3780 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3781 ON_BAILOUT(self->GetIsolate(), 3782 "v8::HasIndexedPropertiesInExternalArrayData()", 3783 return false); 3784 return self->HasExternalArrayElements(); 3785 } 3786 3787 3788 void* v8::Object::GetIndexedPropertiesExternalArrayData() { 3789 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3790 ON_BAILOUT(self->GetIsolate(), 3791 "v8::GetIndexedPropertiesExternalArrayData()", 3792 return NULL); 3793 if (self->HasExternalArrayElements()) { 3794 return i::ExternalArray::cast(self->elements())->external_pointer(); 3795 } else { 3796 return NULL; 3797 } 3798 } 3799 3800 3801 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() { 3802 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3803 ON_BAILOUT(self->GetIsolate(), 3804 "v8::GetIndexedPropertiesExternalArrayDataType()", 3805 return static_cast<ExternalArrayType>(-1)); 3806 switch (self->elements()->map()->instance_type()) { 3807 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size) \ 3808 case i::EXTERNAL_##TYPE##_ARRAY_TYPE: \ 3809 return kExternal##Type##Array; 3810 TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE) 3811 #undef INSTANCE_TYPE_TO_ARRAY_TYPE 3812 default: 3813 return static_cast<ExternalArrayType>(-1); 3814 } 3815 } 3816 3817 3818 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { 3819 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3820 ON_BAILOUT(self->GetIsolate(), 3821 "v8::GetIndexedPropertiesExternalArrayDataLength()", 3822 return 0); 3823 if (self->HasExternalArrayElements()) { 3824 return i::ExternalArray::cast(self->elements())->length(); 3825 } else { 3826 return -1; 3827 } 3828 } 3829 3830 3831 bool v8::Object::IsCallable() { 3832 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3833 ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false); 3834 ENTER_V8(isolate); 3835 i::HandleScope scope(isolate); 3836 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3837 return obj->IsCallable(); 3838 } 3839 3840 3841 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv, 3842 int argc, 3843 v8::Handle<v8::Value> argv[]) { 3844 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3845 ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", 3846 return Local<v8::Value>()); 3847 LOG_API(isolate, "Object::CallAsFunction"); 3848 ENTER_V8(isolate); 3849 i::Logger::TimerEventScope timer_scope( 3850 isolate, i::Logger::TimerEventScope::v8_execute); 3851 i::HandleScope scope(isolate); 3852 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3853 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 3854 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3855 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 3856 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>(); 3857 if (obj->IsJSFunction()) { 3858 fun = i::Handle<i::JSFunction>::cast(obj); 3859 } else { 3860 EXCEPTION_PREAMBLE(isolate); 3861 i::Handle<i::Object> delegate; 3862 has_pending_exception = !i::Execution::TryGetFunctionDelegate( 3863 isolate, obj).ToHandle(&delegate); 3864 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3865 fun = i::Handle<i::JSFunction>::cast(delegate); 3866 recv_obj = obj; 3867 } 3868 EXCEPTION_PREAMBLE(isolate); 3869 i::Handle<i::Object> returned; 3870 has_pending_exception = !i::Execution::Call( 3871 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned); 3872 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>()); 3873 return Utils::ToLocal(scope.CloseAndEscape(returned)); 3874 } 3875 3876 3877 Local<v8::Value> Object::CallAsConstructor(int argc, 3878 v8::Handle<v8::Value> argv[]) { 3879 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3880 ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", 3881 return Local<v8::Object>()); 3882 LOG_API(isolate, "Object::CallAsConstructor"); 3883 ENTER_V8(isolate); 3884 i::Logger::TimerEventScope timer_scope( 3885 isolate, i::Logger::TimerEventScope::v8_execute); 3886 i::HandleScope scope(isolate); 3887 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3888 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3889 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 3890 if (obj->IsJSFunction()) { 3891 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); 3892 EXCEPTION_PREAMBLE(isolate); 3893 i::Handle<i::Object> returned; 3894 has_pending_exception = !i::Execution::New( 3895 fun, argc, args).ToHandle(&returned); 3896 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 3897 return Utils::ToLocal(scope.CloseAndEscape( 3898 i::Handle<i::JSObject>::cast(returned))); 3899 } 3900 EXCEPTION_PREAMBLE(isolate); 3901 i::Handle<i::Object> delegate; 3902 has_pending_exception = !i::Execution::TryGetConstructorDelegate( 3903 isolate, obj).ToHandle(&delegate); 3904 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 3905 if (!delegate->IsUndefined()) { 3906 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate); 3907 EXCEPTION_PREAMBLE(isolate); 3908 i::Handle<i::Object> returned; 3909 has_pending_exception = !i::Execution::Call( 3910 isolate, fun, obj, argc, args).ToHandle(&returned); 3911 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 3912 ASSERT(!delegate->IsUndefined()); 3913 return Utils::ToLocal(scope.CloseAndEscape(returned)); 3914 } 3915 return Local<v8::Object>(); 3916 } 3917 3918 3919 Local<Function> Function::New(Isolate* v8_isolate, 3920 FunctionCallback callback, 3921 Local<Value> data, 3922 int length) { 3923 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 3924 LOG_API(isolate, "Function::New"); 3925 ENTER_V8(isolate); 3926 return FunctionTemplateNew( 3927 isolate, callback, data, Local<Signature>(), length, true)-> 3928 GetFunction(); 3929 } 3930 3931 3932 Local<v8::Object> Function::NewInstance() const { 3933 return NewInstance(0, NULL); 3934 } 3935 3936 3937 Local<v8::Object> Function::NewInstance(int argc, 3938 v8::Handle<v8::Value> argv[]) const { 3939 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3940 ON_BAILOUT(isolate, "v8::Function::NewInstance()", 3941 return Local<v8::Object>()); 3942 LOG_API(isolate, "Function::NewInstance"); 3943 ENTER_V8(isolate); 3944 i::Logger::TimerEventScope timer_scope( 3945 isolate, i::Logger::TimerEventScope::v8_execute); 3946 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 3947 i::Handle<i::JSFunction> function = Utils::OpenHandle(this); 3948 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3949 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 3950 EXCEPTION_PREAMBLE(isolate); 3951 i::Handle<i::Object> returned; 3952 has_pending_exception = !i::Execution::New( 3953 function, argc, args).ToHandle(&returned); 3954 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 3955 return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned))); 3956 } 3957 3958 3959 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc, 3960 v8::Handle<v8::Value> argv[]) { 3961 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3962 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>()); 3963 LOG_API(isolate, "Function::Call"); 3964 ENTER_V8(isolate); 3965 i::Logger::TimerEventScope timer_scope( 3966 isolate, i::Logger::TimerEventScope::v8_execute); 3967 i::HandleScope scope(isolate); 3968 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this); 3969 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 3970 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3971 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 3972 EXCEPTION_PREAMBLE(isolate); 3973 i::Handle<i::Object> returned; 3974 has_pending_exception = !i::Execution::Call( 3975 isolate, fun, recv_obj, argc, args, true).ToHandle(&returned); 3976 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>()); 3977 return Utils::ToLocal(scope.CloseAndEscape(returned)); 3978 } 3979 3980 3981 void Function::SetName(v8::Handle<v8::String> name) { 3982 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3983 ENTER_V8(isolate); 3984 USE(isolate); 3985 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3986 func->shared()->set_name(*Utils::OpenHandle(*name)); 3987 } 3988 3989 3990 Handle<Value> Function::GetName() const { 3991 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3992 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(), 3993 func->GetIsolate())); 3994 } 3995 3996 3997 Handle<Value> Function::GetInferredName() const { 3998 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3999 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(), 4000 func->GetIsolate())); 4001 } 4002 4003 4004 Handle<Value> Function::GetDisplayName() const { 4005 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4006 ON_BAILOUT(isolate, "v8::Function::GetDisplayName()", 4007 return ToApiHandle<Primitive>( 4008 isolate->factory()->undefined_value())); 4009 ENTER_V8(isolate); 4010 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4011 i::Handle<i::String> property_name = 4012 isolate->factory()->InternalizeOneByteString( 4013 STATIC_ASCII_VECTOR("displayName")); 4014 i::LookupResult lookup(isolate); 4015 func->LookupRealNamedProperty(property_name, &lookup); 4016 if (lookup.IsFound()) { 4017 i::Object* value = lookup.GetLazyValue(); 4018 if (value && value->IsString()) { 4019 i::String* name = i::String::cast(value); 4020 if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name)); 4021 } 4022 } 4023 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 4024 } 4025 4026 4027 ScriptOrigin Function::GetScriptOrigin() const { 4028 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4029 if (func->shared()->script()->IsScript()) { 4030 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4031 i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script); 4032 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate()); 4033 v8::ScriptOrigin origin( 4034 Utils::ToLocal(scriptName), 4035 v8::Integer::New(isolate, script->line_offset()->value()), 4036 v8::Integer::New(isolate, script->column_offset()->value())); 4037 return origin; 4038 } 4039 return v8::ScriptOrigin(Handle<Value>()); 4040 } 4041 4042 4043 const int Function::kLineOffsetNotFound = -1; 4044 4045 4046 int Function::GetScriptLineNumber() const { 4047 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4048 if (func->shared()->script()->IsScript()) { 4049 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4050 return i::Script::GetLineNumber(script, func->shared()->start_position()); 4051 } 4052 return kLineOffsetNotFound; 4053 } 4054 4055 4056 int Function::GetScriptColumnNumber() const { 4057 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4058 if (func->shared()->script()->IsScript()) { 4059 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4060 return i::Script::GetColumnNumber(script, func->shared()->start_position()); 4061 } 4062 return kLineOffsetNotFound; 4063 } 4064 4065 4066 bool Function::IsBuiltin() const { 4067 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4068 return func->IsBuiltin(); 4069 } 4070 4071 4072 int Function::ScriptId() const { 4073 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4074 if (!func->shared()->script()->IsScript()) { 4075 return v8::UnboundScript::kNoScriptId; 4076 } 4077 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4078 return script->id()->value(); 4079 } 4080 4081 4082 Local<v8::Value> Function::GetBoundFunction() const { 4083 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4084 if (!func->shared()->bound()) { 4085 return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate())); 4086 } 4087 i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>( 4088 i::FixedArray::cast(func->function_bindings())); 4089 i::Handle<i::Object> original( 4090 bound_args->get(i::JSFunction::kBoundFunctionIndex), 4091 func->GetIsolate()); 4092 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original)); 4093 } 4094 4095 4096 int String::Length() const { 4097 i::Handle<i::String> str = Utils::OpenHandle(this); 4098 return str->length(); 4099 } 4100 4101 4102 bool String::IsOneByte() const { 4103 i::Handle<i::String> str = Utils::OpenHandle(this); 4104 return str->HasOnlyOneByteChars(); 4105 } 4106 4107 4108 // Helpers for ContainsOnlyOneByteHelper 4109 template<size_t size> struct OneByteMask; 4110 template<> struct OneByteMask<4> { 4111 static const uint32_t value = 0xFF00FF00; 4112 }; 4113 template<> struct OneByteMask<8> { 4114 static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00); 4115 }; 4116 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value; 4117 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1; 4118 static inline bool Unaligned(const uint16_t* chars) { 4119 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask; 4120 } 4121 4122 4123 static inline const uint16_t* Align(const uint16_t* chars) { 4124 return reinterpret_cast<uint16_t*>( 4125 reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask); 4126 } 4127 4128 class ContainsOnlyOneByteHelper { 4129 public: 4130 ContainsOnlyOneByteHelper() : is_one_byte_(true) {} 4131 bool Check(i::String* string) { 4132 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0); 4133 if (cons_string == NULL) return is_one_byte_; 4134 return CheckCons(cons_string); 4135 } 4136 void VisitOneByteString(const uint8_t* chars, int length) { 4137 // Nothing to do. 4138 } 4139 void VisitTwoByteString(const uint16_t* chars, int length) { 4140 // Accumulated bits. 4141 uintptr_t acc = 0; 4142 // Align to uintptr_t. 4143 const uint16_t* end = chars + length; 4144 while (Unaligned(chars) && chars != end) { 4145 acc |= *chars++; 4146 } 4147 // Read word aligned in blocks, 4148 // checking the return value at the end of each block. 4149 const uint16_t* aligned_end = Align(end); 4150 const int increment = sizeof(uintptr_t)/sizeof(uint16_t); 4151 const int inner_loops = 16; 4152 while (chars + inner_loops*increment < aligned_end) { 4153 for (int i = 0; i < inner_loops; i++) { 4154 acc |= *reinterpret_cast<const uintptr_t*>(chars); 4155 chars += increment; 4156 } 4157 // Check for early return. 4158 if ((acc & kOneByteMask) != 0) { 4159 is_one_byte_ = false; 4160 return; 4161 } 4162 } 4163 // Read the rest. 4164 while (chars != end) { 4165 acc |= *chars++; 4166 } 4167 // Check result. 4168 if ((acc & kOneByteMask) != 0) is_one_byte_ = false; 4169 } 4170 4171 private: 4172 bool CheckCons(i::ConsString* cons_string) { 4173 while (true) { 4174 // Check left side if flat. 4175 i::String* left = cons_string->first(); 4176 i::ConsString* left_as_cons = 4177 i::String::VisitFlat(this, left, 0); 4178 if (!is_one_byte_) return false; 4179 // Check right side if flat. 4180 i::String* right = cons_string->second(); 4181 i::ConsString* right_as_cons = 4182 i::String::VisitFlat(this, right, 0); 4183 if (!is_one_byte_) return false; 4184 // Standard recurse/iterate trick. 4185 if (left_as_cons != NULL && right_as_cons != NULL) { 4186 if (left->length() < right->length()) { 4187 CheckCons(left_as_cons); 4188 cons_string = right_as_cons; 4189 } else { 4190 CheckCons(right_as_cons); 4191 cons_string = left_as_cons; 4192 } 4193 // Check fast return. 4194 if (!is_one_byte_) return false; 4195 continue; 4196 } 4197 // Descend left in place. 4198 if (left_as_cons != NULL) { 4199 cons_string = left_as_cons; 4200 continue; 4201 } 4202 // Descend right in place. 4203 if (right_as_cons != NULL) { 4204 cons_string = right_as_cons; 4205 continue; 4206 } 4207 // Terminate. 4208 break; 4209 } 4210 return is_one_byte_; 4211 } 4212 bool is_one_byte_; 4213 DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper); 4214 }; 4215 4216 4217 bool String::ContainsOnlyOneByte() const { 4218 i::Handle<i::String> str = Utils::OpenHandle(this); 4219 if (str->HasOnlyOneByteChars()) return true; 4220 ContainsOnlyOneByteHelper helper; 4221 return helper.Check(*str); 4222 } 4223 4224 4225 class Utf8LengthHelper : public i::AllStatic { 4226 public: 4227 enum State { 4228 kEndsWithLeadingSurrogate = 1 << 0, 4229 kStartsWithTrailingSurrogate = 1 << 1, 4230 kLeftmostEdgeIsCalculated = 1 << 2, 4231 kRightmostEdgeIsCalculated = 1 << 3, 4232 kLeftmostEdgeIsSurrogate = 1 << 4, 4233 kRightmostEdgeIsSurrogate = 1 << 5 4234 }; 4235 4236 static const uint8_t kInitialState = 0; 4237 4238 static inline bool EndsWithSurrogate(uint8_t state) { 4239 return state & kEndsWithLeadingSurrogate; 4240 } 4241 4242 static inline bool StartsWithSurrogate(uint8_t state) { 4243 return state & kStartsWithTrailingSurrogate; 4244 } 4245 4246 class Visitor { 4247 public: 4248 inline explicit Visitor() 4249 : utf8_length_(0), 4250 state_(kInitialState) {} 4251 4252 void VisitOneByteString(const uint8_t* chars, int length) { 4253 int utf8_length = 0; 4254 // Add in length 1 for each non-ASCII character. 4255 for (int i = 0; i < length; i++) { 4256 utf8_length += *chars++ >> 7; 4257 } 4258 // Add in length 1 for each character. 4259 utf8_length_ = utf8_length + length; 4260 state_ = kInitialState; 4261 } 4262 4263 void VisitTwoByteString(const uint16_t* chars, int length) { 4264 int utf8_length = 0; 4265 int last_character = unibrow::Utf16::kNoPreviousCharacter; 4266 for (int i = 0; i < length; i++) { 4267 uint16_t c = chars[i]; 4268 utf8_length += unibrow::Utf8::Length(c, last_character); 4269 last_character = c; 4270 } 4271 utf8_length_ = utf8_length; 4272 uint8_t state = 0; 4273 if (unibrow::Utf16::IsTrailSurrogate(chars[0])) { 4274 state |= kStartsWithTrailingSurrogate; 4275 } 4276 if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) { 4277 state |= kEndsWithLeadingSurrogate; 4278 } 4279 state_ = state; 4280 } 4281 4282 static i::ConsString* VisitFlat(i::String* string, 4283 int* length, 4284 uint8_t* state) { 4285 Visitor visitor; 4286 i::ConsString* cons_string = i::String::VisitFlat(&visitor, string); 4287 *length = visitor.utf8_length_; 4288 *state = visitor.state_; 4289 return cons_string; 4290 } 4291 4292 private: 4293 int utf8_length_; 4294 uint8_t state_; 4295 DISALLOW_COPY_AND_ASSIGN(Visitor); 4296 }; 4297 4298 static inline void MergeLeafLeft(int* length, 4299 uint8_t* state, 4300 uint8_t leaf_state) { 4301 bool edge_surrogate = StartsWithSurrogate(leaf_state); 4302 if (!(*state & kLeftmostEdgeIsCalculated)) { 4303 ASSERT(!(*state & kLeftmostEdgeIsSurrogate)); 4304 *state |= kLeftmostEdgeIsCalculated 4305 | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0); 4306 } else if (EndsWithSurrogate(*state) && edge_surrogate) { 4307 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4308 } 4309 if (EndsWithSurrogate(leaf_state)) { 4310 *state |= kEndsWithLeadingSurrogate; 4311 } else { 4312 *state &= ~kEndsWithLeadingSurrogate; 4313 } 4314 } 4315 4316 static inline void MergeLeafRight(int* length, 4317 uint8_t* state, 4318 uint8_t leaf_state) { 4319 bool edge_surrogate = EndsWithSurrogate(leaf_state); 4320 if (!(*state & kRightmostEdgeIsCalculated)) { 4321 ASSERT(!(*state & kRightmostEdgeIsSurrogate)); 4322 *state |= (kRightmostEdgeIsCalculated 4323 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0)); 4324 } else if (edge_surrogate && StartsWithSurrogate(*state)) { 4325 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4326 } 4327 if (StartsWithSurrogate(leaf_state)) { 4328 *state |= kStartsWithTrailingSurrogate; 4329 } else { 4330 *state &= ~kStartsWithTrailingSurrogate; 4331 } 4332 } 4333 4334 static inline void MergeTerminal(int* length, 4335 uint8_t state, 4336 uint8_t* state_out) { 4337 ASSERT((state & kLeftmostEdgeIsCalculated) && 4338 (state & kRightmostEdgeIsCalculated)); 4339 if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) { 4340 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4341 } 4342 *state_out = kInitialState | 4343 (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) | 4344 (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0); 4345 } 4346 4347 static int Calculate(i::ConsString* current, uint8_t* state_out) { 4348 using namespace internal; 4349 int total_length = 0; 4350 uint8_t state = kInitialState; 4351 while (true) { 4352 i::String* left = current->first(); 4353 i::String* right = current->second(); 4354 uint8_t right_leaf_state; 4355 uint8_t left_leaf_state; 4356 int leaf_length; 4357 ConsString* left_as_cons = 4358 Visitor::VisitFlat(left, &leaf_length, &left_leaf_state); 4359 if (left_as_cons == NULL) { 4360 total_length += leaf_length; 4361 MergeLeafLeft(&total_length, &state, left_leaf_state); 4362 } 4363 ConsString* right_as_cons = 4364 Visitor::VisitFlat(right, &leaf_length, &right_leaf_state); 4365 if (right_as_cons == NULL) { 4366 total_length += leaf_length; 4367 MergeLeafRight(&total_length, &state, right_leaf_state); 4368 if (left_as_cons != NULL) { 4369 // 1 Leaf node. Descend in place. 4370 current = left_as_cons; 4371 continue; 4372 } else { 4373 // Terminal node. 4374 MergeTerminal(&total_length, state, state_out); 4375 return total_length; 4376 } 4377 } else if (left_as_cons == NULL) { 4378 // 1 Leaf node. Descend in place. 4379 current = right_as_cons; 4380 continue; 4381 } 4382 // Both strings are ConsStrings. 4383 // Recurse on smallest. 4384 if (left->length() < right->length()) { 4385 total_length += Calculate(left_as_cons, &left_leaf_state); 4386 MergeLeafLeft(&total_length, &state, left_leaf_state); 4387 current = right_as_cons; 4388 } else { 4389 total_length += Calculate(right_as_cons, &right_leaf_state); 4390 MergeLeafRight(&total_length, &state, right_leaf_state); 4391 current = left_as_cons; 4392 } 4393 } 4394 UNREACHABLE(); 4395 return 0; 4396 } 4397 4398 static inline int Calculate(i::ConsString* current) { 4399 uint8_t state = kInitialState; 4400 return Calculate(current, &state); 4401 } 4402 4403 private: 4404 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper); 4405 }; 4406 4407 4408 static int Utf8Length(i::String* str, i::Isolate* isolate) { 4409 int length = str->length(); 4410 if (length == 0) return 0; 4411 uint8_t state; 4412 i::ConsString* cons_string = 4413 Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state); 4414 if (cons_string == NULL) return length; 4415 return Utf8LengthHelper::Calculate(cons_string); 4416 } 4417 4418 4419 int String::Utf8Length() const { 4420 i::Handle<i::String> str = Utils::OpenHandle(this); 4421 i::Isolate* isolate = str->GetIsolate(); 4422 return v8::Utf8Length(*str, isolate); 4423 } 4424 4425 4426 class Utf8WriterVisitor { 4427 public: 4428 Utf8WriterVisitor( 4429 char* buffer, 4430 int capacity, 4431 bool skip_capacity_check, 4432 bool replace_invalid_utf8) 4433 : early_termination_(false), 4434 last_character_(unibrow::Utf16::kNoPreviousCharacter), 4435 buffer_(buffer), 4436 start_(buffer), 4437 capacity_(capacity), 4438 skip_capacity_check_(capacity == -1 || skip_capacity_check), 4439 replace_invalid_utf8_(replace_invalid_utf8), 4440 utf16_chars_read_(0) { 4441 } 4442 4443 static int WriteEndCharacter(uint16_t character, 4444 int last_character, 4445 int remaining, 4446 char* const buffer, 4447 bool replace_invalid_utf8) { 4448 using namespace unibrow; 4449 ASSERT(remaining > 0); 4450 // We can't use a local buffer here because Encode needs to modify 4451 // previous characters in the stream. We know, however, that 4452 // exactly one character will be advanced. 4453 if (Utf16::IsSurrogatePair(last_character, character)) { 4454 int written = Utf8::Encode(buffer, 4455 character, 4456 last_character, 4457 replace_invalid_utf8); 4458 ASSERT(written == 1); 4459 return written; 4460 } 4461 // Use a scratch buffer to check the required characters. 4462 char temp_buffer[Utf8::kMaxEncodedSize]; 4463 // Can't encode using last_character as gcc has array bounds issues. 4464 int written = Utf8::Encode(temp_buffer, 4465 character, 4466 Utf16::kNoPreviousCharacter, 4467 replace_invalid_utf8); 4468 // Won't fit. 4469 if (written > remaining) return 0; 4470 // Copy over the character from temp_buffer. 4471 for (int j = 0; j < written; j++) { 4472 buffer[j] = temp_buffer[j]; 4473 } 4474 return written; 4475 } 4476 4477 // Visit writes out a group of code units (chars) of a v8::String to the 4478 // internal buffer_. This is done in two phases. The first phase calculates a 4479 // pesimistic estimate (writable_length) on how many code units can be safely 4480 // written without exceeding the buffer capacity and without writing the last 4481 // code unit (it could be a lead surrogate). The estimated number of code 4482 // units is then written out in one go, and the reported byte usage is used 4483 // to correct the estimate. This is repeated until the estimate becomes <= 0 4484 // or all code units have been written out. The second phase writes out code 4485 // units until the buffer capacity is reached, would be exceeded by the next 4486 // unit, or all units have been written out. 4487 template<typename Char> 4488 void Visit(const Char* chars, const int length) { 4489 using namespace unibrow; 4490 ASSERT(!early_termination_); 4491 if (length == 0) return; 4492 // Copy state to stack. 4493 char* buffer = buffer_; 4494 int last_character = 4495 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_; 4496 int i = 0; 4497 // Do a fast loop where there is no exit capacity check. 4498 while (true) { 4499 int fast_length; 4500 if (skip_capacity_check_) { 4501 fast_length = length; 4502 } else { 4503 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 4504 // Need enough space to write everything but one character. 4505 STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3); 4506 int max_size_per_char = sizeof(Char) == 1 ? 2 : 3; 4507 int writable_length = 4508 (remaining_capacity - max_size_per_char)/max_size_per_char; 4509 // Need to drop into slow loop. 4510 if (writable_length <= 0) break; 4511 fast_length = i + writable_length; 4512 if (fast_length > length) fast_length = length; 4513 } 4514 // Write the characters to the stream. 4515 if (sizeof(Char) == 1) { 4516 for (; i < fast_length; i++) { 4517 buffer += 4518 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++)); 4519 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); 4520 } 4521 } else { 4522 for (; i < fast_length; i++) { 4523 uint16_t character = *chars++; 4524 buffer += Utf8::Encode(buffer, 4525 character, 4526 last_character, 4527 replace_invalid_utf8_); 4528 last_character = character; 4529 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); 4530 } 4531 } 4532 // Array is fully written. Exit. 4533 if (fast_length == length) { 4534 // Write state back out to object. 4535 last_character_ = last_character; 4536 buffer_ = buffer; 4537 utf16_chars_read_ += length; 4538 return; 4539 } 4540 } 4541 ASSERT(!skip_capacity_check_); 4542 // Slow loop. Must check capacity on each iteration. 4543 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 4544 ASSERT(remaining_capacity >= 0); 4545 for (; i < length && remaining_capacity > 0; i++) { 4546 uint16_t character = *chars++; 4547 // remaining_capacity is <= 3 bytes at this point, so we do not write out 4548 // an umatched lead surrogate. 4549 if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) { 4550 early_termination_ = true; 4551 break; 4552 } 4553 int written = WriteEndCharacter(character, 4554 last_character, 4555 remaining_capacity, 4556 buffer,