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 <limits> 13 #include <vector> 14 #include "include/v8-debug.h" 15 #include "include/v8-experimental.h" 16 #include "include/v8-profiler.h" 17 #include "include/v8-testing.h" 18 #include "include/v8-util.h" 19 #include "src/accessors.h" 20 #include "src/api-experimental.h" 21 #include "src/api-natives.h" 22 #include "src/assert-scope.h" 23 #include "src/background-parsing-task.h" 24 #include "src/base/functional.h" 25 #include "src/base/platform/platform.h" 26 #include "src/base/platform/time.h" 27 #include "src/base/safe_conversions.h" 28 #include "src/base/utils/random-number-generator.h" 29 #include "src/bootstrapper.h" 30 #include "src/char-predicates-inl.h" 31 #include "src/code-stubs.h" 32 #include "src/compiler-dispatcher/compiler-dispatcher.h" 33 #include "src/compiler.h" 34 #include "src/context-measure.h" 35 #include "src/contexts.h" 36 #include "src/conversions-inl.h" 37 #include "src/counters.h" 38 #include "src/debug/debug-coverage.h" 39 #include "src/debug/debug.h" 40 #include "src/deoptimizer.h" 41 #include "src/execution.h" 42 #include "src/frames-inl.h" 43 #include "src/gdb-jit.h" 44 #include "src/global-handles.h" 45 #include "src/globals.h" 46 #include "src/icu_util.h" 47 #include "src/isolate-inl.h" 48 #include "src/json-parser.h" 49 #include "src/json-stringifier.h" 50 #include "src/messages.h" 51 #include "src/objects-inl.h" 52 #include "src/parsing/parser.h" 53 #include "src/parsing/scanner-character-streams.h" 54 #include "src/pending-compilation-error-handler.h" 55 #include "src/profiler/cpu-profiler.h" 56 #include "src/profiler/heap-profiler.h" 57 #include "src/profiler/heap-snapshot-generator-inl.h" 58 #include "src/profiler/profile-generator-inl.h" 59 #include "src/profiler/tick-sample.h" 60 #include "src/property-descriptor.h" 61 #include "src/property-details.h" 62 #include "src/property.h" 63 #include "src/prototype.h" 64 #include "src/runtime-profiler.h" 65 #include "src/runtime/runtime.h" 66 #include "src/simulator.h" 67 #include "src/snapshot/code-serializer.h" 68 #include "src/snapshot/natives.h" 69 #include "src/snapshot/snapshot.h" 70 #include "src/startup-data-util.h" 71 #include "src/tracing/trace-event.h" 72 #include "src/unicode-inl.h" 73 #include "src/v8.h" 74 #include "src/v8threads.h" 75 #include "src/value-serializer.h" 76 #include "src/version.h" 77 #include "src/vm-state-inl.h" 78 #include "src/wasm/wasm-module.h" 79 #include "src/wasm/wasm-objects.h" 80 #include "src/wasm/wasm-result.h" 81 82 namespace v8 { 83 84 #define LOG_API(isolate, class_name, function_name) \ 85 i::RuntimeCallTimerScope _runtime_timer( \ 86 isolate, &i::RuntimeCallStats::API_##class_name##_##function_name); \ 87 LOG(isolate, ApiEntryCall("v8::" #class_name "::" #function_name)) 88 89 #define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate)) 90 91 #define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, class_name, \ 92 function_name, bailout_value, \ 93 HandleScopeClass, do_callback) \ 94 if (IsExecutionTerminatingCheck(isolate)) { \ 95 return bailout_value; \ 96 } \ 97 HandleScopeClass handle_scope(isolate); \ 98 CallDepthScope<do_callback> call_depth_scope(isolate, context); \ 99 LOG_API(isolate, class_name, function_name); \ 100 ENTER_V8(isolate); \ 101 bool has_pending_exception = false 102 103 #define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \ 104 if (IsExecutionTerminatingCheck(isolate)) { \ 105 return MaybeLocal<T>(); \ 106 } \ 107 InternalEscapableScope handle_scope(isolate); \ 108 CallDepthScope<false> call_depth_scope(isolate, v8::Local<v8::Context>()); \ 109 ENTER_V8(isolate); \ 110 bool has_pending_exception = false 111 112 #define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ 113 bailout_value, HandleScopeClass, \ 114 do_callback) \ 115 auto isolate = context.IsEmpty() \ 116 ? i::Isolate::Current() \ 117 : reinterpret_cast<i::Isolate*>(context->GetIsolate()); \ 118 PREPARE_FOR_EXECUTION_GENERIC(isolate, context, class_name, function_name, \ 119 bailout_value, HandleScopeClass, do_callback); 120 121 #define PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( \ 122 category, name, context, class_name, function_name, bailout_value, \ 123 HandleScopeClass, do_callback) \ 124 auto isolate = context.IsEmpty() \ 125 ? i::Isolate::Current() \ 126 : reinterpret_cast<i::Isolate*>(context->GetIsolate()); \ 127 TRACE_EVENT_CALL_STATS_SCOPED(isolate, category, name); \ 128 PREPARE_FOR_EXECUTION_GENERIC(isolate, context, class_name, function_name, \ 129 bailout_value, HandleScopeClass, do_callback); 130 131 #define PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, class_name, function_name, \ 132 T) \ 133 PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), class_name, \ 134 function_name, MaybeLocal<T>(), \ 135 InternalEscapableScope, false); 136 137 #define PREPARE_FOR_EXECUTION(context, class_name, function_name, T) \ 138 PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ 139 MaybeLocal<T>(), InternalEscapableScope, \ 140 false) 141 142 #define PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, class_name, \ 143 function_name, T) \ 144 PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ 145 MaybeLocal<T>(), InternalEscapableScope, \ 146 true) 147 148 #define PREPARE_FOR_EXECUTION_PRIMITIVE(context, class_name, function_name, T) \ 149 PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ 150 Nothing<T>(), i::HandleScope, false) 151 152 #define PREPARE_FOR_EXECUTION_BOOL(context, class_name, function_name) \ 153 PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ 154 false, i::HandleScope, false) 155 156 #ifdef DEBUG 157 #define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ 158 i::VMState<v8::OTHER> __state__((isolate)); \ 159 i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)); \ 160 i::DisallowExceptions __no_exceptions__((isolate)) 161 162 #define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ 163 i::VMState<v8::OTHER> __state__((isolate)); \ 164 i::DisallowExceptions __no_exceptions__((isolate)) 165 #else 166 #define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ 167 i::VMState<v8::OTHER> __state__((isolate)); 168 169 #define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ 170 i::VMState<v8::OTHER> __state__((isolate)); 171 #endif // DEBUG 172 173 #define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \ 174 do { \ 175 if (has_pending_exception) { \ 176 call_depth_scope.Escape(); \ 177 return value; \ 178 } \ 179 } while (false) 180 181 182 #define RETURN_ON_FAILED_EXECUTION(T) \ 183 EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, MaybeLocal<T>()) 184 185 186 #define RETURN_ON_FAILED_EXECUTION_PRIMITIVE(T) \ 187 EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, Nothing<T>()) 188 189 #define RETURN_ON_FAILED_EXECUTION_BOOL() \ 190 EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, false) 191 192 #define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \ 193 return maybe_local.FromMaybe(Local<T>()); 194 195 196 #define RETURN_ESCAPED(value) return handle_scope.Escape(value); 197 198 199 namespace { 200 201 Local<Context> ContextFromHeapObject(i::Handle<i::Object> obj) { 202 return reinterpret_cast<v8::Isolate*>(i::HeapObject::cast(*obj)->GetIsolate()) 203 ->GetCurrentContext(); 204 } 205 206 class InternalEscapableScope : public v8::EscapableHandleScope { 207 public: 208 explicit inline InternalEscapableScope(i::Isolate* isolate) 209 : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {} 210 }; 211 212 213 #ifdef DEBUG 214 void CheckMicrotasksScopesConsistency(i::Isolate* isolate) { 215 auto handle_scope_implementer = isolate->handle_scope_implementer(); 216 if (handle_scope_implementer->microtasks_policy() == 217 v8::MicrotasksPolicy::kScoped) { 218 DCHECK(handle_scope_implementer->GetMicrotasksScopeDepth() || 219 !handle_scope_implementer->DebugMicrotasksScopeDepthIsZero()); 220 } 221 } 222 #endif 223 224 template <bool do_callback> 225 class CallDepthScope { 226 public: 227 explicit CallDepthScope(i::Isolate* isolate, Local<Context> context) 228 : isolate_(isolate), context_(context), escaped_(false) { 229 // TODO(dcarney): remove this when blink stops crashing. 230 DCHECK(!isolate_->external_caught_exception()); 231 isolate_->handle_scope_implementer()->IncrementCallDepth(); 232 if (!context.IsEmpty()) { 233 i::Handle<i::Context> env = Utils::OpenHandle(*context); 234 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 235 if (isolate->context() != nullptr && 236 isolate->context()->native_context() == env->native_context() && 237 impl->LastEnteredContextWas(env)) { 238 context_ = Local<Context>(); 239 } else { 240 context_->Enter(); 241 } 242 } 243 if (do_callback) isolate_->FireBeforeCallEnteredCallback(); 244 } 245 ~CallDepthScope() { 246 if (!context_.IsEmpty()) context_->Exit(); 247 if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); 248 if (do_callback) isolate_->FireCallCompletedCallback(); 249 #ifdef DEBUG 250 if (do_callback) CheckMicrotasksScopesConsistency(isolate_); 251 #endif 252 } 253 254 void Escape() { 255 DCHECK(!escaped_); 256 escaped_ = true; 257 auto handle_scope_implementer = isolate_->handle_scope_implementer(); 258 handle_scope_implementer->DecrementCallDepth(); 259 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); 260 isolate_->OptionalRescheduleException(call_depth_is_zero); 261 } 262 263 private: 264 i::Isolate* const isolate_; 265 Local<Context> context_; 266 bool escaped_; 267 bool do_callback_; 268 }; 269 270 } // namespace 271 272 273 static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, 274 i::Handle<i::Script> script) { 275 i::Handle<i::Object> scriptName(script->GetNameOrSourceURL(), isolate); 276 i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate); 277 v8::Isolate* v8_isolate = 278 reinterpret_cast<v8::Isolate*>(script->GetIsolate()); 279 ScriptOriginOptions options(script->origin_options()); 280 v8::ScriptOrigin origin( 281 Utils::ToLocal(scriptName), 282 v8::Integer::New(v8_isolate, script->line_offset()), 283 v8::Integer::New(v8_isolate, script->column_offset()), 284 v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()), 285 v8::Integer::New(v8_isolate, script->id()), 286 Utils::ToLocal(source_map_url), 287 v8::Boolean::New(v8_isolate, options.IsOpaque()), 288 v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), 289 v8::Boolean::New(v8_isolate, options.IsModule())); 290 return origin; 291 } 292 293 294 // --- E x c e p t i o n B e h a v i o r --- 295 296 297 void i::FatalProcessOutOfMemory(const char* location) { 298 i::V8::FatalProcessOutOfMemory(location, false); 299 } 300 301 // When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default 302 // OOM error handler is called and execution is stopped. 303 void i::V8::FatalProcessOutOfMemory(const char* location, bool is_heap_oom) { 304 i::Isolate* isolate = i::Isolate::Current(); 305 char last_few_messages[Heap::kTraceRingBufferSize + 1]; 306 char js_stacktrace[Heap::kStacktraceBufferSize + 1]; 307 i::HeapStats heap_stats; 308 309 if (isolate == nullptr) { 310 // On a background thread -> we cannot retrieve memory information from the 311 // Isolate. Write easy-to-recognize values on the stack. 312 memset(last_few_messages, 0x0badc0de, Heap::kTraceRingBufferSize + 1); 313 memset(js_stacktrace, 0x0badc0de, Heap::kStacktraceBufferSize + 1); 314 memset(&heap_stats, 0xbadc0de, sizeof(heap_stats)); 315 // Note that the embedder's oom handler won't be called in this case. We 316 // just crash. 317 FATAL("API fatal error handler returned after process out of memory"); 318 return; 319 } 320 321 memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1); 322 memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1); 323 324 intptr_t start_marker; 325 heap_stats.start_marker = &start_marker; 326 size_t new_space_size; 327 heap_stats.new_space_size = &new_space_size; 328 size_t new_space_capacity; 329 heap_stats.new_space_capacity = &new_space_capacity; 330 size_t old_space_size; 331 heap_stats.old_space_size = &old_space_size; 332 size_t old_space_capacity; 333 heap_stats.old_space_capacity = &old_space_capacity; 334 size_t code_space_size; 335 heap_stats.code_space_size = &code_space_size; 336 size_t code_space_capacity; 337 heap_stats.code_space_capacity = &code_space_capacity; 338 size_t map_space_size; 339 heap_stats.map_space_size = &map_space_size; 340 size_t map_space_capacity; 341 heap_stats.map_space_capacity = &map_space_capacity; 342 size_t lo_space_size; 343 heap_stats.lo_space_size = &lo_space_size; 344 size_t global_handle_count; 345 heap_stats.global_handle_count = &global_handle_count; 346 size_t weak_global_handle_count; 347 heap_stats.weak_global_handle_count = &weak_global_handle_count; 348 size_t pending_global_handle_count; 349 heap_stats.pending_global_handle_count = &pending_global_handle_count; 350 size_t near_death_global_handle_count; 351 heap_stats.near_death_global_handle_count = &near_death_global_handle_count; 352 size_t free_global_handle_count; 353 heap_stats.free_global_handle_count = &free_global_handle_count; 354 size_t memory_allocator_size; 355 heap_stats.memory_allocator_size = &memory_allocator_size; 356 size_t memory_allocator_capacity; 357 heap_stats.memory_allocator_capacity = &memory_allocator_capacity; 358 size_t malloced_memory; 359 heap_stats.malloced_memory = &malloced_memory; 360 size_t malloced_peak_memory; 361 heap_stats.malloced_peak_memory = &malloced_peak_memory; 362 size_t objects_per_type[LAST_TYPE + 1] = {0}; 363 heap_stats.objects_per_type = objects_per_type; 364 size_t size_per_type[LAST_TYPE + 1] = {0}; 365 heap_stats.size_per_type = size_per_type; 366 int os_error; 367 heap_stats.os_error = &os_error; 368 heap_stats.last_few_messages = last_few_messages; 369 heap_stats.js_stacktrace = js_stacktrace; 370 intptr_t end_marker; 371 heap_stats.end_marker = &end_marker; 372 if (isolate->heap()->HasBeenSetUp()) { 373 // BUG(1718): Don't use the take_snapshot since we don't support 374 // HeapIterator here without doing a special GC. 375 isolate->heap()->RecordStats(&heap_stats, false); 376 char* first_newline = strchr(last_few_messages, '\n'); 377 if (first_newline == NULL || first_newline[1] == '\0') 378 first_newline = last_few_messages; 379 PrintF("\n<--- Last few GCs --->\n%s\n", first_newline); 380 PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace); 381 } 382 Utils::ReportOOMFailure(location, is_heap_oom); 383 // If the fatal error handler returns, we stop execution. 384 FATAL("API fatal error handler returned after process out of memory"); 385 } 386 387 388 void Utils::ReportApiFailure(const char* location, const char* message) { 389 i::Isolate* isolate = i::Isolate::Current(); 390 FatalErrorCallback callback = isolate->exception_behavior(); 391 if (callback == nullptr) { 392 base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location, 393 message); 394 base::OS::Abort(); 395 } else { 396 callback(location, message); 397 } 398 isolate->SignalFatalError(); 399 } 400 401 void Utils::ReportOOMFailure(const char* location, bool is_heap_oom) { 402 i::Isolate* isolate = i::Isolate::Current(); 403 OOMErrorCallback oom_callback = isolate->oom_behavior(); 404 if (oom_callback == nullptr) { 405 // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See 406 // crbug.com/614440. 407 FatalErrorCallback fatal_callback = isolate->exception_behavior(); 408 if (fatal_callback == nullptr) { 409 base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n", 410 is_heap_oom ? "javascript" : "process", location); 411 base::OS::Abort(); 412 } else { 413 fatal_callback(location, 414 is_heap_oom 415 ? "Allocation failed - JavaScript heap out of memory" 416 : "Allocation failed - process out of memory"); 417 } 418 } else { 419 oom_callback(location, is_heap_oom); 420 } 421 isolate->SignalFatalError(); 422 } 423 424 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { 425 if (isolate->has_scheduled_exception()) { 426 return isolate->scheduled_exception() == 427 isolate->heap()->termination_exception(); 428 } 429 return false; 430 } 431 432 433 void V8::SetNativesDataBlob(StartupData* natives_blob) { 434 i::V8::SetNativesBlob(natives_blob); 435 } 436 437 438 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { 439 i::V8::SetSnapshotBlob(snapshot_blob); 440 } 441 442 namespace { 443 444 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 445 public: 446 virtual void* Allocate(size_t length) { 447 void* data = AllocateUninitialized(length); 448 return data == NULL ? data : memset(data, 0, length); 449 } 450 virtual void* AllocateUninitialized(size_t length) { return malloc(length); } 451 virtual void Free(void* data, size_t) { free(data); } 452 }; 453 454 bool RunExtraCode(Isolate* isolate, Local<Context> context, 455 const char* utf8_source, const char* name) { 456 base::ElapsedTimer timer; 457 timer.Start(); 458 Context::Scope context_scope(context); 459 TryCatch try_catch(isolate); 460 Local<String> source_string; 461 if (!String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal) 462 .ToLocal(&source_string)) { 463 return false; 464 } 465 Local<String> resource_name = 466 String::NewFromUtf8(isolate, name, NewStringType::kNormal) 467 .ToLocalChecked(); 468 ScriptOrigin origin(resource_name); 469 ScriptCompiler::Source source(source_string, origin); 470 Local<Script> script; 471 if (!ScriptCompiler::Compile(context, &source).ToLocal(&script)) return false; 472 if (script->Run(context).IsEmpty()) return false; 473 if (i::FLAG_profile_deserialization) { 474 i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name, 475 timer.Elapsed().InMillisecondsF()); 476 } 477 timer.Stop(); 478 CHECK(!try_catch.HasCaught()); 479 return true; 480 } 481 482 struct SnapshotCreatorData { 483 explicit SnapshotCreatorData(Isolate* isolate) 484 : isolate_(isolate), 485 default_context_(), 486 contexts_(isolate), 487 templates_(isolate), 488 created_(false) {} 489 490 static SnapshotCreatorData* cast(void* data) { 491 return reinterpret_cast<SnapshotCreatorData*>(data); 492 } 493 494 ArrayBufferAllocator allocator_; 495 Isolate* isolate_; 496 Persistent<Context> default_context_; 497 PersistentValueVector<Context> contexts_; 498 PersistentValueVector<Template> templates_; 499 std::vector<SerializeInternalFieldsCallback> internal_fields_serializers_; 500 bool created_; 501 }; 502 503 } // namespace 504 505 SnapshotCreator::SnapshotCreator(intptr_t* external_references, 506 StartupData* existing_snapshot) { 507 i::Isolate* internal_isolate = new i::Isolate(true); 508 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); 509 SnapshotCreatorData* data = new SnapshotCreatorData(isolate); 510 data->isolate_ = isolate; 511 internal_isolate->set_array_buffer_allocator(&data->allocator_); 512 internal_isolate->set_api_external_references(external_references); 513 isolate->Enter(); 514 if (existing_snapshot) { 515 internal_isolate->set_snapshot_blob(existing_snapshot); 516 i::Snapshot::Initialize(internal_isolate); 517 } else { 518 internal_isolate->Init(nullptr); 519 } 520 data_ = data; 521 } 522 523 SnapshotCreator::~SnapshotCreator() { 524 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); 525 DCHECK(data->created_); 526 Isolate* isolate = data->isolate_; 527 isolate->Exit(); 528 isolate->Dispose(); 529 delete data; 530 } 531 532 Isolate* SnapshotCreator::GetIsolate() { 533 return SnapshotCreatorData::cast(data_)->isolate_; 534 } 535 536 void SnapshotCreator::SetDefaultContext(Local<Context> context) { 537 DCHECK(!context.IsEmpty()); 538 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); 539 DCHECK(!data->created_); 540 DCHECK(data->default_context_.IsEmpty()); 541 Isolate* isolate = data->isolate_; 542 CHECK_EQ(isolate, context->GetIsolate()); 543 data->default_context_.Reset(isolate, context); 544 } 545 546 size_t SnapshotCreator::AddContext(Local<Context> context, 547 SerializeInternalFieldsCallback callback) { 548 DCHECK(!context.IsEmpty()); 549 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); 550 DCHECK(!data->created_); 551 Isolate* isolate = data->isolate_; 552 CHECK_EQ(isolate, context->GetIsolate()); 553 size_t index = static_cast<int>(data->contexts_.Size()); 554 data->contexts_.Append(context); 555 data->internal_fields_serializers_.push_back(callback); 556 return index; 557 } 558 559 size_t SnapshotCreator::AddTemplate(Local<Template> template_obj) { 560 DCHECK(!template_obj.IsEmpty()); 561 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); 562 DCHECK(!data->created_); 563 DCHECK_EQ(reinterpret_cast<i::Isolate*>(data->isolate_), 564 Utils::OpenHandle(*template_obj)->GetIsolate()); 565 size_t index = static_cast<int>(data->templates_.Size()); 566 data->templates_.Append(template_obj); 567 return index; 568 } 569 570 StartupData SnapshotCreator::CreateBlob( 571 SnapshotCreator::FunctionCodeHandling function_code_handling) { 572 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); 573 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); 574 DCHECK(!data->created_); 575 DCHECK(!data->default_context_.IsEmpty()); 576 577 int num_additional_contexts = static_cast<int>(data->contexts_.Size()); 578 579 { 580 int num_templates = static_cast<int>(data->templates_.Size()); 581 i::HandleScope scope(isolate); 582 i::Handle<i::FixedArray> templates = 583 isolate->factory()->NewFixedArray(num_templates, i::TENURED); 584 for (int i = 0; i < num_templates; i++) { 585 templates->set(i, *v8::Utils::OpenHandle(*data->templates_.Get(i))); 586 } 587 isolate->heap()->SetSerializedTemplates(*templates); 588 data->templates_.Clear(); 589 590 // We need to store the global proxy size upfront in case we need the 591 // bootstrapper to create a global proxy before we deserialize the context. 592 i::Handle<i::FixedArray> global_proxy_sizes = 593 isolate->factory()->NewFixedArray(num_additional_contexts, i::TENURED); 594 for (int i = 0; i < num_additional_contexts; i++) { 595 i::Handle<i::Context> context = 596 v8::Utils::OpenHandle(*data->contexts_.Get(i)); 597 global_proxy_sizes->set(i, 598 i::Smi::FromInt(context->global_proxy()->Size())); 599 } 600 isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes); 601 } 602 603 // If we don't do this then we end up with a stray root pointing at the 604 // context even after we have disposed of the context. 605 isolate->heap()->CollectAllAvailableGarbage( 606 i::GarbageCollectionReason::kSnapshotCreator); 607 isolate->heap()->CompactWeakFixedArrays(); 608 609 i::DisallowHeapAllocation no_gc_from_here_on; 610 611 i::List<i::Object*> contexts(num_additional_contexts); 612 i::Object* default_context; 613 { 614 i::HandleScope scope(isolate); 615 default_context = 616 *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)); 617 data->default_context_.Reset(); 618 for (int i = 0; i < num_additional_contexts; i++) { 619 i::Handle<i::Context> context = 620 v8::Utils::OpenHandle(*data->contexts_.Get(i)); 621 contexts.Add(*context); 622 } 623 data->contexts_.Clear(); 624 } 625 626 #ifdef DEBUG 627 i::ExternalReferenceTable::instance(isolate)->ResetCount(); 628 #endif // DEBUG 629 630 i::StartupSerializer startup_serializer(isolate, function_code_handling); 631 startup_serializer.SerializeStrongReferences(); 632 633 // Serialize each context with a new partial serializer. 634 i::List<i::SnapshotData*> context_snapshots(num_additional_contexts + 1); 635 636 { 637 // The default snapshot does not support internal fields. 638 i::PartialSerializer partial_serializer( 639 isolate, &startup_serializer, v8::SerializeInternalFieldsCallback()); 640 partial_serializer.Serialize(&default_context, false); 641 context_snapshots.Add(new i::SnapshotData(&partial_serializer)); 642 } 643 644 for (int i = 0; i < num_additional_contexts; i++) { 645 i::PartialSerializer partial_serializer( 646 isolate, &startup_serializer, data->internal_fields_serializers_[i]); 647 partial_serializer.Serialize(&contexts[i], true); 648 context_snapshots.Add(new i::SnapshotData(&partial_serializer)); 649 } 650 651 startup_serializer.SerializeWeakReferencesAndDeferred(); 652 653 #ifdef DEBUG 654 if (i::FLAG_external_reference_stats) { 655 i::ExternalReferenceTable::instance(isolate)->PrintCount(); 656 } 657 #endif // DEBUG 658 659 i::SnapshotData startup_snapshot(&startup_serializer); 660 StartupData result = 661 i::Snapshot::CreateSnapshotBlob(&startup_snapshot, &context_snapshots); 662 663 // Delete heap-allocated context snapshot instances. 664 for (const auto& context_snapshot : context_snapshots) { 665 delete context_snapshot; 666 } 667 data->created_ = true; 668 return result; 669 } 670 671 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { 672 // Create a new isolate and a new context from scratch, optionally run 673 // a script to embed, and serialize to create a snapshot blob. 674 StartupData result = {nullptr, 0}; 675 base::ElapsedTimer timer; 676 timer.Start(); 677 { 678 SnapshotCreator snapshot_creator; 679 Isolate* isolate = snapshot_creator.GetIsolate(); 680 { 681 HandleScope scope(isolate); 682 Local<Context> context = Context::New(isolate); 683 if (embedded_source != NULL && 684 !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { 685 return result; 686 } 687 snapshot_creator.SetDefaultContext(context); 688 } 689 result = snapshot_creator.CreateBlob( 690 SnapshotCreator::FunctionCodeHandling::kClear); 691 } 692 693 if (i::FLAG_profile_deserialization) { 694 i::PrintF("Creating snapshot took %0.3f ms\n", 695 timer.Elapsed().InMillisecondsF()); 696 } 697 timer.Stop(); 698 return result; 699 } 700 701 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, 702 const char* warmup_source) { 703 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL); 704 CHECK(warmup_source != NULL); 705 // Use following steps to create a warmed up snapshot blob from a cold one: 706 // - Create a new isolate from the cold snapshot. 707 // - Create a new context to run the warmup script. This will trigger 708 // compilation of executed functions. 709 // - Create a new context. This context will be unpolluted. 710 // - Serialize the isolate and the second context into a new snapshot blob. 711 StartupData result = {nullptr, 0}; 712 base::ElapsedTimer timer; 713 timer.Start(); 714 { 715 SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob); 716 Isolate* isolate = snapshot_creator.GetIsolate(); 717 { 718 HandleScope scope(isolate); 719 Local<Context> context = Context::New(isolate); 720 if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) { 721 return result; 722 } 723 } 724 { 725 HandleScope handle_scope(isolate); 726 isolate->ContextDisposedNotification(false); 727 Local<Context> context = Context::New(isolate); 728 snapshot_creator.SetDefaultContext(context); 729 } 730 result = snapshot_creator.CreateBlob( 731 SnapshotCreator::FunctionCodeHandling::kKeep); 732 } 733 734 if (i::FLAG_profile_deserialization) { 735 i::PrintF("Warming up snapshot took %0.3f ms\n", 736 timer.Elapsed().InMillisecondsF()); 737 } 738 timer.Stop(); 739 return result; 740 } 741 742 743 void V8::SetFlagsFromString(const char* str, int length) { 744 i::FlagList::SetFlagsFromString(str, length); 745 i::FlagList::EnforceFlagImplications(); 746 } 747 748 749 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 750 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 751 } 752 753 754 RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 755 756 757 RegisteredExtension::RegisteredExtension(Extension* extension) 758 : extension_(extension) { } 759 760 761 void RegisteredExtension::Register(RegisteredExtension* that) { 762 that->next_ = first_extension_; 763 first_extension_ = that; 764 } 765 766 767 void RegisteredExtension::UnregisterAll() { 768 RegisteredExtension* re = first_extension_; 769 while (re != NULL) { 770 RegisteredExtension* next = re->next(); 771 delete re; 772 re = next; 773 } 774 first_extension_ = NULL; 775 } 776 777 778 void RegisterExtension(Extension* that) { 779 RegisteredExtension* extension = new RegisteredExtension(that); 780 RegisteredExtension::Register(extension); 781 } 782 783 784 Extension::Extension(const char* name, 785 const char* source, 786 int dep_count, 787 const char** deps, 788 int source_length) 789 : name_(name), 790 source_length_(source_length >= 0 ? 791 source_length : 792 (source ? static_cast<int>(strlen(source)) : 0)), 793 source_(source, source_length_), 794 dep_count_(dep_count), 795 deps_(deps), 796 auto_enable_(false) { 797 CHECK(source != NULL || source_length_ == 0); 798 } 799 800 ResourceConstraints::ResourceConstraints() 801 : max_semi_space_size_(0), 802 max_old_space_size_(0), 803 max_executable_size_(0), 804 stack_limit_(NULL), 805 code_range_size_(0), 806 max_zone_pool_size_(0) {} 807 808 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory, 809 uint64_t virtual_memory_limit) { 810 #if V8_OS_ANDROID 811 // Android has higher physical memory requirements before raising the maximum 812 // heap size limits since it has no swap space. 813 const uint64_t low_limit = 512ul * i::MB; 814 const uint64_t medium_limit = 1ul * i::GB; 815 const uint64_t high_limit = 2ul * i::GB; 816 #else 817 const uint64_t low_limit = 512ul * i::MB; 818 const uint64_t medium_limit = 768ul * i::MB; 819 const uint64_t high_limit = 1ul * i::GB; 820 #endif 821 822 if (physical_memory <= low_limit) { 823 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice); 824 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice); 825 set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice); 826 set_max_zone_pool_size(i::AccountingAllocator::kMaxPoolSizeLowMemoryDevice); 827 } else if (physical_memory <= medium_limit) { 828 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice); 829 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice); 830 set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice); 831 set_max_zone_pool_size( 832 i::AccountingAllocator::kMaxPoolSizeMediumMemoryDevice); 833 } else if (physical_memory <= high_limit) { 834 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice); 835 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice); 836 set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice); 837 set_max_zone_pool_size( 838 i::AccountingAllocator::kMaxPoolSizeHighMemoryDevice); 839 } else { 840 set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice); 841 set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice); 842 set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice); 843 set_max_zone_pool_size( 844 i::AccountingAllocator::kMaxPoolSizeHugeMemoryDevice); 845 } 846 847 if (virtual_memory_limit > 0 && i::kRequiresCodeRange) { 848 // Reserve no more than 1/8 of the memory for the code range, but at most 849 // kMaximalCodeRangeSize. 850 set_code_range_size( 851 i::Min(i::kMaximalCodeRangeSize / i::MB, 852 static_cast<size_t>((virtual_memory_limit >> 3) / i::MB))); 853 } 854 } 855 856 857 void SetResourceConstraints(i::Isolate* isolate, 858 const ResourceConstraints& constraints) { 859 int semi_space_size = constraints.max_semi_space_size(); 860 int old_space_size = constraints.max_old_space_size(); 861 int max_executable_size = constraints.max_executable_size(); 862 size_t code_range_size = constraints.code_range_size(); 863 size_t max_pool_size = constraints.max_zone_pool_size(); 864 if (semi_space_size != 0 || old_space_size != 0 || 865 max_executable_size != 0 || code_range_size != 0) { 866 isolate->heap()->ConfigureHeap(semi_space_size, old_space_size, 867 max_executable_size, code_range_size); 868 } 869 isolate->allocator()->ConfigureSegmentPool(max_pool_size); 870 871 if (constraints.stack_limit() != NULL) { 872 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints.stack_limit()); 873 isolate->stack_guard()->SetStackLimit(limit); 874 } 875 } 876 877 878 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) { 879 LOG_API(isolate, Persistent, New); 880 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj); 881 #ifdef VERIFY_HEAP 882 if (i::FLAG_verify_heap) { 883 (*obj)->ObjectVerify(); 884 } 885 #endif // VERIFY_HEAP 886 return result.location(); 887 } 888 889 890 i::Object** V8::CopyPersistent(i::Object** obj) { 891 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj); 892 #ifdef VERIFY_HEAP 893 if (i::FLAG_verify_heap) { 894 (*obj)->ObjectVerify(); 895 } 896 #endif // VERIFY_HEAP 897 return result.location(); 898 } 899 900 void V8::RegisterExternallyReferencedObject(i::Object** object, 901 i::Isolate* isolate) { 902 isolate->heap()->RegisterExternallyReferencedObject(object); 903 } 904 905 void V8::MakeWeak(i::Object** location, void* parameter, 906 int internal_field_index1, int internal_field_index2, 907 WeakCallbackInfo<void>::Callback weak_callback) { 908 WeakCallbackType type = WeakCallbackType::kParameter; 909 if (internal_field_index1 == 0) { 910 if (internal_field_index2 == 1) { 911 type = WeakCallbackType::kInternalFields; 912 } else { 913 DCHECK_EQ(internal_field_index2, -1); 914 type = WeakCallbackType::kInternalFields; 915 } 916 } else { 917 DCHECK_EQ(internal_field_index1, -1); 918 DCHECK_EQ(internal_field_index2, -1); 919 } 920 i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type); 921 } 922 923 void V8::MakeWeak(i::Object** location, void* parameter, 924 WeakCallbackInfo<void>::Callback weak_callback, 925 WeakCallbackType type) { 926 i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type); 927 } 928 929 void V8::MakeWeak(i::Object*** location_addr) { 930 i::GlobalHandles::MakeWeak(location_addr); 931 } 932 933 void* V8::ClearWeak(i::Object** location) { 934 return i::GlobalHandles::ClearWeakness(location); 935 } 936 937 void V8::DisposeGlobal(i::Object** location) { 938 i::GlobalHandles::Destroy(location); 939 } 940 941 942 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) { 943 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 944 i::Object* object = *Utils::OpenHandle(value); 945 isolate->eternal_handles()->Create(isolate, object, index); 946 } 947 948 949 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) { 950 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 951 return Utils::ToLocal(isolate->eternal_handles()->Get(index)); 952 } 953 954 955 void V8::FromJustIsNothing() { 956 Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing."); 957 } 958 959 960 void V8::ToLocalEmpty() { 961 Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal."); 962 } 963 964 965 void V8::InternalFieldOutOfBounds(int index) { 966 Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback, 967 "WeakCallbackInfo::GetInternalField", 968 "Internal field out of bounds."); 969 } 970 971 972 // --- H a n d l e s --- 973 974 975 HandleScope::HandleScope(Isolate* isolate) { 976 Initialize(isolate); 977 } 978 979 980 void HandleScope::Initialize(Isolate* isolate) { 981 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 982 // We do not want to check the correct usage of the Locker class all over the 983 // place, so we do it only here: Without a HandleScope, an embedder can do 984 // almost nothing, so it is enough to check in this central place. 985 // We make an exception if the serializer is enabled, which means that the 986 // Isolate is exclusively used to create a snapshot. 987 Utils::ApiCheck( 988 !v8::Locker::IsActive() || 989 internal_isolate->thread_manager()->IsLockedByCurrentThread() || 990 internal_isolate->serializer_enabled(), 991 "HandleScope::HandleScope", 992 "Entering the V8 API without proper locking in place"); 993 i::HandleScopeData* current = internal_isolate->handle_scope_data(); 994 isolate_ = internal_isolate; 995 prev_next_ = current->next; 996 prev_limit_ = current->limit; 997 current->level++; 998 } 999 1000 1001 HandleScope::~HandleScope() { 1002 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_); 1003 } 1004 1005 V8_NORETURN void* HandleScope::operator new(size_t) { 1006 base::OS::Abort(); 1007 abort(); 1008 } 1009 1010 void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); } 1011 1012 int HandleScope::NumberOfHandles(Isolate* isolate) { 1013 return i::HandleScope::NumberOfHandles( 1014 reinterpret_cast<i::Isolate*>(isolate)); 1015 } 1016 1017 1018 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) { 1019 return i::HandleScope::CreateHandle(isolate, value); 1020 } 1021 1022 1023 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object, 1024 i::Object* value) { 1025 DCHECK(heap_object->IsHeapObject()); 1026 return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value); 1027 } 1028 1029 1030 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) { 1031 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 1032 escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value()); 1033 Initialize(v8_isolate); 1034 } 1035 1036 1037 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) { 1038 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap(); 1039 Utils::ApiCheck((*escape_slot_)->IsTheHole(heap->isolate()), 1040 "EscapableHandleScope::Escape", "Escape value set twice"); 1041 if (escape_value == NULL) { 1042 *escape_slot_ = heap->undefined_value(); 1043 return NULL; 1044 } 1045 *escape_slot_ = *escape_value; 1046 return escape_slot_; 1047 } 1048 1049 V8_NORETURN void* EscapableHandleScope::operator new(size_t) { 1050 base::OS::Abort(); 1051 abort(); 1052 } 1053 1054 void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } 1055 1056 SealHandleScope::SealHandleScope(Isolate* isolate) 1057 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { 1058 i::HandleScopeData* current = isolate_->handle_scope_data(); 1059 prev_limit_ = current->limit; 1060 current->limit = current->next; 1061 prev_sealed_level_ = current->sealed_level; 1062 current->sealed_level = current->level; 1063 } 1064 1065 1066 SealHandleScope::~SealHandleScope() { 1067 i::HandleScopeData* current = isolate_->handle_scope_data(); 1068 DCHECK_EQ(current->next, current->limit); 1069 current->limit = prev_limit_; 1070 DCHECK_EQ(current->level, current->sealed_level); 1071 current->sealed_level = prev_sealed_level_; 1072 } 1073 1074 V8_NORETURN void* SealHandleScope::operator new(size_t) { 1075 base::OS::Abort(); 1076 abort(); 1077 } 1078 1079 void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } 1080 1081 void Context::Enter() { 1082 i::Handle<i::Context> env = Utils::OpenHandle(this); 1083 i::Isolate* isolate = env->GetIsolate(); 1084 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1085 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 1086 impl->EnterContext(env); 1087 impl->SaveContext(isolate->context()); 1088 isolate->set_context(*env); 1089 } 1090 1091 1092 void Context::Exit() { 1093 i::Handle<i::Context> env = Utils::OpenHandle(this); 1094 i::Isolate* isolate = env->GetIsolate(); 1095 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1096 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 1097 if (!Utils::ApiCheck(impl->LastEnteredContextWas(env), 1098 "v8::Context::Exit()", 1099 "Cannot exit non-entered context")) { 1100 return; 1101 } 1102 impl->LeaveContext(); 1103 isolate->set_context(impl->RestoreContext()); 1104 } 1105 1106 1107 static void* DecodeSmiToAligned(i::Object* value, const char* location) { 1108 Utils::ApiCheck(value->IsSmi(), location, "Not a Smi"); 1109 return reinterpret_cast<void*>(value); 1110 } 1111 1112 1113 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) { 1114 i::Smi* smi = reinterpret_cast<i::Smi*>(value); 1115 Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned"); 1116 return smi; 1117 } 1118 1119 1120 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context, 1121 int index, 1122 bool can_grow, 1123 const char* location) { 1124 i::Handle<i::Context> env = Utils::OpenHandle(context); 1125 i::Isolate* isolate = env->GetIsolate(); 1126 bool ok = 1127 Utils::ApiCheck(env->IsNativeContext(), 1128 location, 1129 "Not a native context") && 1130 Utils::ApiCheck(index >= 0, location, "Negative index"); 1131 if (!ok) return i::Handle<i::FixedArray>(); 1132 i::Handle<i::FixedArray> data(env->embedder_data()); 1133 if (index < data->length()) return data; 1134 if (!Utils::ApiCheck(can_grow, location, "Index too large")) { 1135 return i::Handle<i::FixedArray>(); 1136 } 1137 int new_size = i::Max(index, data->length() << 1) + 1; 1138 int grow_by = new_size - data->length(); 1139 data = isolate->factory()->CopyFixedArrayAndGrow(data, grow_by); 1140 env->set_embedder_data(*data); 1141 return data; 1142 } 1143 1144 1145 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) { 1146 const char* location = "v8::Context::GetEmbedderData()"; 1147 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 1148 if (data.is_null()) return Local<Value>(); 1149 i::Handle<i::Object> result(data->get(index), data->GetIsolate()); 1150 return Utils::ToLocal(result); 1151 } 1152 1153 1154 void Context::SetEmbedderData(int index, v8::Local<Value> value) { 1155 const char* location = "v8::Context::SetEmbedderData()"; 1156 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 1157 if (data.is_null()) return; 1158 i::Handle<i::Object> val = Utils::OpenHandle(*value); 1159 data->set(index, *val); 1160 DCHECK_EQ(*Utils::OpenHandle(*value), 1161 *Utils::OpenHandle(*GetEmbedderData(index))); 1162 } 1163 1164 1165 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) { 1166 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()"; 1167 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 1168 if (data.is_null()) return NULL; 1169 return DecodeSmiToAligned(data->get(index), location); 1170 } 1171 1172 1173 void Context::SetAlignedPointerInEmbedderData(int index, void* value) { 1174 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()"; 1175 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 1176 data->set(index, EncodeAlignedAsSmi(value, location)); 1177 DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index)); 1178 } 1179 1180 1181 // --- T e m p l a t e --- 1182 1183 1184 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) { 1185 that->set_number_of_properties(0); 1186 that->set_tag(i::Smi::FromInt(type)); 1187 } 1188 1189 1190 void Template::Set(v8::Local<Name> name, v8::Local<Data> value, 1191 v8::PropertyAttribute attribute) { 1192 auto templ = Utils::OpenHandle(this); 1193 i::Isolate* isolate = templ->GetIsolate(); 1194 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1195 i::HandleScope scope(isolate); 1196 auto value_obj = Utils::OpenHandle(*value); 1197 CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo()); 1198 if (value_obj->IsObjectTemplateInfo()) { 1199 templ->set_serial_number(i::Smi::kZero); 1200 if (templ->IsFunctionTemplateInfo()) { 1201 i::Handle<i::FunctionTemplateInfo>::cast(templ)->set_do_not_cache(true); 1202 } 1203 } 1204 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name), 1205 value_obj, 1206 static_cast<i::PropertyAttributes>(attribute)); 1207 } 1208 1209 void Template::SetPrivate(v8::Local<Private> name, v8::Local<Data> value, 1210 v8::PropertyAttribute attribute) { 1211 Set(Utils::ToLocal(Utils::OpenHandle(reinterpret_cast<Name*>(*name))), value, 1212 attribute); 1213 } 1214 1215 void Template::SetAccessorProperty( 1216 v8::Local<v8::Name> name, 1217 v8::Local<FunctionTemplate> getter, 1218 v8::Local<FunctionTemplate> setter, 1219 v8::PropertyAttribute attribute, 1220 v8::AccessControl access_control) { 1221 // TODO(verwaest): Remove |access_control|. 1222 DCHECK_EQ(v8::DEFAULT, access_control); 1223 auto templ = Utils::OpenHandle(this); 1224 auto isolate = templ->GetIsolate(); 1225 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1226 DCHECK(!name.IsEmpty()); 1227 DCHECK(!getter.IsEmpty() || !setter.IsEmpty()); 1228 i::HandleScope scope(isolate); 1229 i::ApiNatives::AddAccessorProperty( 1230 isolate, templ, Utils::OpenHandle(*name), 1231 Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true), 1232 static_cast<i::PropertyAttributes>(attribute)); 1233 } 1234 1235 1236 // --- F u n c t i o n T e m p l a t e --- 1237 static void InitializeFunctionTemplate( 1238 i::Handle<i::FunctionTemplateInfo> info) { 1239 InitializeTemplate(info, Consts::FUNCTION_TEMPLATE); 1240 info->set_flag(0); 1241 } 1242 1243 static Local<ObjectTemplate> ObjectTemplateNew( 1244 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor, 1245 bool do_not_cache); 1246 1247 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { 1248 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 1249 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1250 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(), 1251 i_isolate); 1252 if (result->IsUndefined(i_isolate)) { 1253 // Do not cache prototype objects. 1254 result = Utils::OpenHandle( 1255 *ObjectTemplateNew(i_isolate, Local<FunctionTemplate>(), true)); 1256 Utils::OpenHandle(this)->set_prototype_template(*result); 1257 } 1258 return ToApiHandle<ObjectTemplate>(result); 1259 } 1260 1261 void FunctionTemplate::SetPrototypeProviderTemplate( 1262 Local<FunctionTemplate> prototype_provider) { 1263 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 1264 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1265 i::Handle<i::Object> result = Utils::OpenHandle(*prototype_provider); 1266 auto info = Utils::OpenHandle(this); 1267 CHECK(info->prototype_template()->IsUndefined(i_isolate)); 1268 CHECK(info->parent_template()->IsUndefined(i_isolate)); 1269 info->set_prototype_provider_template(*result); 1270 } 1271 1272 static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info, 1273 const char* func) { 1274 Utils::ApiCheck(!info->instantiated(), func, 1275 "FunctionTemplate already instantiated"); 1276 } 1277 1278 1279 void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) { 1280 auto info = Utils::OpenHandle(this); 1281 EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit"); 1282 i::Isolate* i_isolate = info->GetIsolate(); 1283 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1284 CHECK(info->prototype_provider_template()->IsUndefined(i_isolate)); 1285 info->set_parent_template(*Utils::OpenHandle(*value)); 1286 } 1287 1288 static Local<FunctionTemplate> FunctionTemplateNew( 1289 i::Isolate* isolate, FunctionCallback callback, 1290 experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data, 1291 v8::Local<Signature> signature, int length, bool do_not_cache, 1292 v8::Local<Private> cached_property_name = v8::Local<Private>()) { 1293 i::Handle<i::Struct> struct_obj = 1294 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE); 1295 i::Handle<i::FunctionTemplateInfo> obj = 1296 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj); 1297 InitializeFunctionTemplate(obj); 1298 obj->set_do_not_cache(do_not_cache); 1299 int next_serial_number = i::FunctionTemplateInfo::kInvalidSerialNumber; 1300 if (!do_not_cache) { 1301 next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); 1302 } 1303 obj->set_serial_number(i::Smi::FromInt(next_serial_number)); 1304 if (callback != 0) { 1305 if (data.IsEmpty()) { 1306 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1307 } 1308 Utils::ToLocal(obj)->SetCallHandler(callback, data, fast_handler); 1309 } 1310 obj->set_length(length); 1311 obj->set_undetectable(false); 1312 obj->set_needs_access_check(false); 1313 obj->set_accept_any_receiver(true); 1314 if (!signature.IsEmpty()) 1315 obj->set_signature(*Utils::OpenHandle(*signature)); 1316 obj->set_cached_property_name( 1317 cached_property_name.IsEmpty() 1318 ? isolate->heap()->the_hole_value() 1319 : *Utils::OpenHandle(*cached_property_name)); 1320 return Utils::ToLocal(obj); 1321 } 1322 1323 Local<FunctionTemplate> FunctionTemplate::New( 1324 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data, 1325 v8::Local<Signature> signature, int length, ConstructorBehavior behavior) { 1326 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1327 // Changes to the environment cannot be captured in the snapshot. Expect no 1328 // function templates when the isolate is created for serialization. 1329 LOG_API(i_isolate, FunctionTemplate, New); 1330 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1331 auto templ = FunctionTemplateNew(i_isolate, callback, nullptr, data, 1332 signature, length, false); 1333 if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); 1334 return templ; 1335 } 1336 1337 MaybeLocal<FunctionTemplate> FunctionTemplate::FromSnapshot(Isolate* isolate, 1338 size_t index) { 1339 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1340 i::FixedArray* templates = i_isolate->heap()->serialized_templates(); 1341 int int_index = static_cast<int>(index); 1342 if (int_index < templates->length()) { 1343 i::Object* info = templates->get(int_index); 1344 if (info->IsFunctionTemplateInfo()) { 1345 return Utils::ToLocal(i::Handle<i::FunctionTemplateInfo>( 1346 i::FunctionTemplateInfo::cast(info))); 1347 } 1348 } 1349 return Local<FunctionTemplate>(); 1350 } 1351 1352 Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler( 1353 Isolate* isolate, FunctionCallback callback, 1354 experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data, 1355 v8::Local<Signature> signature, int length) { 1356 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1357 LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler); 1358 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1359 return FunctionTemplateNew(i_isolate, callback, fast_handler, data, signature, 1360 length, false); 1361 } 1362 1363 Local<FunctionTemplate> FunctionTemplate::NewWithCache( 1364 Isolate* isolate, FunctionCallback callback, Local<Private> cache_property, 1365 Local<Value> data, Local<Signature> signature, int length) { 1366 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1367 LOG_API(i_isolate, FunctionTemplate, NewWithCache); 1368 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 1369 return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature, 1370 length, false, cache_property); 1371 } 1372 1373 Local<Signature> Signature::New(Isolate* isolate, 1374 Local<FunctionTemplate> receiver) { 1375 return Utils::SignatureToLocal(Utils::OpenHandle(*receiver)); 1376 } 1377 1378 1379 Local<AccessorSignature> AccessorSignature::New( 1380 Isolate* isolate, Local<FunctionTemplate> receiver) { 1381 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); 1382 } 1383 1384 1385 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ 1386 i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \ 1387 (obj)->setter(*foreign); \ 1388 } while (false) 1389 1390 1391 void FunctionTemplate::SetCallHandler( 1392 FunctionCallback callback, v8::Local<Value> data, 1393 experimental::FastAccessorBuilder* fast_handler) { 1394 auto info = Utils::OpenHandle(this); 1395 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); 1396 i::Isolate* isolate = info->GetIsolate(); 1397 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1398 i::HandleScope scope(isolate); 1399 i::Handle<i::Struct> struct_obj = 1400 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1401 i::Handle<i::CallHandlerInfo> obj = 1402 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1403 SET_FIELD_WRAPPED(obj, set_callback, callback); 1404 i::MaybeHandle<i::Code> code = 1405 i::experimental::BuildCodeFromFastAccessorBuilder(fast_handler); 1406 if (!code.is_null()) { 1407 obj->set_fast_handler(*code.ToHandleChecked()); 1408 } 1409 if (data.IsEmpty()) { 1410 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1411 } 1412 obj->set_data(*Utils::OpenHandle(*data)); 1413 info->set_call_code(*obj); 1414 } 1415 1416 1417 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties( 1418 i::Handle<i::AccessorInfo> obj, v8::Local<Name> name, 1419 v8::AccessControl settings, v8::PropertyAttribute attributes, 1420 v8::Local<AccessorSignature> signature) { 1421 obj->set_name(*Utils::OpenHandle(*name)); 1422 if (settings & ALL_CAN_READ) obj->set_all_can_read(true); 1423 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); 1424 obj->set_property_attributes(static_cast<i::PropertyAttributes>(attributes)); 1425 if (!signature.IsEmpty()) { 1426 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature)); 1427 } 1428 return obj; 1429 } 1430 1431 namespace { 1432 1433 template <typename Getter, typename Setter> 1434 i::Handle<i::AccessorInfo> MakeAccessorInfo( 1435 v8::Local<Name> name, Getter getter, Setter setter, v8::Local<Value> data, 1436 v8::AccessControl settings, v8::PropertyAttribute attributes, 1437 v8::Local<AccessorSignature> signature, bool is_special_data_property, 1438 bool replace_on_access) { 1439 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate(); 1440 i::Handle<i::AccessorInfo> obj = isolate->factory()->NewAccessorInfo(); 1441 SET_FIELD_WRAPPED(obj, set_getter, getter); 1442 DCHECK_IMPLIES(replace_on_access, 1443 is_special_data_property && setter == nullptr); 1444 if (is_special_data_property && setter == nullptr) { 1445 setter = reinterpret_cast<Setter>(&i::Accessors::ReconfigureToDataProperty); 1446 } 1447 SET_FIELD_WRAPPED(obj, set_setter, setter); 1448 i::Address redirected = obj->redirected_getter(); 1449 if (redirected != nullptr) SET_FIELD_WRAPPED(obj, set_js_getter, redirected); 1450 if (data.IsEmpty()) { 1451 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1452 } 1453 obj->set_data(*Utils::OpenHandle(*data)); 1454 obj->set_is_special_data_property(is_special_data_property); 1455 obj->set_replace_on_access(replace_on_access); 1456 return SetAccessorInfoProperties(obj, name, settings, attributes, signature); 1457 } 1458 1459 } // namespace 1460 1461 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { 1462 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true); 1463 if (!Utils::ApiCheck(!handle.is_null(), 1464 "v8::FunctionTemplate::InstanceTemplate()", 1465 "Reading from empty handle")) { 1466 return Local<ObjectTemplate>(); 1467 } 1468 i::Isolate* isolate = handle->GetIsolate(); 1469 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1470 if (handle->instance_template()->IsUndefined(isolate)) { 1471 Local<ObjectTemplate> templ = 1472 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle)); 1473 handle->set_instance_template(*Utils::OpenHandle(*templ)); 1474 } 1475 i::Handle<i::ObjectTemplateInfo> result( 1476 i::ObjectTemplateInfo::cast(handle->instance_template())); 1477 return Utils::ToLocal(result); 1478 } 1479 1480 1481 void FunctionTemplate::SetLength(int length) { 1482 auto info = Utils::OpenHandle(this); 1483 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength"); 1484 auto isolate = info->GetIsolate(); 1485 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1486 info->set_length(length); 1487 } 1488 1489 1490 void FunctionTemplate::SetClassName(Local<String> name) { 1491 auto info = Utils::OpenHandle(this); 1492 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName"); 1493 auto isolate = info->GetIsolate(); 1494 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1495 info->set_class_name(*Utils::OpenHandle(*name)); 1496 } 1497 1498 1499 void FunctionTemplate::SetAcceptAnyReceiver(bool value) { 1500 auto info = Utils::OpenHandle(this); 1501 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver"); 1502 auto isolate = info->GetIsolate(); 1503 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1504 info->set_accept_any_receiver(value); 1505 } 1506 1507 1508 void FunctionTemplate::SetHiddenPrototype(bool value) { 1509 auto info = Utils::OpenHandle(this); 1510 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetHiddenPrototype"); 1511 auto isolate = info->GetIsolate(); 1512 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1513 info->set_hidden_prototype(value); 1514 } 1515 1516 1517 void FunctionTemplate::ReadOnlyPrototype() { 1518 auto info = Utils::OpenHandle(this); 1519 EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype"); 1520 auto isolate = info->GetIsolate(); 1521 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1522 info->set_read_only_prototype(true); 1523 } 1524 1525 1526 void FunctionTemplate::RemovePrototype() { 1527 auto info = Utils::OpenHandle(this); 1528 EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype"); 1529 auto isolate = info->GetIsolate(); 1530 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1531 info->set_remove_prototype(true); 1532 } 1533 1534 1535 // --- O b j e c t T e m p l a t e --- 1536 1537 1538 Local<ObjectTemplate> ObjectTemplate::New( 1539 Isolate* isolate, v8::Local<FunctionTemplate> constructor) { 1540 return New(reinterpret_cast<i::Isolate*>(isolate), constructor); 1541 } 1542 1543 1544 Local<ObjectTemplate> ObjectTemplate::New() { 1545 return New(i::Isolate::Current(), Local<FunctionTemplate>()); 1546 } 1547 1548 static Local<ObjectTemplate> ObjectTemplateNew( 1549 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor, 1550 bool do_not_cache) { 1551 LOG_API(isolate, ObjectTemplate, New); 1552 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1553 i::Handle<i::Struct> struct_obj = 1554 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE); 1555 i::Handle<i::ObjectTemplateInfo> obj = 1556 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj); 1557 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); 1558 int next_serial_number = 0; 1559 if (!do_not_cache) { 1560 next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); 1561 } 1562 obj->set_serial_number(i::Smi::FromInt(next_serial_number)); 1563 if (!constructor.IsEmpty()) 1564 obj->set_constructor(*Utils::OpenHandle(*constructor)); 1565 obj->set_data(i::Smi::kZero); 1566 return Utils::ToLocal(obj); 1567 } 1568 1569 Local<ObjectTemplate> ObjectTemplate::New( 1570 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) { 1571 return ObjectTemplateNew(isolate, constructor, false); 1572 } 1573 1574 MaybeLocal<ObjectTemplate> ObjectTemplate::FromSnapshot(Isolate* isolate, 1575 size_t index) { 1576 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1577 i::FixedArray* templates = i_isolate->heap()->serialized_templates(); 1578 int int_index = static_cast<int>(index); 1579 if (int_index < templates->length()) { 1580 i::Object* info = templates->get(int_index); 1581 if (info->IsObjectTemplateInfo()) { 1582 return Utils::ToLocal( 1583 i::Handle<i::ObjectTemplateInfo>(i::ObjectTemplateInfo::cast(info))); 1584 } 1585 } 1586 return Local<ObjectTemplate>(); 1587 } 1588 1589 // Ensure that the object template has a constructor. If no 1590 // constructor is available we create one. 1591 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor( 1592 i::Isolate* isolate, 1593 ObjectTemplate* object_template) { 1594 i::Object* obj = Utils::OpenHandle(object_template)->constructor(); 1595 if (!obj->IsUndefined(isolate)) { 1596 i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj); 1597 return i::Handle<i::FunctionTemplateInfo>(info, isolate); 1598 } 1599 Local<FunctionTemplate> templ = 1600 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate)); 1601 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ); 1602 constructor->set_instance_template(*Utils::OpenHandle(object_template)); 1603 Utils::OpenHandle(object_template)->set_constructor(*constructor); 1604 return constructor; 1605 } 1606 1607 template <typename Getter, typename Setter, typename Data, typename Template> 1608 static bool TemplateSetAccessor(Template* template_obj, v8::Local<Name> name, 1609 Getter getter, Setter setter, Data data, 1610 AccessControl settings, 1611 PropertyAttribute attribute, 1612 v8::Local<AccessorSignature> signature, 1613 bool is_special_data_property, 1614 bool replace_on_access) { 1615 auto info = Utils::OpenHandle(template_obj); 1616 auto isolate = info->GetIsolate(); 1617 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1618 i::HandleScope scope(isolate); 1619 auto obj = 1620 MakeAccessorInfo(name, getter, setter, data, settings, attribute, 1621 signature, is_special_data_property, replace_on_access); 1622 if (obj.is_null()) return false; 1623 i::ApiNatives::AddNativeDataProperty(isolate, info, obj); 1624 return true; 1625 } 1626 1627 1628 void Template::SetNativeDataProperty(v8::Local<String> name, 1629 AccessorGetterCallback getter, 1630 AccessorSetterCallback setter, 1631 v8::Local<Value> data, 1632 PropertyAttribute attribute, 1633 v8::Local<AccessorSignature> signature, 1634 AccessControl settings) { 1635 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, 1636 signature, true, false); 1637 } 1638 1639 1640 void Template::SetNativeDataProperty(v8::Local<Name> name, 1641 AccessorNameGetterCallback getter, 1642 AccessorNameSetterCallback setter, 1643 v8::Local<Value> data, 1644 PropertyAttribute attribute, 1645 v8::Local<AccessorSignature> signature, 1646 AccessControl settings) { 1647 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, 1648 signature, true, false); 1649 } 1650 1651 void Template::SetLazyDataProperty(v8::Local<Name> name, 1652 AccessorNameGetterCallback getter, 1653 v8::Local<Value> data, 1654 PropertyAttribute attribute) { 1655 TemplateSetAccessor( 1656 this, name, getter, static_cast<AccessorNameSetterCallback>(nullptr), 1657 data, DEFAULT, attribute, Local<AccessorSignature>(), true, true); 1658 } 1659 1660 void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic, 1661 PropertyAttribute attribute) { 1662 auto templ = Utils::OpenHandle(this); 1663 i::Isolate* isolate = templ->GetIsolate(); 1664 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1665 i::HandleScope scope(isolate); 1666 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name), 1667 intrinsic, 1668 static_cast<i::PropertyAttributes>(attribute)); 1669 } 1670 1671 1672 void ObjectTemplate::SetAccessor(v8::Local<String> name, 1673 AccessorGetterCallback getter, 1674 AccessorSetterCallback setter, 1675 v8::Local<Value> data, AccessControl settings, 1676 PropertyAttribute attribute, 1677 v8::Local<AccessorSignature> signature) { 1678 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, 1679 signature, i::FLAG_disable_old_api_accessors, false); 1680 } 1681 1682 1683 void ObjectTemplate::SetAccessor(v8::Local<Name> name, 1684 AccessorNameGetterCallback getter, 1685 AccessorNameSetterCallback setter, 1686 v8::Local<Value> data, AccessControl settings, 1687 PropertyAttribute attribute, 1688 v8::Local<AccessorSignature> signature) { 1689 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute, 1690 signature, i::FLAG_disable_old_api_accessors, false); 1691 } 1692 1693 template <typename Getter, typename Setter, typename Query, typename Descriptor, 1694 typename Deleter, typename Enumerator, typename Definer> 1695 static i::Handle<i::InterceptorInfo> CreateInterceptorInfo( 1696 i::Isolate* isolate, Getter getter, Setter setter, Query query, 1697 Descriptor descriptor, Deleter remover, Enumerator enumerator, 1698 Definer definer, Local<Value> data, PropertyHandlerFlags flags) { 1699 DCHECK(query == nullptr || 1700 descriptor == nullptr); // Either intercept attributes or descriptor. 1701 DCHECK(query == nullptr || 1702 definer == 1703 nullptr); // Only use descriptor callback with definer callback. 1704 auto obj = i::Handle<i::InterceptorInfo>::cast( 1705 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE)); 1706 obj->set_flags(0); 1707 1708 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1709 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1710 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1711 if (descriptor != 0) SET_FIELD_WRAPPED(obj, set_descriptor, descriptor); 1712 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1713 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1714 if (definer != 0) SET_FIELD_WRAPPED(obj, set_definer, definer); 1715 obj->set_can_intercept_symbols( 1716 !(static_cast<int>(flags) & 1717 static_cast<int>(PropertyHandlerFlags::kOnlyInterceptStrings))); 1718 obj->set_all_can_read(static_cast<int>(flags) & 1719 static_cast<int>(PropertyHandlerFlags::kAllCanRead)); 1720 obj->set_non_masking(static_cast<int>(flags) & 1721 static_cast<int>(PropertyHandlerFlags::kNonMasking)); 1722 1723 if (data.IsEmpty()) { 1724 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1725 } 1726 obj->set_data(*Utils::OpenHandle(*data)); 1727 return obj; 1728 } 1729 1730 template <typename Getter, typename Setter, typename Query, typename Descriptor, 1731 typename Deleter, typename Enumerator, typename Definer> 1732 static void ObjectTemplateSetNamedPropertyHandler( 1733 ObjectTemplate* templ, Getter getter, Setter setter, Query query, 1734 Descriptor descriptor, Deleter remover, Enumerator enumerator, 1735 Definer definer, Local<Value> data, PropertyHandlerFlags flags) { 1736 i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate(); 1737 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1738 i::HandleScope scope(isolate); 1739 auto cons = EnsureConstructor(isolate, templ); 1740 EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler"); 1741 auto obj = CreateInterceptorInfo(isolate, getter, setter, query, descriptor, 1742 remover, enumerator, definer, data, flags); 1743 cons->set_named_property_handler(*obj); 1744 } 1745 1746 void ObjectTemplate::SetNamedPropertyHandler( 1747 NamedPropertyGetterCallback getter, NamedPropertySetterCallback setter, 1748 NamedPropertyQueryCallback query, NamedPropertyDeleterCallback remover, 1749 NamedPropertyEnumeratorCallback enumerator, Local<Value> data) { 1750 ObjectTemplateSetNamedPropertyHandler( 1751 this, getter, setter, query, nullptr, remover, enumerator, nullptr, data, 1752 PropertyHandlerFlags::kOnlyInterceptStrings); 1753 } 1754 1755 void ObjectTemplate::SetHandler( 1756 const NamedPropertyHandlerConfiguration& config) { 1757 ObjectTemplateSetNamedPropertyHandler( 1758 this, config.getter, config.setter, config.query, config.descriptor, 1759 config.deleter, config.enumerator, config.definer, config.data, 1760 config.flags); 1761 } 1762 1763 1764 void ObjectTemplate::MarkAsUndetectable() { 1765 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1766 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1767 i::HandleScope scope(isolate); 1768 auto cons = EnsureConstructor(isolate, this); 1769 EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable"); 1770 cons->set_undetectable(true); 1771 } 1772 1773 1774 void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback, 1775 Local<Value> data) { 1776 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1777 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1778 i::HandleScope scope(isolate); 1779 auto cons = EnsureConstructor(isolate, this); 1780 EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback"); 1781 1782 i::Handle<i::Struct> struct_info = 1783 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE); 1784 i::Handle<i::AccessCheckInfo> info = 1785 i::Handle<i::AccessCheckInfo>::cast(struct_info); 1786 1787 SET_FIELD_WRAPPED(info, set_callback, callback); 1788 info->set_named_interceptor(nullptr); 1789 info->set_indexed_interceptor(nullptr); 1790 1791 if (data.IsEmpty()) { 1792 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1793 } 1794 info->set_data(*Utils::OpenHandle(*data)); 1795 1796 cons->set_access_check_info(*info); 1797 cons->set_needs_access_check(true); 1798 } 1799 1800 void ObjectTemplate::SetAccessCheckCallbackAndHandler( 1801 AccessCheckCallback callback, 1802 const NamedPropertyHandlerConfiguration& named_handler, 1803 const IndexedPropertyHandlerConfiguration& indexed_handler, 1804 Local<Value> data) { 1805 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1806 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1807 i::HandleScope scope(isolate); 1808 auto cons = EnsureConstructor(isolate, this); 1809 EnsureNotInstantiated( 1810 cons, "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler"); 1811 1812 i::Handle<i::Struct> struct_info = 1813 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE); 1814 i::Handle<i::AccessCheckInfo> info = 1815 i::Handle<i::AccessCheckInfo>::cast(struct_info); 1816 1817 SET_FIELD_WRAPPED(info, set_callback, callback); 1818 auto named_interceptor = CreateInterceptorInfo( 1819 isolate, named_handler.getter, named_handler.setter, named_handler.query, 1820 named_handler.descriptor, named_handler.deleter, named_handler.enumerator, 1821 named_handler.definer, named_handler.data, named_handler.flags); 1822 info->set_named_interceptor(*named_interceptor); 1823 auto indexed_interceptor = CreateInterceptorInfo( 1824 isolate, indexed_handler.getter, indexed_handler.setter, 1825 indexed_handler.query, indexed_handler.descriptor, 1826 indexed_handler.deleter, indexed_handler.enumerator, 1827 indexed_handler.definer, indexed_handler.data, indexed_handler.flags); 1828 info->set_indexed_interceptor(*indexed_interceptor); 1829 1830 if (data.IsEmpty()) { 1831 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1832 } 1833 info->set_data(*Utils::OpenHandle(*data)); 1834 1835 cons->set_access_check_info(*info); 1836 cons->set_needs_access_check(true); 1837 } 1838 1839 void ObjectTemplate::SetHandler( 1840 const IndexedPropertyHandlerConfiguration& config) { 1841 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1842 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1843 i::HandleScope scope(isolate); 1844 auto cons = EnsureConstructor(isolate, this); 1845 EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetHandler"); 1846 auto obj = CreateInterceptorInfo(isolate, config.getter, config.setter, 1847 config.query, config.descriptor, 1848 config.deleter, config.enumerator, 1849 config.definer, config.data, config.flags); 1850 cons->set_indexed_property_handler(*obj); 1851 } 1852 1853 1854 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, 1855 Local<Value> data) { 1856 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1857 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1858 i::HandleScope scope(isolate); 1859 auto cons = EnsureConstructor(isolate, this); 1860 EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler"); 1861 i::Handle<i::Struct> struct_obj = 1862 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1863 i::Handle<i::CallHandlerInfo> obj = 1864 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1865 SET_FIELD_WRAPPED(obj, set_callback, callback); 1866 if (data.IsEmpty()) { 1867 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1868 } 1869 obj->set_data(*Utils::OpenHandle(*data)); 1870 cons->set_instance_call_handler(*obj); 1871 } 1872 1873 1874 int ObjectTemplate::InternalFieldCount() { 1875 return Utils::OpenHandle(this)->internal_field_count(); 1876 } 1877 1878 1879 void ObjectTemplate::SetInternalFieldCount(int value) { 1880 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1881 if (!Utils::ApiCheck(i::Smi::IsValid(value), 1882 "v8::ObjectTemplate::SetInternalFieldCount()", 1883 "Invalid internal field count")) { 1884 return; 1885 } 1886 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1887 if (value > 0) { 1888 // The internal field count is set by the constructor function's 1889 // construct code, so we ensure that there is a constructor 1890 // function to do the setting. 1891 EnsureConstructor(isolate, this); 1892 } 1893 Utils::OpenHandle(this)->set_internal_field_count(value); 1894 } 1895 1896 bool ObjectTemplate::IsImmutableProto() { 1897 return Utils::OpenHandle(this)->immutable_proto(); 1898 } 1899 1900 void ObjectTemplate::SetImmutableProto() { 1901 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1902 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 1903 Utils::OpenHandle(this)->set_immutable_proto(true); 1904 } 1905 1906 // --- S c r i p t s --- 1907 1908 1909 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a 1910 // JSFunction. 1911 1912 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_, 1913 BufferPolicy buffer_policy_) 1914 : data(data_), 1915 length(length_), 1916 rejected(false), 1917 buffer_policy(buffer_policy_) {} 1918 1919 1920 ScriptCompiler::CachedData::~CachedData() { 1921 if (buffer_policy == BufferOwned) { 1922 delete[] data; 1923 } 1924 } 1925 1926 1927 bool ScriptCompiler::ExternalSourceStream::SetBookmark() { return false; } 1928 1929 1930 void ScriptCompiler::ExternalSourceStream::ResetToBookmark() { UNREACHABLE(); } 1931 1932 1933 ScriptCompiler::StreamedSource::StreamedSource(ExternalSourceStream* stream, 1934 Encoding encoding) 1935 : impl_(new i::StreamedSource(stream, encoding)) {} 1936 1937 1938 ScriptCompiler::StreamedSource::~StreamedSource() { delete impl_; } 1939 1940 1941 const ScriptCompiler::CachedData* 1942 ScriptCompiler::StreamedSource::GetCachedData() const { 1943 return impl_->cached_data.get(); 1944 } 1945 1946 1947 Local<Script> UnboundScript::BindToCurrentContext() { 1948 i::Handle<i::HeapObject> obj = 1949 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1950 i::Isolate* isolate = obj->GetIsolate(); 1951 i::Handle<i::SharedFunctionInfo> function_info( 1952 i::SharedFunctionInfo::cast(*obj), isolate); 1953 i::Handle<i::JSFunction> function = 1954 isolate->factory()->NewFunctionFromSharedFunctionInfo( 1955 function_info, isolate->native_context()); 1956 return ToApiHandle<Script>(function); 1957 } 1958 1959 1960 int UnboundScript::GetId() { 1961 i::Handle<i::HeapObject> obj = 1962 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1963 i::Isolate* isolate = obj->GetIsolate(); 1964 LOG_API(isolate, UnboundScript, GetId); 1965 i::HandleScope scope(isolate); 1966 i::Handle<i::SharedFunctionInfo> function_info( 1967 i::SharedFunctionInfo::cast(*obj)); 1968 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1969 return script->id(); 1970 } 1971 1972 1973 int UnboundScript::GetLineNumber(int code_pos) { 1974 i::Handle<i::SharedFunctionInfo> obj = 1975 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 1976 i::Isolate* isolate = obj->GetIsolate(); 1977 LOG_API(isolate, UnboundScript, GetLineNumber); 1978 if (obj->script()->IsScript()) { 1979 i::Handle<i::Script> script(i::Script::cast(obj->script())); 1980 return i::Script::GetLineNumber(script, code_pos); 1981 } else { 1982 return -1; 1983 } 1984 } 1985 1986 1987 Local<Value> UnboundScript::GetScriptName() { 1988 i::Handle<i::SharedFunctionInfo> obj = 1989 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 1990 i::Isolate* isolate = obj->GetIsolate(); 1991 LOG_API(isolate, UnboundScript, GetName); 1992 if (obj->script()->IsScript()) { 1993 i::Object* name = i::Script::cast(obj->script())->name(); 1994 return Utils::ToLocal(i::Handle<i::Object>(name, isolate)); 1995 } else { 1996 return Local<String>(); 1997 } 1998 } 1999 2000 2001 Local<Value> UnboundScript::GetSourceURL() { 2002 i::Handle<i::SharedFunctionInfo> obj = 2003 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 2004 i::Isolate* isolate = obj->GetIsolate(); 2005 LOG_API(isolate, UnboundScript, GetSourceURL); 2006 if (obj->script()->IsScript()) { 2007 i::Object* url = i::Script::cast(obj->script())->source_url(); 2008 return Utils::ToLocal(i::Handle<i::Object>(url, isolate)); 2009 } else { 2010 return Local<String>(); 2011 } 2012 } 2013 2014 2015 Local<Value> UnboundScript::GetSourceMappingURL() { 2016 i::Handle<i::SharedFunctionInfo> obj = 2017 i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this)); 2018 i::Isolate* isolate = obj->GetIsolate(); 2019 LOG_API(isolate, UnboundScript, GetSourceMappingURL); 2020 if (obj->script()->IsScript()) { 2021 i::Object* url = i::Script::cast(obj->script())->source_mapping_url(); 2022 return Utils::ToLocal(i::Handle<i::Object>(url, isolate)); 2023 } else { 2024 return Local<String>(); 2025 } 2026 } 2027 2028 2029 MaybeLocal<Value> Script::Run(Local<Context> context) { 2030 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 2031 "v8", "V8.Execute", context, Script, Run, MaybeLocal<Value>(), 2032 InternalEscapableScope, true); 2033 i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true); 2034 i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy()); 2035 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 2036 auto fun = i::Handle<i::JSFunction>::cast(Utils::OpenHandle(this)); 2037 2038 i::Handle<i::Object> receiver = isolate->global_proxy(); 2039 Local<Value> result; 2040 has_pending_exception = !ToLocal<Value>( 2041 i::Execution::Call(isolate, fun, receiver, 0, nullptr), &result); 2042 2043 RETURN_ON_FAILED_EXECUTION(Value); 2044 RETURN_ESCAPED(result); 2045 } 2046 2047 2048 Local<Value> Script::Run() { 2049 auto self = Utils::OpenHandle(this, true); 2050 // If execution is terminating, Compile(..)->Run() requires this 2051 // check. 2052 if (self.is_null()) return Local<Value>(); 2053 auto context = ContextFromHeapObject(self); 2054 RETURN_TO_LOCAL_UNCHECKED(Run(context), Value); 2055 } 2056 2057 2058 Local<UnboundScript> Script::GetUnboundScript() { 2059 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2060 return ToApiHandle<UnboundScript>( 2061 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared())); 2062 } 2063 2064 int Module::GetModuleRequestsLength() const { 2065 i::Handle<i::Module> self = Utils::OpenHandle(this); 2066 return self->info()->module_requests()->length(); 2067 } 2068 2069 Local<String> Module::GetModuleRequest(int i) const { 2070 CHECK_GE(i, 0); 2071 i::Handle<i::Module> self = Utils::OpenHandle(this); 2072 i::Isolate* isolate = self->GetIsolate(); 2073 i::Handle<i::FixedArray> module_requests(self->info()->module_requests(), 2074 isolate); 2075 CHECK_LT(i, module_requests->length()); 2076 return ToApiHandle<String>(i::handle(module_requests->get(i), isolate)); 2077 } 2078 2079 int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); } 2080 2081 bool Module::Instantiate(Local<Context> context, 2082 Module::ResolveCallback callback) { 2083 PREPARE_FOR_EXECUTION_BOOL(context, Module, Instantiate); 2084 has_pending_exception = 2085 !i::Module::Instantiate(Utils::OpenHandle(this), context, callback); 2086 RETURN_ON_FAILED_EXECUTION_BOOL(); 2087 return true; 2088 } 2089 2090 MaybeLocal<Value> Module::Evaluate(Local<Context> context) { 2091 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 2092 "v8", "V8.Execute", context, Module, Evaluate, MaybeLocal<Value>(), 2093 InternalEscapableScope, true); 2094 i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true); 2095 i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy()); 2096 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 2097 2098 i::Handle<i::Module> self = Utils::OpenHandle(this); 2099 // It's an API error to call Evaluate before Instantiate. 2100 CHECK(self->instantiated()); 2101 2102 Local<Value> result; 2103 has_pending_exception = !ToLocal(i::Module::Evaluate(self), &result); 2104 RETURN_ON_FAILED_EXECUTION(Value); 2105 RETURN_ESCAPED(result); 2106 } 2107 2108 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal( 2109 Isolate* v8_isolate, Source* source, CompileOptions options) { 2110 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 2111 PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, ScriptCompiler, CompileUnbound, 2112 UnboundScript); 2113 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.ScriptCompiler"); 2114 2115 // Don't try to produce any kind of cache when the debugger is loaded. 2116 if (isolate->debug()->is_loaded() && 2117 (options == kProduceParserCache || options == kProduceCodeCache)) { 2118 options = kNoCompileOptions; 2119 } 2120 2121 i::ScriptData* script_data = NULL; 2122 if (options == kConsumeParserCache || options == kConsumeCodeCache) { 2123 DCHECK(source->cached_data); 2124 // ScriptData takes care of pointer-aligning the data. 2125 script_data = new i::ScriptData(source->cached_data->data, 2126 source->cached_data->length); 2127 } 2128 2129 i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string)); 2130 i::Handle<i::SharedFunctionInfo> result; 2131 { 2132 i::HistogramTimerScope total(isolate->counters()->compile_script(), true); 2133 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript"); 2134 i::Handle<i::Object> name_obj; 2135 i::Handle<i::Object> source_map_url; 2136 int line_offset = 0; 2137 int column_offset = 0; 2138 if (!source->resource_name.IsEmpty()) { 2139 name_obj = Utils::OpenHandle(*(source->resource_name)); 2140 } 2141 if (!source->resource_line_offset.IsEmpty()) { 2142 line_offset = static_cast<int>(source->resource_line_offset->Value()); 2143 } 2144 if (!source->resource_column_offset.IsEmpty()) { 2145 column_offset = 2146 static_cast<int>(source->resource_column_offset->Value()); 2147 } 2148 if (!source->source_map_url.IsEmpty()) { 2149 source_map_url = Utils::OpenHandle(*(source->source_map_url)); 2150 } 2151 result = i::Compiler::GetSharedFunctionInfoForScript( 2152 str, name_obj, line_offset, column_offset, source->resource_options, 2153 source_map_url, isolate->native_context(), NULL, &script_data, options, 2154 i::NOT_NATIVES_CODE); 2155 has_pending_exception = result.is_null(); 2156 if (has_pending_exception && script_data != NULL) { 2157 // This case won't happen during normal operation; we have compiled 2158 // successfully and produced cached data, and but the second compilation 2159 // of the same source code fails. 2160 delete script_data; 2161 script_data = NULL; 2162 } 2163 RETURN_ON_FAILED_EXECUTION(UnboundScript); 2164 2165 if ((options == kProduceParserCache || options == kProduceCodeCache) && 2166 script_data != NULL) { 2167 // script_data now contains the data that was generated. source will 2168 // take the ownership. 2169 source->cached_data = new CachedData( 2170 script_data->data(), script_data->length(), CachedData::BufferOwned); 2171 script_data->ReleaseDataOwnership(); 2172 } else if (options == kConsumeParserCache || options == kConsumeCodeCache) { 2173 source->cached_data->rejected = script_data->rejected(); 2174 } 2175 delete script_data; 2176 } 2177 RETURN_ESCAPED(ToApiHandle<UnboundScript>(result)); 2178 } 2179 2180 2181 MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundScript( 2182 Isolate* v8_isolate, Source* source, CompileOptions options) { 2183 Utils::ApiCheck( 2184 !source->GetResourceOptions().IsModule(), 2185 "v8::ScriptCompiler::CompileUnboundScript", 2186 "v8::ScriptCompiler::CompileModule must be used to compile modules"); 2187 return CompileUnboundInternal(v8_isolate, source, options); 2188 } 2189 2190 2191 Local<UnboundScript> ScriptCompiler::CompileUnbound(Isolate* v8_isolate, 2192 Source* source, 2193 CompileOptions options) { 2194 Utils::ApiCheck( 2195 !source->GetResourceOptions().IsModule(), 2196 "v8::ScriptCompiler::CompileUnbound", 2197 "v8::ScriptCompiler::CompileModule must be used to compile modules"); 2198 RETURN_TO_LOCAL_UNCHECKED(CompileUnboundInternal(v8_isolate, source, options), 2199 UnboundScript); 2200 } 2201 2202 2203 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context, 2204 Source* source, 2205 CompileOptions options) { 2206 Utils::ApiCheck( 2207 !source->GetResourceOptions().IsModule(), "v8::ScriptCompiler::Compile", 2208 "v8::ScriptCompiler::CompileModule must be used to compile modules"); 2209 auto isolate = context->GetIsolate(); 2210 auto maybe = CompileUnboundInternal(isolate, source, options); 2211 Local<UnboundScript> result; 2212 if (!maybe.ToLocal(&result)) return MaybeLocal<Script>(); 2213 v8::Context::Scope scope(context); 2214 return result->BindToCurrentContext(); 2215 } 2216 2217 2218 Local<Script> ScriptCompiler::Compile( 2219 Isolate* v8_isolate, 2220 Source* source, 2221 CompileOptions options) { 2222 auto context = v8_isolate->GetCurrentContext(); 2223 RETURN_TO_LOCAL_UNCHECKED(Compile(context, source, options), Script); 2224 } 2225 2226 MaybeLocal<Module> ScriptCompiler::CompileModule(Isolate* isolate, 2227 Source* source) { 2228 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2229 2230 Utils::ApiCheck(source->GetResourceOptions().IsModule(), 2231 "v8::ScriptCompiler::CompileModule", 2232 "Invalid ScriptOrigin: is_module must be true"); 2233 auto maybe = CompileUnboundInternal(isolate, source, kNoCompileOptions); 2234 Local<UnboundScript> unbound; 2235 if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>(); 2236 2237 i::Handle<i::SharedFunctionInfo> shared = Utils::OpenHandle(*unbound); 2238 return ToApiHandle<Module>(i_isolate->factory()->NewModule(shared)); 2239 } 2240 2241 2242 class IsIdentifierHelper { 2243 public: 2244 IsIdentifierHelper() : is_identifier_(false), first_char_(true) {} 2245 2246 bool Check(i::String* string) { 2247 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0); 2248 if (cons_string == NULL) return is_identifier_; 2249 // We don't support cons strings here. 2250 return false; 2251 } 2252 void VisitOneByteString(const uint8_t* chars, int length) { 2253 for (int i = 0; i < length; ++i) { 2254 if (first_char_) { 2255 first_char_ = false; 2256 is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]); 2257 } else { 2258 is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]); 2259 } 2260 } 2261 } 2262 void VisitTwoByteString(const uint16_t* chars, int length) { 2263 for (int i = 0; i < length; ++i) { 2264 if (first_char_) { 2265 first_char_ = false; 2266 is_identifier_ = unicode_cache_.IsIdentifierStart(chars[0]); 2267 } else { 2268 is_identifier_ &= unicode_cache_.IsIdentifierPart(chars[i]); 2269 } 2270 } 2271 } 2272 2273 private: 2274 bool is_identifier_; 2275 bool first_char_; 2276 i::UnicodeCache unicode_cache_; 2277 DISALLOW_COPY_AND_ASSIGN(IsIdentifierHelper); 2278 }; 2279 2280 2281 MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext( 2282 Local<Context> v8_context, Source* source, size_t arguments_count, 2283 Local<String> arguments[], size_t context_extension_count, 2284 Local<Object> context_extensions[]) { 2285 PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext, 2286 Function); 2287 TRACE_EVENT0("v8", "V8.ScriptCompiler"); 2288 i::Handle<i::String> source_string; 2289 int parameters_end_pos = i::kNoSourcePosition; 2290 auto factory = isolate->factory(); 2291 if (arguments_count) { 2292 if (i::FLAG_harmony_function_tostring) { 2293 source_string = factory->NewStringFromStaticChars("(function anonymous("); 2294 } else { 2295 source_string = factory->NewStringFromStaticChars("(function("); 2296 } 2297 for (size_t i = 0; i < arguments_count; ++i) { 2298 IsIdentifierHelper helper; 2299 if (!helper.Check(*Utils::OpenHandle(*arguments[i]))) { 2300 return Local<Function>(); 2301 } 2302 has_pending_exception = 2303 !factory->NewConsString(source_string, 2304 Utils::OpenHandle(*arguments[i])) 2305 .ToHandle(&source_string); 2306 RETURN_ON_FAILED_EXECUTION(Function); 2307 if (i + 1 == arguments_count) continue; 2308 has_pending_exception = 2309 !factory->NewConsString(source_string, 2310 factory->LookupSingleCharacterStringFromCode( 2311 ',')).ToHandle(&source_string); 2312 RETURN_ON_FAILED_EXECUTION(Function); 2313 } 2314 i::Handle<i::String> brackets; 2315 if (i::FLAG_harmony_function_tostring) { 2316 brackets = factory->NewStringFromStaticChars("\n) {"); 2317 parameters_end_pos = source_string->length() - 3; 2318 } else { 2319 brackets = factory->NewStringFromStaticChars("){"); 2320 } 2321 has_pending_exception = !factory->NewConsString(source_string, brackets) 2322 .ToHandle(&source_string); 2323 RETURN_ON_FAILED_EXECUTION(Function); 2324 } else { 2325 if (i::FLAG_harmony_function_tostring) { 2326 source_string = 2327 factory->NewStringFromStaticChars("(function anonymous(\n) {"); 2328 parameters_end_pos = source_string->length() - 3; 2329 } else { 2330 source_string = factory->NewStringFromStaticChars("(function(){"); 2331 } 2332 } 2333 2334 int scope_position = source_string->length(); 2335 has_pending_exception = 2336 !factory->NewConsString(source_string, 2337 Utils::OpenHandle(*source->source_string)) 2338 .ToHandle(&source_string); 2339 RETURN_ON_FAILED_EXECUTION(Function); 2340 // Include \n in case the source contains a line end comment. 2341 auto brackets = factory->NewStringFromStaticChars("\n})"); 2342 has_pending_exception = 2343 !factory->NewConsString(source_string, brackets).ToHandle(&source_string); 2344 RETURN_ON_FAILED_EXECUTION(Function); 2345 2346 i::Handle<i::Context> context = Utils::OpenHandle(*v8_context); 2347 i::Handle<i::SharedFunctionInfo> outer_info(context->closure()->shared(), 2348 isolate); 2349 for (size_t i = 0; i < context_extension_count; ++i) { 2350 i::Handle<i::JSReceiver> extension = 2351 Utils::OpenHandle(*context_extensions[i]); 2352 if (!extension->IsJSObject()) return Local<Function>(); 2353 i::Handle<i::JSFunction> closure(context->closure(), isolate); 2354 context = factory->NewWithContext( 2355 closure, context, 2356 i::ScopeInfo::CreateForWithScope( 2357 isolate, context->IsNativeContext() 2358 ? i::Handle<i::ScopeInfo>::null() 2359 : i::Handle<i::ScopeInfo>(context->scope_info())), 2360 extension); 2361 } 2362 2363 i::Handle<i::Object> name_obj; 2364 int eval_scope_position = 0; 2365 int eval_position = i::kNoSourcePosition; 2366 int line_offset = 0; 2367 int column_offset = 0; 2368 if (!source->resource_name.IsEmpty()) { 2369 name_obj = Utils::OpenHandle(*(source->resource_name)); 2370 } 2371 if (!source->resource_line_offset.IsEmpty()) { 2372 line_offset = static_cast<int>(source->resource_line_offset->Value()); 2373 } 2374 if (!source->resource_column_offset.IsEmpty()) { 2375 column_offset = static_cast<int>(source->resource_column_offset->Value()); 2376 } 2377 i::Handle<i::JSFunction> fun; 2378 has_pending_exception = 2379 !i::Compiler::GetFunctionFromEval( 2380 source_string, outer_info, context, i::SLOPPY, 2381 i::ONLY_SINGLE_FUNCTION_LITERAL, parameters_end_pos, 2382 eval_scope_position, eval_position, line_offset, 2383 column_offset - scope_position, name_obj, source->resource_options) 2384 .ToHandle(&fun); 2385 if (has_pending_exception) { 2386 isolate->ReportPendingMessages(); 2387 } 2388 RETURN_ON_FAILED_EXECUTION(Function); 2389 2390 i::Handle<i::Object> result; 2391 has_pending_exception = 2392 !i::Execution::Call(isolate, fun, 2393 Utils::OpenHandle(*v8_context->Global()), 0, 2394 nullptr).ToHandle(&result); 2395 RETURN_ON_FAILED_EXECUTION(Function); 2396 RETURN_ESCAPED( 2397 Utils::CallableToLocal(i::Handle<i::JSFunction>::cast(result))); 2398 } 2399 2400 2401 Local<Function> ScriptCompiler::CompileFunctionInContext( 2402 Isolate* v8_isolate, Source* source, Local<Context> v8_context, 2403 size_t arguments_count, Local<String> arguments[], 2404 size_t context_extension_count, Local<Object> context_extensions[]) { 2405 RETURN_TO_LOCAL_UNCHECKED( 2406 CompileFunctionInContext(v8_context, source, arguments_count, arguments, 2407 context_extension_count, context_extensions), 2408 Function); 2409 } 2410 2411 2412 ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreamingScript( 2413 Isolate* v8_isolate, StreamedSource* source, CompileOptions options) { 2414 if (!i::FLAG_script_streaming) { 2415 return nullptr; 2416 } 2417 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 2418 return new i::BackgroundParsingTask(source->impl(), options, 2419 i::FLAG_stack_size, isolate); 2420 } 2421 2422 2423 MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context, 2424 StreamedSource* v8_source, 2425 Local<String> full_source_string, 2426 const ScriptOrigin& origin) { 2427 PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script); 2428 TRACE_EVENT0("v8", "V8.ScriptCompiler"); 2429 i::StreamedSource* source = v8_source->impl(); 2430 i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string)); 2431 i::Handle<i::Script> script = isolate->factory()->NewScript(str); 2432 if (!origin.ResourceName().IsEmpty()) { 2433 script->set_name(*Utils::OpenHandle(*(origin.ResourceName()))); 2434 } 2435 if (!origin.ResourceLineOffset().IsEmpty()) { 2436 script->set_line_offset( 2437 static_cast<int>(origin.ResourceLineOffset()->Value())); 2438 } 2439 if (!origin.ResourceColumnOffset().IsEmpty()) { 2440 script->set_column_offset( 2441 static_cast<int>(origin.ResourceColumnOffset()->Value())); 2442 } 2443 script->set_origin_options(origin.Options()); 2444 if (!origin.SourceMapUrl().IsEmpty()) { 2445 script->set_source_mapping_url( 2446 *Utils::OpenHandle(*(origin.SourceMapUrl()))); 2447 } 2448 2449 source->info->set_script(script); 2450 if (source->info->literal() == nullptr) { 2451 source->parser->ReportErrors(isolate, script); 2452 } 2453 source->parser->UpdateStatistics(isolate, script); 2454 2455 i::DeferredHandleScope deferred_handle_scope(isolate); 2456 { 2457 // Internalize AST values on the main thread. 2458 source->info->ReopenHandlesInNewHandleScope(); 2459 source->info->ast_value_factory()->Internalize(isolate); 2460 source->parser->HandleSourceURLComments(isolate, script); 2461 } 2462 source->info->set_deferred_handles(deferred_handle_scope.Detach()); 2463 2464 i::Handle<i::SharedFunctionInfo> result; 2465 if (source->info->literal() != nullptr) { 2466 // Parsing has succeeded. 2467 result = i::Compiler::GetSharedFunctionInfoForStreamedScript( 2468 script, source->info.get(), str->length()); 2469 } 2470 has_pending_exception = result.is_null(); 2471 if (has_pending_exception) isolate->ReportPendingMessages(); 2472 2473 source->Release(); 2474 2475 RETURN_ON_FAILED_EXECUTION(Script); 2476 2477 Local<UnboundScript> generic = ToApiHandle<UnboundScript>(result); 2478 if (generic.IsEmpty()) return Local<Script>(); 2479 Local<Script> bound = generic->BindToCurrentContext(); 2480 if (bound.IsEmpty()) return Local<Script>(); 2481 RETURN_ESCAPED(bound); 2482 } 2483 2484 2485 Local<Script> ScriptCompiler::Compile(Isolate* v8_isolate, 2486 StreamedSource* v8_source, 2487 Local<String> full_source_string, 2488 const ScriptOrigin& origin) { 2489 auto context = v8_isolate->GetCurrentContext(); 2490 RETURN_TO_LOCAL_UNCHECKED( 2491 Compile(context, v8_source, full_source_string, origin), Script); 2492 } 2493 2494 2495 uint32_t ScriptCompiler::CachedDataVersionTag() { 2496 return static_cast<uint32_t>(base::hash_combine( 2497 internal::Version::Hash(), internal::FlagList::Hash(), 2498 static_cast<uint32_t>(internal::CpuFeatures::SupportedFeatures()))); 2499 } 2500 2501 2502 MaybeLocal<Script> Script::Compile(Local<Context> context, Local<String> source, 2503 ScriptOrigin* origin) { 2504 if (origin) { 2505 ScriptCompiler::Source script_source(source, *origin); 2506 return ScriptCompiler::Compile(context, &script_source); 2507 } 2508 ScriptCompiler::Source script_source(source); 2509 return ScriptCompiler::Compile(context, &script_source); 2510 } 2511 2512 2513 Local<Script> Script::Compile(v8::Local<String> source, 2514 v8::ScriptOrigin* origin) { 2515 auto str = Utils::OpenHandle(*source); 2516 auto context = ContextFromHeapObject(str); 2517 RETURN_TO_LOCAL_UNCHECKED(Compile(context, source, origin), Script); 2518 } 2519 2520 2521 Local<Script> Script::Compile(v8::Local<String> source, 2522 v8::Local<String> file_name) { 2523 auto str = Utils::OpenHandle(*source); 2524 auto context = ContextFromHeapObject(str); 2525 ScriptOrigin origin(file_name); 2526 return Compile(context, source, &origin).FromMaybe(Local<Script>()); 2527 } 2528 2529 2530 // --- E x c e p t i o n s --- 2531 2532 2533 v8::TryCatch::TryCatch() 2534 : isolate_(i::Isolate::Current()), 2535 next_(isolate_->try_catch_handler()), 2536 is_verbose_(false), 2537 can_continue_(true), 2538 capture_message_(true), 2539 rethrow_(false), 2540 has_terminated_(false) { 2541 ResetInternal(); 2542 // Special handling for simulators which have a separate JS stack. 2543 js_stack_comparable_address_ = 2544 reinterpret_cast<void*>(i::SimulatorStack::RegisterCTryCatch( 2545 isolate_, i::GetCurrentStackPosition())); 2546 isolate_->RegisterTryCatchHandler(this); 2547 } 2548 2549 2550 v8::TryCatch::TryCatch(v8::Isolate* isolate) 2551 : isolate_(reinterpret_cast<i::Isolate*>(isolate)), 2552 next_(isolate_->try_catch_handler()), 2553 is_verbose_(false), 2554 can_continue_(true), 2555 capture_message_(true), 2556 rethrow_(false), 2557 has_terminated_(false) { 2558 ResetInternal(); 2559 // Special handling for simulators which have a separate JS stack. 2560 js_stack_comparable_address_ = 2561 reinterpret_cast<void*>(i::SimulatorStack::RegisterCTryCatch( 2562 isolate_, i::GetCurrentStackPosition())); 2563 isolate_->RegisterTryCatchHandler(this); 2564 } 2565 2566 2567 v8::TryCatch::~TryCatch() { 2568 if (rethrow_) { 2569 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_); 2570 v8::HandleScope scope(isolate); 2571 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception()); 2572 if (HasCaught() && capture_message_) { 2573 // If an exception was caught and rethrow_ is indicated, the saved 2574 // message, script, and location need to be restored to Isolate TLS 2575 // for reuse. capture_message_ needs to be disabled so that Throw() 2576 // does not create a new message. 2577 isolate_->thread_local_top()->rethrowing_message_ = true; 2578 isolate_->RestorePendingMessageFromTryCatch(this); 2579 } 2580 isolate_->UnregisterTryCatchHandler(this); 2581 i::SimulatorStack::UnregisterCTryCatch(isolate_); 2582 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc); 2583 DCHECK(!isolate_->thread_local_top()->rethrowing_message_); 2584 } else { 2585 if (HasCaught() && isolate_->has_scheduled_exception()) { 2586 // If an exception was caught but is still scheduled because no API call 2587 // promoted it, then it is canceled to prevent it from being propagated. 2588 // Note that this will not cancel termination exceptions. 2589 isolate_->CancelScheduledExceptionFromTryCatch(this); 2590 } 2591 isolate_->UnregisterTryCatchHandler(this); 2592 i::SimulatorStack::UnregisterCTryCatch(isolate_); 2593 } 2594 } 2595 2596 V8_NORETURN void* v8::TryCatch::operator new(size_t) { 2597 base::OS::Abort(); 2598 abort(); 2599 } 2600 2601 void v8::TryCatch::operator delete(void*, size_t) { base::OS::Abort(); } 2602 2603 bool v8::TryCatch::HasCaught() const { 2604 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(isolate_); 2605 } 2606 2607 2608 bool v8::TryCatch::CanContinue() const { 2609 return can_continue_; 2610 } 2611 2612 2613 bool v8::TryCatch::HasTerminated() const { 2614 return has_terminated_; 2615 } 2616 2617 2618 v8::Local<v8::Value> v8::TryCatch::ReThrow() { 2619 if (!HasCaught()) return v8::Local<v8::Value>(); 2620 rethrow_ = true; 2621 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_)); 2622 } 2623 2624 2625 v8::Local<Value> v8::TryCatch::Exception() const { 2626 if (HasCaught()) { 2627 // Check for out of memory exception. 2628 i::Object* exception = reinterpret_cast<i::Object*>(exception_); 2629 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_)); 2630 } else { 2631 return v8::Local<Value>(); 2632 } 2633 } 2634 2635 2636 MaybeLocal<Value> v8::TryCatch::StackTrace(Local<Context> context) const { 2637 if (!HasCaught()) return v8::Local<Value>(); 2638 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_); 2639 if (!raw_obj->IsJSObject()) return v8::Local<Value>(); 2640 PREPARE_FOR_EXECUTION(context, TryCatch, StackTrace, Value); 2641 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_); 2642 i::Handle<i::String> name = isolate->factory()->stack_string(); 2643 Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name); 2644 has_pending_exception = !maybe.IsJust(); 2645 RETURN_ON_FAILED_EXECUTION(Value); 2646 if (!maybe.FromJust()) return v8::Local<Value>(); 2647 Local<Value> result; 2648 has_pending_exception = 2649 !ToLocal<Value>(i::JSReceiver::GetProperty(obj, name), &result); 2650 RETURN_ON_FAILED_EXECUTION(Value); 2651 RETURN_ESCAPED(result); 2652 } 2653 2654 2655 v8::Local<Value> v8::TryCatch::StackTrace() const { 2656 auto context = reinterpret_cast<v8::Isolate*>(isolate_)->GetCurrentContext(); 2657 RETURN_TO_LOCAL_UNCHECKED(StackTrace(context), Value); 2658 } 2659 2660 2661 v8::Local<v8::Message> v8::TryCatch::Message() const { 2662 i::Object* message = reinterpret_cast<i::Object*>(message_obj_); 2663 DCHECK(message->IsJSMessageObject() || message->IsTheHole(isolate_)); 2664 if (HasCaught() && !message->IsTheHole(isolate_)) { 2665 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_)); 2666 } else { 2667 return v8::Local<v8::Message>(); 2668 } 2669 } 2670 2671 2672 void v8::TryCatch::Reset() { 2673 if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) { 2674 // If an exception was caught but is still scheduled because no API call 2675 // promoted it, then it is canceled to prevent it from being propagated. 2676 // Note that this will not cancel termination exceptions. 2677 isolate_->CancelScheduledExceptionFromTryCatch(this); 2678 } 2679 ResetInternal(); 2680 } 2681 2682 2683 void v8::TryCatch::ResetInternal() { 2684 i::Object* the_hole = isolate_->heap()->the_hole_value(); 2685 exception_ = the_hole; 2686 message_obj_ = the_hole; 2687 } 2688 2689 2690 void v8::TryCatch::SetVerbose(bool value) { 2691 is_verbose_ = value; 2692 } 2693 2694 2695 void v8::TryCatch::SetCaptureMessage(bool value) { 2696 capture_message_ = value; 2697 } 2698 2699 2700 // --- M e s s a g e --- 2701 2702 2703 Local<String> Message::Get() const { 2704 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2705 ENTER_V8(isolate); 2706 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2707 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2708 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj); 2709 Local<String> result = Utils::ToLocal(raw_result); 2710 return scope.Escape(result); 2711 } 2712 2713 2714 ScriptOrigin Message::GetScriptOrigin() const { 2715 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2716 auto message = i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2717 auto script_wraper = i::Handle<i::Object>(message->script(), isolate); 2718 auto script_value = i::Handle<i::JSValue>::cast(script_wraper); 2719 i::Handle<i::Script> script(i::Script::cast(script_value->value())); 2720 return GetScriptOriginForScript(isolate, script); 2721 } 2722 2723 2724 v8::Local<Value> Message::GetScriptResourceName() const { 2725 return GetScriptOrigin().ResourceName(); 2726 } 2727 2728 2729 v8::Local<v8::StackTrace> Message::GetStackTrace() const { 2730 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2731 ENTER_V8(isolate); 2732 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2733 auto message = i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2734 i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate); 2735 if (!stackFramesObj->IsJSArray()) return v8::Local<v8::StackTrace>(); 2736 auto stackTrace = i::Handle<i::JSArray>::cast(stackFramesObj); 2737 return scope.Escape(Utils::StackTraceToLocal(stackTrace)); 2738 } 2739 2740 2741 Maybe<int> Message::GetLineNumber(Local<Context> context) const { 2742 auto self = Utils::OpenHandle(this); 2743 i::Isolate* isolate = self->GetIsolate(); 2744 ENTER_V8(isolate); 2745 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate)); 2746 auto msg = i::Handle<i::JSMessageObject>::cast(self); 2747 return Just(msg->GetLineNumber()); 2748 } 2749 2750 2751 int Message::GetLineNumber() const { 2752 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 2753 return GetLineNumber(context).FromMaybe(0); 2754 } 2755 2756 2757 int Message::GetStartPosition() const { 2758 auto self = Utils::OpenHandle(this); 2759 return self->start_position(); 2760 } 2761 2762 2763 int Message::GetEndPosition() const { 2764 auto self = Utils::OpenHandle(this); 2765 return self->end_position(); 2766 } 2767 2768 int Message::ErrorLevel() const { 2769 auto self = Utils::OpenHandle(this); 2770 return self->error_level(); 2771 } 2772 2773 Maybe<int> Message::GetStartColumn(Local<Context> context) const { 2774 auto self = Utils::OpenHandle(this); 2775 i::Isolate* isolate = self->GetIsolate(); 2776 ENTER_V8(isolate); 2777 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate)); 2778 auto msg = i::Handle<i::JSMessageObject>::cast(self); 2779 return Just(msg->GetColumnNumber()); 2780 } 2781 2782 2783 int Message::GetStartColumn() const { 2784 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 2785 const int default_value = kNoColumnInfo; 2786 return GetStartColumn(context).FromMaybe(default_value); 2787 } 2788 2789 2790 Maybe<int> Message::GetEndColumn(Local<Context> context) const { 2791 auto self = Utils::OpenHandle(this); 2792 i::Isolate* isolate = self->GetIsolate(); 2793 ENTER_V8(isolate); 2794 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate)); 2795 auto msg = i::Handle<i::JSMessageObject>::cast(self); 2796 const int column_number = msg->GetColumnNumber(); 2797 if (column_number == -1) return Just(-1); 2798 const int start = self->start_position(); 2799 const int end = self->end_position(); 2800 return Just(column_number + (end - start)); 2801 } 2802 2803 2804 int Message::GetEndColumn() const { 2805 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 2806 const int default_value = kNoColumnInfo; 2807 return GetEndColumn(context).FromMaybe(default_value); 2808 } 2809 2810 2811 bool Message::IsSharedCrossOrigin() const { 2812 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2813 ENTER_V8(isolate); 2814 auto self = Utils::OpenHandle(this); 2815 auto script = i::Handle<i::JSValue>::cast( 2816 i::Handle<i::Object>(self->script(), isolate)); 2817 return i::Script::cast(script->value()) 2818 ->origin_options() 2819 .IsSharedCrossOrigin(); 2820 } 2821 2822 bool Message::IsOpaque() const { 2823 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2824 ENTER_V8(isolate); 2825 auto self = Utils::OpenHandle(this); 2826 auto script = i::Handle<i::JSValue>::cast( 2827 i::Handle<i::Object>(self->script(), isolate)); 2828 return i::Script::cast(script->value())->origin_options().IsOpaque(); 2829 } 2830 2831 2832 MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const { 2833 auto self = Utils::OpenHandle(this); 2834 i::Isolate* isolate = self->GetIsolate(); 2835 ENTER_V8(isolate); 2836 EscapableHandleScope handle_scope(reinterpret_cast<Isolate*>(isolate)); 2837 auto msg = i::Handle<i::JSMessageObject>::cast(self); 2838 RETURN_ESCAPED(Utils::ToLocal(msg->GetSourceLine())); 2839 } 2840 2841 2842 Local<String> Message::GetSourceLine() const { 2843 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 2844 RETURN_TO_LOCAL_UNCHECKED(GetSourceLine(context), String) 2845 } 2846 2847 2848 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) { 2849 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2850 ENTER_V8(i_isolate); 2851 i_isolate->PrintCurrentStackTrace(out); 2852 } 2853 2854 2855 // --- S t a c k T r a c e --- 2856 2857 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const { 2858 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2859 ENTER_V8(isolate); 2860 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2861 auto self = Utils::OpenHandle(this); 2862 auto obj = i::JSReceiver::GetElement(isolate, self, index).ToHandleChecked(); 2863 auto jsobj = i::Handle<i::JSObject>::cast(obj); 2864 return scope.Escape(Utils::StackFrameToLocal(jsobj)); 2865 } 2866 2867 2868 int StackTrace::GetFrameCount() const { 2869 return i::Smi::cast(Utils::OpenHandle(this)->length())->value(); 2870 } 2871 2872 2873 Local<Array> StackTrace::AsArray() { 2874 return Utils::ToLocal(Utils::OpenHandle(this)); 2875 } 2876 2877 2878 Local<StackTrace> StackTrace::CurrentStackTrace( 2879 Isolate* isolate, 2880 int frame_limit, 2881 StackTraceOptions options) { 2882 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2883 ENTER_V8(i_isolate); 2884 // TODO(dcarney): remove when ScriptDebugServer is fixed. 2885 options = static_cast<StackTraceOptions>( 2886 static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins); 2887 i::Handle<i::JSArray> stackTrace = 2888 i_isolate->CaptureCurrentStackTrace(frame_limit, options); 2889 return Utils::StackTraceToLocal(stackTrace); 2890 } 2891 2892 2893 // --- S t a c k F r a m e --- 2894 2895 static int getIntProperty(const StackFrame* f, const char* propertyName, 2896 int defaultValue) { 2897 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate(); 2898 ENTER_V8(isolate); 2899 i::HandleScope scope(isolate); 2900 i::Handle<i::JSObject> self = Utils::OpenHandle(f); 2901 i::Handle<i::Object> obj = 2902 i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked(); 2903 return obj->IsSmi() ? i::Smi::cast(*obj)->value() : defaultValue; 2904 } 2905 2906 2907 int StackFrame::GetLineNumber() const { 2908 return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo); 2909 } 2910 2911 2912 int StackFrame::GetColumn() const { 2913 return getIntProperty(this, "column", Message::kNoColumnInfo); 2914 } 2915 2916 2917 int StackFrame::GetScriptId() const { 2918 return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo); 2919 } 2920 2921 2922 static Local<String> getStringProperty(const StackFrame* f, 2923 const char* propertyName) { 2924 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate(); 2925 ENTER_V8(isolate); 2926 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2927 i::Handle<i::JSObject> self = Utils::OpenHandle(f); 2928 i::Handle<i::Object> obj = 2929 i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked(); 2930 return obj->IsString() 2931 ? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj))) 2932 : Local<String>(); 2933 } 2934 2935 2936 Local<String> StackFrame::GetScriptName() const { 2937 return getStringProperty(this, "scriptName"); 2938 } 2939 2940 2941 Local<String> StackFrame::GetScriptNameOrSourceURL() const { 2942 return getStringProperty(this, "scriptNameOrSourceURL"); 2943 } 2944 2945 2946 Local<String> StackFrame::GetFunctionName() const { 2947 return getStringProperty(this, "functionName"); 2948 } 2949 2950 2951 static bool getBoolProperty(const StackFrame* f, const char* propertyName) { 2952 i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate(); 2953 ENTER_V8(isolate); 2954 i::HandleScope scope(isolate); 2955 i::Handle<i::JSObject> self = Utils::OpenHandle(f); 2956 i::Handle<i::Object> obj = 2957 i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked(); 2958 return obj->IsTrue(isolate); 2959 } 2960 2961 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); } 2962 2963 2964 bool StackFrame::IsConstructor() const { 2965 return getBoolProperty(this, "isConstructor"); 2966 } 2967 2968 2969 // --- N a t i v e W e a k M a p --- 2970 2971 Local<NativeWeakMap> NativeWeakMap::New(Isolate* v8_isolate) { 2972 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 2973 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 2974 i::Handle<i::JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap(); 2975 i::JSWeakCollection::Initialize(weakmap, isolate); 2976 return Utils::NativeWeakMapToLocal(weakmap); 2977 } 2978 2979 2980 void NativeWeakMap::Set(Local<Value> v8_key, Local<Value> v8_value) { 2981 i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); 2982 i::Isolate* isolate = weak_collection->GetIsolate(); 2983 ENTER_V8(isolate); 2984 i::HandleScope scope(isolate); 2985 i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); 2986 i::Handle<i::Object> value = Utils::OpenHandle(*v8_value); 2987 if (!key->IsJSReceiver() && !key->IsSymbol()) { 2988 DCHECK(false); 2989 return; 2990 } 2991 i::Handle<i::ObjectHashTable> table( 2992 i::ObjectHashTable::cast(weak_collection->table())); 2993 if (!table->IsKey(isolate, *key)) { 2994 DCHECK(false); 2995 return; 2996 } 2997 int32_t hash = i::Object::GetOrCreateHash(isolate, key)->value(); 2998 i::JSWeakCollection::Set(weak_collection, key, value, hash); 2999 } 3000 3001 3002 Local<Value> NativeWeakMap::Get(Local<Value> v8_key) { 3003 i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); 3004 i::Isolate* isolate = weak_collection->GetIsolate(); 3005 ENTER_V8(isolate); 3006 i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); 3007 if (!key->IsJSReceiver() && !key->IsSymbol()) { 3008 DCHECK(false); 3009 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 3010 } 3011 i::Handle<i::ObjectHashTable> table( 3012 i::ObjectHashTable::cast(weak_collection->table())); 3013 if (!table->IsKey(isolate, *key)) { 3014 DCHECK(false); 3015 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 3016 } 3017 i::Handle<i::Object> lookup(table->Lookup(key), isolate); 3018 if (lookup->IsTheHole(isolate)) 3019 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 3020 return Utils::ToLocal(lookup); 3021 } 3022 3023 3024 bool NativeWeakMap::Has(Local<Value> v8_key) { 3025 i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); 3026 i::Isolate* isolate = weak_collection->GetIsolate(); 3027 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 3028 i::HandleScope scope(isolate); 3029 i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); 3030 if (!key->IsJSReceiver() && !key->IsSymbol()) { 3031 DCHECK(false); 3032 return false; 3033 } 3034 i::Handle<i::ObjectHashTable> table( 3035 i::ObjectHashTable::cast(weak_collection->table())); 3036 if (!table->IsKey(isolate, *key)) { 3037 DCHECK(false); 3038 return false; 3039 } 3040 i::Handle<i::Object> lookup(table->Lookup(key), isolate); 3041 return !lookup->IsTheHole(isolate); 3042 } 3043 3044 3045 bool NativeWeakMap::Delete(Local<Value> v8_key) { 3046 i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); 3047 i::Isolate* isolate = weak_collection->GetIsolate(); 3048 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 3049 i::HandleScope scope(isolate); 3050 i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); 3051 if (!key->IsJSReceiver() && !key->IsSymbol()) { 3052 DCHECK(false); 3053 return false; 3054 } 3055 i::Handle<i::ObjectHashTable> table( 3056 i::ObjectHashTable::cast(weak_collection->table())); 3057 if (!table->IsKey(isolate, *key)) { 3058 DCHECK(false); 3059 return false; 3060 } 3061 int32_t hash = i::Object::GetOrCreateHash(isolate, key)->value(); 3062 return i::JSWeakCollection::Delete(weak_collection, key, hash); 3063 } 3064 3065 3066 // --- J S O N --- 3067 3068 MaybeLocal<Value> JSON::Parse(Isolate* v8_isolate, Local<String> json_string) { 3069 auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 3070 PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, JSON, Parse, Value); 3071 i::Handle<i::String> string = Utils::OpenHandle(*json_string); 3072 i::Handle<i::String> source = i::String::Flatten(string); 3073 i::Handle<i::Object> undefined = isolate->factory()->undefined_value(); 3074 auto maybe = source->IsSeqOneByteString() 3075 ? i::JsonParser<true>::Parse(isolate, source, undefined) 3076 : i::JsonParser<false>::Parse(isolate, source, undefined); 3077 Local<Value> result; 3078 has_pending_exception = !ToLocal<Value>(maybe, &result); 3079 RETURN_ON_FAILED_EXECUTION(Value); 3080 RETURN_ESCAPED(result); 3081 } 3082 3083 MaybeLocal<Value> JSON::Parse(Local<Context> context, 3084 Local<String> json_string) { 3085 PREPARE_FOR_EXECUTION(context, JSON, Parse, Value); 3086 i::Handle<i::String> string = Utils::OpenHandle(*json_string); 3087 i::Handle<i::String> source = i::String::Flatten(string); 3088 i::Handle<i::Object> undefined = isolate->factory()->undefined_value(); 3089 auto maybe = source->IsSeqOneByteString() 3090 ? i::JsonParser<true>::Parse(isolate, source, undefined) 3091 : i::JsonParser<false>::Parse(isolate, source, undefined); 3092 Local<Value> result; 3093 has_pending_exception = !ToLocal<Value>(maybe, &result); 3094 RETURN_ON_FAILED_EXECUTION(Value); 3095 RETURN_ESCAPED(result); 3096 } 3097 3098 Local<Value> JSON::Parse(Local<String> json_string) { 3099 RETURN_TO_LOCAL_UNCHECKED(Parse(Local<Context>(), json_string), Value); 3100 } 3101 3102 MaybeLocal<String> JSON::Stringify(Local<Context> context, 3103 Local<Object> json_object, 3104 Local<String> gap) { 3105 PREPARE_FOR_EXECUTION(context, JSON, Stringify, String); 3106 i::Handle<i::Object> object = Utils::OpenHandle(*json_object); 3107 i::Handle<i::Object> replacer = isolate->factory()->undefined_value(); 3108 i::Handle<i::String> gap_string = gap.IsEmpty() 3109 ? isolate->factory()->empty_string() 3110 : Utils::OpenHandle(*gap); 3111 i::Handle<i::Object> maybe; 3112 has_pending_exception = !i::JsonStringifier(isolate) 3113 .Stringify(object, replacer, gap_string) 3114 .ToHandle(&maybe); 3115 RETURN_ON_FAILED_EXECUTION(String); 3116 Local<String> result; 3117 has_pending_exception = 3118 !ToLocal<String>(i::Object::ToString(isolate, maybe), &result); 3119 RETURN_ON_FAILED_EXECUTION(String); 3120 RETURN_ESCAPED(result); 3121 } 3122 3123 // --- V a l u e S e r i a l i z a t i o n --- 3124 3125 Maybe<bool> ValueSerializer::Delegate::WriteHostObject(Isolate* v8_isolate, 3126 Local<Object> object) { 3127 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 3128 isolate->ScheduleThrow(*isolate->factory()->NewError( 3129 isolate->error_function(), i::MessageTemplate::kDataCloneError, 3130 Utils::OpenHandle(*object))); 3131 return Nothing<bool>(); 3132 } 3133 3134 Maybe<uint32_t> ValueSerializer::Delegate::GetSharedArrayBufferId( 3135 Isolate* v8_isolate, Local<SharedArrayBuffer> shared_array_buffer) { 3136 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 3137 isolate->ScheduleThrow(*isolate->factory()->NewError( 3138 isolate->error_function(), i::MessageTemplate::kDataCloneError, 3139 Utils::OpenHandle(*shared_array_buffer))); 3140 return Nothing<uint32_t>(); 3141 } 3142 3143 void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer, 3144 size_t size, 3145 size_t* actual_size) { 3146 *actual_size = size; 3147 return realloc(old_buffer, size); 3148 } 3149 3150 void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) { 3151 return free(buffer); 3152 } 3153 3154 struct ValueSerializer::PrivateData { 3155 explicit PrivateData(i::Isolate* i, ValueSerializer::Delegate* delegate) 3156 : isolate(i), serializer(i, delegate) {} 3157 i::Isolate* isolate; 3158 i::ValueSerializer serializer; 3159 }; 3160 3161 ValueSerializer::ValueSerializer(Isolate* isolate) 3162 : ValueSerializer(isolate, nullptr) {} 3163 3164 ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate) 3165 : private_( 3166 new PrivateData(reinterpret_cast<i::Isolate*>(isolate), delegate)) {} 3167 3168 ValueSerializer::~ValueSerializer() { delete private_; } 3169 3170 void ValueSerializer::WriteHeader() { private_->serializer.WriteHeader(); } 3171 3172 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { 3173 private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode); 3174 } 3175 3176 Maybe<bool> ValueSerializer::WriteValue(Local<Context> context, 3177 Local<Value> value) { 3178 PREPARE_FOR_EXECUTION_PRIMITIVE(context, ValueSerializer, WriteValue, bool); 3179 i::Handle<i::Object> object = Utils::OpenHandle(*value); 3180 Maybe<bool> result = private_->serializer.WriteObject(object); 3181 has_pending_exception = result.IsNothing(); 3182 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 3183 return result; 3184 } 3185 3186 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() { 3187 return private_->serializer.ReleaseBuffer(); 3188 } 3189 3190 std::pair<uint8_t*, size_t> ValueSerializer::Release() { 3191 return private_->serializer.Release(); 3192 } 3193 3194 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, 3195 Local<ArrayBuffer> array_buffer) { 3196 private_->serializer.TransferArrayBuffer(transfer_id, 3197 Utils::OpenHandle(*array_buffer)); 3198 } 3199 3200 void ValueSerializer::TransferSharedArrayBuffer( 3201 uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) { 3202 private_->serializer.TransferArrayBuffer( 3203 transfer_id, Utils::OpenHandle(*shared_array_buffer)); 3204 } 3205 3206 void ValueSerializer::WriteUint32(uint32_t value) { 3207 private_->serializer.WriteUint32(value); 3208 } 3209 3210 void ValueSerializer::WriteUint64(uint64_t value) { 3211 private_->serializer.WriteUint64(value); 3212 } 3213 3214 void ValueSerializer::WriteDouble(double value) { 3215 private_->serializer.WriteDouble(value); 3216 } 3217 3218 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { 3219 private_->serializer.WriteRawBytes(source, length); 3220 } 3221 3222 MaybeLocal<Object> ValueDeserializer::Delegate::ReadHostObject( 3223 Isolate* v8_isolate) { 3224 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 3225 isolate->ScheduleThrow(*isolate->factory()->NewError( 3226 isolate->error_function(), 3227 i::MessageTemplate::kDataCloneDeserializationError)); 3228 return MaybeLocal<Object>(); 3229 } 3230 3231 struct ValueDeserializer::PrivateData { 3232 PrivateData(i::Isolate* i, i::Vector<const uint8_t> data, Delegate* delegate) 3233 : isolate(i), deserializer(i, data, delegate) {} 3234 i::Isolate* isolate; 3235 i::ValueDeserializer deserializer; 3236 bool has_aborted = false; 3237 bool supports_legacy_wire_format = false; 3238 }; 3239 3240 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data, 3241 size_t size) 3242 : ValueDeserializer(isolate, data, size, nullptr) {} 3243 3244 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data, 3245 size_t size, Delegate* delegate) { 3246 if (base::IsValueInRangeForNumericType<int>(size)) { 3247 private_ = new PrivateData( 3248 reinterpret_cast<i::Isolate*>(isolate), 3249 i::Vector<const uint8_t>(data, static_cast<int>(size)), delegate); 3250 } else { 3251 private_ = new PrivateData(reinterpret_cast<i::Isolate*>(isolate), 3252 i::Vector<const uint8_t>(nullptr, 0), nullptr); 3253 private_->has_aborted = true; 3254 } 3255 } 3256 3257 ValueDeserializer::~ValueDeserializer() { delete private_; } 3258 3259 Maybe<bool> ValueDeserializer::ReadHeader(Local<Context> context) { 3260 PREPARE_FOR_EXECUTION_PRIMITIVE(context, ValueDeserializer, ReadHeader, bool); 3261 3262 // We could have aborted during the constructor. 3263 // If so, ReadHeader is where we report it. 3264 if (private_->has_aborted) { 3265 isolate->Throw(*isolate->factory()->NewError( 3266 i::MessageTemplate::kDataCloneDeserializationError)); 3267 has_pending_exception = true; 3268 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 3269 } 3270 3271 bool read_header = false; 3272 has_pending_exception = !private_->deserializer.ReadHeader().To(&read_header); 3273 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 3274 DCHECK(read_header); 3275 3276 // TODO(jbroman): Today, all wire formats are "legacy". When a more supported 3277 // format is added, compare the version of the internal serializer to the 3278 // minimum non-legacy version number. 3279 if (!private_->supports_legacy_wire_format) { 3280 isolate->Throw(*isolate->factory()->NewError( 3281 i::MessageTemplate::kDataCloneDeserializationVersionError)); 3282 has_pending_exception = true; 3283 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 3284 } 3285 3286 return Just(true); 3287 } 3288 3289 void ValueDeserializer::SetSupportsLegacyWireFormat( 3290 bool supports_legacy_wire_format) { 3291 private_->supports_legacy_wire_format = supports_legacy_wire_format; 3292 } 3293 3294 uint32_t ValueDeserializer::GetWireFormatVersion() const { 3295 CHECK(!private_->has_aborted); 3296 return private_->deserializer.GetWireFormatVersion(); 3297 } 3298 3299 MaybeLocal<Value> ValueDeserializer::ReadValue(Local<Context> context) { 3300 CHECK(!private_->has_aborted); 3301 PREPARE_FOR_EXECUTION(context, ValueDeserializer, ReadValue, Value); 3302 i::MaybeHandle<i::Object> result; 3303 if (GetWireFormatVersion() > 0) { 3304 result = private_->deserializer.ReadObject(); 3305 } else { 3306 result = 3307 private_->deserializer.ReadObjectUsingEntireBufferForLegacyFormat(); 3308 } 3309 Local<Value> value; 3310 has_pending_exception = !ToLocal(result, &value); 3311 RETURN_ON_FAILED_EXECUTION(Value); 3312 RETURN_ESCAPED(value); 3313 } 3314 3315 void ValueDeserializer::TransferArrayBuffer(uint32_t transfer_id, 3316 Local<ArrayBuffer> array_buffer) { 3317 CHECK(!private_->has_aborted); 3318 private_->deserializer.TransferArrayBuffer(transfer_id, 3319 Utils::OpenHandle(*array_buffer)); 3320 } 3321 3322 void ValueDeserializer::TransferSharedArrayBuffer( 3323 uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) { 3324 CHECK(!private_->has_aborted); 3325 private_->deserializer.TransferArrayBuffer( 3326 transfer_id, Utils::OpenHandle(*shared_array_buffer)); 3327 } 3328 3329 bool ValueDeserializer::ReadUint32(uint32_t* value) { 3330 return private_->deserializer.ReadUint32(value); 3331 } 3332 3333 bool ValueDeserializer::ReadUint64(uint64_t* value) { 3334 return private_->deserializer.ReadUint64(value); 3335 } 3336 3337 bool ValueDeserializer::ReadDouble(double* value) { 3338 return private_->deserializer.ReadDouble(value); 3339 } 3340 3341 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) { 3342 return private_->deserializer.ReadRawBytes(length, data); 3343 } 3344 3345 // --- D a t a --- 3346 3347 bool Value::FullIsUndefined() const { 3348 i::Handle<i::Object> object = Utils::OpenHandle(this); 3349 bool result = false; 3350 if (!object->IsSmi()) { 3351 result = object->IsUndefined(i::HeapObject::cast(*object)->GetIsolate()); 3352 } 3353 DCHECK_EQ(result, QuickIsUndefined()); 3354 return result; 3355 } 3356 3357 3358 bool Value::FullIsNull() const { 3359 i::Handle<i::Object> object = Utils::OpenHandle(this); 3360 bool result = false; 3361 if (!object->IsSmi()) { 3362 result = object->IsNull(i::HeapObject::cast(*object)->GetIsolate()); 3363 } 3364 DCHECK_EQ(result, QuickIsNull()); 3365 return result; 3366 } 3367 3368 3369 bool Value::IsTrue() const { 3370 i::Handle<i::Object> object = Utils::OpenHandle(this); 3371 if (object->IsSmi()) return false; 3372 return object->IsTrue(i::HeapObject::cast(*object)->GetIsolate()); 3373 } 3374 3375 3376 bool Value::IsFalse() const { 3377 i::Handle<i::Object> object = Utils::OpenHandle(this); 3378 if (object->IsSmi()) return false; 3379 return object->IsFalse(i::HeapObject::cast(*object)->GetIsolate()); 3380 } 3381 3382 3383 bool Value::IsFunction() const { return Utils::OpenHandle(this)->IsCallable(); } 3384 3385 3386 bool Value::IsName() const { 3387 return Utils::OpenHandle(this)->IsName(); 3388 } 3389 3390 3391 bool Value::FullIsString() const { 3392 bool result = Utils::OpenHandle(this)->IsString(); 3393 DCHECK_EQ(result, QuickIsString()); 3394 return result; 3395 } 3396 3397 3398 bool Value::IsSymbol() const { 3399 return Utils::OpenHandle(this)->IsSymbol(); 3400 } 3401 3402 3403 bool Value::IsArray() const { 3404 return Utils::OpenHandle(this)->IsJSArray(); 3405 } 3406 3407 3408 bool Value::IsArrayBuffer() const { 3409 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3410 return obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj)->is_shared(); 3411 } 3412 3413 3414 bool Value::IsArrayBufferView() const { 3415 return Utils::OpenHandle(this)->IsJSArrayBufferView(); 3416 } 3417 3418 3419 bool Value::IsTypedArray() const { 3420 return Utils::OpenHandle(this)->IsJSTypedArray(); 3421 } 3422 3423 3424 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 3425 bool Value::Is##Type##Array() const { \ 3426 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ 3427 return obj->IsJSTypedArray() && \ 3428 i::JSTypedArray::cast(*obj)->type() == i::kExternal##Type##Array; \ 3429 } 3430 3431 3432 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY) 3433 3434 #undef VALUE_IS_TYPED_ARRAY 3435 3436 3437 bool Value::IsDataView() const { 3438 return Utils::OpenHandle(this)->IsJSDataView(); 3439 } 3440 3441 3442 bool Value::IsSharedArrayBuffer() const { 3443 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3444 return obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj)->is_shared(); 3445 } 3446 3447 3448 bool Value::IsObject() const { return Utils::OpenHandle(this)->IsJSReceiver(); } 3449 3450 3451 bool Value::IsNumber() const { 3452 return Utils::OpenHandle(this)->IsNumber(); 3453 } 3454 3455 3456 bool Value::IsProxy() const { return Utils::OpenHandle(this)->IsJSProxy(); } 3457 3458 bool Value::IsWebAssemblyCompiledModule() const { 3459 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3460 if (!obj->IsJSObject()) return false; 3461 i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj); 3462 return js_obj->GetIsolate()->native_context()->wasm_module_constructor() == 3463 js_obj->map()->GetConstructor(); 3464 } 3465 3466 #define VALUE_IS_SPECIFIC_TYPE(Type, Class) \ 3467 bool Value::Is##Type() const { \ 3468 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ 3469 if (!obj->IsHeapObject()) return false; \ 3470 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); \ 3471 return obj->HasSpecificClassOf(isolate->heap()->Class##_string()); \ 3472 } 3473 3474 VALUE_IS_SPECIFIC_TYPE(ArgumentsObject, Arguments) 3475 VALUE_IS_SPECIFIC_TYPE(BooleanObject, Boolean) 3476 VALUE_IS_SPECIFIC_TYPE(NumberObject, Number) 3477 VALUE_IS_SPECIFIC_TYPE(StringObject, String) 3478 VALUE_IS_SPECIFIC_TYPE(SymbolObject, Symbol) 3479 VALUE_IS_SPECIFIC_TYPE(Date, Date) 3480 VALUE_IS_SPECIFIC_TYPE(Map, Map) 3481 VALUE_IS_SPECIFIC_TYPE(Set, Set) 3482 VALUE_IS_SPECIFIC_TYPE(WeakMap, WeakMap) 3483 VALUE_IS_SPECIFIC_TYPE(WeakSet, WeakSet) 3484 3485 #undef VALUE_IS_SPECIFIC_TYPE 3486 3487 3488 bool Value::IsBoolean() const { 3489 return Utils::OpenHandle(this)->IsBoolean(); 3490 } 3491 3492 3493 bool Value::IsExternal() const { 3494 return Utils::OpenHandle(this)->IsExternal(); 3495 } 3496 3497 3498 bool Value::IsInt32() const { 3499 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3500 if (obj->IsSmi()) return true; 3501 if (obj->IsNumber()) { 3502 return i::IsInt32Double(obj->Number()); 3503 } 3504 return false; 3505 } 3506 3507 3508 bool Value::IsUint32() const { 3509 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3510 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0; 3511 if (obj->IsNumber()) { 3512 double value = obj->Number(); 3513 return !i::IsMinusZero(value) && 3514 value >= 0 && 3515 value <= i::kMaxUInt32 && 3516 value == i::FastUI2D(i::FastD2UI(value)); 3517 } 3518 return false; 3519 } 3520 3521 3522 bool Value::IsNativeError() const { 3523 return Utils::OpenHandle(this)->IsJSError(); 3524 } 3525 3526 3527 bool Value::IsRegExp() const { 3528 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3529 return obj->IsJSRegExp(); 3530 } 3531 3532 bool Value::IsAsyncFunction() const { 3533 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3534 if (!obj->IsJSFunction()) return false; 3535 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(obj); 3536 return i::IsAsyncFunction(func->shared()->kind()); 3537 } 3538 3539 bool Value::IsGeneratorFunction() const { 3540 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3541 if (!obj->IsJSFunction()) return false; 3542 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(obj); 3543 return i::IsGeneratorFunction(func->shared()->kind()); 3544 } 3545 3546 3547 bool Value::IsGeneratorObject() const { 3548 return Utils::OpenHandle(this)->IsJSGeneratorObject(); 3549 } 3550 3551 3552 bool Value::IsMapIterator() const { 3553 return Utils::OpenHandle(this)->IsJSMapIterator(); 3554 } 3555 3556 3557 bool Value::IsSetIterator() const { 3558 return Utils::OpenHandle(this)->IsJSSetIterator(); 3559 } 3560 3561 bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); } 3562 3563 MaybeLocal<String> Value::ToString(Local<Context> context) const { 3564 auto obj = Utils::OpenHandle(this); 3565 if (obj->IsString()) return ToApiHandle<String>(obj); 3566 PREPARE_FOR_EXECUTION(context, Object, ToString, String); 3567 Local<String> result; 3568 has_pending_exception = 3569 !ToLocal<String>(i::Object::ToString(isolate, obj), &result); 3570 RETURN_ON_FAILED_EXECUTION(String); 3571 RETURN_ESCAPED(result); 3572 } 3573 3574 3575 Local<String> Value::ToString(Isolate* isolate) const { 3576 RETURN_TO_LOCAL_UNCHECKED(ToString(isolate->GetCurrentContext()), String); 3577 } 3578 3579 3580 MaybeLocal<String> Value::ToDetailString(Local<Context> context) const { 3581 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3582 if (obj->IsString()) return ToApiHandle<String>(obj); 3583 PREPARE_FOR_EXECUTION(context, Object, ToDetailString, String); 3584 Local<String> result = 3585 Utils::ToLocal(i::Object::NoSideEffectsToString(isolate, obj)); 3586 RETURN_ON_FAILED_EXECUTION(String); 3587 RETURN_ESCAPED(result); 3588 } 3589 3590 3591 Local<String> Value::ToDetailString(Isolate* isolate) const { 3592 RETURN_TO_LOCAL_UNCHECKED(ToDetailString(isolate->GetCurrentContext()), 3593 String); 3594 } 3595 3596 3597 MaybeLocal<Object> Value::ToObject(Local<Context> context) const { 3598 auto obj = Utils::OpenHandle(this); 3599 if (obj->IsJSReceiver()) return ToApiHandle<Object>(obj); 3600 PREPARE_FOR_EXECUTION(context, Object, ToObject, Object); 3601 Local<Object> result; 3602 has_pending_exception = 3603 !ToLocal<Object>(i::Object::ToObject(isolate, obj), &result); 3604 RETURN_ON_FAILED_EXECUTION(Object); 3605 RETURN_ESCAPED(result); 3606 } 3607 3608 3609 Local<v8::Object> Value::ToObject(Isolate* isolate) const { 3610 RETURN_TO_LOCAL_UNCHECKED(ToObject(isolate->GetCurrentContext()), Object); 3611 } 3612 3613 3614 MaybeLocal<Boolean> Value::ToBoolean(Local<Context> context) const { 3615 auto obj = Utils::OpenHandle(this); 3616 if (obj->IsBoolean()) return ToApiHandle<Boolean>(obj); 3617 auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate()); 3618 auto val = isolate->factory()->ToBoolean(obj->BooleanValue()); 3619 return ToApiHandle<Boolean>(val); 3620 } 3621 3622 3623 Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const { 3624 return ToBoolean(v8_isolate->GetCurrentContext()).ToLocalChecked(); 3625 } 3626 3627 3628 MaybeLocal<Number> Value::ToNumber(Local<Context> context) const { 3629 auto obj = Utils::OpenHandle(this); 3630 if (obj->IsNumber()) return ToApiHandle<Number>(obj); 3631 PREPARE_FOR_EXECUTION(context, Object, ToNumber, Number); 3632 Local<Number> result; 3633 has_pending_exception = !ToLocal<Number>(i::Object::ToNumber(obj), &result); 3634 RETURN_ON_FAILED_EXECUTION(Number); 3635 RETURN_ESCAPED(result); 3636 } 3637 3638 3639 Local<Number> Value::ToNumber(Isolate* isolate) const { 3640 RETURN_TO_LOCAL_UNCHECKED(ToNumber(isolate->GetCurrentContext()), Number); 3641 } 3642 3643 3644 MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const { 3645 auto obj = Utils::OpenHandle(this); 3646 if (obj->IsSmi()) return ToApiHandle<Integer>(obj); 3647 PREPARE_FOR_EXECUTION(context, Object, ToInteger, Integer); 3648 Local<Integer> result; 3649 has_pending_exception = 3650 !ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result); 3651 RETURN_ON_FAILED_EXECUTION(Integer); 3652 RETURN_ESCAPED(result); 3653 } 3654 3655 3656 Local<Integer> Value::ToInteger(Isolate* isolate) const { 3657 RETURN_TO_LOCAL_UNCHECKED(ToInteger(isolate->GetCurrentContext()), Integer); 3658 } 3659 3660 3661 MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const { 3662 auto obj = Utils::OpenHandle(this); 3663 if (obj->IsSmi()) return ToApiHandle<Int32>(obj); 3664 Local<Int32> result; 3665 PREPARE_FOR_EXECUTION(context, Object, ToInt32, Int32); 3666 has_pending_exception = 3667 !ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result); 3668 RETURN_ON_FAILED_EXECUTION(Int32); 3669 RETURN_ESCAPED(result); 3670 } 3671 3672 3673 Local<Int32> Value::ToInt32(Isolate* isolate) const { 3674 RETURN_TO_LOCAL_UNCHECKED(ToInt32(isolate->GetCurrentContext()), Int32); 3675 } 3676 3677 3678 MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const { 3679 auto obj = Utils::OpenHandle(this); 3680 if (obj->IsSmi()) return ToApiHandle<Uint32>(obj); 3681 Local<Uint32> result; 3682 PREPARE_FOR_EXECUTION(context, Object, ToUint32, Uint32); 3683 has_pending_exception = 3684 !ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result); 3685 RETURN_ON_FAILED_EXECUTION(Uint32); 3686 RETURN_ESCAPED(result); 3687 } 3688 3689 3690 Local<Uint32> Value::ToUint32(Isolate* isolate) const { 3691 RETURN_TO_LOCAL_UNCHECKED(ToUint32(isolate->GetCurrentContext()), Uint32); 3692 } 3693 3694 3695 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { 3696 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 3697 Utils::ApiCheck(isolate != NULL && !isolate->IsDead(), 3698 "v8::internal::Internals::CheckInitialized", 3699 "Isolate is not initialized or V8 has died"); 3700 } 3701 3702 3703 void External::CheckCast(v8::Value* that) { 3704 Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(), "v8::External::Cast", 3705 "Could not convert to external"); 3706 } 3707 3708 3709 void v8::Object::CheckCast(Value* that) { 3710 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3711 Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast", 3712 "Could not convert to object"); 3713 } 3714 3715 3716 void v8::Function::CheckCast(Value* that) { 3717 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3718 Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast", 3719 "Could not convert to function"); 3720 } 3721 3722 3723 void v8::Boolean::CheckCast(v8::Value* that) { 3724 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3725 Utils::ApiCheck(obj->IsBoolean(), "v8::Boolean::Cast", 3726 "Could not convert to boolean"); 3727 } 3728 3729 3730 void v8::Name::CheckCast(v8::Value* that) { 3731 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3732 Utils::ApiCheck(obj->IsName(), "v8::Name::Cast", "Could not convert to name"); 3733 } 3734 3735 3736 void v8::String::CheckCast(v8::Value* that) { 3737 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3738 Utils::ApiCheck(obj->IsString(), "v8::String::Cast", 3739 "Could not convert to string"); 3740 } 3741 3742 3743 void v8::Symbol::CheckCast(v8::Value* that) { 3744 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3745 Utils::ApiCheck(obj->IsSymbol(), "v8::Symbol::Cast", 3746 "Could not convert to symbol"); 3747 } 3748 3749 3750 void v8::Number::CheckCast(v8::Value* that) { 3751 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3752 Utils::ApiCheck(obj->IsNumber(), 3753 "v8::Number::Cast()", 3754 "Could not convert to number"); 3755 } 3756 3757 3758 void v8::Integer::CheckCast(v8::Value* that) { 3759 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3760 Utils::ApiCheck(obj->IsNumber(), "v8::Integer::Cast", 3761 "Could not convert to number"); 3762 } 3763 3764 3765 void v8::Int32::CheckCast(v8::Value* that) { 3766 Utils::ApiCheck(that->IsInt32(), "v8::Int32::Cast", 3767 "Could not convert to 32-bit signed integer"); 3768 } 3769 3770 3771 void v8::Uint32::CheckCast(v8::Value* that) { 3772 Utils::ApiCheck(that->IsUint32(), "v8::Uint32::Cast", 3773 "Could not convert to 32-bit unsigned integer"); 3774 } 3775 3776 3777 void v8::Array::CheckCast(Value* that) { 3778 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3779 Utils::ApiCheck(obj->IsJSArray(), "v8::Array::Cast", 3780 "Could not convert to array"); 3781 } 3782 3783 3784 void v8::Map::CheckCast(Value* that) { 3785 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3786 Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast", "Could not convert to Map"); 3787 } 3788 3789 3790 void v8::Set::CheckCast(Value* that) { 3791 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3792 Utils::ApiCheck(obj->IsJSSet(), "v8_Set_Cast", "Could not convert to Set"); 3793 } 3794 3795 3796 void v8::Promise::CheckCast(Value* that) { 3797 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Cast", 3798 "Could not convert to promise"); 3799 } 3800 3801 3802 void v8::Promise::Resolver::CheckCast(Value* that) { 3803 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Resolver::Cast", 3804 "Could not convert to promise resolver"); 3805 } 3806 3807 3808 void v8::Proxy::CheckCast(Value* that) { 3809 Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast", 3810 "Could not convert to proxy"); 3811 } 3812 3813 void v8::WasmCompiledModule::CheckCast(Value* that) { 3814 Utils::ApiCheck(that->IsWebAssemblyCompiledModule(), 3815 "v8::WasmCompiledModule::Cast", 3816 "Could not convert to wasm compiled module"); 3817 } 3818 3819 void v8::ArrayBuffer::CheckCast(Value* that) { 3820 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3821 Utils::ApiCheck( 3822 obj->IsJSArrayBuffer() && !i::JSArrayBuffer::cast(*obj)->is_shared(), 3823 "v8::ArrayBuffer::Cast()", "Could not convert to ArrayBuffer"); 3824 } 3825 3826 3827 void v8::ArrayBufferView::CheckCast(Value* that) { 3828 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3829 Utils::ApiCheck(obj->IsJSArrayBufferView(), 3830 "v8::ArrayBufferView::Cast()", 3831 "Could not convert to ArrayBufferView"); 3832 } 3833 3834 3835 void v8::TypedArray::CheckCast(Value* that) { 3836 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3837 Utils::ApiCheck(obj->IsJSTypedArray(), 3838 "v8::TypedArray::Cast()", 3839 "Could not convert to TypedArray"); 3840 } 3841 3842 3843 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size) \ 3844 void v8::Type##Array::CheckCast(Value* that) { \ 3845 i::Handle<i::Object> obj = Utils::OpenHandle(that); \ 3846 Utils::ApiCheck( \ 3847 obj->IsJSTypedArray() && \ 3848 i::JSTypedArray::cast(*obj)->type() == i::kExternal##Type##Array, \ 3849 "v8::" #Type "Array::Cast()", "Could not convert to " #Type "Array"); \ 3850 } 3851 3852 3853 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST) 3854 3855 #undef CHECK_TYPED_ARRAY_CAST 3856 3857 3858 void v8::DataView::CheckCast(Value* that) { 3859 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3860 Utils::ApiCheck(obj->IsJSDataView(), 3861 "v8::DataView::Cast()", 3862 "Could not convert to DataView"); 3863 } 3864 3865 3866 void v8::SharedArrayBuffer::CheckCast(Value* that) { 3867 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3868 Utils::ApiCheck( 3869 obj->IsJSArrayBuffer() && i::JSArrayBuffer::cast(*obj)->is_shared(), 3870 "v8::SharedArrayBuffer::Cast()", 3871 "Could not convert to SharedArrayBuffer"); 3872 } 3873 3874 3875 void v8::Date::CheckCast(v8::Value* that) { 3876 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3877 i::Isolate* isolate = NULL; 3878 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 3879 Utils::ApiCheck(isolate != NULL && 3880 obj->HasSpecificClassOf(isolate->heap()->Date_string()), 3881 "v8::Date::Cast()", 3882 "Could not convert to date"); 3883 } 3884 3885 3886 void v8::StringObject::CheckCast(v8::Value* that) { 3887 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3888 i::Isolate* isolate = NULL; 3889 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 3890 Utils::ApiCheck(isolate != NULL && 3891 obj->HasSpecificClassOf(isolate->heap()->String_string()), 3892 "v8::StringObject::Cast()", 3893 "Could not convert to StringObject"); 3894 } 3895 3896 3897 void v8::SymbolObject::CheckCast(v8::Value* that) { 3898 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3899 i::Isolate* isolate = NULL; 3900 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 3901 Utils::ApiCheck(isolate != NULL && 3902 obj->HasSpecificClassOf(isolate->heap()->Symbol_string()), 3903 "v8::SymbolObject::Cast()", 3904 "Could not convert to SymbolObject"); 3905 } 3906 3907 3908 void v8::NumberObject::CheckCast(v8::Value* that) { 3909 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3910 i::Isolate* isolate = NULL; 3911 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 3912 Utils::ApiCheck(isolate != NULL && 3913 obj->HasSpecificClassOf(isolate->heap()->Number_string()), 3914 "v8::NumberObject::Cast()", 3915 "Could not convert to NumberObject"); 3916 } 3917 3918 3919 void v8::BooleanObject::CheckCast(v8::Value* that) { 3920 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3921 i::Isolate* isolate = NULL; 3922 if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate(); 3923 Utils::ApiCheck(isolate != NULL && 3924 obj->HasSpecificClassOf(isolate->heap()->Boolean_string()), 3925 "v8::BooleanObject::Cast()", 3926 "Could not convert to BooleanObject"); 3927 } 3928 3929 3930 void v8::RegExp::CheckCast(v8::Value* that) { 3931 i::Handle<i::Object> obj = Utils::OpenHandle(that); 3932 Utils::ApiCheck(obj->IsJSRegExp(), 3933 "v8::RegExp::Cast()", 3934 "Could not convert to regular expression"); 3935 } 3936 3937 3938 Maybe<bool> Value::BooleanValue(Local<Context> context) const { 3939 return Just(Utils::OpenHandle(this)->BooleanValue()); 3940 } 3941 3942 3943 bool Value::BooleanValue() const { 3944 return Utils::OpenHandle(this)->BooleanValue(); 3945 } 3946 3947 3948 Maybe<double> Value::NumberValue(Local<Context> context) const { 3949 auto obj = Utils::OpenHandle(this); 3950 if (obj->IsNumber()) return Just(obj->Number()); 3951 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, NumberValue, double); 3952 i::Handle<i::Object> num; 3953 has_pending_exception = !i::Object::ToNumber(obj).ToHandle(&num); 3954 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double); 3955 return Just(num->Number()); 3956 } 3957 3958 3959 double Value::NumberValue() const { 3960 auto obj = Utils::OpenHandle(this); 3961 if (obj->IsNumber()) return obj->Number(); 3962 return NumberValue(ContextFromHeapObject(obj)) 3963 .FromMaybe(std::numeric_limits<double>::quiet_NaN()); 3964 } 3965 3966 3967 Maybe<int64_t> Value::IntegerValue(Local<Context> context) const { 3968 auto obj = Utils::OpenHandle(this); 3969 if (obj->IsNumber()) { 3970 return Just(NumberToInt64(*obj)); 3971 } 3972 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, IntegerValue, int64_t); 3973 i::Handle<i::Object> num; 3974 has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num); 3975 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t); 3976 return Just(NumberToInt64(*num)); 3977 } 3978 3979 3980 int64_t Value::IntegerValue() const { 3981 auto obj = Utils::OpenHandle(this); 3982 if (obj->IsNumber()) { 3983 if (obj->IsSmi()) { 3984 return i::Smi::cast(*obj)->value(); 3985 } else { 3986 return static_cast<int64_t>(obj->Number()); 3987 } 3988 } 3989 return IntegerValue(ContextFromHeapObject(obj)).FromMaybe(0); 3990 } 3991 3992 3993 Maybe<int32_t> Value::Int32Value(Local<Context> context) const { 3994 auto obj = Utils::OpenHandle(this); 3995 if (obj->IsNumber()) return Just(NumberToInt32(*obj)); 3996 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Int32Value, int32_t); 3997 i::Handle<i::Object> num; 3998 has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num); 3999 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t); 4000 return Just(num->IsSmi() ? i::Smi::cast(*num)->value() 4001 : static_cast<int32_t>(num->Number())); 4002 } 4003 4004 4005 int32_t Value::Int32Value() const { 4006 auto obj = Utils::OpenHandle(this); 4007 if (obj->IsNumber()) return NumberToInt32(*obj); 4008 return Int32Value(ContextFromHeapObject(obj)).FromMaybe(0); 4009 } 4010 4011 4012 Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const { 4013 auto obj = Utils::OpenHandle(this); 4014 if (obj->IsNumber()) return Just(NumberToUint32(*obj)); 4015 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Uint32Value, uint32_t); 4016 i::Handle<i::Object> num; 4017 has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num); 4018 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t); 4019 return Just(num->IsSmi() ? static_cast<uint32_t>(i::Smi::cast(*num)->value()) 4020 : static_cast<uint32_t>(num->Number())); 4021 } 4022 4023 4024 uint32_t Value::Uint32Value() const { 4025 auto obj = Utils::OpenHandle(this); 4026 if (obj->IsNumber()) return NumberToUint32(*obj); 4027 return Uint32Value(ContextFromHeapObject(obj)).FromMaybe(0); 4028 } 4029 4030 4031 MaybeLocal<Uint32> Value::ToArrayIndex(Local<Context> context) const { 4032 auto self = Utils::OpenHandle(this); 4033 if (self->IsSmi()) { 4034 if (i::Smi::cast(*self)->value() >= 0) return Utils::Uint32ToLocal(self); 4035 return Local<Uint32>(); 4036 } 4037 PREPARE_FOR_EXECUTION(context, Object, ToArrayIndex, Uint32); 4038 i::Handle<i::Object> string_obj; 4039 has_pending_exception = 4040 !i::Object::ToString(isolate, self).ToHandle(&string_obj); 4041 RETURN_ON_FAILED_EXECUTION(Uint32); 4042 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj); 4043 uint32_t index; 4044 if (str->AsArrayIndex(&index)) { 4045 i::Handle<i::Object> value; 4046 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) { 4047 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate); 4048 } else { 4049 value = isolate->factory()->NewNumber(index); 4050 } 4051 RETURN_ESCAPED(Utils::Uint32ToLocal(value)); 4052 } 4053 return Local<Uint32>(); 4054 } 4055 4056 4057 Local<Uint32> Value::ToArrayIndex() const { 4058 auto self = Utils::OpenHandle(this); 4059 if (self->IsSmi()) { 4060 if (i::Smi::cast(*self)->value() >= 0) return Utils::Uint32ToLocal(self); 4061 return Local<Uint32>(); 4062 } 4063 auto context = ContextFromHeapObject(self); 4064 RETURN_TO_LOCAL_UNCHECKED(ToArrayIndex(context), Uint32); 4065 } 4066 4067 4068 Maybe<bool> Value::Equals(Local<Context> context, Local<Value> that) const { 4069 auto self = Utils::OpenHandle(this); 4070 auto other = Utils::OpenHandle(*that); 4071 return i::Object::Equals(self, other); 4072 } 4073 4074 4075 bool Value::Equals(Local<Value> that) const { 4076 auto self = Utils::OpenHandle(this); 4077 auto other = Utils::OpenHandle(*that); 4078 if (self->IsSmi() && other->IsSmi()) { 4079 return self->Number() == other->Number(); 4080 } 4081 if (self->IsJSObject() && other->IsJSObject()) { 4082 return *self == *other; 4083 } 4084 auto heap_object = self->IsSmi() ? other : self; 4085 auto context = ContextFromHeapObject(heap_object); 4086 return Equals(context, that).FromMaybe(false); 4087 } 4088 4089 4090 bool Value::StrictEquals(Local<Value> that) const { 4091 auto self = Utils::OpenHandle(this); 4092 auto other = Utils::OpenHandle(*that); 4093 return self->StrictEquals(*other); 4094 } 4095 4096 4097 bool Value::SameValue(Local<Value> that) const { 4098 auto self = Utils::OpenHandle(this); 4099 auto other = Utils::OpenHandle(*that); 4100 return self->SameValue(*other); 4101 } 4102 4103 Local<String> Value::TypeOf(v8::Isolate* external_isolate) { 4104 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 4105 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 4106 LOG_API(isolate, Value, TypeOf); 4107 return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this))); 4108 } 4109 4110 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, 4111 v8::Local<Value> key, v8::Local<Value> value) { 4112 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Set, bool); 4113 auto self = Utils::OpenHandle(this); 4114 auto key_obj = Utils::OpenHandle(*key); 4115 auto value_obj = Utils::OpenHandle(*value); 4116 has_pending_exception = 4117 i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj, 4118 i::SLOPPY).is_null(); 4119 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4120 return Just(true); 4121 } 4122 4123 4124 bool v8::Object::Set(v8::Local<Value> key, v8::Local<Value> value) { 4125 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4126 return Set(context, key, value).FromMaybe(false); 4127 } 4128 4129 4130 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index, 4131 v8::Local<Value> value) { 4132 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Set, bool); 4133 auto self = Utils::OpenHandle(this); 4134 auto value_obj = Utils::OpenHandle(*value); 4135 has_pending_exception = i::Object::SetElement(isolate, self, index, value_obj, 4136 i::SLOPPY).is_null(); 4137 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4138 return Just(true); 4139 } 4140 4141 4142 bool v8::Object::Set(uint32_t index, v8::Local<Value> value) { 4143 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4144 return Set(context, index, value).FromMaybe(false); 4145 } 4146 4147 4148 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context, 4149 v8::Local<Name> key, 4150 v8::Local<Value> value) { 4151 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, CreateDataProperty, bool); 4152 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4153 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key); 4154 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 4155 4156 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4157 isolate, self, key_obj, self, i::LookupIterator::OWN); 4158 Maybe<bool> result = 4159 i::JSReceiver::CreateDataProperty(&it, value_obj, i::Object::DONT_THROW); 4160 has_pending_exception = result.IsNothing(); 4161 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4162 return result; 4163 } 4164 4165 4166 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context, 4167 uint32_t index, 4168 v8::Local<Value> value) { 4169 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, CreateDataProperty, bool); 4170 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4171 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 4172 4173 i::LookupIterator it(isolate, self, index, self, i::LookupIterator::OWN); 4174 Maybe<bool> result = 4175 i::JSReceiver::CreateDataProperty(&it, value_obj, i::Object::DONT_THROW); 4176 has_pending_exception = result.IsNothing(); 4177 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4178 return result; 4179 } 4180 4181 struct v8::PropertyDescriptor::PrivateData { 4182 PrivateData() : desc() {} 4183 i::PropertyDescriptor desc; 4184 }; 4185 4186 v8::PropertyDescriptor::PropertyDescriptor() : private_(new PrivateData()) {} 4187 4188 // DataDescriptor 4189 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value) 4190 : private_(new PrivateData()) { 4191 private_->desc.set_value(Utils::OpenHandle(*value, true)); 4192 } 4193 4194 // DataDescriptor with writable field 4195 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> value, 4196 bool writable) 4197 : private_(new PrivateData()) { 4198 private_->desc.set_value(Utils::OpenHandle(*value, true)); 4199 private_->desc.set_writable(writable); 4200 } 4201 4202 // AccessorDescriptor 4203 v8::PropertyDescriptor::PropertyDescriptor(v8::Local<v8::Value> get, 4204 v8::Local<v8::Value> set) 4205 : private_(new PrivateData()) { 4206 DCHECK(get.IsEmpty() || get->IsUndefined() || get->IsFunction()); 4207 DCHECK(set.IsEmpty() || set->IsUndefined() || set->IsFunction()); 4208 private_->desc.set_get(Utils::OpenHandle(*get, true)); 4209 private_->desc.set_set(Utils::OpenHandle(*set, true)); 4210 } 4211 4212 v8::PropertyDescriptor::~PropertyDescriptor() { delete private_; } 4213 4214 v8::Local<Value> v8::PropertyDescriptor::value() const { 4215 DCHECK(private_->desc.has_value()); 4216 return Utils::ToLocal(private_->desc.value()); 4217 } 4218 4219 v8::Local<Value> v8::PropertyDescriptor::get() const { 4220 DCHECK(private_->desc.has_get()); 4221 return Utils::ToLocal(private_->desc.get()); 4222 } 4223 4224 v8::Local<Value> v8::PropertyDescriptor::set() const { 4225 DCHECK(private_->desc.has_set()); 4226 return Utils::ToLocal(private_->desc.set()); 4227 } 4228 4229 bool v8::PropertyDescriptor::has_value() const { 4230 return private_->desc.has_value(); 4231 } 4232 bool v8::PropertyDescriptor::has_get() const { 4233 return private_->desc.has_get(); 4234 } 4235 bool v8::PropertyDescriptor::has_set() const { 4236 return private_->desc.has_set(); 4237 } 4238 4239 bool v8::PropertyDescriptor::writable() const { 4240 DCHECK(private_->desc.has_writable()); 4241 return private_->desc.writable(); 4242 } 4243 4244 bool v8::PropertyDescriptor::has_writable() const { 4245 return private_->desc.has_writable(); 4246 } 4247 4248 void v8::PropertyDescriptor::set_enumerable(bool enumerable) { 4249 private_->desc.set_enumerable(enumerable); 4250 } 4251 4252 bool v8::PropertyDescriptor::enumerable() const { 4253 DCHECK(private_->desc.has_enumerable()); 4254 return private_->desc.enumerable(); 4255 } 4256 4257 bool v8::PropertyDescriptor::has_enumerable() const { 4258 return private_->desc.has_enumerable(); 4259 } 4260 4261 void v8::PropertyDescriptor::set_configurable(bool configurable) { 4262 private_->desc.set_configurable(configurable); 4263 } 4264 4265 bool v8::PropertyDescriptor::configurable() const { 4266 DCHECK(private_->desc.has_configurable()); 4267 return private_->desc.configurable(); 4268 } 4269 4270 bool v8::PropertyDescriptor::has_configurable() const { 4271 return private_->desc.has_configurable(); 4272 } 4273 4274 Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context, 4275 v8::Local<Name> key, 4276 v8::Local<Value> value, 4277 v8::PropertyAttribute attributes) { 4278 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, DefineOwnProperty, bool); 4279 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4280 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key); 4281 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 4282 4283 i::PropertyDescriptor desc; 4284 desc.set_writable(!(attributes & v8::ReadOnly)); 4285 desc.set_enumerable(!(attributes & v8::DontEnum)); 4286 desc.set_configurable(!(attributes & v8::DontDelete)); 4287 desc.set_value(value_obj); 4288 Maybe<bool> success = i::JSReceiver::DefineOwnProperty( 4289 isolate, self, key_obj, &desc, i::Object::DONT_THROW); 4290 // Even though we said DONT_THROW, there might be accessors that do throw. 4291 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4292 return success; 4293 } 4294 4295 Maybe<bool> v8::Object::DefineProperty(v8::Local<v8::Context> context, 4296 v8::Local<Name> key, 4297 PropertyDescriptor& descriptor) { 4298 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, DefineProperty, bool); 4299 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4300 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key); 4301 4302 Maybe<bool> success = i::JSReceiver::DefineOwnProperty( 4303 isolate, self, key_obj, &descriptor.get_private()->desc, 4304 i::Object::DONT_THROW); 4305 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4306 return success; 4307 } 4308 4309 MUST_USE_RESULT 4310 static i::MaybeHandle<i::Object> DefineObjectProperty( 4311 i::Handle<i::JSObject> js_object, i::Handle<i::Object> key, 4312 i::Handle<i::Object> value, i::PropertyAttributes attrs) { 4313 i::Isolate* isolate = js_object->GetIsolate(); 4314 bool success = false; 4315 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4316 isolate, js_object, key, &success, i::LookupIterator::OWN); 4317 if (!success) return i::MaybeHandle<i::Object>(); 4318 4319 return i::JSObject::DefineOwnPropertyIgnoreAttributes( 4320 &it, value, attrs, i::JSObject::FORCE_FIELD); 4321 } 4322 4323 4324 Maybe<bool> v8::Object::ForceSet(v8::Local<v8::Context> context, 4325 v8::Local<Value> key, v8::Local<Value> value, 4326 v8::PropertyAttribute attribs) { 4327 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, ForceSet, bool); 4328 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this)); 4329 auto key_obj = Utils::OpenHandle(*key); 4330 auto value_obj = Utils::OpenHandle(*value); 4331 has_pending_exception = 4332 DefineObjectProperty(self, key_obj, value_obj, 4333 static_cast<i::PropertyAttributes>(attribs)) 4334 .is_null(); 4335 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4336 return Just(true); 4337 } 4338 4339 4340 bool v8::Object::ForceSet(v8::Local<Value> key, v8::Local<Value> value, 4341 v8::PropertyAttribute attribs) { 4342 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4343 PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), Object, ForceSet, 4344 false, i::HandleScope, false); 4345 i::Handle<i::JSObject> self = 4346 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this)); 4347 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 4348 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 4349 has_pending_exception = 4350 DefineObjectProperty(self, key_obj, value_obj, 4351 static_cast<i::PropertyAttributes>(attribs)) 4352 .is_null(); 4353 EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, false); 4354 return true; 4355 } 4356 4357 4358 Maybe<bool> v8::Object::SetPrivate(Local<Context> context, Local<Private> key, 4359 Local<Value> value) { 4360 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetPrivate, bool); 4361 auto self = Utils::OpenHandle(this); 4362 auto key_obj = Utils::OpenHandle(reinterpret_cast<Name*>(*key)); 4363 auto value_obj = Utils::OpenHandle(*value); 4364 if (self->IsJSProxy()) { 4365 i::PropertyDescriptor desc; 4366 desc.set_writable(true); 4367 desc.set_enumerable(false); 4368 desc.set_configurable(true); 4369 desc.set_value(value_obj); 4370 return i::JSProxy::SetPrivateProperty( 4371 isolate, i::Handle<i::JSProxy>::cast(self), 4372 i::Handle<i::Symbol>::cast(key_obj), &desc, i::Object::DONT_THROW); 4373 } 4374 auto js_object = i::Handle<i::JSObject>::cast(self); 4375 i::LookupIterator it(js_object, key_obj, js_object); 4376 has_pending_exception = i::JSObject::DefineOwnPropertyIgnoreAttributes( 4377 &it, value_obj, i::DONT_ENUM) 4378 .is_null(); 4379 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4380 return Just(true); 4381 } 4382 4383 4384 MaybeLocal<Value> v8::Object::Get(Local<v8::Context> context, 4385 Local<Value> key) { 4386 PREPARE_FOR_EXECUTION(context, Object, Get, Value); 4387 auto self = Utils::OpenHandle(this); 4388 auto key_obj = Utils::OpenHandle(*key); 4389 i::Handle<i::Object> result; 4390 has_pending_exception = 4391 !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result); 4392 RETURN_ON_FAILED_EXECUTION(Value); 4393 RETURN_ESCAPED(Utils::ToLocal(result)); 4394 } 4395 4396 4397 Local<Value> v8::Object::Get(v8::Local<Value> key) { 4398 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4399 RETURN_TO_LOCAL_UNCHECKED(Get(context, key), Value); 4400 } 4401 4402 4403 MaybeLocal<Value> v8::Object::Get(Local<Context> context, uint32_t index) { 4404 PREPARE_FOR_EXECUTION(context, Object, Get, Value); 4405 auto self = Utils::OpenHandle(this); 4406 i::Handle<i::Object> result; 4407 has_pending_exception = 4408 !i::JSReceiver::GetElement(isolate, self, index).ToHandle(&result); 4409 RETURN_ON_FAILED_EXECUTION(Value); 4410 RETURN_ESCAPED(Utils::ToLocal(result)); 4411 } 4412 4413 4414 Local<Value> v8::Object::Get(uint32_t index) { 4415 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4416 RETURN_TO_LOCAL_UNCHECKED(Get(context, index), Value); 4417 } 4418 4419 4420 MaybeLocal<Value> v8::Object::GetPrivate(Local<Context> context, 4421 Local<Private> key) { 4422 return Get(context, Local<Value>(reinterpret_cast<Value*>(*key))); 4423 } 4424 4425 4426 Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes( 4427 Local<Context> context, Local<Value> key) { 4428 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, GetPropertyAttributes, 4429 PropertyAttribute); 4430 auto self = Utils::OpenHandle(this); 4431 auto key_obj = Utils::OpenHandle(*key); 4432 if (!key_obj->IsName()) { 4433 has_pending_exception = 4434 !i::Object::ToString(isolate, key_obj).ToHandle(&key_obj); 4435 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute); 4436 } 4437 auto key_name = i::Handle<i::Name>::cast(key_obj); 4438 auto result = i::JSReceiver::GetPropertyAttributes(self, key_name); 4439 has_pending_exception = result.IsNothing(); 4440 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute); 4441 if (result.FromJust() == i::ABSENT) { 4442 return Just(static_cast<PropertyAttribute>(i::NONE)); 4443 } 4444 return Just(static_cast<PropertyAttribute>(result.FromJust())); 4445 } 4446 4447 4448 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Local<Value> key) { 4449 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4450 return GetPropertyAttributes(context, key) 4451 .FromMaybe(static_cast<PropertyAttribute>(i::NONE)); 4452 } 4453 4454 4455 MaybeLocal<Value> v8::Object::GetOwnPropertyDescriptor(Local<Context> context, 4456 Local<String> key) { 4457 PREPARE_FOR_EXECUTION(context, Object, GetOwnPropertyDescriptor, Value); 4458 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 4459 i::Handle<i::String> key_name = Utils::OpenHandle(*key); 4460 4461 i::PropertyDescriptor desc; 4462 Maybe<bool> found = 4463 i::JSReceiver::GetOwnPropertyDescriptor(isolate, obj, key_name, &desc); 4464 has_pending_exception = found.IsNothing(); 4465 RETURN_ON_FAILED_EXECUTION(Value); 4466 if (!found.FromJust()) { 4467 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 4468 } 4469 RETURN_ESCAPED(Utils::ToLocal(desc.ToObject(isolate))); 4470 } 4471 4472 4473 Local<Value> v8::Object::GetOwnPropertyDescriptor(Local<String> key) { 4474 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4475 RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyDescriptor(context, key), Value); 4476 } 4477 4478 4479 Local<Value> v8::Object::GetPrototype() { 4480 auto isolate = Utils::OpenHandle(this)->GetIsolate(); 4481 auto self = Utils::OpenHandle(this); 4482 i::PrototypeIterator iter(isolate, self); 4483 return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter)); 4484 } 4485 4486 4487 Maybe<bool> v8::Object::SetPrototype(Local<Context> context, 4488 Local<Value> value) { 4489 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetPrototype, bool); 4490 auto self = Utils::OpenHandle(this); 4491 auto value_obj = Utils::OpenHandle(*value); 4492 // We do not allow exceptions thrown while setting the prototype 4493 // to propagate outside. 4494 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); 4495 auto result = i::JSReceiver::SetPrototype(self, value_obj, false, 4496 i::Object::THROW_ON_ERROR); 4497 has_pending_exception = result.IsNothing(); 4498 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4499 return Just(true); 4500 } 4501 4502 4503 bool v8::Object::SetPrototype(Local<Value> value) { 4504 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4505 return SetPrototype(context, value).FromMaybe(false); 4506 } 4507 4508 Local<Object> v8::Object::FindInstanceInPrototypeChain( 4509 v8::Local<FunctionTemplate> tmpl) { 4510 auto self = Utils::OpenHandle(this); 4511 auto isolate = self->GetIsolate(); 4512 i::PrototypeIterator iter(isolate, *self, i::kStartAtReceiver); 4513 auto tmpl_info = *Utils::OpenHandle(*tmpl); 4514 while (!tmpl_info->IsTemplateFor(iter.GetCurrent<i::JSObject>())) { 4515 iter.Advance(); 4516 if (iter.IsAtEnd()) return Local<Object>(); 4517 if (!iter.GetCurrent()->IsJSObject()) return Local<Object>(); 4518 } 4519 // IsTemplateFor() ensures that iter.GetCurrent() can't be a Proxy here. 4520 return Utils::ToLocal(i::handle(iter.GetCurrent<i::JSObject>(), isolate)); 4521 } 4522 4523 MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context) { 4524 return GetPropertyNames( 4525 context, v8::KeyCollectionMode::kIncludePrototypes, 4526 static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS), 4527 v8::IndexFilter::kIncludeIndices); 4528 } 4529 4530 MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context, 4531 KeyCollectionMode mode, 4532 PropertyFilter property_filter, 4533 IndexFilter index_filter) { 4534 PREPARE_FOR_EXECUTION(context, Object, GetPropertyNames, Array); 4535 auto self = Utils::OpenHandle(this); 4536 i::Handle<i::FixedArray> value; 4537 i::KeyAccumulator accumulator( 4538 isolate, static_cast<i::KeyCollectionMode>(mode), 4539 static_cast<i::PropertyFilter>(property_filter)); 4540 accumulator.set_skip_indices(index_filter == IndexFilter::kSkipIndices); 4541 has_pending_exception = accumulator.CollectKeys(self, self).IsNothing(); 4542 RETURN_ON_FAILED_EXECUTION(Array); 4543 value = accumulator.GetKeys(i::GetKeysConversion::kKeepNumbers); 4544 DCHECK(self->map()->EnumLength() == i::kInvalidEnumCacheSentinel || 4545 self->map()->EnumLength() == 0 || 4546 self->map()->instance_descriptors()->GetEnumCache() != *value); 4547 auto result = isolate->factory()->NewJSArrayWithElements(value); 4548 RETURN_ESCAPED(Utils::ToLocal(result)); 4549 } 4550 4551 4552 Local<Array> v8::Object::GetPropertyNames() { 4553 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4554 RETURN_TO_LOCAL_UNCHECKED(GetPropertyNames(context), Array); 4555 } 4556 4557 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) { 4558 return GetOwnPropertyNames( 4559 context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS)); 4560 } 4561 4562 Local<Array> v8::Object::GetOwnPropertyNames() { 4563 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4564 RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array); 4565 } 4566 4567 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context, 4568 PropertyFilter filter) { 4569 return GetPropertyNames(context, KeyCollectionMode::kOwnOnly, filter, 4570 v8::IndexFilter::kIncludeIndices); 4571 } 4572 4573 MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) { 4574 PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String); 4575 auto self = Utils::OpenHandle(this); 4576 Local<Value> result; 4577 has_pending_exception = 4578 !ToLocal<Value>(i::Execution::Call(isolate, isolate->object_to_string(), 4579 self, 0, nullptr), 4580 &result); 4581 RETURN_ON_FAILED_EXECUTION(String); 4582 RETURN_ESCAPED(Local<String>::Cast(result)); 4583 } 4584 4585 4586 Local<String> v8::Object::ObjectProtoToString() { 4587 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4588 RETURN_TO_LOCAL_UNCHECKED(ObjectProtoToString(context), String); 4589 } 4590 4591 4592 Local<String> v8::Object::GetConstructorName() { 4593 auto self = Utils::OpenHandle(this); 4594 i::Handle<i::String> name = i::JSReceiver::GetConstructorName(self); 4595 return Utils::ToLocal(name); 4596 } 4597 4598 Maybe<bool> v8::Object::SetIntegrityLevel(Local<Context> context, 4599 IntegrityLevel level) { 4600 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetIntegrityLevel, bool); 4601 auto self = Utils::OpenHandle(this); 4602 i::JSReceiver::IntegrityLevel i_level = 4603 level == IntegrityLevel::kFrozen ? i::FROZEN : i::SEALED; 4604 Maybe<bool> result = 4605 i::JSReceiver::SetIntegrityLevel(self, i_level, i::Object::DONT_THROW); 4606 has_pending_exception = result.IsNothing(); 4607 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4608 return result; 4609 } 4610 4611 Maybe<bool> v8::Object::Delete(Local<Context> context, Local<Value> key) { 4612 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Delete, bool); 4613 auto self = Utils::OpenHandle(this); 4614 auto key_obj = Utils::OpenHandle(*key); 4615 Maybe<bool> result = 4616 i::Runtime::DeleteObjectProperty(isolate, self, key_obj, i::SLOPPY); 4617 has_pending_exception = result.IsNothing(); 4618 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4619 return result; 4620 } 4621 4622 4623 bool v8::Object::Delete(v8::Local<Value> key) { 4624 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4625 return Delete(context, key).FromMaybe(false); 4626 } 4627 4628 4629 Maybe<bool> v8::Object::DeletePrivate(Local<Context> context, 4630 Local<Private> key) { 4631 return Delete(context, Local<Value>(reinterpret_cast<Value*>(*key))); 4632 } 4633 4634 4635 Maybe<bool> v8::Object::Has(Local<Context> context, Local<Value> key) { 4636 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Get, bool); 4637 auto self = Utils::OpenHandle(this); 4638 auto key_obj = Utils::OpenHandle(*key); 4639 Maybe<bool> maybe = Nothing<bool>(); 4640 // Check if the given key is an array index. 4641 uint32_t index = 0; 4642 if (key_obj->ToArrayIndex(&index)) { 4643 maybe = i::JSReceiver::HasElement(self, index); 4644 } else { 4645 // Convert the key to a name - possibly by calling back into JavaScript. 4646 i::Handle<i::Name> name; 4647 if (i::Object::ToName(isolate, key_obj).ToHandle(&name)) { 4648 maybe = i::JSReceiver::HasProperty(self, name); 4649 } 4650 } 4651 has_pending_exception = maybe.IsNothing(); 4652 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4653 return maybe; 4654 } 4655 4656 4657 bool v8::Object::Has(v8::Local<Value> key) { 4658 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4659 return Has(context, key).FromMaybe(false); 4660 } 4661 4662 4663 Maybe<bool> v8::Object::HasPrivate(Local<Context> context, Local<Private> key) { 4664 return HasOwnProperty(context, Local<Name>(reinterpret_cast<Name*>(*key))); 4665 } 4666 4667 4668 Maybe<bool> v8::Object::Delete(Local<Context> context, uint32_t index) { 4669 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, DeleteProperty, bool); 4670 auto self = Utils::OpenHandle(this); 4671 Maybe<bool> result = i::JSReceiver::DeleteElement(self, index); 4672 has_pending_exception = result.IsNothing(); 4673 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4674 return result; 4675 } 4676 4677 4678 bool v8::Object::Delete(uint32_t index) { 4679 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4680 return Delete(context, index).FromMaybe(false); 4681 } 4682 4683 4684 Maybe<bool> v8::Object::Has(Local<Context> context, uint32_t index) { 4685 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Get, bool); 4686 auto self = Utils::OpenHandle(this); 4687 auto maybe = i::JSReceiver::HasElement(self, index); 4688 has_pending_exception = maybe.IsNothing(); 4689 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4690 return maybe; 4691 } 4692 4693 4694 bool v8::Object::Has(uint32_t index) { 4695 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4696 return Has(context, index).FromMaybe(false); 4697 } 4698 4699 4700 template <typename Getter, typename Setter, typename Data> 4701 static Maybe<bool> ObjectSetAccessor(Local<Context> context, Object* self, 4702 Local<Name> name, Getter getter, 4703 Setter setter, Data data, 4704 AccessControl settings, 4705 PropertyAttribute attributes) { 4706 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetAccessor, bool); 4707 if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false); 4708 i::Handle<i::JSObject> obj = 4709 i::Handle<i::JSObject>::cast(Utils::OpenHandle(self)); 4710 v8::Local<AccessorSignature> signature; 4711 auto info = 4712 MakeAccessorInfo(name, getter, setter, data, settings, attributes, 4713 signature, i::FLAG_disable_old_api_accessors, false); 4714 if (info.is_null()) return Nothing<bool>(); 4715 bool fast = obj->HasFastProperties(); 4716 i::Handle<i::Object> result; 4717 has_pending_exception = 4718 !i::JSObject::SetAccessor(obj, info).ToHandle(&result); 4719 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4720 if (result->IsUndefined(obj->GetIsolate())) return Just(false); 4721 if (fast) { 4722 i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor"); 4723 } 4724 return Just(true); 4725 } 4726 4727 4728 Maybe<bool> Object::SetAccessor(Local<Context> context, Local<Name> name, 4729 AccessorNameGetterCallback getter, 4730 AccessorNameSetterCallback setter, 4731 MaybeLocal<Value> data, AccessControl settings, 4732 PropertyAttribute attribute) { 4733 return ObjectSetAccessor(context, this, name, getter, setter, 4734 data.FromMaybe(Local<Value>()), settings, attribute); 4735 } 4736 4737 4738 bool Object::SetAccessor(Local<String> name, AccessorGetterCallback getter, 4739 AccessorSetterCallback setter, v8::Local<Value> data, 4740 AccessControl settings, PropertyAttribute attributes) { 4741 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4742 return ObjectSetAccessor(context, this, name, getter, setter, data, settings, 4743 attributes).FromMaybe(false); 4744 } 4745 4746 4747 bool Object::SetAccessor(Local<Name> name, AccessorNameGetterCallback getter, 4748 AccessorNameSetterCallback setter, 4749 v8::Local<Value> data, AccessControl settings, 4750 PropertyAttribute attributes) { 4751 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4752 return ObjectSetAccessor(context, this, name, getter, setter, data, settings, 4753 attributes).FromMaybe(false); 4754 } 4755 4756 4757 void Object::SetAccessorProperty(Local<Name> name, Local<Function> getter, 4758 Local<Function> setter, 4759 PropertyAttribute attribute, 4760 AccessControl settings) { 4761 // TODO(verwaest): Remove |settings|. 4762 DCHECK_EQ(v8::DEFAULT, settings); 4763 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4764 ENTER_V8(isolate); 4765 i::HandleScope scope(isolate); 4766 auto self = Utils::OpenHandle(this); 4767 if (!self->IsJSObject()) return; 4768 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter); 4769 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true); 4770 if (setter_i.is_null()) setter_i = isolate->factory()->null_value(); 4771 i::JSObject::DefineAccessor(i::Handle<i::JSObject>::cast(self), 4772 v8::Utils::OpenHandle(*name), getter_i, setter_i, 4773 static_cast<i::PropertyAttributes>(attribute)); 4774 } 4775 4776 4777 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, 4778 Local<Name> key) { 4779 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasOwnProperty, bool); 4780 auto self = Utils::OpenHandle(this); 4781 auto key_val = Utils::OpenHandle(*key); 4782 auto result = i::JSReceiver::HasOwnProperty(self, key_val); 4783 has_pending_exception = result.IsNothing(); 4784 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4785 return result; 4786 } 4787 4788 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, uint32_t index) { 4789 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasOwnProperty, bool); 4790 auto self = Utils::OpenHandle(this); 4791 auto result = i::JSReceiver::HasOwnProperty(self, index); 4792 has_pending_exception = result.IsNothing(); 4793 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4794 return result; 4795 } 4796 4797 bool v8::Object::HasOwnProperty(Local<String> key) { 4798 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4799 return HasOwnProperty(context, key).FromMaybe(false); 4800 } 4801 4802 4803 Maybe<bool> v8::Object::HasRealNamedProperty(Local<Context> context, 4804 Local<Name> key) { 4805 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealNamedProperty, bool); 4806 auto self = Utils::OpenHandle(this); 4807 if (!self->IsJSObject()) return Just(false); 4808 auto key_val = Utils::OpenHandle(*key); 4809 auto result = i::JSObject::HasRealNamedProperty( 4810 i::Handle<i::JSObject>::cast(self), key_val); 4811 has_pending_exception = result.IsNothing(); 4812 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4813 return result; 4814 } 4815 4816 4817 bool v8::Object::HasRealNamedProperty(Local<String> key) { 4818 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4819 return HasRealNamedProperty(context, key).FromMaybe(false); 4820 } 4821 4822 4823 Maybe<bool> v8::Object::HasRealIndexedProperty(Local<Context> context, 4824 uint32_t index) { 4825 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealIndexedProperty, 4826 bool); 4827 auto self = Utils::OpenHandle(this); 4828 if (!self->IsJSObject()) return Just(false); 4829 auto result = i::JSObject::HasRealElementProperty( 4830 i::Handle<i::JSObject>::cast(self), index); 4831 has_pending_exception = result.IsNothing(); 4832 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4833 return result; 4834 } 4835 4836 4837 bool v8::Object::HasRealIndexedProperty(uint32_t index) { 4838 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4839 return HasRealIndexedProperty(context, index).FromMaybe(false); 4840 } 4841 4842 4843 Maybe<bool> v8::Object::HasRealNamedCallbackProperty(Local<Context> context, 4844 Local<Name> key) { 4845 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealNamedCallbackProperty, 4846 bool); 4847 auto self = Utils::OpenHandle(this); 4848 if (!self->IsJSObject()) return Just(false); 4849 auto key_val = Utils::OpenHandle(*key); 4850 auto result = i::JSObject::HasRealNamedCallbackProperty( 4851 i::Handle<i::JSObject>::cast(self), key_val); 4852 has_pending_exception = result.IsNothing(); 4853 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); 4854 return result; 4855 } 4856 4857 4858 bool v8::Object::HasRealNamedCallbackProperty(Local<String> key) { 4859 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4860 return HasRealNamedCallbackProperty(context, key).FromMaybe(false); 4861 } 4862 4863 4864 bool v8::Object::HasNamedLookupInterceptor() { 4865 auto self = Utils::OpenHandle(this); 4866 return self->IsJSObject() && 4867 i::Handle<i::JSObject>::cast(self)->HasNamedInterceptor(); 4868 } 4869 4870 4871 bool v8::Object::HasIndexedLookupInterceptor() { 4872 auto self = Utils::OpenHandle(this); 4873 return self->IsJSObject() && 4874 i::Handle<i::JSObject>::cast(self)->HasIndexedInterceptor(); 4875 } 4876 4877 4878 MaybeLocal<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( 4879 Local<Context> context, Local<Name> key) { 4880 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedPropertyInPrototypeChain, 4881 Value); 4882 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4883 if (!self->IsJSObject()) return MaybeLocal<Value>(); 4884 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key); 4885 i::PrototypeIterator iter(isolate, self); 4886 if (iter.IsAtEnd()) return MaybeLocal<Value>(); 4887 i::Handle<i::JSReceiver> proto = 4888 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter); 4889 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4890 isolate, self, key_obj, proto, 4891 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 4892 Local<Value> result; 4893 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result); 4894 RETURN_ON_FAILED_EXECUTION(Value); 4895 if (!it.IsFound()) return MaybeLocal<Value>(); 4896 RETURN_ESCAPED(result); 4897 } 4898 4899 4900 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( 4901 Local<String> key) { 4902 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4903 RETURN_TO_LOCAL_UNCHECKED(GetRealNamedPropertyInPrototypeChain(context, key), 4904 Value); 4905 } 4906 4907 4908 Maybe<PropertyAttribute> 4909 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain( 4910 Local<Context> context, Local<Name> key) { 4911 PREPARE_FOR_EXECUTION_PRIMITIVE( 4912 context, Object, GetRealNamedPropertyAttributesInPrototypeChain, 4913 PropertyAttribute); 4914 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 4915 if (!self->IsJSObject()) return Nothing<PropertyAttribute>(); 4916 i::Handle<i::Name> key_obj = Utils::OpenHandle(*key); 4917 i::PrototypeIterator iter(isolate, self); 4918 if (iter.IsAtEnd()) return Nothing<PropertyAttribute>(); 4919 i::Handle<i::JSReceiver> proto = 4920 i::PrototypeIterator::GetCurrent<i::JSReceiver>(iter); 4921 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4922 isolate, self, key_obj, proto, 4923 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 4924 Maybe<i::PropertyAttributes> result = 4925 i::JSReceiver::GetPropertyAttributes(&it); 4926 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute); 4927 if (!it.IsFound()) return Nothing<PropertyAttribute>(); 4928 if (result.FromJust() == i::ABSENT) return Just(None); 4929 return Just(static_cast<PropertyAttribute>(result.FromJust())); 4930 } 4931 4932 4933 Maybe<PropertyAttribute> 4934 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(Local<String> key) { 4935 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4936 return GetRealNamedPropertyAttributesInPrototypeChain(context, key); 4937 } 4938 4939 4940 MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context, 4941 Local<Name> key) { 4942 PREPARE_FOR_EXECUTION(context, Object, GetRealNamedProperty, Value); 4943 auto self = Utils::OpenHandle(this); 4944 auto key_obj = Utils::OpenHandle(*key); 4945 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4946 isolate, self, key_obj, self, 4947 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 4948 Local<Value> result; 4949 has_pending_exception = !ToLocal<Value>(i::Object::GetProperty(&it), &result); 4950 RETURN_ON_FAILED_EXECUTION(Value); 4951 if (!it.IsFound()) return MaybeLocal<Value>(); 4952 RETURN_ESCAPED(result); 4953 } 4954 4955 4956 Local<Value> v8::Object::GetRealNamedProperty(Local<String> key) { 4957 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4958 RETURN_TO_LOCAL_UNCHECKED(GetRealNamedProperty(context, key), Value); 4959 } 4960 4961 4962 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes( 4963 Local<Context> context, Local<Name> key) { 4964 PREPARE_FOR_EXECUTION_PRIMITIVE( 4965 context, Object, GetRealNamedPropertyAttributes, PropertyAttribute); 4966 auto self = Utils::OpenHandle(this); 4967 auto key_obj = Utils::OpenHandle(*key); 4968 i::LookupIterator it = i::LookupIterator::PropertyOrElement( 4969 isolate, self, key_obj, self, 4970 i::LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 4971 auto result = i::JSReceiver::GetPropertyAttributes(&it); 4972 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(PropertyAttribute); 4973 if (!it.IsFound()) return Nothing<PropertyAttribute>(); 4974 if (result.FromJust() == i::ABSENT) { 4975 return Just(static_cast<PropertyAttribute>(i::NONE)); 4976 } 4977 return Just<PropertyAttribute>( 4978 static_cast<PropertyAttribute>(result.FromJust())); 4979 } 4980 4981 4982 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes( 4983 Local<String> key) { 4984 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 4985 return GetRealNamedPropertyAttributes(context, key); 4986 } 4987 4988 4989 Local<v8::Object> v8::Object::Clone() { 4990 auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this)); 4991 auto isolate = self->GetIsolate(); 4992 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 4993 auto result = isolate->factory()->CopyJSObject(self); 4994 CHECK(!result.is_null()); 4995 return Utils::ToLocal(result); 4996 } 4997 4998 4999 Local<v8::Context> v8::Object::CreationContext() { 5000 auto self = Utils::OpenHandle(this); 5001 return Utils::ToLocal(self->GetCreationContext()); 5002 } 5003 5004 5005 int v8::Object::GetIdentityHash() { 5006 auto isolate = Utils::OpenHandle(this)->GetIsolate(); 5007 i::HandleScope scope(isolate); 5008 auto self = Utils::OpenHandle(this); 5009 return i::JSReceiver::GetOrCreateIdentityHash(isolate, self)->value(); 5010 } 5011 5012 5013 bool v8::Object::IsCallable() { 5014 auto self = Utils::OpenHandle(this); 5015 return self->IsCallable(); 5016 } 5017 5018 bool v8::Object::IsConstructor() { 5019 auto self = Utils::OpenHandle(this); 5020 return self->IsConstructor(); 5021 } 5022 5023 MaybeLocal<Value> Object::CallAsFunction(Local<Context> context, 5024 Local<Value> recv, int argc, 5025 Local<Value> argv[]) { 5026 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 5027 "v8", "V8.Execute", context, Object, CallAsFunction, MaybeLocal<Value>(), 5028 InternalEscapableScope, true); 5029 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 5030 auto self = Utils::OpenHandle(this); 5031 auto recv_obj = Utils::OpenHandle(*recv); 5032 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**)); 5033 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 5034 Local<Value> result; 5035 has_pending_exception = !ToLocal<Value>( 5036 i::Execution::Call(isolate, self, recv_obj, argc, args), &result); 5037 RETURN_ON_FAILED_EXECUTION(Value); 5038 RETURN_ESCAPED(result); 5039 } 5040 5041 5042 Local<v8::Value> Object::CallAsFunction(v8::Local<v8::Value> recv, int argc, 5043 v8::Local<v8::Value> argv[]) { 5044 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 5045 Local<Value>* argv_cast = reinterpret_cast<Local<Value>*>(argv); 5046 RETURN_TO_LOCAL_UNCHECKED(CallAsFunction(context, recv, argc, argv_cast), 5047 Value); 5048 } 5049 5050 5051 MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc, 5052 Local<Value> argv[]) { 5053 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 5054 "v8", "V8.Execute", context, Object, CallAsConstructor, 5055 MaybeLocal<Value>(), InternalEscapableScope, true); 5056 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 5057 auto self = Utils::OpenHandle(this); 5058 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**)); 5059 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 5060 Local<Value> result; 5061 has_pending_exception = !ToLocal<Value>( 5062 i::Execution::New(isolate, self, self, argc, args), &result); 5063 RETURN_ON_FAILED_EXECUTION(Value); 5064 RETURN_ESCAPED(result); 5065 } 5066 5067 5068 Local<v8::Value> Object::CallAsConstructor(int argc, 5069 v8::Local<v8::Value> argv[]) { 5070 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 5071 Local<Value>* argv_cast = reinterpret_cast<Local<Value>*>(argv); 5072 RETURN_TO_LOCAL_UNCHECKED(CallAsConstructor(context, argc, argv_cast), Value); 5073 } 5074 5075 MaybeLocal<Function> Function::New(Local<Context> context, 5076 FunctionCallback callback, Local<Value> data, 5077 int length, ConstructorBehavior behavior) { 5078 i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate(); 5079 LOG_API(isolate, Function, New); 5080 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 5081 auto templ = FunctionTemplateNew(isolate, callback, nullptr, data, 5082 Local<Signature>(), length, true); 5083 if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); 5084 return templ->GetFunction(context); 5085 } 5086 5087 5088 Local<Function> Function::New(Isolate* v8_isolate, FunctionCallback callback, 5089 Local<Value> data, int length) { 5090 return Function::New(v8_isolate->GetCurrentContext(), callback, data, length, 5091 ConstructorBehavior::kAllow) 5092 .FromMaybe(Local<Function>()); 5093 } 5094 5095 5096 Local<v8::Object> Function::NewInstance() const { 5097 return NewInstance(Isolate::GetCurrent()->GetCurrentContext(), 0, NULL) 5098 .FromMaybe(Local<Object>()); 5099 } 5100 5101 5102 MaybeLocal<Object> Function::NewInstance(Local<Context> context, int argc, 5103 v8::Local<v8::Value> argv[]) const { 5104 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 5105 "v8", "V8.Execute", context, Function, NewInstance, MaybeLocal<Object>(), 5106 InternalEscapableScope, true); 5107 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 5108 auto self = Utils::OpenHandle(this); 5109 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**)); 5110 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 5111 Local<Object> result; 5112 has_pending_exception = !ToLocal<Object>( 5113 i::Execution::New(isolate, self, self, argc, args), &result); 5114 RETURN_ON_FAILED_EXECUTION(Object); 5115 RETURN_ESCAPED(result); 5116 } 5117 5118 5119 Local<v8::Object> Function::NewInstance(int argc, 5120 v8::Local<v8::Value> argv[]) const { 5121 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 5122 RETURN_TO_LOCAL_UNCHECKED(NewInstance(context, argc, argv), Object); 5123 } 5124 5125 5126 MaybeLocal<v8::Value> Function::Call(Local<Context> context, 5127 v8::Local<v8::Value> recv, int argc, 5128 v8::Local<v8::Value> argv[]) { 5129 PREPARE_FOR_EXECUTION_WITH_CONTEXT_IN_RUNTIME_CALL_STATS_SCOPE( 5130 "v8", "V8.Execute", context, Function, Call, MaybeLocal<Value>(), 5131 InternalEscapableScope, true); 5132 i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate); 5133 auto self = Utils::OpenHandle(this); 5134 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 5135 STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**)); 5136 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 5137 Local<Value> result; 5138 has_pending_exception = !ToLocal<Value>( 5139 i::Execution::Call(isolate, self, recv_obj, argc, args), &result); 5140 RETURN_ON_FAILED_EXECUTION(Value); 5141 RETURN_ESCAPED(result); 5142 } 5143 5144 5145 Local<v8::Value> Function::Call(v8::Local<v8::Value> recv, int argc, 5146 v8::Local<v8::Value> argv[]) { 5147 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 5148 RETURN_TO_LOCAL_UNCHECKED(Call(context, recv, argc, argv), Value); 5149 } 5150 5151 5152 void Function::SetName(v8::Local<v8::String> name) { 5153 auto self = Utils::OpenHandle(this); 5154 if (!self->IsJSFunction()) return; 5155 auto func = i::Handle<i::JSFunction>::cast(self); 5156 func->shared()->set_name(*Utils::OpenHandle(*name)); 5157 } 5158 5159 5160 Local<Value> Function::GetName() const { 5161 auto self = Utils::OpenHandle(this); 5162 i::Isolate* isolate = self->GetIsolate(); 5163 if (self->IsJSBoundFunction()) { 5164 auto func = i::Handle<i::JSBoundFunction>::cast(self); 5165 i::Handle<i::Object> name; 5166 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, name, 5167 i::JSBoundFunction::GetName(isolate, func), 5168 Local<Value>()); 5169 return Utils::ToLocal(name); 5170 } 5171 if (self->IsJSFunction()) { 5172 auto func = i::Handle<i::JSFunction>::cast(self); 5173 return Utils::ToLocal(handle(func->shared()->name(), isolate)); 5174 } 5175 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 5176 } 5177 5178 5179 Local<Value> Function::GetInferredName() const { 5180 auto self = Utils::OpenHandle(this); 5181 if (!self->IsJSFunction()) { 5182 return ToApiHandle<Primitive>( 5183 self->GetIsolate()->factory()->undefined_value()); 5184 } 5185 auto func = i::Handle<i::JSFunction>::cast(self); 5186 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(), 5187 func->GetIsolate())); 5188 } 5189 5190 5191 Local<Value> Function::GetDebugName() const { 5192 auto self = Utils::OpenHandle(this); 5193 if (!self->IsJSFunction()) { 5194 return ToApiHandle<Primitive>( 5195 self->GetIsolate()->factory()->undefined_value()); 5196 } 5197 auto func = i::Handle<i::JSFunction>::cast(self); 5198 i::Handle<i::String> name = i::JSFunction::GetDebugName(func); 5199 return Utils::ToLocal(i::Handle<i::Object>(*name, name->GetIsolate())); 5200 } 5201 5202 5203 Local<Value> Function::GetDisplayName() const { 5204 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 5205 ENTER_V8(isolate); 5206 auto self = Utils::OpenHandle(this); 5207 if (!self->IsJSFunction()) { 5208 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 5209 } 5210 auto func = i::Handle<i::JSFunction>::cast(self); 5211 i::Handle<i::String> property_name = 5212 isolate->factory()->NewStringFromStaticChars("displayName"); 5213 i::Handle<i::Object> value = 5214 i::JSReceiver::GetDataProperty(func, property_name); 5215 if (value->IsString()) { 5216 i::Handle<i::String> name = i::Handle<i::String>::cast(value); 5217 if (name->length() > 0) return Utils::ToLocal(name); 5218 } 5219 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 5220 } 5221 5222 5223 ScriptOrigin Function::GetScriptOrigin() const { 5224 auto self = Utils::OpenHandle(this); 5225 if (!self->IsJSFunction()) { 5226 return v8::ScriptOrigin(Local<Value>()); 5227 } 5228 auto func = i::Handle<i::JSFunction>::cast(self); 5229 if (func->shared()->script()->IsScript()) { 5230 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 5231 return GetScriptOriginForScript(func->GetIsolate(), script); 5232 } 5233 return v8::ScriptOrigin(Local<Value>()); 5234 } 5235 5236 5237 const int Function::kLineOffsetNotFound = -1; 5238 5239 5240 int Function::GetScriptLineNumber() const { 5241 auto self = Utils::OpenHandle(this); 5242 if (!self->IsJSFunction()) { 5243 return kLineOffsetNotFound; 5244 } 5245 auto func = i::Handle<i::JSFunction>::cast(self); 5246 if (func->shared()->script()->IsScript()) { 5247 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 5248 return i::Script::GetLineNumber(script, func->shared()->start_position()); 5249 } 5250 return kLineOffsetNotFound; 5251 } 5252 5253 5254 int Function::GetScriptColumnNumber() const { 5255 auto self = Utils::OpenHandle(this); 5256 if (!self->IsJSFunction()) { 5257 return kLineOffsetNotFound; 5258 } 5259 auto func = i::Handle<i::JSFunction>::cast(self); 5260 if (func->shared()->script()->IsScript()) { 5261 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 5262 return i::Script::GetColumnNumber(script, func->shared()->start_position()); 5263 } 5264 return kLineOffsetNotFound; 5265 } 5266 5267 5268 bool Function::IsBuiltin() const { 5269 auto self = Utils::OpenHandle(this); 5270 if (!self->IsJSFunction()) { 5271 return false; 5272 } 5273 auto func = i::Handle<i::JSFunction>::cast(self); 5274 return !func->shared()->IsUserJavaScript(); 5275 } 5276 5277 5278 int Function::ScriptId() const { 5279 auto self = Utils::OpenHandle(this); 5280 if (!self->IsJSFunction()) { 5281 return v8::UnboundScript::kNoScriptId; 5282 } 5283 auto func = i::Handle<i::JSFunction>::cast(self); 5284 if (!func->shared()->script()->IsScript()) { 5285 return v8::UnboundScript::kNoScriptId; 5286 } 5287 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 5288 return script->id(); 5289 } 5290 5291 5292 Local<v8::Value> Function::GetBoundFunction() const { 5293 auto self = Utils::OpenHandle(this); 5294 if (self->IsJSBoundFunction()) { 5295 auto bound_function = i::Handle<i::JSBoundFunction>::cast(self); 5296 auto bound_target_function = i::handle( 5297 bound_function->bound_target_function(), bound_function->GetIsolate()); 5298 return Utils::CallableToLocal(bound_target_function); 5299 } 5300 return v8::Undefined(reinterpret_cast<v8::Isolate*>(self->GetIsolate())); 5301 } 5302 5303 5304 int Name::GetIdentityHash() { 5305 auto self = Utils::OpenHandle(this); 5306 return static_cast<int>(self->Hash()); 5307 } 5308 5309 5310 int String::Length() const { 5311 i::Handle<i::String> str = Utils::OpenHandle(this); 5312 return str->length(); 5313 } 5314 5315 5316 bool String::IsOneByte() const { 5317 i::Handle<i::String> str = Utils::OpenHandle(this); 5318 return str->HasOnlyOneByteChars(); 5319 } 5320 5321 5322 // Helpers for ContainsOnlyOneByteHelper 5323 template<size_t size> struct OneByteMask; 5324 template<> struct OneByteMask<4> { 5325 static const uint32_t value = 0xFF00FF00; 5326 }; 5327 template<> struct OneByteMask<8> { 5328 static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00); 5329 }; 5330 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value; 5331 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1; 5332 static inline bool Unaligned(const uint16_t* chars) { 5333 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask; 5334 } 5335 5336 5337 static inline const uint16_t* Align(const uint16_t* chars) { 5338 return reinterpret_cast<uint16_t*>( 5339 reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask); 5340 } 5341 5342 class ContainsOnlyOneByteHelper { 5343 public: 5344 ContainsOnlyOneByteHelper() : is_one_byte_(true) {} 5345 bool Check(i::String* string) { 5346 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0); 5347 if (cons_string == NULL) return is_one_byte_; 5348 return CheckCons(cons_string); 5349 } 5350 void VisitOneByteString(const uint8_t* chars, int length) { 5351 // Nothing to do. 5352 } 5353 void VisitTwoByteString(const uint16_t* chars, int length) { 5354 // Accumulated bits. 5355 uintptr_t acc = 0; 5356 // Align to uintptr_t. 5357 const uint16_t* end = chars + length; 5358 while (Unaligned(chars) && chars != end) { 5359 acc |= *chars++; 5360 } 5361 // Read word aligned in blocks, 5362 // checking the return value at the end of each block. 5363 const uint16_t* aligned_end = Align(end); 5364 const int increment = sizeof(uintptr_t)/sizeof(uint16_t); 5365 const int inner_loops = 16; 5366 while (chars + inner_loops*increment < aligned_end) { 5367 for (int i = 0; i < inner_loops; i++) { 5368 acc |= *reinterpret_cast<const uintptr_t*>(chars); 5369 chars += increment; 5370 } 5371 // Check for early return. 5372 if ((acc & kOneByteMask) != 0) { 5373 is_one_byte_ = false; 5374 return; 5375 } 5376 } 5377 // Read the rest. 5378 while (chars != end) { 5379 acc |= *chars++; 5380 } 5381 // Check result. 5382 if ((acc & kOneByteMask) != 0) is_one_byte_ = false; 5383 } 5384 5385 private: 5386 bool CheckCons(i::ConsString* cons_string) { 5387 while (true) { 5388 // Check left side if flat. 5389 i::String* left = cons_string->first(); 5390 i::ConsString* left_as_cons = 5391 i::String::VisitFlat(this, left, 0); 5392 if (!is_one_byte_) return false; 5393 // Check right side if flat. 5394 i::String* right = cons_string->second(); 5395 i::ConsString* right_as_cons = 5396 i::String::VisitFlat(this, right, 0); 5397 if (!is_one_byte_) return false; 5398 // Standard recurse/iterate trick. 5399 if (left_as_cons != NULL && right_as_cons != NULL) { 5400 if (left->length() < right->length()) { 5401 CheckCons(left_as_cons); 5402 cons_string = right_as_cons; 5403 } else { 5404 CheckCons(right_as_cons); 5405 cons_string = left_as_cons; 5406 } 5407 // Check fast return. 5408 if (!is_one_byte_) return false; 5409 continue; 5410 } 5411 // Descend left in place. 5412 if (left_as_cons != NULL) { 5413 cons_string = left_as_cons; 5414 continue; 5415 } 5416 // Descend right in place. 5417 if (right_as_cons != NULL) { 5418 cons_string = right_as_cons; 5419 continue; 5420 } 5421 // Terminate. 5422 break; 5423 } 5424 return is_one_byte_; 5425 } 5426 bool is_one_byte_; 5427 DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper); 5428 }; 5429 5430 5431 bool String::ContainsOnlyOneByte() const { 5432 i::Handle<i::String> str = Utils::OpenHandle(this); 5433 if (str->HasOnlyOneByteChars()) return true; 5434 ContainsOnlyOneByteHelper helper; 5435 return helper.Check(*str); 5436 } 5437 5438 5439 class Utf8LengthHelper : public i::AllStatic { 5440 public: 5441 enum State { 5442 kEndsWithLeadingSurrogate = 1 << 0, 5443 kStartsWithTrailingSurrogate = 1 << 1, 5444 kLeftmostEdgeIsCalculated = 1 << 2, 5445 kRightmostEdgeIsCalculated = 1 << 3, 5446 kLeftmostEdgeIsSurrogate = 1 << 4, 5447 kRightmostEdgeIsSurrogate = 1 << 5 5448 }; 5449 5450 static const uint8_t kInitialState = 0; 5451 5452 static inline bool EndsWithSurrogate(uint8_t state) { 5453 return state & kEndsWithLeadingSurrogate; 5454 } 5455 5456 static inline bool StartsWithSurrogate(uint8_t state) { 5457 return state & kStartsWithTrailingSurrogate; 5458 } 5459 5460 class Visitor { 5461 public: 5462 Visitor() : utf8_length_(0), state_(kInitialState) {} 5463 5464 void VisitOneByteString(const uint8_t* chars, int length) { 5465 int utf8_length = 0; 5466 // Add in length 1 for each non-Latin1 character. 5467 for (int i = 0; i < length; i++) { 5468 utf8_length += *chars++ >> 7; 5469 } 5470 // Add in length 1 for each character. 5471 utf8_length_ = utf8_length + length; 5472 state_ = kInitialState; 5473 } 5474 5475 void VisitTwoByteString(const uint16_t* chars, int length) { 5476 int utf8_length = 0; 5477 int last_character = unibrow::Utf16::kNoPreviousCharacter; 5478 for (int i = 0; i < length; i++) { 5479 uint16_t c = chars[i]; 5480 utf8_length += unibrow::Utf8::Length(c, last_character); 5481 last_character = c; 5482 } 5483 utf8_length_ = utf8_length; 5484 uint8_t state = 0; 5485 if (unibrow::Utf16::IsTrailSurrogate(chars[0])) { 5486 state |= kStartsWithTrailingSurrogate; 5487 } 5488 if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) { 5489 state |= kEndsWithLeadingSurrogate; 5490 } 5491 state_ = state; 5492 } 5493 5494 static i::ConsString* VisitFlat(i::String* string, 5495 int* length, 5496 uint8_t* state) { 5497 Visitor visitor; 5498 i::ConsString* cons_string = i::String::VisitFlat(&visitor, string); 5499 *length = visitor.utf8_length_; 5500 *state = visitor.state_; 5501 return cons_string; 5502 } 5503 5504 private: 5505 int utf8_length_; 5506 uint8_t state_; 5507 DISALLOW_COPY_AND_ASSIGN(Visitor); 5508 }; 5509 5510 static inline void MergeLeafLeft(int* length, 5511 uint8_t* state, 5512 uint8_t leaf_state) { 5513 bool edge_surrogate = StartsWithSurrogate(leaf_state); 5514 if (!(*state & kLeftmostEdgeIsCalculated)) { 5515 DCHECK(!(*state & kLeftmostEdgeIsSurrogate)); 5516 *state |= kLeftmostEdgeIsCalculated 5517 | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0); 5518 } else if (EndsWithSurrogate(*state) && edge_surrogate) { 5519 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 5520 } 5521 if (EndsWithSurrogate(leaf_state)) { 5522 *state |= kEndsWithLeadingSurrogate; 5523 } else { 5524 *state &= ~kEndsWithLeadingSurrogate; 5525 } 5526 } 5527 5528 static inline void MergeLeafRight(int* length, 5529 uint8_t* state, 5530 uint8_t leaf_state) { 5531 bool edge_surrogate = EndsWithSurrogate(leaf_state); 5532 if (!(*state & kRightmostEdgeIsCalculated)) { 5533 DCHECK(!(*state & kRightmostEdgeIsSurrogate)); 5534 *state |= (kRightmostEdgeIsCalculated 5535 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0)); 5536 } else if (edge_surrogate && StartsWithSurrogate(*state)) { 5537 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 5538 } 5539 if (StartsWithSurrogate(leaf_state)) { 5540 *state |= kStartsWithTrailingSurrogate; 5541 } else { 5542 *state &= ~kStartsWithTrailingSurrogate; 5543 } 5544 } 5545 5546 static inline void MergeTerminal(int* length, 5547 uint8_t state, 5548 uint8_t* state_out) { 5549 DCHECK((state & kLeftmostEdgeIsCalculated) && 5550 (state & kRightmostEdgeIsCalculated)); 5551 if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) { 5552 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 5553 } 5554 *state_out = kInitialState | 5555 (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) | 5556 (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0); 5557 } 5558 5559 static int Calculate(i::ConsString* current, uint8_t* state_out) { 5560 using internal::ConsString; 5561 int total_length = 0; 5562 uint8_t state = kInitialState; 5563 while (true) { 5564 i::String* left = current->first(); 5565 i::String* right = current->second(); 5566 uint8_t right_leaf_state; 5567 uint8_t left_leaf_state; 5568 int leaf_length; 5569 ConsString* left_as_cons = 5570 Visitor::VisitFlat(left, &leaf_length, &left_leaf_state); 5571 if (left_as_cons == NULL) { 5572 total_length += leaf_length; 5573 MergeLeafLeft(&total_length, &state, left_leaf_state); 5574 } 5575 ConsString* right_as_cons = 5576 Visitor::VisitFlat(right, &leaf_length, &right_leaf_state); 5577 if (right_as_cons == NULL) { 5578 total_length += leaf_length; 5579 MergeLeafRight(&total_length, &state, right_leaf_state); 5580 if (left_as_cons != NULL) { 5581 // 1 Leaf node. Descend in place. 5582 current = left_as_cons; 5583 continue; 5584 } else { 5585 // Terminal node. 5586 MergeTerminal(&total_length, state, state_out); 5587 return total_length; 5588 } 5589 } else if (left_as_cons == NULL) { 5590 // 1 Leaf node. Descend in place. 5591 current = right_as_cons; 5592 continue; 5593 } 5594 // Both strings are ConsStrings. 5595 // Recurse on smallest. 5596 if (left->length() < right->length()) { 5597 total_length += Calculate(left_as_cons, &left_leaf_state); 5598 MergeLeafLeft(&total_length, &state, left_leaf_state); 5599 current = right_as_cons; 5600 } else { 5601 total_length += Calculate(right_as_cons, &right_leaf_state); 5602 MergeLeafRight(&total_length, &state, right_leaf_state); 5603 current = left_as_cons; 5604 } 5605 } 5606 UNREACHABLE(); 5607 return 0; 5608 } 5609 5610 static inline int Calculate(i::ConsString* current) { 5611 uint8_t state = kInitialState; 5612 return Calculate(current, &state); 5613 } 5614 5615 private: 5616 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper); 5617 }; 5618 5619 5620 static int Utf8Length(i::String* str, i::Isolate* isolate) { 5621 int length = str->length(); 5622 if (length == 0) return 0; 5623 uint8_t state; 5624 i::ConsString* cons_string = 5625 Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state); 5626 if (cons_string == NULL) return length; 5627 return Utf8LengthHelper::Calculate(cons_string); 5628 } 5629 5630 5631 int String::Utf8Length() const { 5632 i::Handle<i::String> str = Utils::OpenHandle(this); 5633 i::Isolate* isolate = str->GetIsolate(); 5634 return v8::Utf8Length(*str, isolate); 5635 } 5636 5637 5638 class Utf8WriterVisitor { 5639 public: 5640 Utf8WriterVisitor( 5641 char* buffer, 5642 int capacity, 5643 bool skip_capacity_check, 5644 bool replace_invalid_utf8) 5645 : early_termination_(false), 5646 last_character_(unibrow::Utf16::kNoPreviousCharacter), 5647 buffer_(buffer), 5648 start_(buffer), 5649 capacity_(capacity), 5650 skip_capacity_check_(capacity == -1 || skip_capacity_check), 5651 replace_invalid_utf8_(replace_invalid_utf8), 5652 utf16_chars_read_(0) { 5653 } 5654 5655 static int WriteEndCharacter(uint16_t character, 5656 int last_character, 5657 int remaining, 5658 char* const buffer, 5659 bool replace_invalid_utf8) { 5660 DCHECK_GT(remaining, 0); 5661 // We can't use a local buffer here because Encode needs to modify 5662 // previous characters in the stream. We know, however, that 5663 // exactly one character will be advanced. 5664 if (unibrow::Utf16::IsSurrogatePair(last_character, character)) { 5665 int written = unibrow::Utf8::Encode(buffer, character, last_character, 5666 replace_invalid_utf8); 5667 DCHECK_EQ(written, 1); 5668 return written; 5669 } 5670 // Use a scratch buffer to check the required characters. 5671 char temp_buffer[unibrow::Utf8::kMaxEncodedSize]; 5672 // Can't encode using last_character as gcc has array bounds issues. 5673 int written = unibrow::Utf8::Encode(temp_buffer, character, 5674 unibrow::Utf16::kNoPreviousCharacter, 5675 replace_invalid_utf8); 5676 // Won't fit. 5677 if (written > remaining) return 0; 5678 // Copy over the character from temp_buffer. 5679 for (int j = 0; j < written; j++) { 5680 buffer[j] = temp_buffer[j]; 5681 } 5682 return written; 5683 } 5684 5685 // Visit writes out a group of code units (chars) of a v8::String to the 5686 // internal buffer_. This is done in two phases. The first phase calculates a 5687 // pesimistic estimate (writable_length) on how many code units can be safely 5688 // written without exceeding the buffer capacity and without writing the last 5689 // code unit (it could be a lead surrogate). The estimated number of code 5690 // units is then written out in one go, and the reported byte usage is used 5691 // to correct the estimate. This is repeated until the estimate becomes <= 0 5692 // or all code units have been written out. The second phase writes out code 5693 // units until the buffer capacity is reached, would be exceeded by the next 5694 // unit, or all units have been written out. 5695 template<typename Char> 5696 void Visit(const Char* chars, const int length) { 5697 DCHECK(!early_termination_); 5698 if (length == 0) return; 5699 // Copy state to stack. 5700 char* buffer = buffer_; 5701 int last_character = sizeof(Char) == 1 5702 ? unibrow::Utf16::kNoPreviousCharacter 5703 : last_character_; 5704 int i = 0; 5705 // Do a fast loop where there is no exit capacity check. 5706 while (true) { 5707 int fast_length; 5708 if (skip_capacity_check_) { 5709 fast_length = length; 5710 } else { 5711 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 5712 // Need enough space to write everything but one character. 5713 STATIC_ASSERT(unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 5714 3); 5715 int max_size_per_char = sizeof(Char) == 1 ? 2 : 3; 5716 int writable_length = 5717 (remaining_capacity - max_size_per_char)/max_size_per_char; 5718 // Need to drop into slow loop. 5719 if (writable_length <= 0) break; 5720 fast_length = i + writable_length; 5721 if (fast_length > length) fast_length = length; 5722 } 5723 // Write the characters to the stream. 5724 if (sizeof(Char) == 1) { 5725 for (; i < fast_length; i++) { 5726 buffer += unibrow::Utf8::EncodeOneByte( 5727 buffer, static_cast<uint8_t>(*chars++)); 5728 DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_); 5729 } 5730 } else { 5731 for (; i < fast_length; i++) { 5732 uint16_t character = *chars++; 5733 buffer += unibrow::Utf8::Encode(buffer, character, last_character, 5734 replace_invalid_utf8_); 5735 last_character = character; 5736 DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_); 5737 } 5738 } 5739 // Array is fully written. Exit. 5740 if (fast_length == length) { 5741 // Write state back out to object. 5742 last_character_ = last_character; 5743 buffer_ = buffer; 5744 utf16_chars_read_ += length; 5745 return; 5746 } 5747 } 5748 DCHECK(!skip_capacity_check_); 5749 // Slow loop. Must check capacity on each iteration. 5750 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 5751 DCHECK_GE(remaining_capacity, 0); 5752 for (; i < length && remaining_capacity > 0; i++) { 5753 uint16_t character = *chars++; 5754 // remaining_capacity is <= 3 bytes at this point, so we do not write out 5755 // an umatched lead surrogate. 5756 if (replace_invalid_utf8_ && unibrow::Utf16::IsLeadSurrogate(character)) { 5757 early_termination_ = true; 5758 break; 5759 } 5760 int written = WriteEndCharacter(character, 5761 last_character, 5762 remaining_capacity, 5763 buffer, 5764 replace_invalid_utf8_); 5765 if (written == 0) { 5766 early_termination_ = true; 5767 break; 5768 } 5769 buffer += written; 5770 remaining_capacity -= written; 5771 last_character = character; 5772 } 5773 // Write state back out to object. 5774 last_character_ = last_character; 5775 buffer_ = buffer; 5776 utf16_chars_read_ += i; 5777 } 5778 5779 inline bool IsDone() { 5780 return early_termination_; 5781 } 5782 5783 inline void VisitOneByteString(const uint8_t* chars, int length) { 5784 Visit(chars, length); 5785 } 5786 5787 inline void VisitTwoByteString(const uint16_t* chars, int length) { 5788 Visit(chars, length); 5789 } 5790 5791 int CompleteWrite(bool write_null, int* utf16_chars_read_out) { 5792 // Write out number of utf16 characters written to the stream. 5793 if (utf16_chars_read_out != NULL) { 5794 *utf16_chars_read_out = utf16_chars_read_; 5795 } 5796 // Only null terminate if all of the string was written and there's space. 5797 if (write_null && 5798 !early_termination_ && 5799 (capacity_ == -1 || (buffer_ - start_) < capacity_)) { 5800 *buffer_++ = '\0'; 5801 } 5802 return static_cast<int>(buffer_ - start_); 5803 } 5804 5805 private: 5806 bool early_termination_; 5807 int last_character_; 5808 char* buffer_; 5809 char* const start_; 5810 int capacity_; 5811 bool const skip_capacity_check_; 5812 bool const replace_invalid_utf8_; 5813 int utf16_chars_read_; 5814 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor); 5815 }; 5816 5817 5818 static bool RecursivelySerializeToUtf8(i::String* current, 5819 Utf8WriterVisitor* writer, 5820 int recursion_budget) { 5821 while (!writer->IsDone()) { 5822 i::ConsString* cons_string = i::String::VisitFlat(writer, current); 5823 if (cons_string == NULL) return true; // Leaf node. 5824 if (recursion_budget <= 0) return false; 5825 // Must write the left branch first. 5826 i::String* first = cons_string->first(); 5827 bool success = RecursivelySerializeToUtf8(first, 5828 writer, 5829 recursion_budget - 1); 5830 if (!success) return false; 5831 // Inline tail recurse for right branch. 5832 current = cons_string->second(); 5833 } 5834 return true; 5835 } 5836 5837 5838 int String::WriteUtf8(char* buffer, 5839 int capacity, 5840 int* nchars_ref, 5841 int options) const { 5842 i::Handle<i::String> str = Utils::OpenHandle(this); 5843 i::Isolate* isolate = str->GetIsolate(); 5844 LOG_API(isolate, String, WriteUtf8); 5845 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 5846 if (options & HINT_MANY_WRITES_EXPECTED) { 5847 str = i::String::Flatten(str); // Flatten the string for efficiency. 5848 } 5849 const int string_length = str->length(); 5850 bool write_null = !(options & NO_NULL_TERMINATION); 5851 bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8); 5852 int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize; 5853 // First check if we can just write the string without checking capacity. 5854 if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) { 5855 Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8); 5856 const int kMaxRecursion = 100; 5857 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion); 5858 if (success) return writer.CompleteWrite(write_null, nchars_ref); 5859 } else if (capacity >= string_length) { 5860 // First check that the buffer is large enough. 5861 int utf8_bytes = v8::Utf8Length(*str, isolate); 5862 if (utf8_bytes <= capacity) { 5863 // one-byte fast path. 5864 if (utf8_bytes == string_length) { 5865 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options); 5866 if (nchars_ref != NULL) *nchars_ref = string_length; 5867 if (write_null && (utf8_bytes+1 <= capacity)) { 5868 return string_length + 1; 5869 } 5870 return string_length; 5871 } 5872 if (write_null && (utf8_bytes+1 > capacity)) { 5873 options |= NO_NULL_TERMINATION; 5874 } 5875 // Recurse once without a capacity limit. 5876 // This will get into the first branch above. 5877 // TODO(dcarney) Check max left rec. in Utf8Length and fall through. 5878 return WriteUtf8(buffer, -1, nchars_ref, options); 5879 } 5880 } 5881 // Recursive slow path can potentially be unreasonable slow. Flatten. 5882 str = i::String::Flatten(str); 5883 Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8); 5884 i::String::VisitFlat(&writer, *str); 5885 return writer.CompleteWrite(write_null, nchars_ref); 5886 } 5887 5888 5889 template<typename CharType> 5890 static inline int WriteHelper(const String* string, 5891 CharType* buffer, 5892 int start, 5893 int length, 5894 int options) { 5895 i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate(); 5896 LOG_API(isolate, String, Write); 5897 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 5898 DCHECK(start >= 0 && length >= -1); 5899 i::Handle<i::String> str = Utils::OpenHandle(string); 5900 if (options & String::HINT_MANY_WRITES_EXPECTED) { 5901 // Flatten the string for efficiency. This applies whether we are 5902 // using StringCharacterStream or Get(i) to access the characters. 5903 str = i::String::Flatten(str); 5904 } 5905 int end = start + length; 5906 if ((length == -1) || (length > str->length() - start) ) 5907 end = str->length(); 5908 if (end < 0) return 0; 5909 i::String::WriteToFlat(*str, buffer, start, end); 5910 if (!(options & String::NO_NULL_TERMINATION) && 5911 (length == -1 || end - start < length)) { 5912 buffer[end - start] = '\0'; 5913 } 5914 return end - start; 5915 } 5916 5917 5918 int String::WriteOneByte(uint8_t* buffer, 5919 int start, 5920 int length, 5921 int options) const { 5922 return WriteHelper(this, buffer, start, length, options); 5923 } 5924 5925 5926 int String::Write(uint16_t* buffer, 5927 int start, 5928 int length, 5929 int options) const { 5930 return WriteHelper(this, buffer, start, length, options); 5931 } 5932 5933 5934 bool v8::String::IsExternal() const { 5935 i::Handle<i::String> str = Utils::OpenHandle(this); 5936 return i::StringShape(*str).IsExternalTwoByte(); 5937 } 5938 5939 5940 bool v8::String::IsExternalOneByte() const { 5941 i::Handle<i::String> str = Utils::OpenHandle(this); 5942 return i::StringShape(*str).IsExternalOneByte(); 5943 } 5944 5945 5946 void v8::String::VerifyExternalStringResource( 5947 v8::String::ExternalStringResource* value) const { 5948 i::Handle<i::String> str = Utils::OpenHandle(this); 5949 const v8::String::ExternalStringResource* expected; 5950 if (i::StringShape(*str).IsExternalTwoByte()) { 5951 const void* resource = 5952 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); 5953 expected = reinterpret_cast<const ExternalStringResource*>(resource); 5954 } else { 5955 expected = NULL; 5956 } 5957 CHECK_EQ(expected, value); 5958 } 5959 5960 void v8::String::VerifyExternalStringResourceBase( 5961 v8::String::ExternalStringResourceBase* value, Encoding encoding) const { 5962 i::Handle<i::String> str = Utils::OpenHandle(this); 5963 const v8::String::ExternalStringResourceBase* expected; 5964 Encoding expectedEncoding; 5965 if (i::StringShape(*str).IsExternalOneByte()) { 5966 const void* resource = 5967 i::Handle<i::ExternalOneByteString>::cast(str)->resource(); 5968 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); 5969 expectedEncoding = ONE_BYTE_ENCODING; 5970 } else if (i::StringShape(*str).IsExternalTwoByte()) { 5971 const void* resource = 5972 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); 5973 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); 5974 expectedEncoding = TWO_BYTE_ENCODING; 5975 } else { 5976 expected = NULL; 5977 expectedEncoding = 5978 str->IsOneByteRepresentation() ? ONE_BYTE_ENCODING : TWO_BYTE_ENCODING; 5979 } 5980 CHECK_EQ(expected, value); 5981 CHECK_EQ(expectedEncoding, encoding); 5982 } 5983 5984 const v8::String::ExternalOneByteStringResource* 5985 v8::String::GetExternalOneByteStringResource() const { 5986 i::Handle<i::String> str = Utils::OpenHandle(this); 5987 if (i::StringShape(*str).IsExternalOneByte()) { 5988 const void* resource = 5989 i::Handle<i::ExternalOneByteString>::cast(str)->resource(); 5990 return reinterpret_cast<const ExternalOneByteStringResource*>(resource); 5991 } else { 5992 return NULL; 5993 } 5994 } 5995 5996 5997 Local<Value> Symbol::Name() const { 5998 i::Handle<i::Symbol> sym = Utils::OpenHandle(this); 5999 i::Handle<i::Object> name(sym->name(), sym->GetIsolate()); 6000 return Utils::ToLocal(name); 6001 } 6002 6003 6004 Local<Value> Private::Name() const { 6005 return reinterpret_cast<const Symbol*>(this)->Name(); 6006 } 6007 6008 6009 double Number::Value() const { 6010 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6011 return obj->Number(); 6012 } 6013 6014 6015 bool Boolean::Value() const { 6016 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6017 return obj->IsTrue(i::HeapObject::cast(*obj)->GetIsolate()); 6018 } 6019 6020 6021 int64_t Integer::Value() const { 6022 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6023 if (obj->IsSmi()) { 6024 return i::Smi::cast(*obj)->value(); 6025 } else { 6026 return static_cast<int64_t>(obj->Number()); 6027 } 6028 } 6029 6030 6031 int32_t Int32::Value() const { 6032 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6033 if (obj->IsSmi()) { 6034 return i::Smi::cast(*obj)->value(); 6035 } else { 6036 return static_cast<int32_t>(obj->Number()); 6037 } 6038 } 6039 6040 6041 uint32_t Uint32::Value() const { 6042 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6043 if (obj->IsSmi()) { 6044 return i::Smi::cast(*obj)->value(); 6045 } else { 6046 return static_cast<uint32_t>(obj->Number()); 6047 } 6048 } 6049 6050 6051 int v8::Object::InternalFieldCount() { 6052 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 6053 if (!self->IsJSObject()) return 0; 6054 return i::Handle<i::JSObject>::cast(self)->GetInternalFieldCount(); 6055 } 6056 6057 6058 static bool InternalFieldOK(i::Handle<i::JSReceiver> obj, int index, 6059 const char* location) { 6060 return Utils::ApiCheck( 6061 obj->IsJSObject() && 6062 (index < i::Handle<i::JSObject>::cast(obj)->GetInternalFieldCount()), 6063 location, "Internal field out of bounds"); 6064 } 6065 6066 6067 Local<Value> v8::Object::SlowGetInternalField(int index) { 6068 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 6069 const char* location = "v8::Object::GetInternalField()"; 6070 if (!InternalFieldOK(obj, index, location)) return Local<Value>(); 6071 i::Handle<i::Object> value( 6072 i::Handle<i::JSObject>::cast(obj)->GetInternalField(index), 6073 obj->GetIsolate()); 6074 return Utils::ToLocal(value); 6075 } 6076 6077 6078 void v8::Object::SetInternalField(int index, v8::Local<Value> value) { 6079 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 6080 const char* location = "v8::Object::SetInternalField()"; 6081 if (!InternalFieldOK(obj, index, location)) return; 6082 i::Handle<i::Object> val = Utils::OpenHandle(*value); 6083 i::Handle<i::JSObject>::cast(obj)->SetInternalField(index, *val); 6084 } 6085 6086 6087 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) { 6088 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 6089 const char* location = "v8::Object::GetAlignedPointerFromInternalField()"; 6090 if (!InternalFieldOK(obj, index, location)) return NULL; 6091 return DecodeSmiToAligned( 6092 i::Handle<i::JSObject>::cast(obj)->GetInternalField(index), location); 6093 } 6094 6095 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) { 6096 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 6097 const char* location = "v8::Object::SetAlignedPointerInInternalField()"; 6098 if (!InternalFieldOK(obj, index, location)) return; 6099 i::Handle<i::JSObject>::cast(obj) 6100 ->SetInternalField(index, EncodeAlignedAsSmi(value, location)); 6101 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index)); 6102 } 6103 6104 void v8::Object::SetAlignedPointerInInternalFields(int argc, int indices[], 6105 void* values[]) { 6106 i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this); 6107 const char* location = "v8::Object::SetAlignedPointerInInternalFields()"; 6108 i::DisallowHeapAllocation no_gc; 6109 i::JSObject* object = i::JSObject::cast(*obj); 6110 int nof_internal_fields = object->GetInternalFieldCount(); 6111 for (int i = 0; i < argc; i++) { 6112 int index = indices[i]; 6113 if (!Utils::ApiCheck(index < nof_internal_fields, location, 6114 "Internal field out of bounds")) { 6115 return; 6116 } 6117 void* value = values[i]; 6118 object->SetInternalField(index, EncodeAlignedAsSmi(value, location)); 6119 DCHECK_EQ(value, GetAlignedPointerFromInternalField(index)); 6120 } 6121 } 6122 6123 static void* ExternalValue(i::Object* obj) { 6124 // Obscure semantics for undefined, but somehow checked in our unit tests... 6125 if (!obj->IsSmi() && 6126 obj->IsUndefined(i::HeapObject::cast(obj)->GetIsolate())) { 6127 return NULL; 6128 } 6129 i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0); 6130 return i::Foreign::cast(foreign)->foreign_address(); 6131 } 6132 6133 6134 // --- E n v i r o n m e n t --- 6135 6136 6137 void v8::V8::InitializePlatform(Platform* platform) { 6138 i::V8::InitializePlatform(platform); 6139 } 6140 6141 6142 void v8::V8::ShutdownPlatform() { 6143 i::V8::ShutdownPlatform(); 6144 } 6145 6146 6147 bool v8::V8::Initialize() { 6148 i::V8::Initialize(); 6149 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 6150 i::ReadNatives(); 6151 #endif 6152 return true; 6153 } 6154 6155 6156 void v8::V8::SetEntropySource(EntropySource entropy_source) { 6157 base::RandomNumberGenerator::SetEntropySource(entropy_source); 6158 } 6159 6160 6161 void v8::V8::SetReturnAddressLocationResolver( 6162 ReturnAddressLocationResolver return_address_resolver) { 6163 i::StackFrame::SetReturnAddressLocationResolver(return_address_resolver); 6164 } 6165 6166 6167 bool v8::V8::Dispose() { 6168 i::V8::TearDown(); 6169 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 6170 i::DisposeNatives(); 6171 #endif 6172 return true; 6173 } 6174 6175 HeapStatistics::HeapStatistics() 6176 : total_heap_size_(0), 6177 total_heap_size_executable_(0), 6178 total_physical_size_(0), 6179 total_available_size_(0), 6180 used_heap_size_(0), 6181 heap_size_limit_(0), 6182 malloced_memory_(0), 6183 peak_malloced_memory_(0), 6184 does_zap_garbage_(0) {} 6185 6186 HeapSpaceStatistics::HeapSpaceStatistics(): space_name_(0), 6187 space_size_(0), 6188 space_used_size_(0), 6189 space_available_size_(0), 6190 physical_space_size_(0) { } 6191 6192 6193 HeapObjectStatistics::HeapObjectStatistics() 6194 : object_type_(nullptr), 6195 object_sub_type_(nullptr), 6196 object_count_(0), 6197 object_size_(0) {} 6198 6199 HeapCodeStatistics::HeapCodeStatistics() 6200 : code_and_metadata_size_(0), bytecode_and_metadata_size_(0) {} 6201 6202 bool v8::V8::InitializeICU(const char* icu_data_file) { 6203 return i::InitializeICU(icu_data_file); 6204 } 6205 6206 bool v8::V8::InitializeICUDefaultLocation(const char* exec_path, 6207 const char* icu_data_file) { 6208 return i::InitializeICUDefaultLocation(exec_path, icu_data_file); 6209 } 6210 6211 void v8::V8::InitializeExternalStartupData(const char* directory_path) { 6212 i::InitializeExternalStartupData(directory_path); 6213 } 6214 6215 6216 void v8::V8::InitializeExternalStartupData(const char* natives_blob, 6217 const char* snapshot_blob) { 6218 i::InitializeExternalStartupData(natives_blob, snapshot_blob); 6219 } 6220 6221 6222 const char* v8::V8::GetVersion() { 6223 return i::Version::GetVersion(); 6224 } 6225 6226 template <typename ObjectType> 6227 struct InvokeBootstrapper; 6228 6229 template <> 6230 struct InvokeBootstrapper<i::Context> { 6231 i::Handle<i::Context> Invoke( 6232 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy, 6233 v8::Local<v8::ObjectTemplate> global_object_template, 6234 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index, 6235 v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { 6236 return isolate->bootstrapper()->CreateEnvironment( 6237 maybe_global_proxy, global_object_template, extensions, 6238 context_snapshot_index, internal_fields_deserializer); 6239 } 6240 }; 6241 6242 template <> 6243 struct InvokeBootstrapper<i::JSGlobalProxy> { 6244 i::Handle<i::JSGlobalProxy> Invoke( 6245 i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy, 6246 v8::Local<v8::ObjectTemplate> global_object_template, 6247 v8::ExtensionConfiguration* extensions, size_t context_snapshot_index, 6248 v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { 6249 USE(extensions); 6250 USE(context_snapshot_index); 6251 return isolate->bootstrapper()->NewRemoteContext(maybe_global_proxy, 6252 global_object_template); 6253 } 6254 }; 6255 6256 template <typename ObjectType> 6257 static i::Handle<ObjectType> CreateEnvironment( 6258 i::Isolate* isolate, v8::ExtensionConfiguration* extensions, 6259 v8::MaybeLocal<ObjectTemplate> maybe_global_template, 6260 v8::MaybeLocal<Value> maybe_global_proxy, size_t context_snapshot_index, 6261 v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { 6262 i::Handle<ObjectType> result; 6263 6264 { 6265 ENTER_V8_FOR_NEW_CONTEXT(isolate); 6266 v8::Local<ObjectTemplate> proxy_template; 6267 i::Handle<i::FunctionTemplateInfo> proxy_constructor; 6268 i::Handle<i::FunctionTemplateInfo> global_constructor; 6269 i::Handle<i::Object> named_interceptor( 6270 isolate->factory()->undefined_value()); 6271 i::Handle<i::Object> indexed_interceptor( 6272 isolate->factory()->undefined_value()); 6273 6274 if (!maybe_global_template.IsEmpty()) { 6275 v8::Local<v8::ObjectTemplate> global_template = 6276 maybe_global_template.ToLocalChecked(); 6277 // Make sure that the global_template has a constructor. 6278 global_constructor = EnsureConstructor(isolate, *global_template); 6279 6280 // Create a fresh template for the global proxy object. 6281 proxy_template = ObjectTemplate::New( 6282 reinterpret_cast<v8::Isolate*>(isolate)); 6283 proxy_constructor = EnsureConstructor(isolate, *proxy_template); 6284 6285 // Set the global template to be the prototype template of 6286 // global proxy template. 6287 proxy_constructor->set_prototype_template( 6288 *Utils::OpenHandle(*global_template)); 6289 6290 proxy_template->SetInternalFieldCount( 6291 global_template->InternalFieldCount()); 6292 6293 // Migrate security handlers from global_template to 6294 // proxy_template. Temporarily removing access check 6295 // information from the global template. 6296 if (!global_constructor->access_check_info()->IsUndefined(isolate)) { 6297 proxy_constructor->set_access_check_info( 6298 global_constructor->access_check_info()); 6299 proxy_constructor->set_needs_access_check( 6300 global_constructor->needs_access_check()); 6301 global_constructor->set_needs_access_check(false); 6302 global_constructor->set_access_check_info( 6303 isolate->heap()->undefined_value()); 6304 } 6305 6306 // Same for other interceptors. If the global constructor has 6307 // interceptors, we need to replace them temporarily with noop 6308 // interceptors, so the map is correctly marked as having interceptors, 6309 // but we don't invoke any. 6310 if (!global_constructor->named_property_handler()->IsUndefined(isolate)) { 6311 named_interceptor = 6312 handle(global_constructor->named_property_handler(), isolate); 6313 global_constructor->set_named_property_handler( 6314 isolate->heap()->noop_interceptor_info()); 6315 } 6316 if (!global_constructor->indexed_property_handler()->IsUndefined( 6317 isolate)) { 6318 indexed_interceptor = 6319 handle(global_constructor->indexed_property_handler(), isolate); 6320 global_constructor->set_indexed_property_handler( 6321 isolate->heap()->noop_interceptor_info()); 6322 } 6323 } 6324 6325 i::MaybeHandle<i::JSGlobalProxy> maybe_proxy; 6326 if (!maybe_global_proxy.IsEmpty()) { 6327 maybe_proxy = i::Handle<i::JSGlobalProxy>::cast( 6328 Utils::OpenHandle(*maybe_global_proxy.ToLocalChecked())); 6329 } 6330 // Create the environment. 6331 InvokeBootstrapper<ObjectType> invoke; 6332 result = 6333 invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions, 6334 context_snapshot_index, internal_fields_deserializer); 6335 6336 // Restore the access check info and interceptors on the global template. 6337 if (!maybe_global_template.IsEmpty()) { 6338 DCHECK(!global_constructor.is_null()); 6339 DCHECK(!proxy_constructor.is_null()); 6340 global_constructor->set_access_check_info( 6341 proxy_constructor->access_check_info()); 6342 global_constructor->set_needs_access_check( 6343 proxy_constructor->needs_access_check()); 6344 global_constructor->set_named_property_handler(*named_interceptor); 6345 global_constructor->set_indexed_property_handler(*indexed_interceptor); 6346 } 6347 } 6348 // Leave V8. 6349 6350 return result; 6351 } 6352 6353 Local<Context> NewContext( 6354 v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions, 6355 v8::MaybeLocal<ObjectTemplate> global_template, 6356 v8::MaybeLocal<Value> global_object, size_t context_snapshot_index, 6357 v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { 6358 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 6359 TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.NewContext"); 6360 LOG_API(isolate, Context, New); 6361 i::HandleScope scope(isolate); 6362 ExtensionConfiguration no_extensions; 6363 if (extensions == NULL) extensions = &no_extensions; 6364 i::Handle<i::Context> env = CreateEnvironment<i::Context>( 6365 isolate, extensions, global_template, global_object, 6366 context_snapshot_index, internal_fields_deserializer); 6367 if (env.is_null()) { 6368 if (isolate->has_pending_exception()) { 6369 isolate->OptionalRescheduleException(true); 6370 } 6371 return Local<Context>(); 6372 } 6373 return Utils::ToLocal(scope.CloseAndEscape(env)); 6374 } 6375 6376 Local<Context> v8::Context::New(v8::Isolate* external_isolate, 6377 v8::ExtensionConfiguration* extensions, 6378 v8::MaybeLocal<ObjectTemplate> global_template, 6379 v8::MaybeLocal<Value> global_object) { 6380 return NewContext(external_isolate, extensions, global_template, 6381 global_object, 0, DeserializeInternalFieldsCallback()); 6382 } 6383 6384 MaybeLocal<Context> v8::Context::FromSnapshot( 6385 v8::Isolate* external_isolate, size_t context_snapshot_index, 6386 v8::DeserializeInternalFieldsCallback internal_fields_deserializer, 6387 v8::ExtensionConfiguration* extensions, MaybeLocal<Value> global_object) { 6388 size_t index_including_default_context = context_snapshot_index + 1; 6389 if (!i::Snapshot::HasContextSnapshot( 6390 reinterpret_cast<i::Isolate*>(external_isolate), 6391 index_including_default_context)) { 6392 return MaybeLocal<Context>(); 6393 } 6394 return NewContext(external_isolate, extensions, MaybeLocal<ObjectTemplate>(), 6395 global_object, index_including_default_context, 6396 internal_fields_deserializer); 6397 } 6398 6399 MaybeLocal<Object> v8::Context::NewRemoteContext( 6400 v8::Isolate* external_isolate, v8::Local<ObjectTemplate> global_template, 6401 v8::MaybeLocal<v8::Value> global_object) { 6402 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 6403 LOG_API(isolate, Context, NewRemoteContext); 6404 i::HandleScope scope(isolate); 6405 i::Handle<i::FunctionTemplateInfo> global_constructor = 6406 EnsureConstructor(isolate, *global_template); 6407 Utils::ApiCheck(global_constructor->needs_access_check(), 6408 "v8::Context::NewRemoteContext", 6409 "Global template needs to have access checks enabled."); 6410 i::Handle<i::AccessCheckInfo> access_check_info = i::handle( 6411 i::AccessCheckInfo::cast(global_constructor->access_check_info()), 6412 isolate); 6413 Utils::ApiCheck(access_check_info->named_interceptor() != nullptr, 6414 "v8::Context::NewRemoteContext", 6415 "Global template needs to have access check handlers."); 6416 i::Handle<i::JSGlobalProxy> global_proxy = 6417 CreateEnvironment<i::JSGlobalProxy>(isolate, nullptr, global_template, 6418 global_object, 0, 6419 DeserializeInternalFieldsCallback()); 6420 if (global_proxy.is_null()) { 6421 if (isolate->has_pending_exception()) { 6422 isolate->OptionalRescheduleException(true); 6423 } 6424 return MaybeLocal<Object>(); 6425 } 6426 return Utils::ToLocal( 6427 scope.CloseAndEscape(i::Handle<i::JSObject>::cast(global_proxy))); 6428 } 6429 6430 void v8::Context::SetSecurityToken(Local<Value> token) { 6431 i::Handle<i::Context> env = Utils::OpenHandle(this); 6432 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token); 6433 env->set_security_token(*token_handle); 6434 } 6435 6436 6437 void v8::Context::UseDefaultSecurityToken() { 6438 i::Handle<i::Context> env = Utils::OpenHandle(this); 6439 env->set_security_token(env->global_object()); 6440 } 6441 6442 6443 Local<Value> v8::Context::GetSecurityToken() { 6444 i::Handle<i::Context> env = Utils::OpenHandle(this); 6445 i::Isolate* isolate = env->GetIsolate(); 6446 i::Object* security_token = env->security_token(); 6447 i::Handle<i::Object> token_handle(security_token, isolate); 6448 return Utils::ToLocal(token_handle); 6449 } 6450 6451 6452 v8::Isolate* Context::GetIsolate() { 6453 i::Handle<i::Context> env = Utils::OpenHandle(this); 6454 return reinterpret_cast<Isolate*>(env->GetIsolate()); 6455 } 6456 6457 v8::Local<v8::Object> Context::Global() { 6458 i::Handle<i::Context> context = Utils::OpenHandle(this); 6459 i::Isolate* isolate = context->GetIsolate(); 6460 i::Handle<i::Object> global(context->global_proxy(), isolate); 6461 // TODO(dcarney): This should always return the global proxy 6462 // but can't presently as calls to GetProtoype will return the wrong result. 6463 if (i::Handle<i::JSGlobalProxy>::cast( 6464 global)->IsDetachedFrom(context->global_object())) { 6465 global = i::Handle<i::Object>(context->global_object(), isolate); 6466 } 6467 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global)); 6468 } 6469 6470 6471 void Context::DetachGlobal() { 6472 i::Handle<i::Context> context = Utils::OpenHandle(this); 6473 i::Isolate* isolate = context->GetIsolate(); 6474 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 6475 isolate->bootstrapper()->DetachGlobal(context); 6476 } 6477 6478 6479 Local<v8::Object> Context::GetExtrasBindingObject() { 6480 i::Handle<i::Context> context = Utils::OpenHandle(this); 6481 i::Isolate* isolate = context->GetIsolate(); 6482 i::Handle<i::JSObject> binding(context->extras_binding_object(), isolate); 6483 return Utils::ToLocal(binding); 6484 } 6485 6486 6487 void Context::AllowCodeGenerationFromStrings(bool allow) { 6488 i::Handle<i::Context> context = Utils::OpenHandle(this); 6489 i::Isolate* isolate = context->GetIsolate(); 6490 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 6491 context->set_allow_code_gen_from_strings( 6492 allow ? isolate->heap()->true_value() : isolate->heap()->false_value()); 6493 } 6494 6495 6496 bool Context::IsCodeGenerationFromStringsAllowed() { 6497 i::Handle<i::Context> context = Utils::OpenHandle(this); 6498 return !context->allow_code_gen_from_strings()->IsFalse( 6499 context->GetIsolate()); 6500 } 6501 6502 6503 void Context::SetErrorMessageForCodeGenerationFromStrings(Local<String> error) { 6504 i::Handle<i::Context> context = Utils::OpenHandle(this); 6505 i::Handle<i::String> error_handle = Utils::OpenHandle(*error); 6506 context->set_error_message_for_code_gen_from_strings(*error_handle); 6507 } 6508 6509 6510 size_t Context::EstimatedSize() { 6511 return static_cast<size_t>( 6512 i::ContextMeasure(*Utils::OpenHandle(this)).Size()); 6513 } 6514 6515 6516 MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) { 6517 PREPARE_FOR_EXECUTION(context, ObjectTemplate, NewInstance, Object); 6518 auto self = Utils::OpenHandle(this); 6519 Local<Object> result; 6520 has_pending_exception = 6521 !ToLocal<Object>(i::ApiNatives::InstantiateObject(self), &result); 6522 RETURN_ON_FAILED_EXECUTION(Object); 6523 RETURN_ESCAPED(result); 6524 } 6525 6526 6527 Local<v8::Object> ObjectTemplate::NewInstance() { 6528 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 6529 RETURN_TO_LOCAL_UNCHECKED(NewInstance(context), Object); 6530 } 6531 6532 6533 MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) { 6534 PREPARE_FOR_EXECUTION(context, FunctionTemplate, GetFunction, Function); 6535 auto self = Utils::OpenHandle(this); 6536 Local<Function> result; 6537 has_pending_exception = 6538 !ToLocal<Function>(i::ApiNatives::InstantiateFunction(self), &result); 6539 RETURN_ON_FAILED_EXECUTION(Function); 6540 RETURN_ESCAPED(result); 6541 } 6542 6543 6544 Local<v8::Function> FunctionTemplate::GetFunction() { 6545 auto context = ContextFromHeapObject(Utils::OpenHandle(this)); 6546 RETURN_TO_LOCAL_UNCHECKED(GetFunction(context), Function); 6547 } 6548 6549 MaybeLocal<v8::Object> FunctionTemplate::NewRemoteInstance() { 6550 auto self = Utils::OpenHandle(this); 6551 i::Isolate* isolate = self->GetIsolate(); 6552 LOG_API(isolate, FunctionTemplate, NewRemoteInstance); 6553 i::HandleScope scope(isolate); 6554 i::Handle<i::FunctionTemplateInfo> constructor = 6555 EnsureConstructor(isolate, *InstanceTemplate()); 6556 Utils::ApiCheck(constructor->needs_access_check(), 6557 "v8::FunctionTemplate::NewRemoteInstance", 6558 "InstanceTemplate needs to have access checks enabled."); 6559 i::Handle<i::AccessCheckInfo> access_check_info = i::handle( 6560 i::AccessCheckInfo::cast(constructor->access_check_info()), isolate); 6561 Utils::ApiCheck(access_check_info->named_interceptor() != nullptr, 6562 "v8::FunctionTemplate::NewRemoteInstance", 6563 "InstanceTemplate needs to have access check handlers."); 6564 i::Handle<i::JSObject> object; 6565 if (!i::ApiNatives::InstantiateRemoteObject( 6566 Utils::OpenHandle(*InstanceTemplate())) 6567 .ToHandle(&object)) { 6568 if (isolate->has_pending_exception()) { 6569 isolate->OptionalRescheduleException(true); 6570 } 6571 return MaybeLocal<Object>(); 6572 } 6573 return Utils::ToLocal(scope.CloseAndEscape(object)); 6574 } 6575 6576 bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) { 6577 auto self = Utils::OpenHandle(this); 6578 auto obj = Utils::OpenHandle(*value); 6579 if (obj->IsJSObject() && self->IsTemplateFor(i::JSObject::cast(*obj))) { 6580 return true; 6581 } 6582 if (obj->IsJSGlobalProxy()) { 6583 // If it's a global proxy, then test with the global object. Note that the 6584 // inner global object may not necessarily be a JSGlobalObject. 6585 i::PrototypeIterator iter(i::JSObject::cast(*obj)->map()); 6586 // The global proxy should always have a prototype, as it is a bug to call 6587 // this on a detached JSGlobalProxy. 6588 DCHECK(!iter.IsAtEnd()); 6589 return self->IsTemplateFor(iter.GetCurrent<i::JSObject>()); 6590 } 6591 return false; 6592 } 6593 6594 6595 Local<External> v8::External::New(Isolate* isolate, void* value) { 6596 STATIC_ASSERT(sizeof(value) == sizeof(i::Address)); 6597 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6598 LOG_API(i_isolate, External, New); 6599 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6600 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value); 6601 return Utils::ExternalToLocal(external); 6602 } 6603 6604 6605 void* External::Value() const { 6606 return ExternalValue(*Utils::OpenHandle(this)); 6607 } 6608 6609 6610 // anonymous namespace for string creation helper functions 6611 namespace { 6612 6613 inline int StringLength(const char* string) { 6614 return i::StrLength(string); 6615 } 6616 6617 6618 inline int StringLength(const uint8_t* string) { 6619 return i::StrLength(reinterpret_cast<const char*>(string)); 6620 } 6621 6622 6623 inline int StringLength(const uint16_t* string) { 6624 int length = 0; 6625 while (string[length] != '\0') 6626 length++; 6627 return length; 6628 } 6629 6630 6631 MUST_USE_RESULT 6632 inline i::MaybeHandle<i::String> NewString(i::Factory* factory, 6633 v8::NewStringType type, 6634 i::Vector<const char> string) { 6635 if (type == v8::NewStringType::kInternalized) { 6636 return factory->InternalizeUtf8String(string); 6637 } 6638 return factory->NewStringFromUtf8(string); 6639 } 6640 6641 6642 MUST_USE_RESULT 6643 inline i::MaybeHandle<i::String> NewString(i::Factory* factory, 6644 v8::NewStringType type, 6645 i::Vector<const uint8_t> string) { 6646 if (type == v8::NewStringType::kInternalized) { 6647 return factory->InternalizeOneByteString(string); 6648 } 6649 return factory->NewStringFromOneByte(string); 6650 } 6651 6652 6653 MUST_USE_RESULT 6654 inline i::MaybeHandle<i::String> NewString(i::Factory* factory, 6655 v8::NewStringType type, 6656 i::Vector<const uint16_t> string) { 6657 if (type == v8::NewStringType::kInternalized) { 6658 return factory->InternalizeTwoByteString(string); 6659 } 6660 return factory->NewStringFromTwoByte(string); 6661 } 6662 6663 6664 STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength); 6665 6666 } // anonymous namespace 6667 6668 // TODO(dcarney): throw a context free exception. 6669 #define NEW_STRING(isolate, class_name, function_name, Char, data, type, \ 6670 length) \ 6671 MaybeLocal<String> result; \ 6672 if (length == 0) { \ 6673 result = String::Empty(isolate); \ 6674 } else if (length > i::String::kMaxLength) { \ 6675 result = MaybeLocal<String>(); \ 6676 } else { \ 6677 i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate); \ 6678 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); \ 6679 LOG_API(i_isolate, class_name, function_name); \ 6680 if (length < 0) length = StringLength(data); \ 6681 i::Handle<i::String> handle_result = \ 6682 NewString(i_isolate->factory(), type, \ 6683 i::Vector<const Char>(data, length)) \ 6684 .ToHandleChecked(); \ 6685 result = Utils::ToLocal(handle_result); \ 6686 } 6687 6688 Local<String> String::NewFromUtf8(Isolate* isolate, 6689 const char* data, 6690 NewStringType type, 6691 int length) { 6692 NEW_STRING(isolate, String, NewFromUtf8, char, data, 6693 static_cast<v8::NewStringType>(type), length); 6694 RETURN_TO_LOCAL_UNCHECKED(result, String); 6695 } 6696 6697 6698 MaybeLocal<String> String::NewFromUtf8(Isolate* isolate, const char* data, 6699 v8::NewStringType type, int length) { 6700 NEW_STRING(isolate, String, NewFromUtf8, char, data, type, length); 6701 return result; 6702 } 6703 6704 6705 Local<String> String::NewFromOneByte(Isolate* isolate, 6706 const uint8_t* data, 6707 NewStringType type, 6708 int length) { 6709 NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data, 6710 static_cast<v8::NewStringType>(type), length); 6711 RETURN_TO_LOCAL_UNCHECKED(result, String); 6712 } 6713 6714 6715 MaybeLocal<String> String::NewFromOneByte(Isolate* isolate, const uint8_t* data, 6716 v8::NewStringType type, int length) { 6717 NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data, type, length); 6718 return result; 6719 } 6720 6721 6722 Local<String> String::NewFromTwoByte(Isolate* isolate, 6723 const uint16_t* data, 6724 NewStringType type, 6725 int length) { 6726 NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data, 6727 static_cast<v8::NewStringType>(type), length); 6728 RETURN_TO_LOCAL_UNCHECKED(result, String); 6729 } 6730 6731 6732 MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate, 6733 const uint16_t* data, 6734 v8::NewStringType type, int length) { 6735 NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data, type, length); 6736 return result; 6737 } 6738 6739 6740 Local<String> v8::String::Concat(Local<String> left, Local<String> right) { 6741 i::Handle<i::String> left_string = Utils::OpenHandle(*left); 6742 i::Isolate* isolate = left_string->GetIsolate(); 6743 ENTER_V8(isolate); 6744 LOG_API(isolate, String, Concat); 6745 i::Handle<i::String> right_string = Utils::OpenHandle(*right); 6746 // If we are steering towards a range error, do not wait for the error to be 6747 // thrown, and return the null handle instead. 6748 if (left_string->length() + right_string->length() > i::String::kMaxLength) { 6749 return Local<String>(); 6750 } 6751 i::Handle<i::String> result = isolate->factory()->NewConsString( 6752 left_string, right_string).ToHandleChecked(); 6753 return Utils::ToLocal(result); 6754 } 6755 6756 6757 MaybeLocal<String> v8::String::NewExternalTwoByte( 6758 Isolate* isolate, v8::String::ExternalStringResource* resource) { 6759 CHECK(resource && resource->data()); 6760 // TODO(dcarney): throw a context free exception. 6761 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) { 6762 return MaybeLocal<String>(); 6763 } 6764 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6765 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6766 LOG_API(i_isolate, String, NewExternalTwoByte); 6767 if (resource->length() > 0) { 6768 i::Handle<i::String> string = i_isolate->factory() 6769 ->NewExternalStringFromTwoByte(resource) 6770 .ToHandleChecked(); 6771 i_isolate->heap()->RegisterExternalString(*string); 6772 return Utils::ToLocal(string); 6773 } else { 6774 // The resource isn't going to be used, free it immediately. 6775 resource->Dispose(); 6776 return Utils::ToLocal(i_isolate->factory()->empty_string()); 6777 } 6778 } 6779 6780 6781 Local<String> v8::String::NewExternal( 6782 Isolate* isolate, v8::String::ExternalStringResource* resource) { 6783 RETURN_TO_LOCAL_UNCHECKED(NewExternalTwoByte(isolate, resource), String); 6784 } 6785 6786 6787 MaybeLocal<String> v8::String::NewExternalOneByte( 6788 Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) { 6789 CHECK(resource && resource->data()); 6790 // TODO(dcarney): throw a context free exception. 6791 if (resource->length() > static_cast<size_t>(i::String::kMaxLength)) { 6792 return MaybeLocal<String>(); 6793 } 6794 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6795 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6796 LOG_API(i_isolate, String, NewExternalOneByte); 6797 if (resource->length() > 0) { 6798 i::Handle<i::String> string = i_isolate->factory() 6799 ->NewExternalStringFromOneByte(resource) 6800 .ToHandleChecked(); 6801 i_isolate->heap()->RegisterExternalString(*string); 6802 return Utils::ToLocal(string); 6803 } else { 6804 // The resource isn't going to be used, free it immediately. 6805 resource->Dispose(); 6806 return Utils::ToLocal(i_isolate->factory()->empty_string()); 6807 } 6808 } 6809 6810 6811 Local<String> v8::String::NewExternal( 6812 Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) { 6813 RETURN_TO_LOCAL_UNCHECKED(NewExternalOneByte(isolate, resource), String); 6814 } 6815 6816 6817 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { 6818 i::Handle<i::String> obj = Utils::OpenHandle(this); 6819 i::Isolate* isolate = obj->GetIsolate(); 6820 if (i::StringShape(*obj).IsExternal()) { 6821 return false; // Already an external string. 6822 } 6823 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 6824 if (isolate->heap()->IsInGCPostProcessing()) { 6825 return false; 6826 } 6827 CHECK(resource && resource->data()); 6828 6829 bool result = obj->MakeExternal(resource); 6830 // Assert that if CanMakeExternal(), then externalizing actually succeeds. 6831 DCHECK(!CanMakeExternal() || result); 6832 if (result) { 6833 DCHECK(obj->IsExternalString()); 6834 isolate->heap()->RegisterExternalString(*obj); 6835 } 6836 return result; 6837 } 6838 6839 6840 bool v8::String::MakeExternal( 6841 v8::String::ExternalOneByteStringResource* resource) { 6842 i::Handle<i::String> obj = Utils::OpenHandle(this); 6843 i::Isolate* isolate = obj->GetIsolate(); 6844 if (i::StringShape(*obj).IsExternal()) { 6845 return false; // Already an external string. 6846 } 6847 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); 6848 if (isolate->heap()->IsInGCPostProcessing()) { 6849 return false; 6850 } 6851 CHECK(resource && resource->data()); 6852 6853 bool result = obj->MakeExternal(resource); 6854 // Assert that if CanMakeExternal(), then externalizing actually succeeds. 6855 DCHECK(!CanMakeExternal() || result); 6856 if (result) { 6857 DCHECK(obj->IsExternalString()); 6858 isolate->heap()->RegisterExternalString(*obj); 6859 } 6860 return result; 6861 } 6862 6863 6864 bool v8::String::CanMakeExternal() { 6865 i::Handle<i::String> obj = Utils::OpenHandle(this); 6866 if (obj->IsExternalString()) return false; 6867 6868 // Old space strings should be externalized. 6869 i::Isolate* isolate = obj->GetIsolate(); 6870 return !isolate->heap()->new_space()->Contains(*obj); 6871 } 6872 6873 6874 Isolate* v8::Object::GetIsolate() { 6875 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 6876 return reinterpret_cast<Isolate*>(i_isolate); 6877 } 6878 6879 6880 Local<v8::Object> v8::Object::New(Isolate* isolate) { 6881 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6882 LOG_API(i_isolate, Object, New); 6883 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6884 i::Handle<i::JSObject> obj = 6885 i_isolate->factory()->NewJSObject(i_isolate->object_function()); 6886 return Utils::ToLocal(obj); 6887 } 6888 6889 6890 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) { 6891 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6892 LOG_API(i_isolate, NumberObject, New); 6893 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6894 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value); 6895 i::Handle<i::Object> obj = 6896 i::Object::ToObject(i_isolate, number).ToHandleChecked(); 6897 return Utils::ToLocal(obj); 6898 } 6899 6900 6901 double v8::NumberObject::ValueOf() const { 6902 i::Handle<i::Object> obj = Utils::OpenHandle(this); 6903 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 6904 i::Isolate* isolate = jsvalue->GetIsolate(); 6905 LOG_API(isolate, NumberObject, NumberValue); 6906 return jsvalue->value()->Number(); 6907 } 6908 6909 6910 Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) { 6911 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6912 LOG_API(i_isolate, BooleanObject, New); 6913 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); 6914 i::Handle<i::Object> boolean(value ? i_isolate->heap()->true_value() 6915 : i_isolate->heap()->false_value(), 6916 i_isolate); 6917 i::Handle<i::Object> obj = 6918 i::Object::ToObject(i_isolate, boolean).ToHandleChecked();