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
ContextFromHeapObject(i::Handle<i::Object> obj)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:
InternalEscapableScope(i::Isolate * isolate)208 explicit inline InternalEscapableScope(i::Isolate* isolate)
209 : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {}
210 };
211
212
213 #ifdef DEBUG
CheckMicrotasksScopesConsistency(i::Isolate * isolate)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:
CallDepthScope(i::Isolate * isolate,Local<Context> context)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 }
~CallDepthScope()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
Escape()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
GetScriptOriginForScript(i::Isolate * isolate,i::Handle<i::Script> script)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
FatalProcessOutOfMemory(const char * location)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.
FatalProcessOutOfMemory(const char * location,bool is_heap_oom)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
ReportApiFailure(const char * location,const char * message)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
ReportOOMFailure(const char * location,bool is_heap_oom)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
IsExecutionTerminatingCheck(i::Isolate * isolate)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
SetNativesDataBlob(StartupData * natives_blob)433 void V8::SetNativesDataBlob(StartupData* natives_blob) {
434 i::V8::SetNativesBlob(natives_blob);
435 }
436
437
SetSnapshotDataBlob(StartupData * snapshot_blob)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:
Allocate(size_t length)446 virtual void* Allocate(size_t length) {
447 void* data = AllocateUninitialized(length);
448 return data == NULL ? data : memset(data, 0, length);
449 }
AllocateUninitialized(size_t length)450 virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
Free(void * data,size_t)451 virtual void Free(void* data, size_t) { free(data); }
452 };
453
RunExtraCode(Isolate * isolate,Local<Context> context,const char * utf8_source,const char * name)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 {
SnapshotCreatorDatav8::__anon50f97c120211::SnapshotCreatorData483 explicit SnapshotCreatorData(Isolate* isolate)
484 : isolate_(isolate),
485 default_context_(),
486 contexts_(isolate),
487 templates_(isolate),
488 created_(false) {}
489
castv8::__anon50f97c120211::SnapshotCreatorData490 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
SnapshotCreator(intptr_t * external_references,StartupData * existing_snapshot)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
~SnapshotCreator()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
GetIsolate()532 Isolate* SnapshotCreator::GetIsolate() {
533 return SnapshotCreatorData::cast(data_)->isolate_;
534 }
535
SetDefaultContext(Local<Context> context)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
AddContext(Local<Context> context,SerializeInternalFieldsCallback callback)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
AddTemplate(Local<Template> template_obj)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
CreateBlob(SnapshotCreator::FunctionCodeHandling function_code_handling)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
CreateSnapshotDataBlob(const char * embedded_source)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
WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob,const char * warmup_source)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
SetFlagsFromString(const char * str,int length)743 void V8::SetFlagsFromString(const char* str, int length) {
744 i::FlagList::SetFlagsFromString(str, length);
745 i::FlagList::EnforceFlagImplications();
746 }
747
748
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)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
RegisteredExtension(Extension * extension)757 RegisteredExtension::RegisteredExtension(Extension* extension)
758 : extension_(extension) { }
759
760
Register(RegisteredExtension * that)761 void RegisteredExtension::Register(RegisteredExtension* that) {
762 that->next_ = first_extension_;
763 first_extension_ = that;
764 }
765
766
UnregisterAll()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
RegisterExtension(Extension * that)778 void RegisterExtension(Extension* that) {
779 RegisteredExtension* extension = new RegisteredExtension(that);
780 RegisteredExtension::Register(extension);
781 }
782
783
Extension(const char * name,const char * source,int dep_count,const char ** deps,int source_length)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
ResourceConstraints()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
ConfigureDefaults(uint64_t physical_memory,uint64_t virtual_memory_limit)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
SetResourceConstraints(i::Isolate * isolate,const ResourceConstraints & constraints)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
GlobalizeReference(i::Isolate * isolate,i::Object ** obj)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
CopyPersistent(i::Object ** obj)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
RegisterExternallyReferencedObject(i::Object ** object,i::Isolate * isolate)900 void V8::RegisterExternallyReferencedObject(i::Object** object,
901 i::Isolate* isolate) {
902 isolate->heap()->RegisterExternallyReferencedObject(object);
903 }
904
MakeWeak(i::Object ** location,void * parameter,int internal_field_index1,int internal_field_index2,WeakCallbackInfo<void>::Callback weak_callback)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
MakeWeak(i::Object ** location,void * parameter,WeakCallbackInfo<void>::Callback weak_callback,WeakCallbackType type)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
MakeWeak(i::Object *** location_addr)929 void V8::MakeWeak(i::Object*** location_addr) {
930 i::GlobalHandles::MakeWeak(location_addr);
931 }
932
ClearWeak(i::Object ** location)933 void* V8::ClearWeak(i::Object** location) {
934 return i::GlobalHandles::ClearWeakness(location);
935 }
936
DisposeGlobal(i::Object ** location)937 void V8::DisposeGlobal(i::Object** location) {
938 i::GlobalHandles::Destroy(location);
939 }
940
941
Eternalize(Isolate * v8_isolate,Value * value,int * index)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
GetEternal(Isolate * v8_isolate,int index)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
FromJustIsNothing()955 void V8::FromJustIsNothing() {
956 Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing.");
957 }
958
959
ToLocalEmpty()960 void V8::ToLocalEmpty() {
961 Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal.");
962 }
963
964
InternalFieldOutOfBounds(int index)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
HandleScope(Isolate * isolate)975 HandleScope::HandleScope(Isolate* isolate) {
976 Initialize(isolate);
977 }
978
979
Initialize(Isolate * isolate)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
~HandleScope()1001 HandleScope::~HandleScope() {
1002 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
1003 }
1004
operator new(size_t)1005 V8_NORETURN void* HandleScope::operator new(size_t) {
1006 base::OS::Abort();
1007 abort();
1008 }
1009
operator delete(void *,size_t)1010 void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1011
NumberOfHandles(Isolate * isolate)1012 int HandleScope::NumberOfHandles(Isolate* isolate) {
1013 return i::HandleScope::NumberOfHandles(
1014 reinterpret_cast<i::Isolate*>(isolate));
1015 }
1016
1017
CreateHandle(i::Isolate * isolate,i::Object * value)1018 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
1019 return i::HandleScope::CreateHandle(isolate, value);
1020 }
1021
1022
CreateHandle(i::HeapObject * heap_object,i::Object * value)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
EscapableHandleScope(Isolate * v8_isolate)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
Escape(i::Object ** escape_value)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
operator new(size_t)1049 V8_NORETURN void* EscapableHandleScope::operator new(size_t) {
1050 base::OS::Abort();
1051 abort();
1052 }
1053
operator delete(void *,size_t)1054 void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1055
SealHandleScope(Isolate * isolate)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
~SealHandleScope()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
operator new(size_t)1074 V8_NORETURN void* SealHandleScope::operator new(size_t) {
1075 base::OS::Abort();
1076 abort();
1077 }
1078
operator delete(void *,size_t)1079 void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1080
Enter()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
Exit()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
DecodeSmiToAligned(i::Object * value,const char * location)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
EncodeAlignedAsSmi(void * value,const char * location)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
EmbedderDataFor(Context * context,int index,bool can_grow,const char * location)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
SlowGetEmbedderData(int index)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
SetEmbedderData(int index,v8::Local<Value> value)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
SlowGetAlignedPointerFromEmbedderData(int index)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
SetAlignedPointerInEmbedderData(int index,void * value)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
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)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
Set(v8::Local<Name> name,v8::Local<Data> value,v8::PropertyAttribute attribute)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
SetPrivate(v8::Local<Private> name,v8::Local<Data> value,v8::PropertyAttribute attribute)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
SetAccessorProperty(v8::Local<v8::Name> name,v8::Local<FunctionTemplate> getter,v8::Local<FunctionTemplate> setter,v8::PropertyAttribute attribute,v8::AccessControl access_control)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 ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)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
PrototypeTemplate()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
SetPrototypeProviderTemplate(Local<FunctionTemplate> prototype_provider)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
EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info,const char * func)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
Inherit(v8::Local<FunctionTemplate> value)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
FunctionTemplateNew(i::Isolate * isolate,FunctionCallback callback,experimental::FastAccessorBuilder * fast_handler,v8::Local<Value> data,v8::Local<Signature> signature,int length,bool do_not_cache,v8::Local<Private> cached_property_name=v8::Local<Private> ())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
New(Isolate * isolate,FunctionCallback callback,v8::Local<Value> data,v8::Local<Signature> signature,int length,ConstructorBehavior behavior)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
FromSnapshot(Isolate * isolate,size_t index)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
NewWithFastHandler(Isolate * isolate,FunctionCallback callback,experimental::FastAccessorBuilder * fast_handler,v8::Local<Value> data,v8::Local<Signature> signature,int length)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
NewWithCache(Isolate * isolate,FunctionCallback callback,Local<Private> cache_property,Local<Value> data,Local<Signature> signature,int length)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
New(Isolate * isolate,Local<FunctionTemplate> receiver)1373 Local<Signature> Signature::New(Isolate* isolate,
1374 Local<FunctionTemplate> receiver) {
1375 return Utils::SignatureToLocal(Utils::OpenHandle(*receiver));
1376 }
1377
1378
New(Isolate * isolate,Local<FunctionTemplate> receiver)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
SetCallHandler(FunctionCallback callback,v8::Local<Value> data,experimental::FastAccessorBuilder * fast_handler)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
SetAccessorInfoProperties(i::Handle<i::AccessorInfo> obj,v8::Local<Name> name,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Local<AccessorSignature> signature)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>
MakeAccessorInfo(v8::Local<Name> name,Getter getter,Setter setter,v8::Local<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes,v8::Local<AccessorSignature> signature,bool is_special_data_property,bool replace_on_access)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
InstanceTemplate()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
SetLength(int length)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
SetClassName(Local<String> name)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
SetAcceptAnyReceiver(bool value)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
SetHiddenPrototype(bool value)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
ReadOnlyPrototype()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
RemovePrototype()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
New(Isolate * isolate,v8::Local<FunctionTemplate> constructor)1538 Local<ObjectTemplate> ObjectTemplate::New(
1539 Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1540 return New(reinterpret_cast<i::Isolate*>(isolate), constructor);
1541 }
1542
1543
New()1544 Local<ObjectTemplate> ObjectTemplate::New() {
1545 return New(i::Isolate::Current(), Local<FunctionTemplate>());
1546 }
1547
ObjectTemplateNew(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor,bool do_not_cache)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
New(i::Isolate * isolate,v8::Local<FunctionTemplate> constructor)1569 Local<ObjectTemplate> ObjectTemplate::New(
1570 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1571 return ObjectTemplateNew(isolate, constructor, false);
1572 }
1573
FromSnapshot(Isolate * isolate,size_t index)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.
EnsureConstructor(i::Isolate * isolate,ObjectTemplate * object_template)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>
TemplateSetAccessor(Template * template_obj,v8::Local<Name> name,Getter getter,Setter setter,Data data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,bool is_special_data_property,bool replace_on_access)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
SetNativeDataProperty(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings)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
SetNativeDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,PropertyAttribute attribute,v8::Local<AccessorSignature> signature,AccessControl settings)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
SetLazyDataProperty(v8::Local<Name> name,AccessorNameGetterCallback getter,v8::Local<Value> data,PropertyAttribute attribute)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
SetIntrinsicDataProperty(Local<Name> name,Intrinsic intrinsic,PropertyAttribute attribute)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
SetAccessor(v8::Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature)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
SetAccessor(v8::Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attribute,v8::Local<AccessorSignature> signature)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>
CreateInterceptorInfo(i::Isolate * isolate,Getter getter,Setter setter,Query query,Descriptor descriptor,Deleter remover,Enumerator enumerator,Definer definer,Local<Value> data,PropertyHandlerFlags flags)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>
ObjectTemplateSetNamedPropertyHandler(ObjectTemplate * templ,Getter getter,Setter setter,Query query,Descriptor descriptor,Deleter remover,Enumerator enumerator,Definer definer,Local<Value> data,PropertyHandlerFlags flags)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
SetNamedPropertyHandler(NamedPropertyGetterCallback getter,NamedPropertySetterCallback setter,NamedPropertyQueryCallback query,NamedPropertyDeleterCallback remover,NamedPropertyEnumeratorCallback enumerator,Local<Value> data)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
SetHandler(const NamedPropertyHandlerConfiguration & config)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
MarkAsUndetectable()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
SetAccessCheckCallback(AccessCheckCallback callback,Local<Value> data)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
SetAccessCheckCallbackAndHandler(AccessCheckCallback callback,const NamedPropertyHandlerConfiguration & named_handler,const IndexedPropertyHandlerConfiguration & indexed_handler,Local<Value> data)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
SetHandler(const IndexedPropertyHandlerConfiguration & config)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
SetCallAsFunctionHandler(FunctionCallback callback,Local<Value> data)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
InternalFieldCount()1874 int ObjectTemplate::InternalFieldCount() {
1875 return Utils::OpenHandle(this)->internal_field_count();
1876 }
1877
1878
SetInternalFieldCount(int value)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
IsImmutableProto()1896 bool ObjectTemplate::IsImmutableProto() {
1897 return Utils::OpenHandle(this)->immutable_proto();
1898 }
1899
SetImmutableProto()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
CachedData(const uint8_t * data_,int length_,BufferPolicy buffer_policy_)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
~CachedData()1920 ScriptCompiler::CachedData::~CachedData() {
1921 if (buffer_policy == BufferOwned) {
1922 delete[] data;
1923 }
1924 }
1925
1926
SetBookmark()1927 bool ScriptCompiler::ExternalSourceStream::SetBookmark() { return false; }
1928
1929
ResetToBookmark()1930 void ScriptCompiler::ExternalSourceStream::ResetToBookmark() { UNREACHABLE(); }
1931
1932
StreamedSource(ExternalSourceStream * stream,Encoding encoding)1933 ScriptCompiler::StreamedSource::StreamedSource(ExternalSourceStream* stream,
1934 Encoding encoding)
1935 : impl_(new i::StreamedSource(stream, encoding)) {}
1936
1937
~StreamedSource()1938 ScriptCompiler::StreamedSource::~StreamedSource() { delete impl_; }
1939
1940
1941 const ScriptCompiler::CachedData*
GetCachedData() const1942 ScriptCompiler::StreamedSource::GetCachedData() const {
1943 return impl_->cached_data.get();
1944 }
1945
1946
BindToCurrentContext()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
GetId()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
GetLineNumber(int code_pos)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
GetScriptName()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
GetSourceURL()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
GetSourceMappingURL()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
Run(Local<Context> context)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
Run()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
GetUnboundScript()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
GetModuleRequestsLength() const2064 int Module::GetModuleRequestsLength() const {
2065 i::Handle<i::Module> self = Utils::OpenHandle(this);
2066 return self->info()->module_requests()->length();
2067 }
2068
GetModuleRequest(int i) const2069 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
GetIdentityHash() const2079 int Module::GetIdentityHash() const { return Utils::OpenHandle(this)->hash(); }
2080
Instantiate(Local<Context> context,Module::ResolveCallback callback)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
Evaluate(Local<Context> context)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
CompileUnboundInternal(Isolate * v8_isolate,Source * source,CompileOptions options)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
CompileUnboundScript(Isolate * v8_isolate,Source * source,CompileOptions options)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
CompileUnbound(Isolate * v8_isolate,Source * source,CompileOptions options)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
Compile(Local<Context> context,Source * source,CompileOptions options)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
Compile(Isolate * v8_isolate,Source * source,CompileOptions options)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
CompileModule(Isolate * isolate,Source * source)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:
IsIdentifierHelper()2244 IsIdentifierHelper() : is_identifier_(false), first_char_(true) {}
2245
Check(i::String * string)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 }
VisitOneByteString(const uint8_t * chars,int length)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 }
VisitTwoByteString(const uint16_t * chars,int length)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
CompileFunctionInContext(Local<Context> v8_context,Source * source,size_t arguments_count,Local<String> arguments[],size_t context_extension_count,Local<Object> context_extensions[])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
CompileFunctionInContext(Isolate * v8_isolate,Source * source,Local<Context> v8_context,size_t arguments_count,Local<String> arguments[],size_t context_extension_count,Local<Object> context_extensions[])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
StartStreamingScript(Isolate * v8_isolate,StreamedSource * source,CompileOptions options)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
Compile(Local<Context> context,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)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
Compile(Isolate * v8_isolate,StreamedSource * v8_source,Local<String> full_source_string,const ScriptOrigin & origin)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
CachedDataVersionTag()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
Compile(Local<Context> context,Local<String> source,ScriptOrigin * origin)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
Compile(v8::Local<String> source,v8::ScriptOrigin * origin)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
Compile(v8::Local<String> source,v8::Local<String> file_name)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
TryCatch()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
TryCatch(v8::Isolate * isolate)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
~TryCatch()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
operator new(size_t)2596 V8_NORETURN void* v8::TryCatch::operator new(size_t) {
2597 base::OS::Abort();
2598 abort();
2599 }
2600
operator delete(void *,size_t)2601 void v8::TryCatch::operator delete(void*, size_t) { base::OS::Abort(); }
2602
HasCaught() const2603 bool v8::TryCatch::HasCaught() const {
2604 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(isolate_);
2605 }
2606
2607
CanContinue() const2608 bool v8::TryCatch::CanContinue() const {
2609 return can_continue_;
2610 }
2611
2612
HasTerminated() const2613 bool v8::TryCatch::HasTerminated() const {
2614 return has_terminated_;
2615 }
2616
2617
ReThrow()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
Exception() const2625 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
StackTrace(Local<Context> context) const2636 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
StackTrace() const2655 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
Message() const2661 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
Reset()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
ResetInternal()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
SetVerbose(bool value)2690 void v8::TryCatch::SetVerbose(bool value) {
2691 is_verbose_ = value;
2692 }
2693
2694
SetCaptureMessage(bool value)2695 void v8::TryCatch::SetCaptureMessage(bool value) {
2696 capture_message_ = value;
2697 }
2698
2699
2700 // --- M e s s a g e ---
2701
2702
Get() const2703 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
GetScriptOrigin() const2714 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
GetScriptResourceName() const2724 v8::Local<Value> Message::GetScriptResourceName() const {
2725 return GetScriptOrigin().ResourceName();
2726 }
2727
2728
GetStackTrace() const2729 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
GetLineNumber(Local<Context> context) const2741 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
GetLineNumber() const2751 int Message::GetLineNumber() const {
2752 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
2753 return GetLineNumber(context).FromMaybe(0);
2754 }
2755
2756
GetStartPosition() const2757 int Message::GetStartPosition() const {
2758 auto self = Utils::OpenHandle(this);
2759 return self->start_position();
2760 }
2761
2762
GetEndPosition() const2763 int Message::GetEndPosition() const {
2764 auto self = Utils::OpenHandle(this);
2765 return self->end_position();
2766 }
2767
ErrorLevel() const2768 int Message::ErrorLevel() const {
2769 auto self = Utils::OpenHandle(this);
2770 return self->error_level();
2771 }
2772
GetStartColumn(Local<Context> context) const2773 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
GetStartColumn() const2783 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
GetEndColumn(Local<Context> context) const2790 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
GetEndColumn() const2804 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
IsSharedCrossOrigin() const2811 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
IsOpaque() const2822 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
GetSourceLine(Local<Context> context) const2832 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
GetSourceLine() const2842 Local<String> Message::GetSourceLine() const {
2843 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
2844 RETURN_TO_LOCAL_UNCHECKED(GetSourceLine(context), String)
2845 }
2846
2847
PrintCurrentStackTrace(Isolate * isolate,FILE * out)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
GetFrame(uint32_t index) const2857 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
GetFrameCount() const2868 int StackTrace::GetFrameCount() const {
2869 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2870 }
2871
2872
AsArray()2873 Local<Array> StackTrace::AsArray() {
2874 return Utils::ToLocal(Utils::OpenHandle(this));
2875 }
2876
2877
CurrentStackTrace(Isolate * isolate,int frame_limit,StackTraceOptions options)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
getIntProperty(const StackFrame * f,const char * propertyName,int defaultValue)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
GetLineNumber() const2907 int StackFrame::GetLineNumber() const {
2908 return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo);
2909 }
2910
2911
GetColumn() const2912 int StackFrame::GetColumn() const {
2913 return getIntProperty(this, "column", Message::kNoColumnInfo);
2914 }
2915
2916
GetScriptId() const2917 int StackFrame::GetScriptId() const {
2918 return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo);
2919 }
2920
2921
getStringProperty(const StackFrame * f,const char * propertyName)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
GetScriptName() const2936 Local<String> StackFrame::GetScriptName() const {
2937 return getStringProperty(this, "scriptName");
2938 }
2939
2940
GetScriptNameOrSourceURL() const2941 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2942 return getStringProperty(this, "scriptNameOrSourceURL");
2943 }
2944
2945
GetFunctionName() const2946 Local<String> StackFrame::GetFunctionName() const {
2947 return getStringProperty(this, "functionName");
2948 }
2949
2950
getBoolProperty(const StackFrame * f,const char * propertyName)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
IsEval() const2961 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }
2962
2963
IsConstructor() const2964 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
New(Isolate * v8_isolate)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
Set(Local<Value> v8_key,Local<Value> v8_value)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
Get(Local<Value> v8_key)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
Has(Local<Value> v8_key)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
Delete(Local<Value> v8_key)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
Parse(Isolate * v8_isolate,Local<String> json_string)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
Parse(Local<Context> context,Local<String> json_string)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
Parse(Local<String> json_string)3098 Local<Value> JSON::Parse(Local<String> json_string) {
3099 RETURN_TO_LOCAL_UNCHECKED(Parse(Local<Context>(), json_string), Value);
3100 }
3101
Stringify(Local<Context> context,Local<Object> json_object,Local<String> gap)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
WriteHostObject(Isolate * v8_isolate,Local<Object> object)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
GetSharedArrayBufferId(Isolate * v8_isolate,Local<SharedArrayBuffer> shared_array_buffer)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
ReallocateBufferMemory(void * old_buffer,size_t size,size_t * actual_size)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
FreeBufferMemory(void * buffer)3150 void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) {
3151 return free(buffer);
3152 }
3153
3154 struct ValueSerializer::PrivateData {
PrivateDatav8::ValueSerializer::PrivateData3155 explicit PrivateData(i::Isolate* i, ValueSerializer::Delegate* delegate)
3156 : isolate(i), serializer(i, delegate) {}
3157 i::Isolate* isolate;
3158 i::ValueSerializer serializer;
3159 };
3160
ValueSerializer(Isolate * isolate)3161 ValueSerializer::ValueSerializer(Isolate* isolate)
3162 : ValueSerializer(isolate, nullptr) {}
3163
ValueSerializer(Isolate * isolate,Delegate * delegate)3164 ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate)
3165 : private_(
3166 new PrivateData(reinterpret_cast<i::Isolate*>(isolate), delegate)) {}
3167
~ValueSerializer()3168 ValueSerializer::~ValueSerializer() { delete private_; }
3169
WriteHeader()3170 void ValueSerializer::WriteHeader() { private_->serializer.WriteHeader(); }
3171
SetTreatArrayBufferViewsAsHostObjects(bool mode)3172 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {
3173 private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode);
3174 }
3175
WriteValue(Local<Context> context,Local<Value> value)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
ReleaseBuffer()3186 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() {
3187 return private_->serializer.ReleaseBuffer();
3188 }
3189
Release()3190 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
3191 return private_->serializer.Release();
3192 }
3193
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)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
TransferSharedArrayBuffer(uint32_t transfer_id,Local<SharedArrayBuffer> shared_array_buffer)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
WriteUint32(uint32_t value)3206 void ValueSerializer::WriteUint32(uint32_t value) {
3207 private_->serializer.WriteUint32(value);
3208 }
3209
WriteUint64(uint64_t value)3210 void ValueSerializer::WriteUint64(uint64_t value) {
3211 private_->serializer.WriteUint64(value);
3212 }
3213
WriteDouble(double value)3214 void ValueSerializer::WriteDouble(double value) {
3215 private_->serializer.WriteDouble(value);
3216 }
3217
WriteRawBytes(const void * source,size_t length)3218 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
3219 private_->serializer.WriteRawBytes(source, length);
3220 }
3221
ReadHostObject(Isolate * v8_isolate)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 {
PrivateDatav8::ValueDeserializer::PrivateData3232 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
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size)3240 ValueDeserializer::ValueDeserializer(Isolate* isolate, const uint8_t* data,
3241 size_t size)
3242 : ValueDeserializer(isolate, data, size, nullptr) {}
3243
ValueDeserializer(Isolate * isolate,const uint8_t * data,size_t size,Delegate * delegate)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
~ValueDeserializer()3257 ValueDeserializer::~ValueDeserializer() { delete private_; }
3258
ReadHeader(Local<Context> context)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
SetSupportsLegacyWireFormat(bool supports_legacy_wire_format)3289 void ValueDeserializer::SetSupportsLegacyWireFormat(
3290 bool supports_legacy_wire_format) {
3291 private_->supports_legacy_wire_format = supports_legacy_wire_format;
3292 }
3293
GetWireFormatVersion() const3294 uint32_t ValueDeserializer::GetWireFormatVersion() const {
3295 CHECK(!private_->has_aborted);
3296 return private_->deserializer.GetWireFormatVersion();
3297 }
3298
ReadValue(Local<Context> context)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
TransferArrayBuffer(uint32_t transfer_id,Local<ArrayBuffer> array_buffer)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
TransferSharedArrayBuffer(uint32_t transfer_id,Local<SharedArrayBuffer> shared_array_buffer)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
ReadUint32(uint32_t * value)3329 bool ValueDeserializer::ReadUint32(uint32_t* value) {
3330 return private_->deserializer.ReadUint32(value);
3331 }
3332
ReadUint64(uint64_t * value)3333 bool ValueDeserializer::ReadUint64(uint64_t* value) {
3334 return private_->deserializer.ReadUint64(value);
3335 }
3336
ReadDouble(double * value)3337 bool ValueDeserializer::ReadDouble(double* value) {
3338 return private_->deserializer.ReadDouble(value);
3339 }
3340
ReadRawBytes(size_t length,const void ** data)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
FullIsUndefined() const3347 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
FullIsNull() const3358 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
IsTrue() const3369 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
IsFalse() const3376 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
IsFunction() const3383 bool Value::IsFunction() const { return Utils::OpenHandle(this)->IsCallable(); }
3384
3385
IsName() const3386 bool Value::IsName() const {
3387 return Utils::OpenHandle(this)->IsName();
3388 }
3389
3390
FullIsString() const3391 bool Value::FullIsString() const {
3392 bool result = Utils::OpenHandle(this)->IsString();
3393 DCHECK_EQ(result, QuickIsString());
3394 return result;
3395 }
3396
3397
IsSymbol() const3398 bool Value::IsSymbol() const {
3399 return Utils::OpenHandle(this)->IsSymbol();
3400 }
3401
3402
IsArray() const3403 bool Value::IsArray() const {
3404 return Utils::OpenHandle(this)->IsJSArray();
3405 }
3406
3407
IsArrayBuffer() const3408 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
IsArrayBufferView() const3414 bool Value::IsArrayBufferView() const {
3415 return Utils::OpenHandle(this)->IsJSArrayBufferView();
3416 }
3417
3418
IsTypedArray() const3419 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
TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)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
IsSharedArrayBuffer() const3442 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
IsObject() const3448 bool Value::IsObject() const { return Utils::OpenHandle(this)->IsJSReceiver(); }
3449
3450
IsNumber() const3451 bool Value::IsNumber() const {
3452 return Utils::OpenHandle(this)->IsNumber();
3453 }
3454
3455
IsProxy() const3456 bool Value::IsProxy() const { return Utils::OpenHandle(this)->IsJSProxy(); }
3457
IsWebAssemblyCompiledModule() const3458 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
VALUE_IS_SPECIFIC_TYPE(ArgumentsObject,Arguments)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
IsExternal() const3493 bool Value::IsExternal() const {
3494 return Utils::OpenHandle(this)->IsExternal();
3495 }
3496
3497
IsInt32() const3498 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
IsUint32() const3508 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
IsNativeError() const3522 bool Value::IsNativeError() const {
3523 return Utils::OpenHandle(this)->IsJSError();
3524 }
3525
3526
IsRegExp() const3527 bool Value::IsRegExp() const {
3528 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3529 return obj->IsJSRegExp();
3530 }
3531
IsAsyncFunction() const3532 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
IsGeneratorFunction() const3539 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
IsGeneratorObject() const3547 bool Value::IsGeneratorObject() const {
3548 return Utils::OpenHandle(this)->IsJSGeneratorObject();
3549 }
3550
3551
IsMapIterator() const3552 bool Value::IsMapIterator() const {
3553 return Utils::OpenHandle(this)->IsJSMapIterator();
3554 }
3555
3556
IsSetIterator() const3557 bool Value::IsSetIterator() const {
3558 return Utils::OpenHandle(this)->IsJSSetIterator();
3559 }
3560
IsPromise() const3561 bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); }
3562
ToString(Local<Context> context) const3563 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
ToString(Isolate * isolate) const3575 Local<String> Value::ToString(Isolate* isolate) const {
3576 RETURN_TO_LOCAL_UNCHECKED(ToString(isolate->GetCurrentContext()), String);
3577 }
3578
3579
ToDetailString(Local<Context> context) const3580 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
ToDetailString(Isolate * isolate) const3591 Local<String> Value::ToDetailString(Isolate* isolate) const {
3592 RETURN_TO_LOCAL_UNCHECKED(ToDetailString(isolate->GetCurrentContext()),
3593 String);
3594 }
3595
3596
ToObject(Local<Context> context) const3597 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
ToObject(Isolate * isolate) const3609 Local<v8::Object> Value::ToObject(Isolate* isolate) const {
3610 RETURN_TO_LOCAL_UNCHECKED(ToObject(isolate->GetCurrentContext()), Object);
3611 }
3612
3613
ToBoolean(Local<Context> context) const3614 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
ToBoolean(Isolate * v8_isolate) const3623 Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
3624 return ToBoolean(v8_isolate->GetCurrentContext()).ToLocalChecked();
3625 }
3626
3627
ToNumber(Local<Context> context) const3628 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
ToNumber(Isolate * isolate) const3639 Local<Number> Value::ToNumber(Isolate* isolate) const {
3640 RETURN_TO_LOCAL_UNCHECKED(ToNumber(isolate->GetCurrentContext()), Number);
3641 }
3642
3643
ToInteger(Local<Context> context) const3644 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
ToInteger(Isolate * isolate) const3656 Local<Integer> Value::ToInteger(Isolate* isolate) const {
3657 RETURN_TO_LOCAL_UNCHECKED(ToInteger(isolate->GetCurrentContext()), Integer);
3658 }
3659
3660
ToInt32(Local<Context> context) const3661 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
ToInt32(Isolate * isolate) const3673 Local<Int32> Value::ToInt32(Isolate* isolate) const {
3674 RETURN_TO_LOCAL_UNCHECKED(ToInt32(isolate->GetCurrentContext()), Int32);
3675 }
3676
3677
ToUint32(Local<Context> context) const3678 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
ToUint32(Isolate * isolate) const3690 Local<Uint32> Value::ToUint32(Isolate* isolate) const {
3691 RETURN_TO_LOCAL_UNCHECKED(ToUint32(isolate->GetCurrentContext()), Uint32);
3692 }
3693
3694
CheckInitializedImpl(v8::Isolate * external_isolate)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
CheckCast(v8::Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)3796 void v8::Promise::CheckCast(Value* that) {
3797 Utils::ApiCheck(that->IsPromise(), "v8::Promise::Cast",
3798 "Could not convert to promise");
3799 }
3800
3801
CheckCast(Value * that)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
CheckCast(Value * that)3808 void v8::Proxy::CheckCast(Value* that) {
3809 Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast",
3810 "Could not convert to proxy");
3811 }
3812
CheckCast(Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)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
CheckCast(Value * that)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
TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)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
CheckCast(Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
CheckCast(v8::Value * that)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
BooleanValue(Local<Context> context) const3938 Maybe<bool> Value::BooleanValue(Local<Context> context) const {
3939 return Just(Utils::OpenHandle(this)->BooleanValue());
3940 }
3941
3942
BooleanValue() const3943 bool Value::BooleanValue() const {
3944 return Utils::OpenHandle(this)->BooleanValue();
3945 }
3946
3947
NumberValue(Local<Context> context) const3948 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
NumberValue() const3959 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
IntegerValue(Local<Context> context) const3967 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
IntegerValue() const3980 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
Int32Value(Local<Context> context) const3993 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
Int32Value() const4005 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
Uint32Value(Local<Context> context) const4012 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
Uint32Value() const4024 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
ToArrayIndex(Local<Context> context) const4031 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
ToArrayIndex() const4057 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
Equals(Local<Context> context,Local<Value> that) const4068 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
Equals(Local<Value> that) const4075 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
StrictEquals(Local<Value> that) const4090 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
SameValue(Local<Value> that) const4097 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
TypeOf(v8::Isolate * external_isolate)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
Set(v8::Local<v8::Context> context,v8::Local<Value> key,v8::Local<Value> value)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
Set(v8::Local<Value> key,v8::Local<Value> value)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
Set(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)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
Set(uint32_t index,v8::Local<Value> value)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
CreateDataProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value)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
CreateDataProperty(v8::Local<v8::Context> context,uint32_t index,v8::Local<Value> value)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 {
PrivateDatav8::v8::PropertyDescriptor::PrivateData4182 PrivateData() : desc() {}
4183 i::PropertyDescriptor desc;
4184 };
4185
PropertyDescriptor()4186 v8::PropertyDescriptor::PropertyDescriptor() : private_(new PrivateData()) {}
4187
4188 // DataDescriptor
PropertyDescriptor(v8::Local<v8::Value> value)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
PropertyDescriptor(v8::Local<v8::Value> value,bool writable)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
PropertyDescriptor(v8::Local<v8::Value> get,v8::Local<v8::Value> set)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
~PropertyDescriptor()4212 v8::PropertyDescriptor::~PropertyDescriptor() { delete private_; }
4213
value() const4214 v8::Local<Value> v8::PropertyDescriptor::value() const {
4215 DCHECK(private_->desc.has_value());
4216 return Utils::ToLocal(private_->desc.value());
4217 }
4218
get() const4219 v8::Local<Value> v8::PropertyDescriptor::get() const {
4220 DCHECK(private_->desc.has_get());
4221 return Utils::ToLocal(private_->desc.get());
4222 }
4223
set() const4224 v8::Local<Value> v8::PropertyDescriptor::set() const {
4225 DCHECK(private_->desc.has_set());
4226 return Utils::ToLocal(private_->desc.set());
4227 }
4228
has_value() const4229 bool v8::PropertyDescriptor::has_value() const {
4230 return private_->desc.has_value();
4231 }
has_get() const4232 bool v8::PropertyDescriptor::has_get() const {
4233 return private_->desc.has_get();
4234 }
has_set() const4235 bool v8::PropertyDescriptor::has_set() const {
4236 return private_->desc.has_set();
4237 }
4238
writable() const4239 bool v8::PropertyDescriptor::writable() const {
4240 DCHECK(private_->desc.has_writable());
4241 return private_->desc.writable();
4242 }
4243
has_writable() const4244 bool v8::PropertyDescriptor::has_writable() const {
4245 return private_->desc.has_writable();
4246 }
4247
set_enumerable(bool enumerable)4248 void v8::PropertyDescriptor::set_enumerable(bool enumerable) {
4249 private_->desc.set_enumerable(enumerable);
4250 }
4251
enumerable() const4252 bool v8::PropertyDescriptor::enumerable() const {
4253 DCHECK(private_->desc.has_enumerable());
4254 return private_->desc.enumerable();
4255 }
4256
has_enumerable() const4257 bool v8::PropertyDescriptor::has_enumerable() const {
4258 return private_->desc.has_enumerable();
4259 }
4260
set_configurable(bool configurable)4261 void v8::PropertyDescriptor::set_configurable(bool configurable) {
4262 private_->desc.set_configurable(configurable);
4263 }
4264
configurable() const4265 bool v8::PropertyDescriptor::configurable() const {
4266 DCHECK(private_->desc.has_configurable());
4267 return private_->desc.configurable();
4268 }
4269
has_configurable() const4270 bool v8::PropertyDescriptor::has_configurable() const {
4271 return private_->desc.has_configurable();
4272 }
4273
DefineOwnProperty(v8::Local<v8::Context> context,v8::Local<Name> key,v8::Local<Value> value,v8::PropertyAttribute attributes)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
DefineProperty(v8::Local<v8::Context> context,v8::Local<Name> key,PropertyDescriptor & descriptor)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
DefineObjectProperty(i::Handle<i::JSObject> js_object,i::Handle<i::Object> key,i::Handle<i::Object> value,i::PropertyAttributes attrs)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
ForceSet(v8::Local<v8::Context> context,v8::Local<Value> key,v8::Local<Value> value,v8::PropertyAttribute attribs)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
ForceSet(v8::Local<Value> key,v8::Local<Value> value,v8::PropertyAttribute attribs)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
SetPrivate(Local<Context> context,Local<Private> key,Local<Value> value)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
Get(Local<v8::Context> context,Local<Value> key)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
Get(v8::Local<Value> key)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
Get(Local<Context> context,uint32_t index)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
Get(uint32_t index)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
GetPrivate(Local<Context> context,Local<Private> key)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
GetPropertyAttributes(Local<Context> context,Local<Value> key)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
GetPropertyAttributes(v8::Local<Value> key)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
GetOwnPropertyDescriptor(Local<Context> context,Local<String> key)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
GetOwnPropertyDescriptor(Local<String> key)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
GetPrototype()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
SetPrototype(Local<Context> context,Local<Value> value)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
SetPrototype(Local<Value> value)4503 bool v8::Object::SetPrototype(Local<Value> value) {
4504 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
4505 return SetPrototype(context, value).FromMaybe(false);
4506 }
4507
FindInstanceInPrototypeChain(v8::Local<FunctionTemplate> tmpl)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
GetPropertyNames(Local<Context> context)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
GetPropertyNames(Local<Context> context,KeyCollectionMode mode,PropertyFilter property_filter,IndexFilter index_filter)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
GetPropertyNames()4552 Local<Array> v8::Object::GetPropertyNames() {
4553 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
4554 RETURN_TO_LOCAL_UNCHECKED(GetPropertyNames(context), Array);
4555 }
4556
GetOwnPropertyNames(Local<Context> context)4557 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
4558 return GetOwnPropertyNames(
4559 context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS));
4560 }
4561
GetOwnPropertyNames()4562 Local<Array> v8::Object::GetOwnPropertyNames() {
4563 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
4564 RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array);
4565 }
4566
GetOwnPropertyNames(Local<Context> context,PropertyFilter filter)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
ObjectProtoToString(Local<Context> context)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
ObjectProtoToString()4586 Local<String> v8::Object::ObjectProtoToString() {
4587 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
4588 RETURN_TO_LOCAL_UNCHECKED(ObjectProtoToString(context), String);
4589 }
4590
4591
GetConstructorName()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
SetIntegrityLevel(Local<Context> context,IntegrityLevel level)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
Delete(Local<Context> context,Local<Value> key)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
Delete(v8::Local<Value> key)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
DeletePrivate(Local<Context> context,Local<Private> key)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
Has(Local<Context> context,Local<Value> key)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
Has(v8::Local<Value> key)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
HasPrivate(Local<Context> context,Local<Private> key)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
Delete(Local<Context> context,uint32_t index)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
Delete(uint32_t index)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
Has(Local<Context> context,uint32_t index)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
Has(uint32_t index)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>
ObjectSetAccessor(Local<Context> context,Object * self,Local<Name> name,Getter getter,Setter setter,Data data,AccessControl settings,PropertyAttribute attributes)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
SetAccessor(Local<Context> context,Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,MaybeLocal<Value> data,AccessControl settings,PropertyAttribute attribute)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
SetAccessor(Local<String> name,AccessorGetterCallback getter,AccessorSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attributes)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
SetAccessor(Local<Name> name,AccessorNameGetterCallback getter,AccessorNameSetterCallback setter,v8::Local<Value> data,AccessControl settings,PropertyAttribute attributes)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
SetAccessorProperty(Local<Name> name,Local<Function> getter,Local<Function> setter,PropertyAttribute attribute,AccessControl settings)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
HasOwnProperty(Local<Context> context,Local<Name> key)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
HasOwnProperty(Local<Context> context,uint32_t index)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
HasOwnProperty(Local<String> key)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
HasRealNamedProperty(Local<Context> context,Local<Name> key)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
HasRealNamedProperty(Local<String> key)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
HasRealIndexedProperty(Local<Context> context,uint32_t index)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
HasRealIndexedProperty(uint32_t index)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
HasRealNamedCallbackProperty(Local<Context> context,Local<Name> key)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
HasRealNamedCallbackProperty(Local<String> key)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
HasNamedLookupInterceptor()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
HasIndexedLookupInterceptor()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
GetRealNamedPropertyInPrototypeChain(Local<Context> context,Local<Name> key)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
GetRealNamedPropertyInPrototypeChain(Local<String> key)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>
GetRealNamedPropertyAttributesInPrototypeChain(Local<Context> context,Local<Name> key)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>
GetRealNamedPropertyAttributesInPrototypeChain(Local<String> key)4934 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(Local<String> key) {
4935 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
4936 return GetRealNamedPropertyAttributesInPrototypeChain(context, key);
4937 }
4938
4939
GetRealNamedProperty(Local<Context> context,Local<Name> key)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
GetRealNamedProperty(Local<String> key)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
GetRealNamedPropertyAttributes(Local<Context> context,Local<Name> key)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
GetRealNamedPropertyAttributes(Local<String> key)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
Clone()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
CreationContext()4999 Local<v8::Context> v8::Object::CreationContext() {
5000 auto self = Utils::OpenHandle(this);
5001 return Utils::ToLocal(self->GetCreationContext());
5002 }
5003
5004
GetIdentityHash()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
IsCallable()5013 bool v8::Object::IsCallable() {
5014 auto self = Utils::OpenHandle(this);
5015 return self->IsCallable();
5016 }
5017
IsConstructor()5018 bool v8::Object::IsConstructor() {
5019 auto self = Utils::OpenHandle(this);
5020 return self->IsConstructor();
5021 }
5022
CallAsFunction(Local<Context> context,Local<Value> recv,int argc,Local<Value> argv[])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
CallAsFunction(v8::Local<v8::Value> recv,int argc,v8::Local<v8::Value> argv[])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
CallAsConstructor(Local<Context> context,int argc,Local<Value> argv[])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
CallAsConstructor(int argc,v8::Local<v8::Value> argv[])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
New(Local<Context> context,FunctionCallback callback,Local<Value> data,int length,ConstructorBehavior behavior)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
New(Isolate * v8_isolate,FunctionCallback callback,Local<Value> data,int length)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
NewInstance() const5096 Local<v8::Object> Function::NewInstance() const {
5097 return NewInstance(Isolate::GetCurrent()->GetCurrentContext(), 0, NULL)
5098 .FromMaybe(Local<Object>());
5099 }
5100
5101
NewInstance(Local<Context> context,int argc,v8::Local<v8::Value> argv[]) const5102 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
NewInstance(int argc,v8::Local<v8::Value> argv[]) const5119 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
Call(Local<Context> context,v8::Local<v8::Value> recv,int argc,v8::Local<v8::Value> argv[])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
Call(v8::Local<v8::Value> recv,int argc,v8::Local<v8::Value> argv[])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
SetName(v8::Local<v8::String> name)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
GetName() const5160 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
GetInferredName() const5179 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
GetDebugName() const5191 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
GetDisplayName() const5203 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
GetScriptOrigin() const5223 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
GetScriptLineNumber() const5240 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
GetScriptColumnNumber() const5254 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
IsBuiltin() const5268 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
ScriptId() const5278 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
GetBoundFunction() const5292 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
GetIdentityHash()5304 int Name::GetIdentityHash() {
5305 auto self = Utils::OpenHandle(this);
5306 return static_cast<int>(self->Hash());
5307 }
5308
5309
Length() const5310 int String::Length() const {
5311 i::Handle<i::String> str = Utils::OpenHandle(this);
5312 return str->length();
5313 }
5314
5315
IsOneByte() const5316 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;
Unaligned(const uint16_t * chars)5332 static inline bool Unaligned(const uint16_t* chars) {
5333 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
5334 }
5335
5336
Align(const uint16_t * chars)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:
ContainsOnlyOneByteHelper()5344 ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
Check(i::String * string)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 }
VisitOneByteString(const uint8_t * chars,int length)5350 void VisitOneByteString(const uint8_t* chars, int length) {
5351 // Nothing to do.
5352 }
VisitTwoByteString(const uint16_t * chars,int length)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:
CheckCons(i::ConsString * cons_string)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
ContainsOnlyOneByte() const5431 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
EndsWithSurrogate(uint8_t state)5452 static inline bool EndsWithSurrogate(uint8_t state) {
5453 return state & kEndsWithLeadingSurrogate;
5454 }
5455
StartsWithSurrogate(uint8_t state)5456 static inline bool StartsWithSurrogate(uint8_t state) {
5457 return state & kStartsWithTrailingSurrogate;
5458 }
5459
5460 class Visitor {
5461 public:
Visitor()5462 Visitor() : utf8_length_(0), state_(kInitialState) {}
5463
VisitOneByteString(const uint8_t * chars,int length)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
VisitTwoByteString(const uint16_t * chars,int length)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
VisitFlat(i::String * string,int * length,uint8_t * state)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
MergeLeafLeft(int * length,uint8_t * state,uint8_t leaf_state)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
MergeLeafRight(int * length,uint8_t * state,uint8_t leaf_state)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
MergeTerminal(int * length,uint8_t state,uint8_t * state_out)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
Calculate(i::ConsString * current,uint8_t * state_out)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
Calculate(i::ConsString * current)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
Utf8Length(i::String * str,i::Isolate * isolate)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
Utf8Length() const5631 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:
Utf8WriterVisitor(char * buffer,int capacity,bool skip_capacity_check,bool replace_invalid_utf8)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
WriteEndCharacter(uint16_t character,int last_character,int remaining,char * const buffer,bool replace_invalid_utf8)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>
Visit(const Char * chars,const int length)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
IsDone()5779 inline bool IsDone() {
5780 return early_termination_;
5781 }
5782
VisitOneByteString(const uint8_t * chars,int length)5783 inline void VisitOneByteString(const uint8_t* chars, int length) {
5784 Visit(chars, length);
5785 }
5786
VisitTwoByteString(const uint16_t * chars,int length)5787 inline void VisitTwoByteString(const uint16_t* chars, int length) {
5788 Visit(chars, length);
5789 }
5790
CompleteWrite(bool write_null,int * utf16_chars_read_out)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
RecursivelySerializeToUtf8(i::String * current,Utf8WriterVisitor * writer,int recursion_budget)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
WriteUtf8(char * buffer,int capacity,int * nchars_ref,int options) const5838 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>
WriteHelper(const String * string,CharType * buffer,int start,int length,int options)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
WriteOneByte(uint8_t * buffer,int start,int length,int options) const5918 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
Write(uint16_t * buffer,int start,int length,int options) const5926 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
IsExternal() const5934 bool v8::String::IsExternal() const {
5935 i::Handle<i::String> str = Utils::OpenHandle(this);
5936 return i::StringShape(*str).IsExternalTwoByte();
5937 }
5938
5939
IsExternalOneByte() const5940 bool v8::String::IsExternalOneByte() const {
5941 i::Handle<i::String> str = Utils::OpenHandle(this);
5942 return i::StringShape(*str).IsExternalOneByte();
5943 }
5944
5945
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const5946 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
VerifyExternalStringResourceBase(v8::String::ExternalStringResourceBase * value,Encoding encoding) const5960 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*
GetExternalOneByteStringResource() const5985 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
Name() const5997 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
Name() const6004 Local<Value> Private::Name() const {
6005 return reinterpret_cast<const Symbol*>(this)->Name();
6006 }
6007
6008
Value() const6009 double Number::Value() const {
6010 i::Handle<i::Object> obj = Utils::OpenHandle(this);
6011 return obj->Number();
6012 }
6013
6014
Value() const6015 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
Value() const6021 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
Value() const6031 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
Value() const6041 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
InternalFieldCount()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
InternalFieldOK(i::Handle<i::JSReceiver> obj,int index,const char * location)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
SlowGetInternalField(int index)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
SetInternalField(int index,v8::Local<Value> value)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
SlowGetAlignedPointerFromInternalField(int index)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
SetAlignedPointerInInternalField(int index,void * value)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
SetAlignedPointerInInternalFields(int argc,int indices[],void * values[])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
ExternalValue(i::Object * obj)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
InitializePlatform(Platform * platform)6137 void v8::V8::InitializePlatform(Platform* platform) {
6138 i::V8::InitializePlatform(platform);
6139 }
6140
6141
ShutdownPlatform()6142 void v8::V8::ShutdownPlatform() {
6143 i::V8::ShutdownPlatform();
6144 }
6145
6146
Initialize()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
SetEntropySource(EntropySource entropy_source)6156 void v8::V8::SetEntropySource(EntropySource entropy_source) {
6157 base::RandomNumberGenerator::SetEntropySource(entropy_source);
6158 }
6159
6160
SetReturnAddressLocationResolver(ReturnAddressLocationResolver return_address_resolver)6161 void v8::V8::SetReturnAddressLocationResolver(
6162 ReturnAddressLocationResolver return_address_resolver) {
6163 i::StackFrame::SetReturnAddressLocationResolver(return_address_resolver);
6164 }
6165
6166
Dispose()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
HeapStatistics()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
HeapSpaceStatistics()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
HeapObjectStatistics()6193 HeapObjectStatistics::HeapObjectStatistics()
6194 : object_type_(nullptr),
6195 object_sub_type_(nullptr),
6196 object_count_(0),
6197 object_size_(0) {}
6198
HeapCodeStatistics()6199 HeapCodeStatistics::HeapCodeStatistics()
6200 : code_and_metadata_size_(0), bytecode_and_metadata_size_(0) {}
6201
InitializeICU(const char * icu_data_file)6202 bool v8::V8::InitializeICU(const char* icu_data_file) {
6203 return i::InitializeICU(icu_data_file);
6204 }
6205
InitializeICUDefaultLocation(const char * exec_path,const char * icu_data_file)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
InitializeExternalStartupData(const char * directory_path)6211 void v8::V8::InitializeExternalStartupData(const char* directory_path) {
6212 i::InitializeExternalStartupData(directory_path);
6213 }
6214
6215
InitializeExternalStartupData(const char * natives_blob,const char * snapshot_blob)6216 void v8::V8::InitializeExternalStartupData(const char* natives_blob,
6217 const char* snapshot_blob) {
6218 i::InitializeExternalStartupData(natives_blob, snapshot_blob);
6219 }
6220
6221
GetVersion()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> {
Invokev8::InvokeBootstrapper6231 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> {
Invokev8::InvokeBootstrapper6244 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>
CreateEnvironment(i::Isolate * isolate,v8::ExtensionConfiguration * extensions,v8::MaybeLocal<ObjectTemplate> maybe_global_template,v8::MaybeLocal<Value> maybe_global_proxy,size_t context_snapshot_index,v8::DeserializeInternalFieldsCallback internal_fields_deserializer)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
NewContext(v8::Isolate * external_isolate,v8::ExtensionConfiguration * extensions,v8::MaybeLocal<ObjectTemplate> global_template,v8::MaybeLocal<Value> global_object,size_t context_snapshot_index,v8::DeserializeInternalFieldsCallback internal_fields_deserializer)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
New(v8::Isolate * external_isolate,v8::ExtensionConfiguration * extensions,v8::MaybeLocal<ObjectTemplate> global_template,v8::MaybeLocal<Value> global_object)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
FromSnapshot(v8::Isolate * external_isolate,size_t context_snapshot_index,v8::DeserializeInternalFieldsCallback internal_fields_deserializer,v8::ExtensionConfiguration * extensions,MaybeLocal<Value> global_object)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
NewRemoteContext(v8::Isolate * external_isolate,v8::Local<ObjectTemplate> global_template,v8::MaybeLocal<v8::Value> global_object)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
SetSecurityToken(Local<Value> token)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
UseDefaultSecurityToken()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
GetSecurityToken()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
GetIsolate()6452 v8::Isolate* Context::GetIsolate() {
6453 i::Handle<i::Context> env = Utils::OpenHandle(this);
6454 return reinterpret_cast<Isolate*>(env->GetIsolate());
6455 }
6456
Global()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
DetachGlobal()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
GetExtrasBindingObject()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
AllowCodeGenerationFromStrings(bool allow)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
IsCodeGenerationFromStringsAllowed()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
SetErrorMessageForCodeGenerationFromStrings(Local<String> error)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
EstimatedSize()6510 size_t Context::EstimatedSize() {
6511 return static_cast<size_t>(
6512 i::ContextMeasure(*Utils::OpenHandle(this)).Size());
6513 }
6514
6515
NewInstance(Local<Context> context)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
NewInstance()6527 Local<v8::Object> ObjectTemplate::NewInstance() {
6528 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
6529 RETURN_TO_LOCAL_UNCHECKED(NewInstance(context), Object);
6530 }
6531
6532
GetFunction(Local<Context> context)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
GetFunction()6544 Local<v8::Function> FunctionTemplate::GetFunction() {
6545 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
6546 RETURN_TO_LOCAL_UNCHECKED(GetFunction(context), Function);
6547 }
6548
NewRemoteInstance()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
HasInstance(v8::Local<v8::Value> value)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
New(Isolate * isolate,void * value)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
Value() const6605 void* External::Value() const {
6606 return ExternalValue(*Utils::OpenHandle(this));
6607 }
6608
6609
6610 // anonymous namespace for string creation helper functions
6611 namespace {
6612
StringLength(const char * string)6613 inline int StringLength(const char* string) {
6614 return i::StrLength(string);
6615 }
6616
6617
StringLength(const uint8_t * string)6618 inline int StringLength(const uint8_t* string) {
6619 return i::StrLength(reinterpret_cast<const char*>(string));
6620 }
6621
6622
StringLength(const uint16_t * string)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
NewString(i::Factory * factory,v8::NewStringType type,i::Vector<const char> string)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
NewString(i::Factory * factory,v8::NewStringType type,i::Vector<const uint8_t> string)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
NewString(i::Factory * factory,v8::NewStringType type,i::Vector<const uint16_t> string)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
NewFromUtf8(Isolate * isolate,const char * data,NewStringType type,int length)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
NewFromUtf8(Isolate * isolate,const char * data,v8::NewStringType type,int length)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
NewFromOneByte(Isolate * isolate,const uint8_t * data,NewStringType type,int length)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
NewFromOneByte(Isolate * isolate,const uint8_t * data,v8::NewStringType type,int length)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
NewFromTwoByte(Isolate * isolate,const uint16_t * data,NewStringType type,int length)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
NewFromTwoByte(Isolate * isolate,const uint16_t * data,v8::NewStringType type,int length)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
Concat(Local<String> left,Local<String> right)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
NewExternalTwoByte(Isolate * isolate,v8::String::ExternalStringResource * resource)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
NewExternal(Isolate * isolate,v8::String::ExternalStringResource * resource)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
NewExternalOneByte(Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)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
NewExternal(Isolate * isolate,v8::String::ExternalOneByteStringResource * resource)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
MakeExternal(v8::String::ExternalStringResource * resource)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
MakeExternal(v8::String::ExternalOneByteStringResource * resource)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
CanMakeExternal()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
GetIsolate()6874 Isolate* v8::Object::GetIsolate() {
6875 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
6876 return reinterpret_cast<Isolate*>(i_isolate);
6877 }
6878
6879
New(Isolate * isolate)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
New(Isolate * isolate,double value)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
ValueOf() const6901 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
New(Isolate * isolate,bool value)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();
6919 return Utils::ToLocal(obj);
6920 }
6921
6922
New(bool value)6923 Local<v8::Value> v8::BooleanObject::New(bool value) {
6924 return New(Isolate::GetCurrent(), value);
6925 }
6926
6927
ValueOf() const6928 bool v8::BooleanObject::ValueOf() const {
6929 i::Handle<i::Object> obj = Utils::OpenHandle(this);
6930 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
6931 i::Isolate* isolate = jsvalue->GetIsolate();
6932 LOG_API(isolate, BooleanObject, BooleanValue);
6933 return jsvalue->value()->IsTrue(isolate);
6934 }
6935
6936
New(Local<String> value)6937 Local<v8::Value> v8::StringObject::New(Local<String> value) {
6938 i::Handle<i::String> string = Utils::OpenHandle(*value);
6939 i::Isolate* isolate = string->GetIsolate();
6940 LOG_API(isolate, StringObject, New);
6941 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
6942 i::Handle<i::Object> obj =
6943 i::Object::ToObject(isolate, string).ToHandleChecked();
6944 return Utils::ToLocal(obj);
6945 }
6946
6947
ValueOf() const6948 Local<v8::String> v8::StringObject::ValueOf() const {
6949 i::Handle<i::Object> obj = Utils::OpenHandle(this);
6950 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
6951 i::Isolate* isolate = jsvalue->GetIsolate();
6952 LOG_API(isolate, StringObject, StringValue);
6953 return Utils::ToLocal(
6954 i::Handle<i::String>(i::String::cast(jsvalue->value())));
6955 }
6956
6957
New(Isolate * isolate,Local<Symbol> value)6958 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) {
6959 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6960 LOG_API(i_isolate, SymbolObject, New);
6961 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
6962 i::Handle<i::Object> obj = i::Object::ToObject(
6963 i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
6964 return Utils::ToLocal(obj);
6965 }
6966
6967
ValueOf() const6968 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
6969 i::Handle<i::Object> obj = Utils::OpenHandle(this);
6970 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
6971 i::Isolate* isolate = jsvalue->GetIsolate();
6972 LOG_API(isolate, SymbolObject, SymbolValue);
6973 return Utils::ToLocal(
6974 i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
6975 }
6976
6977
New(Local<Context> context,double time)6978 MaybeLocal<v8::Value> v8::Date::New(Local<Context> context, double time) {
6979 if (std::isnan(time)) {
6980 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6981 time = std::numeric_limits<double>::quiet_NaN();
6982 }
6983 PREPARE_FOR_EXECUTION(context, Date, New, Value);
6984 Local<Value> result;
6985 has_pending_exception = !ToLocal<Value>(
6986 i::JSDate::New(isolate->date_function(), isolate->date_function(), time),
6987 &result);
6988 RETURN_ON_FAILED_EXECUTION(Value);
6989 RETURN_ESCAPED(result);
6990 }
6991
6992
New(Isolate * isolate,double time)6993 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
6994 auto context = isolate->GetCurrentContext();
6995 RETURN_TO_LOCAL_UNCHECKED(New(context, time), Value);
6996 }
6997
6998
ValueOf() const6999 double v8::Date::ValueOf() const {
7000 i::Handle<i::Object> obj = Utils::OpenHandle(this);
7001 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
7002 i::Isolate* isolate = jsdate->GetIsolate();
7003 LOG_API(isolate, Date, NumberValue);
7004 return jsdate->value()->Number();
7005 }
7006
7007
DateTimeConfigurationChangeNotification(Isolate * isolate)7008 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
7009 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7010 LOG_API(i_isolate, Date, DateTimeConfigurationChangeNotification);
7011 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7012 i_isolate->date_cache()->ResetDateCache();
7013 if (!i_isolate->eternal_handles()->Exists(
7014 i::EternalHandles::DATE_CACHE_VERSION)) {
7015 return;
7016 }
7017 i::Handle<i::FixedArray> date_cache_version =
7018 i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
7019 i::EternalHandles::DATE_CACHE_VERSION));
7020 DCHECK_EQ(1, date_cache_version->length());
7021 CHECK(date_cache_version->get(0)->IsSmi());
7022 date_cache_version->set(
7023 0,
7024 i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
7025 }
7026
7027
New(Local<Context> context,Local<String> pattern,Flags flags)7028 MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
7029 Local<String> pattern, Flags flags) {
7030 PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
7031 Local<v8::RegExp> result;
7032 has_pending_exception =
7033 !ToLocal<RegExp>(i::JSRegExp::New(Utils::OpenHandle(*pattern),
7034 static_cast<i::JSRegExp::Flags>(flags)),
7035 &result);
7036 RETURN_ON_FAILED_EXECUTION(RegExp);
7037 RETURN_ESCAPED(result);
7038 }
7039
7040
New(Local<String> pattern,Flags flags)7041 Local<v8::RegExp> v8::RegExp::New(Local<String> pattern, Flags flags) {
7042 auto isolate =
7043 reinterpret_cast<Isolate*>(Utils::OpenHandle(*pattern)->GetIsolate());
7044 auto context = isolate->GetCurrentContext();
7045 RETURN_TO_LOCAL_UNCHECKED(New(context, pattern, flags), RegExp);
7046 }
7047
7048
GetSource() const7049 Local<v8::String> v8::RegExp::GetSource() const {
7050 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7051 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
7052 }
7053
7054
7055 // Assert that the static flags cast in GetFlags is valid.
7056 #define REGEXP_FLAG_ASSERT_EQ(flag) \
7057 STATIC_ASSERT(static_cast<int>(v8::RegExp::flag) == \
7058 static_cast<int>(i::JSRegExp::flag))
7059 REGEXP_FLAG_ASSERT_EQ(kNone);
7060 REGEXP_FLAG_ASSERT_EQ(kGlobal);
7061 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase);
7062 REGEXP_FLAG_ASSERT_EQ(kMultiline);
7063 REGEXP_FLAG_ASSERT_EQ(kSticky);
7064 REGEXP_FLAG_ASSERT_EQ(kUnicode);
7065 #undef REGEXP_FLAG_ASSERT_EQ
7066
GetFlags() const7067 v8::RegExp::Flags v8::RegExp::GetFlags() const {
7068 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
7069 return RegExp::Flags(static_cast<int>(obj->GetFlags()));
7070 }
7071
7072
New(Isolate * isolate,int length)7073 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
7074 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7075 LOG_API(i_isolate, Array, New);
7076 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7077 int real_length = length > 0 ? length : 0;
7078 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
7079 i::Handle<i::Object> length_obj =
7080 i_isolate->factory()->NewNumberFromInt(real_length);
7081 obj->set_length(*length_obj);
7082 return Utils::ToLocal(obj);
7083 }
7084
7085
Length() const7086 uint32_t v8::Array::Length() const {
7087 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
7088 i::Object* length = obj->length();
7089 if (length->IsSmi()) {
7090 return i::Smi::cast(length)->value();
7091 } else {
7092 return static_cast<uint32_t>(length->Number());
7093 }
7094 }
7095
7096
CloneElementAt(Local<Context> context,uint32_t index)7097 MaybeLocal<Object> Array::CloneElementAt(Local<Context> context,
7098 uint32_t index) {
7099 PREPARE_FOR_EXECUTION(context, Array, CloneElementAt, Object);
7100 auto self = Utils::OpenHandle(this);
7101 if (!self->HasFastObjectElements()) return Local<Object>();
7102 i::FixedArray* elms = i::FixedArray::cast(self->elements());
7103 i::Object* paragon = elms->get(index);
7104 if (!paragon->IsJSObject()) return Local<Object>();
7105 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
7106 Local<Object> result;
7107 has_pending_exception =
7108 !ToLocal<Object>(isolate->factory()->CopyJSObject(paragon_handle),
7109 &result);
7110 RETURN_ON_FAILED_EXECUTION(Object);
7111 RETURN_ESCAPED(result);
7112 }
7113
7114
CloneElementAt(uint32_t index)7115 Local<Object> Array::CloneElementAt(uint32_t index) { return Local<Object>(); }
7116
7117
New(Isolate * isolate)7118 Local<v8::Map> v8::Map::New(Isolate* isolate) {
7119 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7120 LOG_API(i_isolate, Map, New);
7121 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7122 i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
7123 return Utils::ToLocal(obj);
7124 }
7125
7126
Size() const7127 size_t v8::Map::Size() const {
7128 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7129 return i::OrderedHashMap::cast(obj->table())->NumberOfElements();
7130 }
7131
7132
Clear()7133 void Map::Clear() {
7134 auto self = Utils::OpenHandle(this);
7135 i::Isolate* isolate = self->GetIsolate();
7136 LOG_API(isolate, Map, Clear);
7137 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7138 i::JSMap::Clear(self);
7139 }
7140
7141
Get(Local<Context> context,Local<Value> key)7142 MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
7143 PREPARE_FOR_EXECUTION(context, Map, Get, Value);
7144 auto self = Utils::OpenHandle(this);
7145 Local<Value> result;
7146 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7147 has_pending_exception =
7148 !ToLocal<Value>(i::Execution::Call(isolate, isolate->map_get(), self,
7149 arraysize(argv), argv),
7150 &result);
7151 RETURN_ON_FAILED_EXECUTION(Value);
7152 RETURN_ESCAPED(result);
7153 }
7154
7155
Set(Local<Context> context,Local<Value> key,Local<Value> value)7156 MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
7157 Local<Value> value) {
7158 PREPARE_FOR_EXECUTION(context, Map, Set, Map);
7159 auto self = Utils::OpenHandle(this);
7160 i::Handle<i::Object> result;
7161 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
7162 Utils::OpenHandle(*value)};
7163 has_pending_exception = !i::Execution::Call(isolate, isolate->map_set(), self,
7164 arraysize(argv), argv)
7165 .ToHandle(&result);
7166 RETURN_ON_FAILED_EXECUTION(Map);
7167 RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
7168 }
7169
7170
Has(Local<Context> context,Local<Value> key)7171 Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
7172 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Map, Has, bool);
7173 auto self = Utils::OpenHandle(this);
7174 i::Handle<i::Object> result;
7175 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7176 has_pending_exception = !i::Execution::Call(isolate, isolate->map_has(), self,
7177 arraysize(argv), argv)
7178 .ToHandle(&result);
7179 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7180 return Just(result->IsTrue(isolate));
7181 }
7182
7183
Delete(Local<Context> context,Local<Value> key)7184 Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
7185 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Map, Delete, bool);
7186 auto self = Utils::OpenHandle(this);
7187 i::Handle<i::Object> result;
7188 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7189 has_pending_exception = !i::Execution::Call(isolate, isolate->map_delete(),
7190 self, arraysize(argv), argv)
7191 .ToHandle(&result);
7192 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7193 return Just(result->IsTrue(isolate));
7194 }
7195
7196 namespace {
MapAsArray(i::Isolate * isolate,i::Object * table_obj,int offset,int kind)7197 i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object* table_obj,
7198 int offset, int kind) {
7199 i::Factory* factory = isolate->factory();
7200 i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(table_obj));
7201 if (offset >= table->NumberOfElements()) return factory->NewJSArray(0);
7202 int length = (table->NumberOfElements() - offset) *
7203 (kind == i::JSMapIterator::kKindEntries ? 2 : 1);
7204 i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
7205 int result_index = 0;
7206 {
7207 i::DisallowHeapAllocation no_gc;
7208 int capacity = table->UsedCapacity();
7209 i::Oddball* the_hole = isolate->heap()->the_hole_value();
7210 for (int i = 0; i < capacity; ++i) {
7211 i::Object* key = table->KeyAt(i);
7212 if (key == the_hole) continue;
7213 if (offset-- > 0) continue;
7214 if (kind == i::JSMapIterator::kKindEntries ||
7215 kind == i::JSMapIterator::kKindKeys) {
7216 result->set(result_index++, key);
7217 }
7218 if (kind == i::JSMapIterator::kKindEntries ||
7219 kind == i::JSMapIterator::kKindValues) {
7220 result->set(result_index++, table->ValueAt(i));
7221 }
7222 }
7223 }
7224 DCHECK_EQ(result_index, result->length());
7225 DCHECK_EQ(result_index, length);
7226 return factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
7227 }
7228 } // namespace
7229
AsArray() const7230 Local<Array> Map::AsArray() const {
7231 i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
7232 i::Isolate* isolate = obj->GetIsolate();
7233 LOG_API(isolate, Map, AsArray);
7234 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7235 return Utils::ToLocal(
7236 MapAsArray(isolate, obj->table(), 0, i::JSMapIterator::kKindEntries));
7237 }
7238
7239
New(Isolate * isolate)7240 Local<v8::Set> v8::Set::New(Isolate* isolate) {
7241 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7242 LOG_API(i_isolate, Set, New);
7243 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7244 i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
7245 return Utils::ToLocal(obj);
7246 }
7247
7248
Size() const7249 size_t v8::Set::Size() const {
7250 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7251 return i::OrderedHashSet::cast(obj->table())->NumberOfElements();
7252 }
7253
7254
Clear()7255 void Set::Clear() {
7256 auto self = Utils::OpenHandle(this);
7257 i::Isolate* isolate = self->GetIsolate();
7258 LOG_API(isolate, Set, Clear);
7259 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7260 i::JSSet::Clear(self);
7261 }
7262
7263
Add(Local<Context> context,Local<Value> key)7264 MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
7265 PREPARE_FOR_EXECUTION(context, Set, Add, Set);
7266 auto self = Utils::OpenHandle(this);
7267 i::Handle<i::Object> result;
7268 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7269 has_pending_exception = !i::Execution::Call(isolate, isolate->set_add(), self,
7270 arraysize(argv), argv)
7271 .ToHandle(&result);
7272 RETURN_ON_FAILED_EXECUTION(Set);
7273 RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
7274 }
7275
7276
Has(Local<Context> context,Local<Value> key)7277 Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
7278 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Set, Has, bool);
7279 auto self = Utils::OpenHandle(this);
7280 i::Handle<i::Object> result;
7281 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7282 has_pending_exception = !i::Execution::Call(isolate, isolate->set_has(), self,
7283 arraysize(argv), argv)
7284 .ToHandle(&result);
7285 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7286 return Just(result->IsTrue(isolate));
7287 }
7288
7289
Delete(Local<Context> context,Local<Value> key)7290 Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
7291 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Set, Delete, bool);
7292 auto self = Utils::OpenHandle(this);
7293 i::Handle<i::Object> result;
7294 i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
7295 has_pending_exception = !i::Execution::Call(isolate, isolate->set_delete(),
7296 self, arraysize(argv), argv)
7297 .ToHandle(&result);
7298 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7299 return Just(result->IsTrue(isolate));
7300 }
7301
7302 namespace {
SetAsArray(i::Isolate * isolate,i::Object * table_obj,int offset)7303 i::Handle<i::JSArray> SetAsArray(i::Isolate* isolate, i::Object* table_obj,
7304 int offset) {
7305 i::Factory* factory = isolate->factory();
7306 i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(table_obj));
7307 int length = table->NumberOfElements() - offset;
7308 if (length <= 0) return factory->NewJSArray(0);
7309 i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
7310 int result_index = 0;
7311 {
7312 i::DisallowHeapAllocation no_gc;
7313 int capacity = table->UsedCapacity();
7314 i::Oddball* the_hole = isolate->heap()->the_hole_value();
7315 for (int i = 0; i < capacity; ++i) {
7316 i::Object* key = table->KeyAt(i);
7317 if (key == the_hole) continue;
7318 if (offset-- > 0) continue;
7319 result->set(result_index++, key);
7320 }
7321 }
7322 DCHECK_EQ(result_index, result->length());
7323 DCHECK_EQ(result_index, length);
7324 return factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
7325 }
7326 } // namespace
7327
AsArray() const7328 Local<Array> Set::AsArray() const {
7329 i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
7330 i::Isolate* isolate = obj->GetIsolate();
7331 LOG_API(isolate, Set, AsArray);
7332 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7333 return Utils::ToLocal(SetAsArray(isolate, obj->table(), 0));
7334 }
7335
7336
New(Local<Context> context)7337 MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
7338 PREPARE_FOR_EXECUTION(context, Promise_Resolver, New, Resolver);
7339 i::Handle<i::Object> result;
7340 has_pending_exception =
7341 !i::Execution::Call(isolate, isolate->promise_internal_constructor(),
7342 isolate->factory()->undefined_value(), 0, NULL)
7343 .ToHandle(&result);
7344 RETURN_ON_FAILED_EXECUTION(Promise::Resolver);
7345 RETURN_ESCAPED(Local<Promise::Resolver>::Cast(Utils::ToLocal(result)));
7346 }
7347
7348
New(Isolate * isolate)7349 Local<Promise::Resolver> Promise::Resolver::New(Isolate* isolate) {
7350 RETURN_TO_LOCAL_UNCHECKED(New(isolate->GetCurrentContext()),
7351 Promise::Resolver);
7352 }
7353
7354
GetPromise()7355 Local<Promise> Promise::Resolver::GetPromise() {
7356 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7357 return Local<Promise>::Cast(Utils::ToLocal(promise));
7358 }
7359
7360
Resolve(Local<Context> context,Local<Value> value)7361 Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
7362 Local<Value> value) {
7363 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool);
7364 auto self = Utils::OpenHandle(this);
7365 i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
7366 has_pending_exception =
7367 i::Execution::Call(isolate, isolate->promise_resolve(),
7368 isolate->factory()->undefined_value(), arraysize(argv),
7369 argv)
7370 .is_null();
7371 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7372 return Just(true);
7373 }
7374
7375
Resolve(Local<Value> value)7376 void Promise::Resolver::Resolve(Local<Value> value) {
7377 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
7378 USE(Resolve(context, value));
7379 }
7380
7381
Reject(Local<Context> context,Local<Value> value)7382 Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
7383 Local<Value> value) {
7384 PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool);
7385 auto self = Utils::OpenHandle(this);
7386
7387 // We pass true to trigger the debugger's on exception handler.
7388 i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value),
7389 isolate->factory()->ToBoolean(true)};
7390 has_pending_exception =
7391 i::Execution::Call(isolate, isolate->promise_internal_reject(),
7392 isolate->factory()->undefined_value(), arraysize(argv),
7393 argv)
7394 .is_null();
7395 RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
7396 return Just(true);
7397 }
7398
7399
Reject(Local<Value> value)7400 void Promise::Resolver::Reject(Local<Value> value) {
7401 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
7402 USE(Reject(context, value));
7403 }
7404
7405
Catch(Local<Context> context,Local<Function> handler)7406 MaybeLocal<Promise> Promise::Catch(Local<Context> context,
7407 Local<Function> handler) {
7408 PREPARE_FOR_EXECUTION(context, Promise, Catch, Promise);
7409 auto self = Utils::OpenHandle(this);
7410 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
7411 i::Handle<i::Object> result;
7412 has_pending_exception = !i::Execution::Call(isolate, isolate->promise_catch(),
7413 self, arraysize(argv), argv)
7414 .ToHandle(&result);
7415 RETURN_ON_FAILED_EXECUTION(Promise);
7416 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7417 }
7418
7419
Catch(Local<Function> handler)7420 Local<Promise> Promise::Catch(Local<Function> handler) {
7421 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
7422 RETURN_TO_LOCAL_UNCHECKED(Catch(context, handler), Promise);
7423 }
7424
7425
Then(Local<Context> context,Local<Function> handler)7426 MaybeLocal<Promise> Promise::Then(Local<Context> context,
7427 Local<Function> handler) {
7428 PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
7429 auto self = Utils::OpenHandle(this);
7430 i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
7431 i::Handle<i::Object> result;
7432 has_pending_exception = !i::Execution::Call(isolate, isolate->promise_then(),
7433 self, arraysize(argv), argv)
7434 .ToHandle(&result);
7435 RETURN_ON_FAILED_EXECUTION(Promise);
7436 RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
7437 }
7438
7439
Then(Local<Function> handler)7440 Local<Promise> Promise::Then(Local<Function> handler) {
7441 auto context = ContextFromHeapObject(Utils::OpenHandle(this));
7442 RETURN_TO_LOCAL_UNCHECKED(Then(context, handler), Promise);
7443 }
7444
7445
HasHandler()7446 bool Promise::HasHandler() {
7447 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7448 i::Isolate* isolate = promise->GetIsolate();
7449 LOG_API(isolate, Promise, HasRejectHandler);
7450 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7451 if (promise->IsJSPromise()) {
7452 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7453 return js_promise->has_handler();
7454 }
7455 return false;
7456 }
7457
Result()7458 Local<Value> Promise::Result() {
7459 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7460 i::Isolate* isolate = promise->GetIsolate();
7461 LOG_API(isolate, Promise, Result);
7462 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7463 Utils::ApiCheck(js_promise->status() != kPending, "v8_Promise_Result",
7464 "Promise is still pending");
7465 i::Handle<i::Object> result(js_promise->result(), isolate);
7466 return Utils::ToLocal(result);
7467 }
7468
State()7469 Promise::PromiseState Promise::State() {
7470 i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
7471 i::Isolate* isolate = promise->GetIsolate();
7472 LOG_API(isolate, Promise, Status);
7473 i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise);
7474 return static_cast<PromiseState>(js_promise->status());
7475 }
7476
GetTarget()7477 Local<Object> Proxy::GetTarget() {
7478 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7479 i::Handle<i::JSReceiver> target(self->target());
7480 return Utils::ToLocal(target);
7481 }
7482
7483
GetHandler()7484 Local<Value> Proxy::GetHandler() {
7485 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7486 i::Handle<i::Object> handler(self->handler(), self->GetIsolate());
7487 return Utils::ToLocal(handler);
7488 }
7489
7490
IsRevoked()7491 bool Proxy::IsRevoked() {
7492 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7493 return self->IsRevoked();
7494 }
7495
7496
Revoke()7497 void Proxy::Revoke() {
7498 i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
7499 i::JSProxy::Revoke(self);
7500 }
7501
7502
New(Local<Context> context,Local<Object> local_target,Local<Object> local_handler)7503 MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
7504 Local<Object> local_handler) {
7505 PREPARE_FOR_EXECUTION(context, Proxy, New, Proxy);
7506 i::Handle<i::JSReceiver> target = Utils::OpenHandle(*local_target);
7507 i::Handle<i::JSReceiver> handler = Utils::OpenHandle(*local_handler);
7508 Local<Proxy> result;
7509 has_pending_exception =
7510 !ToLocal<Proxy>(i::JSProxy::New(isolate, target, handler), &result);
7511 RETURN_ON_FAILED_EXECUTION(Proxy);
7512 RETURN_ESCAPED(result);
7513 }
7514
GetWasmWireBytes()7515 Local<String> WasmCompiledModule::GetWasmWireBytes() {
7516 i::Handle<i::JSObject> obj =
7517 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
7518 i::Handle<i::WasmCompiledModule> compiled_part =
7519 i::handle(i::WasmCompiledModule::cast(obj->GetInternalField(0)));
7520 i::Handle<i::String> wire_bytes(compiled_part->module_bytes());
7521 return Local<String>::Cast(Utils::ToLocal(wire_bytes));
7522 }
7523
Serialize()7524 WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
7525 i::Handle<i::JSObject> obj =
7526 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
7527 i::Handle<i::WasmCompiledModule> compiled_part =
7528 i::handle(i::WasmCompiledModule::cast(obj->GetInternalField(0)));
7529
7530 std::unique_ptr<i::ScriptData> script_data =
7531 i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),
7532 compiled_part);
7533 script_data->ReleaseDataOwnership();
7534
7535 size_t size = static_cast<size_t>(script_data->length());
7536 return {std::unique_ptr<const uint8_t[]>(script_data->data()), size};
7537 }
7538
Deserialize(Isolate * isolate,const WasmCompiledModule::CallerOwnedBuffer & serialized_module,const WasmCompiledModule::CallerOwnedBuffer & wire_bytes)7539 MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
7540 Isolate* isolate,
7541 const WasmCompiledModule::CallerOwnedBuffer& serialized_module,
7542 const WasmCompiledModule::CallerOwnedBuffer& wire_bytes) {
7543 int size = static_cast<int>(serialized_module.second);
7544 i::ScriptData sc(serialized_module.first, size);
7545 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7546 i::MaybeHandle<i::FixedArray> maybe_compiled_part =
7547 i::WasmCompiledModuleSerializer::DeserializeWasmModule(
7548 i_isolate, &sc,
7549 {wire_bytes.first, static_cast<int>(wire_bytes.second)});
7550 i::Handle<i::FixedArray> compiled_part;
7551 if (!maybe_compiled_part.ToHandle(&compiled_part)) {
7552 return MaybeLocal<WasmCompiledModule>();
7553 }
7554 i::Handle<i::WasmCompiledModule> compiled_module =
7555 handle(i::WasmCompiledModule::cast(*compiled_part));
7556 return Local<WasmCompiledModule>::Cast(
7557 Utils::ToLocal(i::Handle<i::JSObject>::cast(
7558 i::WasmModuleObject::New(i_isolate, compiled_module))));
7559 }
7560
DeserializeOrCompile(Isolate * isolate,const WasmCompiledModule::CallerOwnedBuffer & serialized_module,const WasmCompiledModule::CallerOwnedBuffer & wire_bytes)7561 MaybeLocal<WasmCompiledModule> WasmCompiledModule::DeserializeOrCompile(
7562 Isolate* isolate,
7563 const WasmCompiledModule::CallerOwnedBuffer& serialized_module,
7564 const WasmCompiledModule::CallerOwnedBuffer& wire_bytes) {
7565 MaybeLocal<WasmCompiledModule> ret =
7566 Deserialize(isolate, serialized_module, wire_bytes);
7567 if (!ret.IsEmpty()) {
7568 return ret;
7569 }
7570 return Compile(isolate, wire_bytes.first, wire_bytes.second);
7571 }
7572
Compile(Isolate * isolate,const uint8_t * start,size_t length)7573 MaybeLocal<WasmCompiledModule> WasmCompiledModule::Compile(Isolate* isolate,
7574 const uint8_t* start,
7575 size_t length) {
7576 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7577 i::wasm::ErrorThrower thrower(i_isolate, "WasmCompiledModule::Deserialize()");
7578 i::MaybeHandle<i::JSObject> maybe_compiled = i::wasm::SyncCompile(
7579 i_isolate, &thrower, i::wasm::ModuleWireBytes(start, start + length));
7580 if (maybe_compiled.is_null()) return MaybeLocal<WasmCompiledModule>();
7581 return Local<WasmCompiledModule>::Cast(
7582 Utils::ToLocal(maybe_compiled.ToHandleChecked()));
7583 }
7584
7585 // static
NewDefaultAllocator()7586 v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() {
7587 return new ArrayBufferAllocator();
7588 }
7589
IsExternal() const7590 bool v8::ArrayBuffer::IsExternal() const {
7591 return Utils::OpenHandle(this)->is_external();
7592 }
7593
7594
IsNeuterable() const7595 bool v8::ArrayBuffer::IsNeuterable() const {
7596 return Utils::OpenHandle(this)->is_neuterable();
7597 }
7598
7599
Externalize()7600 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
7601 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
7602 i::Isolate* isolate = self->GetIsolate();
7603 Utils::ApiCheck(!self->is_external(), "v8_ArrayBuffer_Externalize",
7604 "ArrayBuffer already externalized");
7605 self->set_is_external(true);
7606 isolate->heap()->UnregisterArrayBuffer(*self);
7607
7608 return GetContents();
7609 }
7610
7611
GetContents()7612 v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents() {
7613 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
7614 size_t byte_length = static_cast<size_t>(self->byte_length()->Number());
7615 Contents contents;
7616 contents.data_ = self->backing_store();
7617 contents.byte_length_ = byte_length;
7618 return contents;
7619 }
7620
7621
Neuter()7622 void v8::ArrayBuffer::Neuter() {
7623 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7624 i::Isolate* isolate = obj->GetIsolate();
7625 Utils::ApiCheck(obj->is_external(),
7626 "v8::ArrayBuffer::Neuter",
7627 "Only externalized ArrayBuffers can be neutered");
7628 Utils::ApiCheck(obj->is_neuterable(), "v8::ArrayBuffer::Neuter",
7629 "Only neuterable ArrayBuffers can be neutered");
7630 LOG_API(isolate, ArrayBuffer, Neuter);
7631 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7632 obj->Neuter();
7633 }
7634
7635
ByteLength() const7636 size_t v8::ArrayBuffer::ByteLength() const {
7637 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7638 return static_cast<size_t>(obj->byte_length()->Number());
7639 }
7640
7641
New(Isolate * isolate,size_t byte_length)7642 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
7643 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7644 LOG_API(i_isolate, ArrayBuffer, New);
7645 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7646 i::Handle<i::JSArrayBuffer> obj =
7647 i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
7648 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
7649 // version that throws an exception or otherwise does not crash.
7650 if (!i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length)) {
7651 i::FatalProcessOutOfMemory("v8::ArrayBuffer::New");
7652 }
7653 return Utils::ToLocal(obj);
7654 }
7655
7656
New(Isolate * isolate,void * data,size_t byte_length,ArrayBufferCreationMode mode)7657 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
7658 size_t byte_length,
7659 ArrayBufferCreationMode mode) {
7660 // Embedders must guarantee that the external backing store is valid.
7661 CHECK(byte_length == 0 || data != NULL);
7662 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7663 LOG_API(i_isolate, ArrayBuffer, New);
7664 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7665 i::Handle<i::JSArrayBuffer> obj =
7666 i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
7667 i::JSArrayBuffer::Setup(obj, i_isolate,
7668 mode == ArrayBufferCreationMode::kExternalized, data,
7669 byte_length);
7670 return Utils::ToLocal(obj);
7671 }
7672
7673
Buffer()7674 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
7675 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7676 i::Handle<i::JSArrayBuffer> buffer;
7677 if (obj->IsJSDataView()) {
7678 i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
7679 DCHECK(data_view->buffer()->IsJSArrayBuffer());
7680 buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()));
7681 } else {
7682 DCHECK(obj->IsJSTypedArray());
7683 buffer = i::JSTypedArray::cast(*obj)->GetBuffer();
7684 }
7685 return Utils::ToLocal(buffer);
7686 }
7687
7688
CopyContents(void * dest,size_t byte_length)7689 size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
7690 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
7691 size_t byte_offset = i::NumberToSize(self->byte_offset());
7692 size_t bytes_to_copy =
7693 i::Min(byte_length, i::NumberToSize(self->byte_length()));
7694 if (bytes_to_copy) {
7695 i::DisallowHeapAllocation no_gc;
7696 i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
7697 const char* source = reinterpret_cast<char*>(buffer->backing_store());
7698 if (source == nullptr) {
7699 DCHECK(self->IsJSTypedArray());
7700 i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*self));
7701 i::Handle<i::FixedTypedArrayBase> fixed_array(
7702 i::FixedTypedArrayBase::cast(typed_array->elements()));
7703 source = reinterpret_cast<char*>(fixed_array->DataPtr());
7704 }
7705 memcpy(dest, source + byte_offset, bytes_to_copy);
7706 }
7707 return bytes_to_copy;
7708 }
7709
7710
HasBuffer() const7711 bool v8::ArrayBufferView::HasBuffer() const {
7712 i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
7713 i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
7714 return buffer->backing_store() != nullptr;
7715 }
7716
7717
ByteOffset()7718 size_t v8::ArrayBufferView::ByteOffset() {
7719 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7720 return static_cast<size_t>(obj->byte_offset()->Number());
7721 }
7722
7723
ByteLength()7724 size_t v8::ArrayBufferView::ByteLength() {
7725 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7726 return static_cast<size_t>(obj->byte_length()->Number());
7727 }
7728
7729
Length()7730 size_t v8::TypedArray::Length() {
7731 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
7732 return static_cast<size_t>(obj->length_value());
7733 }
7734
7735 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size) \
7736 Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer, \
7737 size_t byte_offset, size_t length) { \
7738 i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \
7739 LOG_API(isolate, Type##Array, New); \
7740 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
7741 if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue), \
7742 "v8::" #Type \
7743 "Array::New(Local<ArrayBuffer>, size_t, size_t)", \
7744 "length exceeds max allowed value")) { \
7745 return Local<Type##Array>(); \
7746 } \
7747 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); \
7748 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
7749 i::kExternal##Type##Array, buffer, byte_offset, length); \
7750 return Utils::ToLocal##Type##Array(obj); \
7751 } \
7752 Local<Type##Array> Type##Array::New( \
7753 Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset, \
7754 size_t length) { \
7755 CHECK(i::FLAG_harmony_sharedarraybuffer); \
7756 i::Isolate* isolate = \
7757 Utils::OpenHandle(*shared_array_buffer)->GetIsolate(); \
7758 LOG_API(isolate, Type##Array, New); \
7759 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
7760 if (!Utils::ApiCheck( \
7761 length <= static_cast<size_t>(i::Smi::kMaxValue), \
7762 "v8::" #Type \
7763 "Array::New(Local<SharedArrayBuffer>, size_t, size_t)", \
7764 "length exceeds max allowed value")) { \
7765 return Local<Type##Array>(); \
7766 } \
7767 i::Handle<i::JSArrayBuffer> buffer = \
7768 Utils::OpenHandle(*shared_array_buffer); \
7769 i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray( \
7770 i::kExternal##Type##Array, buffer, byte_offset, length); \
7771 return Utils::ToLocal##Type##Array(obj); \
7772 }
7773
TYPED_ARRAYS(TYPED_ARRAY_NEW)7774 TYPED_ARRAYS(TYPED_ARRAY_NEW)
7775 #undef TYPED_ARRAY_NEW
7776
7777 Local<DataView> DataView::New(Local<ArrayBuffer> array_buffer,
7778 size_t byte_offset, size_t byte_length) {
7779 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
7780 i::Isolate* isolate = buffer->GetIsolate();
7781 LOG_API(isolate, DataView, New);
7782 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7783 i::Handle<i::JSDataView> obj =
7784 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
7785 return Utils::ToLocal(obj);
7786 }
7787
7788
New(Local<SharedArrayBuffer> shared_array_buffer,size_t byte_offset,size_t byte_length)7789 Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer,
7790 size_t byte_offset, size_t byte_length) {
7791 CHECK(i::FLAG_harmony_sharedarraybuffer);
7792 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer);
7793 i::Isolate* isolate = buffer->GetIsolate();
7794 LOG_API(isolate, DataView, New);
7795 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
7796 i::Handle<i::JSDataView> obj =
7797 isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
7798 return Utils::ToLocal(obj);
7799 }
7800
7801
IsExternal() const7802 bool v8::SharedArrayBuffer::IsExternal() const {
7803 return Utils::OpenHandle(this)->is_external();
7804 }
7805
7806
Externalize()7807 v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
7808 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
7809 i::Isolate* isolate = self->GetIsolate();
7810 Utils::ApiCheck(!self->is_external(), "v8_SharedArrayBuffer_Externalize",
7811 "SharedArrayBuffer already externalized");
7812 self->set_is_external(true);
7813 isolate->heap()->UnregisterArrayBuffer(*self);
7814 return GetContents();
7815 }
7816
7817
GetContents()7818 v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents() {
7819 i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
7820 size_t byte_length = static_cast<size_t>(self->byte_length()->Number());
7821 Contents contents;
7822 contents.data_ = self->backing_store();
7823 contents.byte_length_ = byte_length;
7824 return contents;
7825 }
7826
7827
ByteLength() const7828 size_t v8::SharedArrayBuffer::ByteLength() const {
7829 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
7830 return static_cast<size_t>(obj->byte_length()->Number());
7831 }
7832
7833
New(Isolate * isolate,size_t byte_length)7834 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
7835 size_t byte_length) {
7836 CHECK(i::FLAG_harmony_sharedarraybuffer);
7837 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7838 LOG_API(i_isolate, SharedArrayBuffer, New);
7839 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7840 i::Handle<i::JSArrayBuffer> obj =
7841 i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
7842 // TODO(jbroman): It may be useful in the future to provide a MaybeLocal
7843 // version that throws an exception or otherwise does not crash.
7844 if (!i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length, true,
7845 i::SharedFlag::kShared)) {
7846 i::FatalProcessOutOfMemory("v8::SharedArrayBuffer::New");
7847 }
7848 return Utils::ToLocalShared(obj);
7849 }
7850
7851
New(Isolate * isolate,void * data,size_t byte_length,ArrayBufferCreationMode mode)7852 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
7853 Isolate* isolate, void* data, size_t byte_length,
7854 ArrayBufferCreationMode mode) {
7855 CHECK(i::FLAG_harmony_sharedarraybuffer);
7856 // Embedders must guarantee that the external backing store is valid.
7857 CHECK(byte_length == 0 || data != NULL);
7858 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7859 LOG_API(i_isolate, SharedArrayBuffer, New);
7860 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7861 i::Handle<i::JSArrayBuffer> obj =
7862 i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
7863 i::JSArrayBuffer::Setup(obj, i_isolate,
7864 mode == ArrayBufferCreationMode::kExternalized, data,
7865 byte_length, i::SharedFlag::kShared);
7866 return Utils::ToLocalShared(obj);
7867 }
7868
7869
New(Isolate * isolate,Local<String> name)7870 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
7871 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7872 LOG_API(i_isolate, Symbol, New);
7873 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7874 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
7875 if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
7876 return Utils::ToLocal(result);
7877 }
7878
7879
For(Isolate * isolate,Local<String> name)7880 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
7881 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7882 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
7883 return Utils::ToLocal(i_isolate->SymbolFor(
7884 i::Heap::kPublicSymbolTableRootIndex, i_name, false));
7885 }
7886
7887
ForApi(Isolate * isolate,Local<String> name)7888 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
7889 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7890 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
7891 return Utils::ToLocal(
7892 i_isolate->SymbolFor(i::Heap::kApiSymbolTableRootIndex, i_name, false));
7893 }
7894
7895
GetIterator(Isolate * isolate)7896 Local<Symbol> v8::Symbol::GetIterator(Isolate* isolate) {
7897 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7898 return Utils::ToLocal(i_isolate->factory()->iterator_symbol());
7899 }
7900
7901
GetUnscopables(Isolate * isolate)7902 Local<Symbol> v8::Symbol::GetUnscopables(Isolate* isolate) {
7903 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7904 return Utils::ToLocal(i_isolate->factory()->unscopables_symbol());
7905 }
7906
GetToPrimitive(Isolate * isolate)7907 Local<Symbol> v8::Symbol::GetToPrimitive(Isolate* isolate) {
7908 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7909 return Utils::ToLocal(i_isolate->factory()->to_primitive_symbol());
7910 }
7911
GetToStringTag(Isolate * isolate)7912 Local<Symbol> v8::Symbol::GetToStringTag(Isolate* isolate) {
7913 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7914 return Utils::ToLocal(i_isolate->factory()->to_string_tag_symbol());
7915 }
7916
7917
GetIsConcatSpreadable(Isolate * isolate)7918 Local<Symbol> v8::Symbol::GetIsConcatSpreadable(Isolate* isolate) {
7919 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7920 return Utils::ToLocal(i_isolate->factory()->is_concat_spreadable_symbol());
7921 }
7922
7923
New(Isolate * isolate,Local<String> name)7924 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
7925 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7926 LOG_API(i_isolate, Private, New);
7927 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7928 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
7929 if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
7930 Local<Symbol> result = Utils::ToLocal(symbol);
7931 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
7932 }
7933
7934
ForApi(Isolate * isolate,Local<String> name)7935 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
7936 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7937 i::Handle<i::String> i_name = Utils::OpenHandle(*name);
7938 Local<Symbol> result = Utils::ToLocal(i_isolate->SymbolFor(
7939 i::Heap::kApiPrivateSymbolTableRootIndex, i_name, true));
7940 return v8::Local<Private>(reinterpret_cast<Private*>(*result));
7941 }
7942
7943
New(Isolate * isolate,double value)7944 Local<Number> v8::Number::New(Isolate* isolate, double value) {
7945 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
7946 if (std::isnan(value)) {
7947 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
7948 value = std::numeric_limits<double>::quiet_NaN();
7949 }
7950 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
7951 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
7952 return Utils::NumberToLocal(result);
7953 }
7954
7955
New(Isolate * isolate,int32_t value)7956 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
7957 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
7958 if (i::Smi::IsValid(value)) {
7959 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
7960 internal_isolate));
7961 }
7962 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
7963 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
7964 return Utils::IntegerToLocal(result);
7965 }
7966
7967
NewFromUnsigned(Isolate * isolate,uint32_t value)7968 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
7969 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
7970 bool fits_into_int32_t = (value & (1 << 31)) == 0;
7971 if (fits_into_int32_t) {
7972 return Integer::New(isolate, static_cast<int32_t>(value));
7973 }
7974 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
7975 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
7976 return Utils::IntegerToLocal(result);
7977 }
7978
7979
ReportExternalAllocationLimitReached()7980 void Isolate::ReportExternalAllocationLimitReached() {
7981 i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
7982 if (heap->gc_state() != i::Heap::NOT_IN_GC) return;
7983 heap->ReportExternalMemoryPressure();
7984 }
7985
7986
GetHeapProfiler()7987 HeapProfiler* Isolate::GetHeapProfiler() {
7988 i::HeapProfiler* heap_profiler =
7989 reinterpret_cast<i::Isolate*>(this)->heap_profiler();
7990 return reinterpret_cast<HeapProfiler*>(heap_profiler);
7991 }
7992
7993
GetCpuProfiler()7994 CpuProfiler* Isolate::GetCpuProfiler() {
7995 i::CpuProfiler* cpu_profiler =
7996 reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
7997 return reinterpret_cast<CpuProfiler*>(cpu_profiler);
7998 }
7999
8000
InContext()8001 bool Isolate::InContext() {
8002 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8003 return isolate->context() != NULL;
8004 }
8005
8006
GetCurrentContext()8007 v8::Local<v8::Context> Isolate::GetCurrentContext() {
8008 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8009 i::Context* context = isolate->context();
8010 if (context == NULL) return Local<Context>();
8011 i::Context* native_context = context->native_context();
8012 if (native_context == NULL) return Local<Context>();
8013 return Utils::ToLocal(i::Handle<i::Context>(native_context));
8014 }
8015
8016
GetCallingContext()8017 v8::Local<v8::Context> Isolate::GetCallingContext() {
8018 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8019 i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
8020 if (calling.is_null()) return Local<Context>();
8021 return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
8022 }
8023
8024
GetEnteredContext()8025 v8::Local<v8::Context> Isolate::GetEnteredContext() {
8026 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8027 i::Handle<i::Object> last =
8028 isolate->handle_scope_implementer()->LastEnteredContext();
8029 if (last.is_null()) return Local<Context>();
8030 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
8031 }
8032
GetEnteredOrMicrotaskContext()8033 v8::Local<v8::Context> Isolate::GetEnteredOrMicrotaskContext() {
8034 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8035 i::Handle<i::Object> last;
8036 if (isolate->handle_scope_implementer()
8037 ->MicrotaskContextIsLastEnteredContext()) {
8038 last = isolate->handle_scope_implementer()->MicrotaskContext();
8039 } else {
8040 last = isolate->handle_scope_implementer()->LastEnteredContext();
8041 }
8042 if (last.is_null()) return Local<Context>();
8043 return Utils::ToLocal(i::Handle<i::Context>::cast(last));
8044 }
8045
ThrowException(v8::Local<v8::Value> value)8046 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
8047 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8048 ENTER_V8(isolate);
8049 // If we're passed an empty handle, we throw an undefined exception
8050 // to deal more gracefully with out of memory situations.
8051 if (value.IsEmpty()) {
8052 isolate->ScheduleThrow(isolate->heap()->undefined_value());
8053 } else {
8054 isolate->ScheduleThrow(*Utils::OpenHandle(*value));
8055 }
8056 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
8057 }
8058
8059
SetObjectGroupId(internal::Object ** object,UniqueId id)8060 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
8061 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
8062 internal_isolate->global_handles()->SetObjectGroupId(
8063 i::Handle<i::Object>(object).location(), id);
8064 }
8065
8066
SetReferenceFromGroup(UniqueId id,internal::Object ** object)8067 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
8068 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
8069 internal_isolate->global_handles()->SetReferenceFromGroup(
8070 id, i::Handle<i::Object>(object).location());
8071 }
8072
8073
SetReference(internal::Object ** parent,internal::Object ** child)8074 void Isolate::SetReference(internal::Object** parent,
8075 internal::Object** child) {
8076 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
8077 i::Object** parent_location = i::Handle<i::Object>(parent).location();
8078 internal_isolate->global_handles()->SetReference(
8079 reinterpret_cast<i::HeapObject**>(parent_location),
8080 i::Handle<i::Object>(child).location());
8081 }
8082
8083
AddGCPrologueCallback(GCCallback callback,GCType gc_type)8084 void Isolate::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
8085 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8086 isolate->heap()->AddGCPrologueCallback(callback, gc_type);
8087 }
8088
8089
RemoveGCPrologueCallback(GCCallback callback)8090 void Isolate::RemoveGCPrologueCallback(GCCallback callback) {
8091 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8092 isolate->heap()->RemoveGCPrologueCallback(callback);
8093 }
8094
8095
AddGCEpilogueCallback(GCCallback callback,GCType gc_type)8096 void Isolate::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
8097 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8098 isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
8099 }
8100
8101
RemoveGCEpilogueCallback(GCCallback callback)8102 void Isolate::RemoveGCEpilogueCallback(GCCallback callback) {
8103 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8104 isolate->heap()->RemoveGCEpilogueCallback(callback);
8105 }
8106
8107
AddGCPrologueCallback(GCCallback callback,GCType gc_type)8108 void V8::AddGCPrologueCallback(GCCallback callback, GCType gc_type) {
8109 i::Isolate* isolate = i::Isolate::Current();
8110 isolate->heap()->AddGCPrologueCallback(
8111 reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
8112 }
8113
8114
AddGCEpilogueCallback(GCCallback callback,GCType gc_type)8115 void V8::AddGCEpilogueCallback(GCCallback callback, GCType gc_type) {
8116 i::Isolate* isolate = i::Isolate::Current();
8117 isolate->heap()->AddGCEpilogueCallback(
8118 reinterpret_cast<v8::Isolate::GCCallback>(callback), gc_type, false);
8119 }
8120
SetEmbedderHeapTracer(EmbedderHeapTracer * tracer)8121 void Isolate::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
8122 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8123 isolate->heap()->SetEmbedderHeapTracer(tracer);
8124 }
8125
TerminateExecution()8126 void Isolate::TerminateExecution() {
8127 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8128 isolate->stack_guard()->RequestTerminateExecution();
8129 }
8130
8131
IsExecutionTerminating()8132 bool Isolate::IsExecutionTerminating() {
8133 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8134 return IsExecutionTerminatingCheck(isolate);
8135 }
8136
8137
CancelTerminateExecution()8138 void Isolate::CancelTerminateExecution() {
8139 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8140 isolate->stack_guard()->ClearTerminateExecution();
8141 isolate->CancelTerminateExecution();
8142 }
8143
8144
RequestInterrupt(InterruptCallback callback,void * data)8145 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
8146 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8147 isolate->RequestInterrupt(callback, data);
8148 }
8149
8150
RequestGarbageCollectionForTesting(GarbageCollectionType type)8151 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
8152 CHECK(i::FLAG_expose_gc);
8153 if (type == kMinorGarbageCollection) {
8154 reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
8155 i::NEW_SPACE, i::GarbageCollectionReason::kTesting,
8156 kGCCallbackFlagForced);
8157 } else {
8158 DCHECK_EQ(kFullGarbageCollection, type);
8159 reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
8160 i::Heap::kAbortIncrementalMarkingMask,
8161 i::GarbageCollectionReason::kTesting, kGCCallbackFlagForced);
8162 }
8163 }
8164
8165
GetCurrent()8166 Isolate* Isolate::GetCurrent() {
8167 i::Isolate* isolate = i::Isolate::Current();
8168 return reinterpret_cast<Isolate*>(isolate);
8169 }
8170
8171
New(const Isolate::CreateParams & params)8172 Isolate* Isolate::New(const Isolate::CreateParams& params) {
8173 i::Isolate* isolate = new i::Isolate(false);
8174 Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
8175 CHECK(params.array_buffer_allocator != NULL);
8176 isolate->set_array_buffer_allocator(params.array_buffer_allocator);
8177 if (params.snapshot_blob != NULL) {
8178 isolate->set_snapshot_blob(params.snapshot_blob);
8179 } else {
8180 isolate->set_snapshot_blob(i::Snapshot::DefaultSnapshotBlob());
8181 }
8182 if (params.entry_hook) {
8183 isolate->set_function_entry_hook(params.entry_hook);
8184 }
8185 auto code_event_handler = params.code_event_handler;
8186 #ifdef ENABLE_GDB_JIT_INTERFACE
8187 if (code_event_handler == nullptr && i::FLAG_gdbjit) {
8188 code_event_handler = i::GDBJITInterface::EventHandler;
8189 }
8190 #endif // ENABLE_GDB_JIT_INTERFACE
8191 if (code_event_handler) {
8192 isolate->InitializeLoggingAndCounters();
8193 isolate->logger()->SetCodeEventHandler(kJitCodeEventDefault,
8194 code_event_handler);
8195 }
8196 if (params.counter_lookup_callback) {
8197 v8_isolate->SetCounterFunction(params.counter_lookup_callback);
8198 }
8199
8200 if (params.create_histogram_callback) {
8201 v8_isolate->SetCreateHistogramFunction(params.create_histogram_callback);
8202 }
8203
8204 if (params.add_histogram_sample_callback) {
8205 v8_isolate->SetAddHistogramSampleFunction(
8206 params.add_histogram_sample_callback);
8207 }
8208
8209 isolate->set_api_external_references(params.external_references);
8210 isolate->set_allow_atomics_wait(params.allow_atomics_wait);
8211 SetResourceConstraints(isolate, params.constraints);
8212 // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
8213 Isolate::Scope isolate_scope(v8_isolate);
8214 if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
8215 isolate->Init(NULL);
8216 }
8217 return v8_isolate;
8218 }
8219
8220
Dispose()8221 void Isolate::Dispose() {
8222 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8223 if (!Utils::ApiCheck(!isolate->IsInUse(),
8224 "v8::Isolate::Dispose()",
8225 "Disposing the isolate that is entered by a thread.")) {
8226 return;
8227 }
8228 isolate->TearDown();
8229 }
8230
8231
DiscardThreadSpecificMetadata()8232 void Isolate::DiscardThreadSpecificMetadata() {
8233 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8234 isolate->DiscardPerThreadDataForThisThread();
8235 }
8236
8237
Enter()8238 void Isolate::Enter() {
8239 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8240 isolate->Enter();
8241 }
8242
8243
Exit()8244 void Isolate::Exit() {
8245 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8246 isolate->Exit();
8247 }
8248
8249
SetAbortOnUncaughtExceptionCallback(AbortOnUncaughtExceptionCallback callback)8250 void Isolate::SetAbortOnUncaughtExceptionCallback(
8251 AbortOnUncaughtExceptionCallback callback) {
8252 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8253 isolate->SetAbortOnUncaughtExceptionCallback(callback);
8254 }
8255
8256
DisallowJavascriptExecutionScope(Isolate * isolate,Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)8257 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
8258 Isolate* isolate,
8259 Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
8260 : on_failure_(on_failure) {
8261 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8262 if (on_failure_ == CRASH_ON_FAILURE) {
8263 internal_ = reinterpret_cast<void*>(
8264 new i::DisallowJavascriptExecution(i_isolate));
8265 } else {
8266 DCHECK_EQ(THROW_ON_FAILURE, on_failure);
8267 internal_ = reinterpret_cast<void*>(
8268 new i::ThrowOnJavascriptExecution(i_isolate));
8269 }
8270 }
8271
8272
~DisallowJavascriptExecutionScope()8273 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
8274 if (on_failure_ == CRASH_ON_FAILURE) {
8275 delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
8276 } else {
8277 delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
8278 }
8279 }
8280
8281
AllowJavascriptExecutionScope(Isolate * isolate)8282 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
8283 Isolate* isolate) {
8284 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8285 internal_assert_ = reinterpret_cast<void*>(
8286 new i::AllowJavascriptExecution(i_isolate));
8287 internal_throws_ = reinterpret_cast<void*>(
8288 new i::NoThrowOnJavascriptExecution(i_isolate));
8289 }
8290
8291
~AllowJavascriptExecutionScope()8292 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
8293 delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
8294 delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
8295 }
8296
8297
SuppressMicrotaskExecutionScope(Isolate * isolate)8298 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
8299 Isolate* isolate)
8300 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
8301 isolate_->handle_scope_implementer()->IncrementCallDepth();
8302 isolate_->handle_scope_implementer()->IncrementMicrotasksSuppressions();
8303 }
8304
8305
~SuppressMicrotaskExecutionScope()8306 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
8307 isolate_->handle_scope_implementer()->DecrementMicrotasksSuppressions();
8308 isolate_->handle_scope_implementer()->DecrementCallDepth();
8309 }
8310
8311
GetHeapStatistics(HeapStatistics * heap_statistics)8312 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
8313 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8314 i::Heap* heap = isolate->heap();
8315 heap_statistics->total_heap_size_ = heap->CommittedMemory();
8316 heap_statistics->total_heap_size_executable_ =
8317 heap->CommittedMemoryExecutable();
8318 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
8319 heap_statistics->total_available_size_ = heap->Available();
8320 heap_statistics->used_heap_size_ = heap->SizeOfObjects();
8321 heap_statistics->heap_size_limit_ = heap->MaxReserved();
8322 heap_statistics->malloced_memory_ =
8323 isolate->allocator()->GetCurrentMemoryUsage();
8324 heap_statistics->peak_malloced_memory_ =
8325 isolate->allocator()->GetMaxMemoryUsage();
8326 heap_statistics->does_zap_garbage_ = heap->ShouldZapGarbage();
8327 }
8328
8329
NumberOfHeapSpaces()8330 size_t Isolate::NumberOfHeapSpaces() {
8331 return i::LAST_SPACE - i::FIRST_SPACE + 1;
8332 }
8333
8334
GetHeapSpaceStatistics(HeapSpaceStatistics * space_statistics,size_t index)8335 bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics,
8336 size_t index) {
8337 if (!space_statistics) return false;
8338 if (!i::Heap::IsValidAllocationSpace(static_cast<i::AllocationSpace>(index)))
8339 return false;
8340
8341 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8342 i::Heap* heap = isolate->heap();
8343 i::Space* space = heap->space(static_cast<int>(index));
8344
8345 space_statistics->space_name_ = heap->GetSpaceName(static_cast<int>(index));
8346 space_statistics->space_size_ = space->CommittedMemory();
8347 space_statistics->space_used_size_ = space->SizeOfObjects();
8348 space_statistics->space_available_size_ = space->Available();
8349 space_statistics->physical_space_size_ = space->CommittedPhysicalMemory();
8350 return true;
8351 }
8352
8353
NumberOfTrackedHeapObjectTypes()8354 size_t Isolate::NumberOfTrackedHeapObjectTypes() {
8355 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8356 i::Heap* heap = isolate->heap();
8357 return heap->NumberOfTrackedHeapObjectTypes();
8358 }
8359
8360
GetHeapObjectStatisticsAtLastGC(HeapObjectStatistics * object_statistics,size_t type_index)8361 bool Isolate::GetHeapObjectStatisticsAtLastGC(
8362 HeapObjectStatistics* object_statistics, size_t type_index) {
8363 if (!object_statistics) return false;
8364 if (V8_LIKELY(!i::FLAG_gc_stats)) return false;
8365
8366 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8367 i::Heap* heap = isolate->heap();
8368 if (type_index >= heap->NumberOfTrackedHeapObjectTypes()) return false;
8369
8370 const char* object_type;
8371 const char* object_sub_type;
8372 size_t object_count = heap->ObjectCountAtLastGC(type_index);
8373 size_t object_size = heap->ObjectSizeAtLastGC(type_index);
8374 if (!heap->GetObjectTypeName(type_index, &object_type, &object_sub_type)) {
8375 // There should be no objects counted when the type is unknown.
8376 DCHECK_EQ(object_count, 0U);
8377 DCHECK_EQ(object_size, 0U);
8378 return false;
8379 }
8380
8381 object_statistics->object_type_ = object_type;
8382 object_statistics->object_sub_type_ = object_sub_type;
8383 object_statistics->object_count_ = object_count;
8384 object_statistics->object_size_ = object_size;
8385 return true;
8386 }
8387
GetHeapCodeAndMetadataStatistics(HeapCodeStatistics * code_statistics)8388 bool Isolate::GetHeapCodeAndMetadataStatistics(
8389 HeapCodeStatistics* code_statistics) {
8390 if (!code_statistics) return false;
8391
8392 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8393 isolate->heap()->CollectCodeStatistics();
8394
8395 code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size();
8396 code_statistics->bytecode_and_metadata_size_ =
8397 isolate->bytecode_and_metadata_size();
8398 return true;
8399 }
8400
GetStackSample(const RegisterState & state,void ** frames,size_t frames_limit,SampleInfo * sample_info)8401 void Isolate::GetStackSample(const RegisterState& state, void** frames,
8402 size_t frames_limit, SampleInfo* sample_info) {
8403 RegisterState regs = state;
8404 if (TickSample::GetStackSample(this, ®s, TickSample::kSkipCEntryFrame,
8405 frames, frames_limit, sample_info)) {
8406 return;
8407 }
8408 sample_info->frames_count = 0;
8409 sample_info->vm_state = OTHER;
8410 sample_info->external_callback_entry = nullptr;
8411 }
8412
NumberOfPhantomHandleResetsSinceLastCall()8413 size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
8414 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8415 size_t result = isolate->global_handles()->NumberOfPhantomHandleResets();
8416 isolate->global_handles()->ResetNumberOfPhantomHandleResets();
8417 return result;
8418 }
8419
SetEventLogger(LogEventCallback that)8420 void Isolate::SetEventLogger(LogEventCallback that) {
8421 // Do not overwrite the event logger if we want to log explicitly.
8422 if (i::FLAG_log_internal_timer_events) return;
8423 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8424 isolate->set_event_logger(that);
8425 }
8426
8427
AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)8428 void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
8429 if (callback == NULL) return;
8430 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8431 isolate->AddBeforeCallEnteredCallback(callback);
8432 }
8433
8434
RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)8435 void Isolate::RemoveBeforeCallEnteredCallback(
8436 BeforeCallEnteredCallback callback) {
8437 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8438 isolate->RemoveBeforeCallEnteredCallback(callback);
8439 }
8440
8441
AddCallCompletedCallback(CallCompletedCallback callback)8442 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
8443 if (callback == NULL) return;
8444 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8445 isolate->AddCallCompletedCallback(callback);
8446 }
8447
8448
RemoveCallCompletedCallback(CallCompletedCallback callback)8449 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
8450 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8451 isolate->RemoveCallCompletedCallback(callback);
8452 }
8453
8454
AddCallCompletedCallback(DeprecatedCallCompletedCallback callback)8455 void Isolate::AddCallCompletedCallback(
8456 DeprecatedCallCompletedCallback callback) {
8457 AddCallCompletedCallback(reinterpret_cast<CallCompletedCallback>(callback));
8458 }
8459
8460
RemoveCallCompletedCallback(DeprecatedCallCompletedCallback callback)8461 void Isolate::RemoveCallCompletedCallback(
8462 DeprecatedCallCompletedCallback callback) {
8463 RemoveCallCompletedCallback(
8464 reinterpret_cast<CallCompletedCallback>(callback));
8465 }
8466
SetPromiseHook(PromiseHook hook)8467 void Isolate::SetPromiseHook(PromiseHook hook) {
8468 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8469 isolate->SetPromiseHook(hook);
8470 }
8471
SetPromiseRejectCallback(PromiseRejectCallback callback)8472 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
8473 if (callback == NULL) return;
8474 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8475 isolate->SetPromiseRejectCallback(callback);
8476 }
8477
8478
RunMicrotasks()8479 void Isolate::RunMicrotasks() {
8480 DCHECK(MicrotasksPolicy::kScoped != GetMicrotasksPolicy());
8481 reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
8482 }
8483
8484
EnqueueMicrotask(Local<Function> microtask)8485 void Isolate::EnqueueMicrotask(Local<Function> microtask) {
8486 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8487 isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
8488 }
8489
8490
EnqueueMicrotask(MicrotaskCallback microtask,void * data)8491 void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
8492 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8493 i::HandleScope scope(isolate);
8494 i::Handle<i::CallHandlerInfo> callback_info =
8495 i::Handle<i::CallHandlerInfo>::cast(
8496 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
8497 SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
8498 SET_FIELD_WRAPPED(callback_info, set_data, data);
8499 isolate->EnqueueMicrotask(callback_info);
8500 }
8501
8502
SetAutorunMicrotasks(bool autorun)8503 void Isolate::SetAutorunMicrotasks(bool autorun) {
8504 SetMicrotasksPolicy(
8505 autorun ? MicrotasksPolicy::kAuto : MicrotasksPolicy::kExplicit);
8506 }
8507
8508
WillAutorunMicrotasks() const8509 bool Isolate::WillAutorunMicrotasks() const {
8510 return GetMicrotasksPolicy() == MicrotasksPolicy::kAuto;
8511 }
8512
8513
SetMicrotasksPolicy(MicrotasksPolicy policy)8514 void Isolate::SetMicrotasksPolicy(MicrotasksPolicy policy) {
8515 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8516 isolate->handle_scope_implementer()->set_microtasks_policy(policy);
8517 }
8518
8519
GetMicrotasksPolicy() const8520 MicrotasksPolicy Isolate::GetMicrotasksPolicy() const {
8521 i::Isolate* isolate =
8522 reinterpret_cast<i::Isolate*>(const_cast<Isolate*>(this));
8523 return isolate->handle_scope_implementer()->microtasks_policy();
8524 }
8525
8526
AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback)8527 void Isolate::AddMicrotasksCompletedCallback(
8528 MicrotasksCompletedCallback callback) {
8529 DCHECK(callback);
8530 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8531 isolate->AddMicrotasksCompletedCallback(callback);
8532 }
8533
8534
RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback)8535 void Isolate::RemoveMicrotasksCompletedCallback(
8536 MicrotasksCompletedCallback callback) {
8537 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8538 isolate->RemoveMicrotasksCompletedCallback(callback);
8539 }
8540
8541
SetUseCounterCallback(UseCounterCallback callback)8542 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
8543 reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
8544 }
8545
8546
SetCounterFunction(CounterLookupCallback callback)8547 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
8548 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8549 isolate->stats_table()->SetCounterFunction(callback);
8550 isolate->InitializeLoggingAndCounters();
8551 isolate->counters()->ResetCounters();
8552 }
8553
8554
SetCreateHistogramFunction(CreateHistogramCallback callback)8555 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
8556 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8557 isolate->stats_table()->SetCreateHistogramFunction(callback);
8558 isolate->InitializeLoggingAndCounters();
8559 isolate->counters()->ResetHistograms();
8560 }
8561
8562
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)8563 void Isolate::SetAddHistogramSampleFunction(
8564 AddHistogramSampleCallback callback) {
8565 reinterpret_cast<i::Isolate*>(this)
8566 ->stats_table()
8567 ->SetAddHistogramSampleFunction(callback);
8568 }
8569
8570
IdleNotification(int idle_time_in_ms)8571 bool Isolate::IdleNotification(int idle_time_in_ms) {
8572 // Returning true tells the caller that it need not
8573 // continue to call IdleNotification.
8574 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8575 if (!i::FLAG_use_idle_notification) return true;
8576 return isolate->heap()->IdleNotification(idle_time_in_ms);
8577 }
8578
8579
IdleNotificationDeadline(double deadline_in_seconds)8580 bool Isolate::IdleNotificationDeadline(double deadline_in_seconds) {
8581 // Returning true tells the caller that it need not
8582 // continue to call IdleNotification.
8583 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8584 if (!i::FLAG_use_idle_notification) return true;
8585 return isolate->heap()->IdleNotification(deadline_in_seconds);
8586 }
8587
8588
LowMemoryNotification()8589 void Isolate::LowMemoryNotification() {
8590 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8591 {
8592 i::HistogramTimerScope idle_notification_scope(
8593 isolate->counters()->gc_low_memory_notification());
8594 TRACE_EVENT0("v8", "V8.GCLowMemoryNotification");
8595 isolate->heap()->CollectAllAvailableGarbage(
8596 i::GarbageCollectionReason::kLowMemoryNotification);
8597 }
8598 }
8599
8600
ContextDisposedNotification(bool dependant_context)8601 int Isolate::ContextDisposedNotification(bool dependant_context) {
8602 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8603 return isolate->heap()->NotifyContextDisposed(dependant_context);
8604 }
8605
8606
IsolateInForegroundNotification()8607 void Isolate::IsolateInForegroundNotification() {
8608 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8609 return isolate->IsolateInForegroundNotification();
8610 }
8611
8612
IsolateInBackgroundNotification()8613 void Isolate::IsolateInBackgroundNotification() {
8614 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8615 return isolate->IsolateInBackgroundNotification();
8616 }
8617
MemoryPressureNotification(MemoryPressureLevel level)8618 void Isolate::MemoryPressureNotification(MemoryPressureLevel level) {
8619 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8620 bool on_isolate_thread =
8621 v8::Locker::IsActive()
8622 ? isolate->thread_manager()->IsLockedByCurrentThread()
8623 : i::ThreadId::Current().Equals(isolate->thread_id());
8624 isolate->heap()->MemoryPressureNotification(level, on_isolate_thread);
8625 isolate->allocator()->MemoryPressureNotification(level);
8626 isolate->compiler_dispatcher()->MemoryPressureNotification(level,
8627 on_isolate_thread);
8628 }
8629
SetRAILMode(RAILMode rail_mode)8630 void Isolate::SetRAILMode(RAILMode rail_mode) {
8631 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8632 return isolate->SetRAILMode(rail_mode);
8633 }
8634
IncreaseHeapLimitForDebugging()8635 void Isolate::IncreaseHeapLimitForDebugging() {
8636 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8637 isolate->heap()->IncreaseHeapLimitForDebugging();
8638 }
8639
RestoreOriginalHeapLimit()8640 void Isolate::RestoreOriginalHeapLimit() {
8641 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8642 isolate->heap()->RestoreOriginalHeapLimit();
8643 }
8644
IsHeapLimitIncreasedForDebugging()8645 bool Isolate::IsHeapLimitIncreasedForDebugging() {
8646 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8647 return isolate->heap()->IsHeapLimitIncreasedForDebugging();
8648 }
8649
SetJitCodeEventHandler(JitCodeEventOptions options,JitCodeEventHandler event_handler)8650 void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
8651 JitCodeEventHandler event_handler) {
8652 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8653 // Ensure that logging is initialized for our isolate.
8654 isolate->InitializeLoggingAndCounters();
8655 isolate->logger()->SetCodeEventHandler(options, event_handler);
8656 }
8657
8658
SetStackLimit(uintptr_t stack_limit)8659 void Isolate::SetStackLimit(uintptr_t stack_limit) {
8660 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8661 CHECK(stack_limit);
8662 isolate->stack_guard()->SetStackLimit(stack_limit);
8663 }
8664
GetCodeRange(void ** start,size_t * length_in_bytes)8665 void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) {
8666 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8667 if (isolate->heap()->memory_allocator()->code_range()->valid()) {
8668 *start = isolate->heap()->memory_allocator()->code_range()->start();
8669 *length_in_bytes =
8670 isolate->heap()->memory_allocator()->code_range()->size();
8671 } else {
8672 *start = NULL;
8673 *length_in_bytes = 0;
8674 }
8675 }
8676
8677
SetFatalErrorHandler(FatalErrorCallback that)8678 void Isolate::SetFatalErrorHandler(FatalErrorCallback that) {
8679 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8680 isolate->set_exception_behavior(that);
8681 }
8682
SetOOMErrorHandler(OOMErrorCallback that)8683 void Isolate::SetOOMErrorHandler(OOMErrorCallback that) {
8684 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8685 isolate->set_oom_behavior(that);
8686 }
8687
SetAllowCodeGenerationFromStringsCallback(AllowCodeGenerationFromStringsCallback callback)8688 void Isolate::SetAllowCodeGenerationFromStringsCallback(
8689 AllowCodeGenerationFromStringsCallback callback) {
8690 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8691 isolate->set_allow_code_gen_callback(callback);
8692 }
8693
SetAllowWasmCompileCallback(AllowWasmCompileCallback callback)8694 void Isolate::SetAllowWasmCompileCallback(AllowWasmCompileCallback callback) {
8695 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8696 isolate->set_allow_wasm_compile_callback(callback);
8697 }
8698
SetAllowWasmInstantiateCallback(AllowWasmInstantiateCallback callback)8699 void Isolate::SetAllowWasmInstantiateCallback(
8700 AllowWasmInstantiateCallback callback) {
8701 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8702 isolate->set_allow_wasm_instantiate_callback(callback);
8703 }
8704
IsDead()8705 bool Isolate::IsDead() {
8706 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8707 return isolate->IsDead();
8708 }
8709
AddMessageListener(MessageCallback that,Local<Value> data)8710 bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) {
8711 return AddMessageListenerWithErrorLevel(that, kMessageError, data);
8712 }
8713
AddMessageListenerWithErrorLevel(MessageCallback that,int message_levels,Local<Value> data)8714 bool Isolate::AddMessageListenerWithErrorLevel(MessageCallback that,
8715 int message_levels,
8716 Local<Value> data) {
8717 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8718 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
8719 i::HandleScope scope(isolate);
8720 i::Handle<i::TemplateList> list = isolate->factory()->message_listeners();
8721 i::Handle<i::FixedArray> listener = isolate->factory()->NewFixedArray(3);
8722 i::Handle<i::Foreign> foreign =
8723 isolate->factory()->NewForeign(FUNCTION_ADDR(that));
8724 listener->set(0, *foreign);
8725 listener->set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
8726 : *Utils::OpenHandle(*data));
8727 listener->set(2, i::Smi::FromInt(message_levels));
8728 list = i::TemplateList::Add(isolate, list, listener);
8729 isolate->heap()->SetMessageListeners(*list);
8730 return true;
8731 }
8732
8733
RemoveMessageListeners(MessageCallback that)8734 void Isolate::RemoveMessageListeners(MessageCallback that) {
8735 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8736 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
8737 i::HandleScope scope(isolate);
8738 i::DisallowHeapAllocation no_gc;
8739 i::TemplateList* listeners = isolate->heap()->message_listeners();
8740 for (int i = 0; i < listeners->length(); i++) {
8741 if (listeners->get(i)->IsUndefined(isolate)) continue; // skip deleted ones
8742 i::FixedArray* listener = i::FixedArray::cast(listeners->get(i));
8743 i::Foreign* callback_obj = i::Foreign::cast(listener->get(0));
8744 if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
8745 listeners->set(i, isolate->heap()->undefined_value());
8746 }
8747 }
8748 }
8749
8750
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)8751 void Isolate::SetFailedAccessCheckCallbackFunction(
8752 FailedAccessCheckCallback callback) {
8753 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8754 isolate->SetFailedAccessCheckCallback(callback);
8755 }
8756
8757
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)8758 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
8759 bool capture, int frame_limit, StackTrace::StackTraceOptions options) {
8760 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8761 isolate->SetCaptureStackTraceForUncaughtExceptions(capture, frame_limit,
8762 options);
8763 }
8764
8765
VisitExternalResources(ExternalResourceVisitor * visitor)8766 void Isolate::VisitExternalResources(ExternalResourceVisitor* visitor) {
8767 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8768 isolate->heap()->VisitExternalResources(visitor);
8769 }
8770
8771
IsInUse()8772 bool Isolate::IsInUse() {
8773 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8774 return isolate->IsInUse();
8775 }
8776
8777
8778 class VisitorAdapter : public i::ObjectVisitor {
8779 public:
VisitorAdapter(PersistentHandleVisitor * visitor)8780 explicit VisitorAdapter(PersistentHandleVisitor* visitor)
8781 : visitor_(visitor) {}
VisitPointers(i::Object ** start,i::Object ** end)8782 void VisitPointers(i::Object** start, i::Object** end) override {
8783 UNREACHABLE();
8784 }
8785 DISABLE_CFI_PERF
VisitEmbedderReference(i::Object ** p,uint16_t class_id)8786 void VisitEmbedderReference(i::Object** p, uint16_t class_id) override {
8787 Value* value = ToApi<Value>(i::Handle<i::Object>(p));
8788 visitor_->VisitPersistentHandle(
8789 reinterpret_cast<Persistent<Value>*>(&value), class_id);
8790 }
8791
8792 private:
8793 PersistentHandleVisitor* visitor_;
8794 };
8795
8796
VisitHandlesWithClassIds(PersistentHandleVisitor * visitor)8797 void Isolate::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
8798 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8799 i::DisallowHeapAllocation no_allocation;
8800 VisitorAdapter visitor_adapter(visitor);
8801 isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
8802 }
8803
8804
VisitHandlesForPartialDependence(PersistentHandleVisitor * visitor)8805 void Isolate::VisitHandlesForPartialDependence(
8806 PersistentHandleVisitor* visitor) {
8807 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8808 i::DisallowHeapAllocation no_allocation;
8809 VisitorAdapter visitor_adapter(visitor);
8810 isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
8811 &visitor_adapter);
8812 }
8813
8814
VisitWeakHandles(PersistentHandleVisitor * visitor)8815 void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) {
8816 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
8817 i::DisallowHeapAllocation no_allocation;
8818 VisitorAdapter visitor_adapter(visitor);
8819 isolate->global_handles()->IterateWeakRootsInNewSpaceWithClassIds(
8820 &visitor_adapter);
8821 }
8822
8823
MicrotasksScope(Isolate * isolate,MicrotasksScope::Type type)8824 MicrotasksScope::MicrotasksScope(Isolate* isolate, MicrotasksScope::Type type)
8825 : isolate_(reinterpret_cast<i::Isolate*>(isolate)),
8826 run_(type == MicrotasksScope::kRunMicrotasks) {
8827 auto handle_scope_implementer = isolate_->handle_scope_implementer();
8828 if (run_) handle_scope_implementer->IncrementMicrotasksScopeDepth();
8829 #ifdef DEBUG
8830 if (!run_) handle_scope_implementer->IncrementDebugMicrotasksScopeDepth();
8831 #endif
8832 }
8833
8834
~MicrotasksScope()8835 MicrotasksScope::~MicrotasksScope() {
8836 auto handle_scope_implementer = isolate_->handle_scope_implementer();
8837 if (run_) {
8838 handle_scope_implementer->DecrementMicrotasksScopeDepth();
8839 if (MicrotasksPolicy::kScoped ==
8840 handle_scope_implementer->microtasks_policy()) {
8841 PerformCheckpoint(reinterpret_cast<Isolate*>(isolate_));
8842 }
8843 }
8844 #ifdef DEBUG
8845 if (!run_) handle_scope_implementer->DecrementDebugMicrotasksScopeDepth();
8846 #endif
8847 }
8848
8849
PerformCheckpoint(Isolate * v8Isolate)8850 void MicrotasksScope::PerformCheckpoint(Isolate* v8Isolate) {
8851 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate);
8852 if (IsExecutionTerminatingCheck(isolate)) return;
8853 auto handle_scope_implementer = isolate->handle_scope_implementer();
8854 if (!handle_scope_implementer->GetMicrotasksScopeDepth() &&
8855 !handle_scope_implementer->HasMicrotasksSuppressions()) {
8856 isolate->RunMicrotasks();
8857 }
8858 }
8859
8860
GetCurrentDepth(Isolate * v8Isolate)8861 int MicrotasksScope::GetCurrentDepth(Isolate* v8Isolate) {
8862 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate);
8863 return isolate->handle_scope_implementer()->GetMicrotasksScopeDepth();
8864 }
8865
IsRunningMicrotasks(Isolate * v8Isolate)8866 bool MicrotasksScope::IsRunningMicrotasks(Isolate* v8Isolate) {
8867 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate);
8868 return isolate->IsRunningMicrotasks();
8869 }
8870
Utf8Value(v8::Local<v8::Value> obj)8871 String::Utf8Value::Utf8Value(v8::Local<v8::Value> obj)
8872 : str_(NULL), length_(0) {
8873 if (obj.IsEmpty()) return;
8874 i::Isolate* isolate = i::Isolate::Current();
8875 Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
8876 ENTER_V8(isolate);
8877 i::HandleScope scope(isolate);
8878 Local<Context> context = v8_isolate->GetCurrentContext();
8879 TryCatch try_catch(v8_isolate);
8880 Local<String> str;
8881 if (!obj->ToString(context).ToLocal(&str)) return;
8882 i::Handle<i::String> i_str = Utils::OpenHandle(*str);
8883 length_ = v8::Utf8Length(*i_str, isolate);
8884 str_ = i::NewArray<char>(length_ + 1);
8885 str->WriteUtf8(str_);
8886 }
8887
8888
~Utf8Value()8889 String::Utf8Value::~Utf8Value() {
8890 i::DeleteArray(str_);
8891 }
8892
8893
Value(v8::Local<v8::Value> obj)8894 String::Value::Value(v8::Local<v8::Value> obj) : str_(NULL), length_(0) {
8895 if (obj.IsEmpty()) return;
8896 i::Isolate* isolate = i::Isolate::Current();
8897 Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
8898 ENTER_V8(isolate);
8899 i::HandleScope scope(isolate);
8900 Local<Context> context = v8_isolate->GetCurrentContext();
8901 TryCatch try_catch(v8_isolate);
8902 Local<String> str;
8903 if (!obj->ToString(context).ToLocal(&str)) return;
8904 length_ = str->Length();
8905 str_ = i::NewArray<uint16_t>(length_ + 1);
8906 str->Write(str_);
8907 }
8908
8909
~Value()8910 String::Value::~Value() {
8911 i::DeleteArray(str_);
8912 }
8913
8914 #define DEFINE_ERROR(NAME, name) \
8915 Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) { \
8916 i::Isolate* isolate = i::Isolate::Current(); \
8917 LOG_API(isolate, NAME, New); \
8918 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \
8919 i::Object* error; \
8920 { \
8921 i::HandleScope scope(isolate); \
8922 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); \
8923 i::Handle<i::JSFunction> constructor = isolate->name##_function(); \
8924 error = *isolate->factory()->NewError(constructor, message); \
8925 } \
8926 i::Handle<i::Object> result(error, isolate); \
8927 return Utils::ToLocal(result); \
8928 }
8929
DEFINE_ERROR(RangeError,range_error)8930 DEFINE_ERROR(RangeError, range_error)
8931 DEFINE_ERROR(ReferenceError, reference_error)
8932 DEFINE_ERROR(SyntaxError, syntax_error)
8933 DEFINE_ERROR(TypeError, type_error)
8934 DEFINE_ERROR(Error, error)
8935
8936 #undef DEFINE_ERROR
8937
8938
8939 Local<Message> Exception::CreateMessage(Isolate* isolate,
8940 Local<Value> exception) {
8941 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
8942 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8943 ENTER_V8(i_isolate);
8944 i::HandleScope scope(i_isolate);
8945 return Utils::MessageToLocal(
8946 scope.CloseAndEscape(i_isolate->CreateMessage(obj, NULL)));
8947 }
8948
8949
CreateMessage(Local<Value> exception)8950 Local<Message> Exception::CreateMessage(Local<Value> exception) {
8951 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
8952 if (!obj->IsHeapObject()) return Local<Message>();
8953 i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
8954 return CreateMessage(reinterpret_cast<Isolate*>(isolate), exception);
8955 }
8956
8957
GetStackTrace(Local<Value> exception)8958 Local<StackTrace> Exception::GetStackTrace(Local<Value> exception) {
8959 i::Handle<i::Object> obj = Utils::OpenHandle(*exception);
8960 if (!obj->IsJSObject()) return Local<StackTrace>();
8961 i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
8962 i::Isolate* isolate = js_obj->GetIsolate();
8963 ENTER_V8(isolate);
8964 return Utils::StackTraceToLocal(isolate->GetDetailedStackTrace(js_obj));
8965 }
8966
8967
8968 // --- D e b u g S u p p o r t ---
8969
SetDebugEventListener(Isolate * isolate,EventCallback that,Local<Value> data)8970 bool Debug::SetDebugEventListener(Isolate* isolate, EventCallback that,
8971 Local<Value> data) {
8972 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
8973 ENTER_V8(i_isolate);
8974 i::HandleScope scope(i_isolate);
8975 if (that == nullptr) {
8976 i_isolate->debug()->SetDebugDelegate(nullptr, false);
8977 } else {
8978 i::Handle<i::Object> i_data = i_isolate->factory()->undefined_value();
8979 if (!data.IsEmpty()) i_data = Utils::OpenHandle(*data);
8980 i::NativeDebugDelegate* delegate =
8981 new i::NativeDebugDelegate(i_isolate, that, i_data);
8982 i_isolate->debug()->SetDebugDelegate(delegate, true);
8983 }
8984 return true;
8985 }
8986
DebugBreak(Isolate * isolate)8987 void Debug::DebugBreak(Isolate* isolate) {
8988 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
8989 }
8990
8991
CancelDebugBreak(Isolate * isolate)8992 void Debug::CancelDebugBreak(Isolate* isolate) {
8993 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8994 internal_isolate->stack_guard()->ClearDebugBreak();
8995 }
8996
8997
CheckDebugBreak(Isolate * isolate)8998 bool Debug::CheckDebugBreak(Isolate* isolate) {
8999 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
9000 return internal_isolate->stack_guard()->CheckDebugBreak();
9001 }
9002
SetMessageHandler(Isolate * isolate,v8::Debug::MessageHandler handler)9003 void Debug::SetMessageHandler(Isolate* isolate,
9004 v8::Debug::MessageHandler handler) {}
9005
SendCommand(Isolate * isolate,const uint16_t * command,int length,ClientData * client_data)9006 void Debug::SendCommand(Isolate* isolate, const uint16_t* command, int length,
9007 ClientData* client_data) {}
9008
Call(Local<Context> context,v8::Local<v8::Function> fun,v8::Local<v8::Value> data)9009 MaybeLocal<Value> Debug::Call(Local<Context> context,
9010 v8::Local<v8::Function> fun,
9011 v8::Local<v8::Value> data) {
9012 PREPARE_FOR_EXECUTION(context, Debug, Call, Value);
9013 i::Handle<i::Object> data_obj;
9014 if (data.IsEmpty()) {
9015 data_obj = isolate->factory()->undefined_value();
9016 } else {
9017 data_obj = Utils::OpenHandle(*data);
9018 }
9019 Local<Value> result;
9020 has_pending_exception =
9021 !ToLocal<Value>(isolate->debug()->Call(Utils::OpenHandle(*fun), data_obj),
9022 &result);
9023 RETURN_ON_FAILED_EXECUTION(Value);
9024 RETURN_ESCAPED(result);
9025 }
9026
9027
ProcessDebugMessages(Isolate * isolate)9028 void Debug::ProcessDebugMessages(Isolate* isolate) {}
9029
GetDebugContext(Isolate * isolate)9030 Local<Context> Debug::GetDebugContext(Isolate* isolate) {
9031 return debug::GetDebugContext(isolate);
9032 }
9033
9034
GetDebuggedContext(Isolate * isolate)9035 MaybeLocal<Context> Debug::GetDebuggedContext(Isolate* isolate) {
9036 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9037 ENTER_V8(i_isolate);
9038 if (!i_isolate->debug()->in_debug_scope()) return MaybeLocal<Context>();
9039 i::Handle<i::Object> calling = i_isolate->GetCallingNativeContext();
9040 if (calling.is_null()) return MaybeLocal<Context>();
9041 return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
9042 }
9043
SetLiveEditEnabled(Isolate * isolate,bool enable)9044 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
9045 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
9046 internal_isolate->debug()->set_live_edit_enabled(enable);
9047 }
9048
IsTailCallEliminationEnabled(Isolate * isolate)9049 bool Debug::IsTailCallEliminationEnabled(Isolate* isolate) {
9050 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
9051 return internal_isolate->is_tail_call_elimination_enabled();
9052 }
9053
SetTailCallEliminationEnabled(Isolate * isolate,bool enabled)9054 void Debug::SetTailCallEliminationEnabled(Isolate* isolate, bool enabled) {
9055 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
9056 internal_isolate->SetTailCallEliminationEnabled(enabled);
9057 }
9058
GetInternalProperties(Isolate * v8_isolate,Local<Value> value)9059 MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate,
9060 Local<Value> value) {
9061 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9062 ENTER_V8(isolate);
9063 i::Handle<i::Object> val = Utils::OpenHandle(*value);
9064 i::Handle<i::JSArray> result;
9065 if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result))
9066 return MaybeLocal<Array>();
9067 return Utils::ToLocal(result);
9068 }
9069
GetDebugContext(Isolate * isolate)9070 Local<Context> debug::GetDebugContext(Isolate* isolate) {
9071 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9072 ENTER_V8(i_isolate);
9073 return Utils::ToLocal(i_isolate->debug()->GetDebugContext());
9074 }
9075
Call(Local<Context> context,v8::Local<v8::Function> fun,v8::Local<v8::Value> data)9076 MaybeLocal<Value> debug::Call(Local<Context> context,
9077 v8::Local<v8::Function> fun,
9078 v8::Local<v8::Value> data) {
9079 return Debug::Call(context, fun, data);
9080 }
9081
SetLiveEditEnabled(Isolate * isolate,bool enable)9082 void debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
9083 Debug::SetLiveEditEnabled(isolate, enable);
9084 }
9085
DebugBreak(Isolate * isolate)9086 void debug::DebugBreak(Isolate* isolate) { Debug::DebugBreak(isolate); }
9087
CancelDebugBreak(Isolate * isolate)9088 void debug::CancelDebugBreak(Isolate* isolate) {
9089 Debug::CancelDebugBreak(isolate);
9090 }
9091
GetInternalProperties(Isolate * isolate,Local<Value> value)9092 MaybeLocal<Array> debug::GetInternalProperties(Isolate* isolate,
9093 Local<Value> value) {
9094 return Debug::GetInternalProperties(isolate, value);
9095 }
9096
ChangeBreakOnException(Isolate * isolate,ExceptionBreakState type)9097 void debug::ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) {
9098 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
9099 internal_isolate->debug()->ChangeBreakOnException(
9100 i::BreakException, type == BreakOnAnyException);
9101 internal_isolate->debug()->ChangeBreakOnException(i::BreakUncaughtException,
9102 type != NoBreakOnException);
9103 }
9104
SetBreakPointsActive(Isolate * v8_isolate,bool is_active)9105 void debug::SetBreakPointsActive(Isolate* v8_isolate, bool is_active) {
9106 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9107 ENTER_V8(isolate);
9108 isolate->debug()->set_break_points_active(is_active);
9109 }
9110
SetOutOfMemoryCallback(Isolate * isolate,OutOfMemoryCallback callback,void * data)9111 void debug::SetOutOfMemoryCallback(Isolate* isolate,
9112 OutOfMemoryCallback callback, void* data) {
9113 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
9114 ENTER_V8(i_isolate);
9115 i_isolate->heap()->SetOutOfMemoryCallback(callback, data);
9116 }
9117
PrepareStep(Isolate * v8_isolate,StepAction action)9118 void debug::PrepareStep(Isolate* v8_isolate, StepAction action) {
9119 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9120 ENTER_V8(isolate);
9121 CHECK(isolate->debug()->CheckExecutionState());
9122 // Clear all current stepping setup.
9123 isolate->debug()->ClearStepping();
9124 // Prepare step.
9125 isolate->debug()->PrepareStep(static_cast<i::StepAction>(action));
9126 }
9127
HasNonBlackboxedFrameOnStack(Isolate * v8_isolate)9128 bool debug::HasNonBlackboxedFrameOnStack(Isolate* v8_isolate) {
9129 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9130 ENTER_V8(isolate);
9131 i::HandleScope scope(isolate);
9132 for (i::StackTraceFrameIterator it(isolate); !it.done(); it.Advance()) {
9133 if (!it.is_javascript()) continue;
9134 if (!isolate->debug()->IsFrameBlackboxed(it.javascript_frame())) {
9135 return true;
9136 }
9137 }
9138 return false;
9139 }
9140
GetIsolate() const9141 v8::Isolate* debug::Script::GetIsolate() const {
9142 return reinterpret_cast<v8::Isolate*>(Utils::OpenHandle(this)->GetIsolate());
9143 }
9144
OriginOptions() const9145 ScriptOriginOptions debug::Script::OriginOptions() const {
9146 return Utils::OpenHandle(this)->origin_options();
9147 }
9148
WasCompiled() const9149 bool debug::Script::WasCompiled() const {
9150 return Utils::OpenHandle(this)->compilation_state() ==
9151 i::Script::COMPILATION_STATE_COMPILED;
9152 }
9153
Id() const9154 int debug::Script::Id() const { return Utils::OpenHandle(this)->id(); }
9155
LineOffset() const9156 int debug::Script::LineOffset() const {
9157 return Utils::OpenHandle(this)->line_offset();
9158 }
9159
ColumnOffset() const9160 int debug::Script::ColumnOffset() const {
9161 return Utils::OpenHandle(this)->column_offset();
9162 }
9163
LineEnds() const9164 std::vector<int> debug::Script::LineEnds() const {
9165 i::Handle<i::Script> script = Utils::OpenHandle(this);
9166 if (script->type() == i::Script::TYPE_WASM) return std::vector<int>();
9167 i::Isolate* isolate = script->GetIsolate();
9168 i::HandleScope scope(isolate);
9169 i::Script::InitLineEnds(script);
9170 CHECK(script->line_ends()->IsFixedArray());
9171 i::Handle<i::FixedArray> line_ends(i::FixedArray::cast(script->line_ends()));
9172 std::vector<int> result(line_ends->length());
9173 for (int i = 0; i < line_ends->length(); ++i) {
9174 i::Smi* line_end = i::Smi::cast(line_ends->get(i));
9175 result[i] = line_end->value();
9176 }
9177 return result;
9178 }
9179
Name() const9180 MaybeLocal<String> debug::Script::Name() const {
9181 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
9182 i::HandleScope handle_scope(isolate);
9183 i::Handle<i::Script> script = Utils::OpenHandle(this);
9184 i::Handle<i::Object> value(script->name(), isolate);
9185 if (!value->IsString()) return MaybeLocal<String>();
9186 return Utils::ToLocal(
9187 handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
9188 }
9189
SourceURL() const9190 MaybeLocal<String> debug::Script::SourceURL() const {
9191 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
9192 i::HandleScope handle_scope(isolate);
9193 i::Handle<i::Script> script = Utils::OpenHandle(this);
9194 i::Handle<i::Object> value(script->source_url(), isolate);
9195 if (!value->IsString()) return MaybeLocal<String>();
9196 return Utils::ToLocal(
9197 handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
9198 }
9199
SourceMappingURL() const9200 MaybeLocal<String> debug::Script::SourceMappingURL() const {
9201 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
9202 i::HandleScope handle_scope(isolate);
9203 i::Handle<i::Script> script = Utils::OpenHandle(this);
9204 i::Handle<i::Object> value(script->source_mapping_url(), isolate);
9205 if (!value->IsString()) return MaybeLocal<String>();
9206 return Utils::ToLocal(
9207 handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
9208 }
9209
ContextData() const9210 MaybeLocal<Value> debug::Script::ContextData() const {
9211 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
9212 i::HandleScope handle_scope(isolate);
9213 i::Handle<i::Script> script = Utils::OpenHandle(this);
9214 i::Handle<i::Object> value(script->context_data(), isolate);
9215 return Utils::ToLocal(handle_scope.CloseAndEscape(value));
9216 }
9217
Source() const9218 MaybeLocal<String> debug::Script::Source() const {
9219 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
9220 i::HandleScope handle_scope(isolate);
9221 i::Handle<i::Script> script = Utils::OpenHandle(this);
9222 i::Handle<i::Object> value(script->source(), isolate);
9223 if (!value->IsString()) return MaybeLocal<String>();
9224 return Utils::ToLocal(
9225 handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value)));
9226 }
9227
IsWasm() const9228 bool debug::Script::IsWasm() const {
9229 return Utils::OpenHandle(this)->type() == i::Script::TYPE_WASM;
9230 }
9231
IsModule() const9232 bool debug::Script::IsModule() const {
9233 return Utils::OpenHandle(this)->origin_options().IsModule();
9234 }
9235
9236 namespace {
GetSmiValue(i::Handle<i::FixedArray> array,int index)9237 int GetSmiValue(i::Handle<i::FixedArray> array, int index) {
9238 return i::Smi::cast(array->get(index))->value();
9239 }
9240 } // namespace
9241
GetPossibleBreakpoints(const debug::Location & start,const debug::Location & end,std::vector<debug::Location> * locations) const9242 bool debug::Script::GetPossibleBreakpoints(
9243 const debug::Location& start, const debug::Location& end,
9244 std::vector<debug::Location>* locations) const {
9245 CHECK(!start.IsEmpty());
9246 i::Handle<i::Script> script = Utils::OpenHandle(this);
9247 if (script->type() == i::Script::TYPE_WASM) {
9248 i::Handle<i::WasmCompiledModule> compiled_module(
9249 i::WasmCompiledModule::cast(script->wasm_compiled_module()));
9250 return compiled_module->GetPossibleBreakpoints(start, end, locations);
9251 }
9252
9253 i::Script::InitLineEnds(script);
9254 CHECK(script->line_ends()->IsFixedArray());
9255 i::Isolate* isolate = script->GetIsolate();
9256 i::Handle<i::FixedArray> line_ends =
9257 i::Handle<i::FixedArray>::cast(i::handle(script->line_ends(), isolate));
9258 CHECK(line_ends->length());
9259
9260 int start_offset = GetSourcePosition(start);
9261 int end_offset;
9262 if (end.IsEmpty()) {
9263 end_offset = GetSmiValue(line_ends, line_ends->length() - 1) + 1;
9264 } else {
9265 end_offset = GetSourcePosition(end);
9266 }
9267 if (start_offset >= end_offset) return true;
9268
9269 std::set<int> offsets;
9270 if (!isolate->debug()->GetPossibleBreakpoints(script, start_offset,
9271 end_offset, &offsets)) {
9272 return false;
9273 }
9274
9275 int current_line_end_index = 0;
9276 for (const auto& it : offsets) {
9277 int offset = it;
9278 while (offset > GetSmiValue(line_ends, current_line_end_index)) {
9279 ++current_line_end_index;
9280 CHECK(current_line_end_index < line_ends->length());
9281 }
9282 int line_offset = 0;
9283
9284 if (current_line_end_index > 0) {
9285 line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1;
9286 }
9287 locations->push_back(debug::Location(
9288 current_line_end_index + script->line_offset(),
9289 offset - line_offset +
9290 (current_line_end_index == 0 ? script->column_offset() : 0)));
9291 }
9292 return true;
9293 }
9294
GetSourcePosition(const debug::Location & location) const9295 int debug::Script::GetSourcePosition(const debug::Location& location) const {
9296 i::Handle<i::Script> script = Utils::OpenHandle(this);
9297 if (script->type() == i::Script::TYPE_WASM) {
9298 // TODO(clemensh): Return the proper thing for wasm.
9299 return 0;
9300 }
9301
9302 int line = std::max(location.GetLineNumber() - script->line_offset(), 0);
9303 int column = location.GetColumnNumber();
9304 if (line == 0) {
9305 column = std::max(0, column - script->column_offset());
9306 }
9307
9308 i::Script::InitLineEnds(script);
9309 CHECK(script->line_ends()->IsFixedArray());
9310 i::Handle<i::FixedArray> line_ends = i::Handle<i::FixedArray>::cast(
9311 i::handle(script->line_ends(), script->GetIsolate()));
9312 CHECK(line_ends->length());
9313 if (line >= line_ends->length())
9314 return GetSmiValue(line_ends, line_ends->length() - 1);
9315 int line_offset = GetSmiValue(line_ends, line);
9316 if (line == 0) return std::min(column, line_offset);
9317 int prev_line_offset = GetSmiValue(line_ends, line - 1);
9318 return std::min(prev_line_offset + column + 1, line_offset);
9319 }
9320
Cast(debug::Script * script)9321 debug::WasmScript* debug::WasmScript::Cast(debug::Script* script) {
9322 CHECK(script->IsWasm());
9323 return static_cast<WasmScript*>(script);
9324 }
9325
NumFunctions() const9326 int debug::WasmScript::NumFunctions() const {
9327 i::DisallowHeapAllocation no_gc;
9328 i::Handle<i::Script> script = Utils::OpenHandle(this);
9329 DCHECK_EQ(i::Script::TYPE_WASM, script->type());
9330 i::WasmCompiledModule* compiled_module =
9331 i::WasmCompiledModule::cast(script->wasm_compiled_module());
9332 DCHECK_GE(i::kMaxInt, compiled_module->module()->functions.size());
9333 return static_cast<int>(compiled_module->module()->functions.size());
9334 }
9335
NumImportedFunctions() const9336 int debug::WasmScript::NumImportedFunctions() const {
9337 i::DisallowHeapAllocation no_gc;
9338 i::Handle<i::Script> script = Utils::OpenHandle(this);
9339 DCHECK_EQ(i::Script::TYPE_WASM, script->type());
9340 i::WasmCompiledModule* compiled_module =
9341 i::WasmCompiledModule::cast(script->wasm_compiled_module());
9342 DCHECK_GE(i::kMaxInt, compiled_module->module()->num_imported_functions);
9343 return static_cast<int>(compiled_module->module()->num_imported_functions);
9344 }
9345
GetFunctionRange(int function_index) const9346 std::pair<int, int> debug::WasmScript::GetFunctionRange(
9347 int function_index) const {
9348 i::DisallowHeapAllocation no_gc;
9349 i::Handle<i::Script> script = Utils::OpenHandle(this);
9350 DCHECK_EQ(i::Script::TYPE_WASM, script->type());
9351 i::WasmCompiledModule* compiled_module =
9352 i::WasmCompiledModule::cast(script->wasm_compiled_module());
9353 DCHECK_LE(0, function_index);
9354 DCHECK_GT(compiled_module->module()->functions.size(), function_index);
9355 i::wasm::WasmFunction& func =
9356 compiled_module->module()->functions[function_index];
9357 DCHECK_GE(i::kMaxInt, func.code_start_offset);
9358 DCHECK_GE(i::kMaxInt, func.code_end_offset);
9359 return std::make_pair(static_cast<int>(func.code_start_offset),
9360 static_cast<int>(func.code_end_offset));
9361 }
9362
DisassembleFunction(int function_index) const9363 debug::WasmDisassembly debug::WasmScript::DisassembleFunction(
9364 int function_index) const {
9365 i::DisallowHeapAllocation no_gc;
9366 i::Handle<i::Script> script = Utils::OpenHandle(this);
9367 DCHECK_EQ(i::Script::TYPE_WASM, script->type());
9368 i::WasmCompiledModule* compiled_module =
9369 i::WasmCompiledModule::cast(script->wasm_compiled_module());
9370 return compiled_module->DisassembleFunction(function_index);
9371 }
9372
Location(int line_number,int column_number)9373 debug::Location::Location(int line_number, int column_number)
9374 : line_number_(line_number), column_number_(column_number) {
9375 CHECK(line_number >= 0);
9376 CHECK(column_number >= 0);
9377 }
9378
Location()9379 debug::Location::Location()
9380 : line_number_(v8::Function::kLineOffsetNotFound),
9381 column_number_(v8::Function::kLineOffsetNotFound) {}
9382
GetLineNumber() const9383 int debug::Location::GetLineNumber() const {
9384 CHECK(line_number_ >= 0);
9385 return line_number_;
9386 }
9387
GetColumnNumber() const9388 int debug::Location::GetColumnNumber() const {
9389 CHECK(column_number_ >= 0);
9390 return column_number_;
9391 }
9392
IsEmpty() const9393 bool debug::Location::IsEmpty() const {
9394 return line_number_ == -1 && column_number_ == -1;
9395 }
9396
GetLoadedScripts(v8::Isolate * v8_isolate,PersistentValueVector<debug::Script> & scripts)9397 void debug::GetLoadedScripts(v8::Isolate* v8_isolate,
9398 PersistentValueVector<debug::Script>& scripts) {
9399 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9400 ENTER_V8(isolate);
9401 // TODO(kozyatinskiy): remove this GC once tests are dealt with.
9402 isolate->heap()->CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask,
9403 i::GarbageCollectionReason::kDebugger);
9404 {
9405 i::DisallowHeapAllocation no_gc;
9406 i::Script::Iterator iterator(isolate);
9407 i::Script* script;
9408 while ((script = iterator.Next())) {
9409 if (script->type() != i::Script::TYPE_NORMAL) continue;
9410 if (script->HasValidSource()) {
9411 i::HandleScope handle_scope(isolate);
9412 i::Handle<i::Script> script_handle(script, isolate);
9413 scripts.Append(ToApiHandle<Script>(script_handle));
9414 }
9415 }
9416 }
9417 }
9418
CompileInspectorScript(Isolate * v8_isolate,Local<String> source)9419 MaybeLocal<UnboundScript> debug::CompileInspectorScript(Isolate* v8_isolate,
9420 Local<String> source) {
9421 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9422 PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript);
9423 i::ScriptData* script_data = NULL;
9424 i::Handle<i::String> str = Utils::OpenHandle(*source);
9425 i::Handle<i::SharedFunctionInfo> result;
9426 {
9427 ScriptOriginOptions origin_options;
9428 result = i::Compiler::GetSharedFunctionInfoForScript(
9429 str, i::Handle<i::Object>(), 0, 0, origin_options,
9430 i::Handle<i::Object>(), isolate->native_context(), NULL, &script_data,
9431 ScriptCompiler::kNoCompileOptions, i::INSPECTOR_CODE);
9432 has_pending_exception = result.is_null();
9433 RETURN_ON_FAILED_EXECUTION(UnboundScript);
9434 }
9435 RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
9436 }
9437
SetDebugDelegate(Isolate * v8_isolate,debug::DebugDelegate * delegate)9438 void debug::SetDebugDelegate(Isolate* v8_isolate,
9439 debug::DebugDelegate* delegate) {
9440 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9441 ENTER_V8(isolate);
9442 isolate->debug()->SetDebugDelegate(delegate, false);
9443 }
9444
ResetBlackboxedStateCache(Isolate * v8_isolate,v8::Local<debug::Script> script)9445 void debug::ResetBlackboxedStateCache(Isolate* v8_isolate,
9446 v8::Local<debug::Script> script) {
9447 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9448 ENTER_V8(isolate);
9449 i::DisallowHeapAllocation no_gc;
9450 i::SharedFunctionInfo::ScriptIterator iter(Utils::OpenHandle(*script));
9451 while (i::SharedFunctionInfo* info = iter.Next()) {
9452 info->set_computed_debug_is_blackboxed(false);
9453 }
9454 }
9455
EstimatedValueSize(Isolate * v8_isolate,v8::Local<v8::Value> value)9456 int debug::EstimatedValueSize(Isolate* v8_isolate, v8::Local<v8::Value> value) {
9457 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9458 ENTER_V8(isolate);
9459 i::Handle<i::Object> object = Utils::OpenHandle(*value);
9460 if (object->IsSmi()) return i::kPointerSize;
9461 CHECK(object->IsHeapObject());
9462 return i::Handle<i::HeapObject>::cast(object)->Size();
9463 }
9464
EntriesPreview(Isolate * v8_isolate,v8::Local<v8::Value> value,bool * is_key_value)9465 v8::MaybeLocal<v8::Array> debug::EntriesPreview(Isolate* v8_isolate,
9466 v8::Local<v8::Value> value,
9467 bool* is_key_value) {
9468 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
9469 ENTER_V8(isolate);
9470 if (value->IsMap()) {
9471 *is_key_value = true;
9472 return value.As<Map>()->AsArray();
9473 }
9474 if (value->IsSet()) {
9475 *is_key_value = false;
9476 return value.As<Set>()->AsArray();
9477 }
9478
9479 i::Handle<i::Object> object = Utils::OpenHandle(*value);
9480 if (object->IsJSWeakCollection()) {
9481 *is_key_value = object->IsJSWeakMap();
9482 return Utils::ToLocal(i::JSWeakCollection::GetEntries(
9483 i::Handle<i::JSWeakCollection>::cast(object), 0));
9484 }
9485 if (object->IsJSMapIterator()) {
9486 i::Handle<i::JSMapIterator> iterator =
9487 i::Handle<i::JSMapIterator>::cast(object);
9488 int iterator_kind = i::Smi::cast(iterator->kind())->value();
9489 *is_key_value = iterator_kind == i::JSMapIterator::kKindEntries;
9490 if (!iterator->HasMore()) return v8::Array::New(v8_isolate);
9491 return Utils::ToLocal(MapAsArray(isolate, iterator->table(),
9492 i::Smi::cast(iterator->index())->value(),
9493 iterator_kind));
9494 }
9495 if (object->IsJSSetIterator()) {
9496 i::Handle<i::JSSetIterator> it = i::Handle<i::JSSetIterator>::cast(object);
9497 *is_key_value = false;
9498 if (!it->HasMore()) return v8::Array::New(v8_isolate);
9499 return Utils::ToLocal(
9500 SetAsArray(isolate, it->table(), i::Smi::cast(it->index())->value()));
9501 }
9502 return v8::MaybeLocal<v8::Array>();
9503 }
9504
Script()9505 MaybeLocal<debug::Script> debug::GeneratorObject::Script() {
9506 i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
9507 i::Object* maybe_script = obj->function()->shared()->script();
9508 if (!maybe_script->IsScript()) return MaybeLocal<debug::Script>();
9509 i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate());
9510 return ToApiHandle<debug::Script>(script);
9511 }
9512
Function()9513 Local<Function> debug::GeneratorObject::Function() {
9514 i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
9515 return Utils::ToLocal(handle(obj->function()));
9516 }
9517
SuspendedLocation()9518 debug::Location debug::GeneratorObject::SuspendedLocation() {
9519 i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this);
9520 CHECK(obj->is_suspended());
9521 i::Object* maybe_script = obj->function()->shared()->script();
9522 if (!maybe_script->IsScript()) return debug::Location();
9523 i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate());
9524 i::Script::PositionInfo info;
9525 i::Script::GetPositionInfo(script, obj->source_position(), &info,
9526 i::Script::WITH_OFFSET);
9527 return debug::Location(info.line, info.column);
9528 }
9529
IsSuspended()9530 bool debug::GeneratorObject::IsSuspended() {
9531 return Utils::OpenHandle(this)->is_suspended();
9532 }
9533
Cast(v8::Local<v8::Value> value)9534 v8::Local<debug::GeneratorObject> debug::GeneratorObject::Cast(
9535 v8::Local<v8::Value> value) {
9536 CHECK(value->IsGeneratorObject());
9537 return ToApiHandle<debug::GeneratorObject>(Utils::OpenHandle(*value));
9538 }
9539
GetFunctionName() const9540 Local<String> CpuProfileNode::GetFunctionName() const {
9541 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9542 i::Isolate* isolate = node->isolate();
9543 const i::CodeEntry* entry = node->entry();
9544 i::Handle<i::String> name =
9545 isolate->factory()->InternalizeUtf8String(entry->name());
9546 if (!entry->has_name_prefix()) {
9547 return ToApiHandle<String>(name);
9548 } else {
9549 // We do not expect this to fail. Change this if it does.
9550 i::Handle<i::String> cons = isolate->factory()->NewConsString(
9551 isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
9552 name).ToHandleChecked();
9553 return ToApiHandle<String>(cons);
9554 }
9555 }
9556
FunctionData(i::CoverageFunction * function,Local<debug::Script> script)9557 debug::Coverage::FunctionData::FunctionData(i::CoverageFunction* function,
9558 Local<debug::Script> script)
9559 : function_(function) {
9560 i::Handle<i::Script> i_script = v8::Utils::OpenHandle(*script);
9561 i::Script::PositionInfo start;
9562 i::Script::PositionInfo end;
9563 i::Script::GetPositionInfo(i_script, function->start, &start,
9564 i::Script::WITH_OFFSET);
9565 i::Script::GetPositionInfo(i_script, function->end, &end,
9566 i::Script::WITH_OFFSET);
9567 start_ = Location(start.line, start.column);
9568 end_ = Location(end.line, end.column);
9569 }
9570
Count()9571 uint32_t debug::Coverage::FunctionData::Count() { return function_->count; }
9572
Name()9573 MaybeLocal<String> debug::Coverage::FunctionData::Name() {
9574 return ToApiHandle<String>(function_->name);
9575 }
9576
GetScript()9577 Local<debug::Script> debug::Coverage::ScriptData::GetScript() {
9578 return ToApiHandle<debug::Script>(script_->script);
9579 }
9580
FunctionCount()9581 size_t debug::Coverage::ScriptData::FunctionCount() {
9582 return script_->functions.size();
9583 }
9584
GetFunctionData(size_t i)9585 debug::Coverage::FunctionData debug::Coverage::ScriptData::GetFunctionData(
9586 size_t i) {
9587 return FunctionData(&script_->functions.at(i), GetScript());
9588 }
9589
~Coverage()9590 debug::Coverage::~Coverage() { delete coverage_; }
9591
ScriptCount()9592 size_t debug::Coverage::ScriptCount() { return coverage_->size(); }
9593
GetScriptData(size_t i)9594 debug::Coverage::ScriptData debug::Coverage::GetScriptData(size_t i) {
9595 return ScriptData(&coverage_->at(i));
9596 }
9597
Collect(Isolate * isolate,bool reset_count)9598 debug::Coverage debug::Coverage::Collect(Isolate* isolate, bool reset_count) {
9599 return Coverage(i::Coverage::Collect(reinterpret_cast<i::Isolate*>(isolate),
9600 reset_count));
9601 }
9602
TogglePrecise(Isolate * isolate,bool enable)9603 void debug::Coverage::TogglePrecise(Isolate* isolate, bool enable) {
9604 i::Coverage::TogglePrecise(reinterpret_cast<i::Isolate*>(isolate), enable);
9605 }
9606
GetFunctionNameStr() const9607 const char* CpuProfileNode::GetFunctionNameStr() const {
9608 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9609 return node->entry()->name();
9610 }
9611
GetScriptId() const9612 int CpuProfileNode::GetScriptId() const {
9613 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9614 const i::CodeEntry* entry = node->entry();
9615 return entry->script_id();
9616 }
9617
GetScriptResourceName() const9618 Local<String> CpuProfileNode::GetScriptResourceName() const {
9619 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9620 i::Isolate* isolate = node->isolate();
9621 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
9622 node->entry()->resource_name()));
9623 }
9624
GetScriptResourceNameStr() const9625 const char* CpuProfileNode::GetScriptResourceNameStr() const {
9626 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9627 return node->entry()->resource_name();
9628 }
9629
GetLineNumber() const9630 int CpuProfileNode::GetLineNumber() const {
9631 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
9632 }
9633
9634
GetColumnNumber() const9635 int CpuProfileNode::GetColumnNumber() const {
9636 return reinterpret_cast<const i::ProfileNode*>(this)->
9637 entry()->column_number();
9638 }
9639
9640
GetHitLineCount() const9641 unsigned int CpuProfileNode::GetHitLineCount() const {
9642 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9643 return node->GetHitLineCount();
9644 }
9645
9646
GetLineTicks(LineTick * entries,unsigned int length) const9647 bool CpuProfileNode::GetLineTicks(LineTick* entries,
9648 unsigned int length) const {
9649 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9650 return node->GetLineTicks(entries, length);
9651 }
9652
9653
GetBailoutReason() const9654 const char* CpuProfileNode::GetBailoutReason() const {
9655 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9656 return node->entry()->bailout_reason();
9657 }
9658
9659
GetHitCount() const9660 unsigned CpuProfileNode::GetHitCount() const {
9661 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
9662 }
9663
9664
GetCallUid() const9665 unsigned CpuProfileNode::GetCallUid() const {
9666 return reinterpret_cast<const i::ProfileNode*>(this)->function_id();
9667 }
9668
9669
GetNodeId() const9670 unsigned CpuProfileNode::GetNodeId() const {
9671 return reinterpret_cast<const i::ProfileNode*>(this)->id();
9672 }
9673
9674
GetChildrenCount() const9675 int CpuProfileNode::GetChildrenCount() const {
9676 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
9677 }
9678
9679
GetChild(int index) const9680 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
9681 const i::ProfileNode* child =
9682 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
9683 return reinterpret_cast<const CpuProfileNode*>(child);
9684 }
9685
9686
GetDeoptInfos() const9687 const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const {
9688 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
9689 return node->deopt_infos();
9690 }
9691
9692
Delete()9693 void CpuProfile::Delete() {
9694 i::CpuProfile* profile = reinterpret_cast<i::CpuProfile*>(this);
9695 i::CpuProfiler* profiler = profile->cpu_profiler();
9696 DCHECK(profiler != nullptr);
9697 profiler->DeleteProfile(profile);
9698 }
9699
9700
GetTitle() const9701 Local<String> CpuProfile::GetTitle() const {
9702 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9703 i::Isolate* isolate = profile->top_down()->isolate();
9704 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
9705 profile->title()));
9706 }
9707
9708
GetTopDownRoot() const9709 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
9710 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9711 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
9712 }
9713
9714
GetSample(int index) const9715 const CpuProfileNode* CpuProfile::GetSample(int index) const {
9716 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9717 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
9718 }
9719
9720
GetSampleTimestamp(int index) const9721 int64_t CpuProfile::GetSampleTimestamp(int index) const {
9722 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9723 return (profile->sample_timestamp(index) - base::TimeTicks())
9724 .InMicroseconds();
9725 }
9726
9727
GetStartTime() const9728 int64_t CpuProfile::GetStartTime() const {
9729 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9730 return (profile->start_time() - base::TimeTicks()).InMicroseconds();
9731 }
9732
9733
GetEndTime() const9734 int64_t CpuProfile::GetEndTime() const {
9735 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
9736 return (profile->end_time() - base::TimeTicks()).InMicroseconds();
9737 }
9738
9739
GetSamplesCount() const9740 int CpuProfile::GetSamplesCount() const {
9741 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
9742 }
9743
New(Isolate * isolate)9744 CpuProfiler* CpuProfiler::New(Isolate* isolate) {
9745 return reinterpret_cast<CpuProfiler*>(
9746 new i::CpuProfiler(reinterpret_cast<i::Isolate*>(isolate)));
9747 }
9748
Dispose()9749 void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
9750
SetSamplingInterval(int us)9751 void CpuProfiler::SetSamplingInterval(int us) {
9752 DCHECK_GE(us, 0);
9753 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
9754 base::TimeDelta::FromMicroseconds(us));
9755 }
9756
CollectSample()9757 void CpuProfiler::CollectSample() {
9758 reinterpret_cast<i::CpuProfiler*>(this)->CollectSample();
9759 }
9760
StartProfiling(Local<String> title,bool record_samples)9761 void CpuProfiler::StartProfiling(Local<String> title, bool record_samples) {
9762 reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
9763 *Utils::OpenHandle(*title), record_samples);
9764 }
9765
9766
StopProfiling(Local<String> title)9767 CpuProfile* CpuProfiler::StopProfiling(Local<String> title) {
9768 return reinterpret_cast<CpuProfile*>(
9769 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
9770 *Utils::OpenHandle(*title)));
9771 }
9772
9773
SetIdle(bool is_idle)9774 void CpuProfiler::SetIdle(bool is_idle) {
9775 i::CpuProfiler* profiler = reinterpret_cast<i::CpuProfiler*>(this);
9776 i::Isolate* isolate = profiler->isolate();
9777 if (!isolate->is_profiling()) return;
9778 v8::StateTag state = isolate->current_vm_state();
9779 DCHECK(state == v8::EXTERNAL || state == v8::IDLE);
9780 if (isolate->js_entry_sp() != NULL) return;
9781 if (is_idle) {
9782 isolate->set_current_vm_state(v8::IDLE);
9783 } else if (state == v8::IDLE) {
9784 isolate->set_current_vm_state(v8::EXTERNAL);
9785 }
9786 }
9787
9788
ToInternal(const HeapGraphEdge * edge)9789 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
9790 return const_cast<i::HeapGraphEdge*>(
9791 reinterpret_cast<const i::HeapGraphEdge*>(edge));
9792 }
9793
9794
GetType() const9795 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
9796 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
9797 }
9798
9799
GetName() const9800 Local<Value> HeapGraphEdge::GetName() const {
9801 i::HeapGraphEdge* edge = ToInternal(this);
9802 i::Isolate* isolate = edge->isolate();
9803 switch (edge->type()) {
9804 case i::HeapGraphEdge::kContextVariable:
9805 case i::HeapGraphEdge::kInternal:
9806 case i::HeapGraphEdge::kProperty:
9807 case i::HeapGraphEdge::kShortcut:
9808 case i::HeapGraphEdge::kWeak:
9809 return ToApiHandle<String>(
9810 isolate->factory()->InternalizeUtf8String(edge->name()));
9811 case i::HeapGraphEdge::kElement:
9812 case i::HeapGraphEdge::kHidden:
9813 return ToApiHandle<Number>(
9814 isolate->factory()->NewNumberFromInt(edge->index()));
9815 default: UNREACHABLE();
9816 }
9817 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
9818 }
9819
9820
GetFromNode() const9821 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
9822 const i::HeapEntry* from = ToInternal(this)->from();
9823 return reinterpret_cast<const HeapGraphNode*>(from);
9824 }
9825
9826
GetToNode() const9827 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
9828 const i::HeapEntry* to = ToInternal(this)->to();
9829 return reinterpret_cast<const HeapGraphNode*>(to);
9830 }
9831
9832
ToInternal(const HeapGraphNode * entry)9833 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
9834 return const_cast<i::HeapEntry*>(
9835 reinterpret_cast<const i::HeapEntry*>(entry));
9836 }
9837
9838
GetType() const9839 HeapGraphNode::Type HeapGraphNode::GetType() const {
9840 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
9841 }
9842
9843
GetName() const9844 Local<String> HeapGraphNode::GetName() const {
9845 i::Isolate* isolate = ToInternal(this)->isolate();
9846 return ToApiHandle<String>(
9847 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
9848 }
9849
9850
GetId() const9851 SnapshotObjectId HeapGraphNode::GetId() const {
9852 return ToInternal(this)->id();
9853 }
9854
9855
GetShallowSize() const9856 size_t HeapGraphNode::GetShallowSize() const {
9857 return ToInternal(this)->self_size();
9858 }
9859
9860
GetChildrenCount() const9861 int HeapGraphNode::GetChildrenCount() const {
9862 return ToInternal(this)->children_count();
9863 }
9864
9865
GetChild(int index) const9866 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
9867 return reinterpret_cast<const HeapGraphEdge*>(ToInternal(this)->child(index));
9868 }
9869
9870
ToInternal(const HeapSnapshot * snapshot)9871 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
9872 return const_cast<i::HeapSnapshot*>(
9873 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
9874 }
9875
9876
Delete()9877 void HeapSnapshot::Delete() {
9878 i::Isolate* isolate = ToInternal(this)->profiler()->isolate();
9879 if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
9880 ToInternal(this)->Delete();
9881 } else {
9882 // If this is the last snapshot, clean up all accessory data as well.
9883 isolate->heap_profiler()->DeleteAllSnapshots();
9884 }
9885 }
9886
9887
GetRoot() const9888 const HeapGraphNode* HeapSnapshot::GetRoot() const {
9889 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
9890 }
9891
9892
GetNodeById(SnapshotObjectId id) const9893 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
9894 return reinterpret_cast<const HeapGraphNode*>(
9895 ToInternal(this)->GetEntryById(id));
9896 }
9897
9898
GetNodesCount() const9899 int HeapSnapshot::GetNodesCount() const {
9900 return ToInternal(this)->entries().length();
9901 }
9902
9903
GetNode(int index) const9904 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
9905 return reinterpret_cast<const HeapGraphNode*>(
9906 &ToInternal(this)->entries().at(index));
9907 }
9908
9909
GetMaxSnapshotJSObjectId() const9910 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
9911 return ToInternal(this)->max_snapshot_js_object_id();
9912 }
9913
9914
Serialize(OutputStream * stream,HeapSnapshot::SerializationFormat format) const9915 void HeapSnapshot::Serialize(OutputStream* stream,
9916 HeapSnapshot::SerializationFormat format) const {
9917 Utils::ApiCheck(format == kJSON,
9918 "v8::HeapSnapshot::Serialize",
9919 "Unknown serialization format");
9920 Utils::ApiCheck(stream->GetChunkSize() > 0,
9921 "v8::HeapSnapshot::Serialize",
9922 "Invalid stream chunk size");
9923 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
9924 serializer.Serialize(stream);
9925 }
9926
9927
9928 // static
9929 STATIC_CONST_MEMBER_DEFINITION const SnapshotObjectId
9930 HeapProfiler::kUnknownObjectId;
9931
9932
GetSnapshotCount()9933 int HeapProfiler::GetSnapshotCount() {
9934 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
9935 }
9936
9937
GetHeapSnapshot(int index)9938 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
9939 return reinterpret_cast<const HeapSnapshot*>(
9940 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
9941 }
9942
9943
GetObjectId(Local<Value> value)9944 SnapshotObjectId HeapProfiler::GetObjectId(Local<Value> value) {
9945 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
9946 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
9947 }
9948
9949
FindObjectById(SnapshotObjectId id)9950 Local<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
9951 i::Handle<i::Object> obj =
9952 reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
9953 if (obj.is_null()) return Local<Value>();
9954 return Utils::ToLocal(obj);
9955 }
9956
9957
ClearObjectIds()9958 void HeapProfiler::ClearObjectIds() {
9959 reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
9960 }
9961
9962
TakeHeapSnapshot(ActivityControl * control,ObjectNameResolver * resolver)9963 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
9964 ActivityControl* control, ObjectNameResolver* resolver) {
9965 return reinterpret_cast<const HeapSnapshot*>(
9966 reinterpret_cast<i::HeapProfiler*>(this)
9967 ->TakeSnapshot(control, resolver));
9968 }
9969
9970
StartTrackingHeapObjects(bool track_allocations)9971 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
9972 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
9973 track_allocations);
9974 }
9975
9976
StopTrackingHeapObjects()9977 void HeapProfiler::StopTrackingHeapObjects() {
9978 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
9979 }
9980
9981
GetHeapStats(OutputStream * stream,int64_t * timestamp_us)9982 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream,
9983 int64_t* timestamp_us) {
9984 i::HeapProfiler* heap_profiler = reinterpret_cast<i::HeapProfiler*>(this);
9985 return heap_profiler->PushHeapObjectsStats(stream, timestamp_us);
9986 }
9987
StartSamplingHeapProfiler(uint64_t sample_interval,int stack_depth,SamplingFlags flags)9988 bool HeapProfiler::StartSamplingHeapProfiler(uint64_t sample_interval,
9989 int stack_depth,
9990 SamplingFlags flags) {
9991 return reinterpret_cast<i::HeapProfiler*>(this)->StartSamplingHeapProfiler(
9992 sample_interval, stack_depth, flags);
9993 }
9994
9995
StopSamplingHeapProfiler()9996 void HeapProfiler::StopSamplingHeapProfiler() {
9997 reinterpret_cast<i::HeapProfiler*>(this)->StopSamplingHeapProfiler();
9998 }
9999
10000
GetAllocationProfile()10001 AllocationProfile* HeapProfiler::GetAllocationProfile() {
10002 return reinterpret_cast<i::HeapProfiler*>(this)->GetAllocationProfile();
10003 }
10004
10005
DeleteAllHeapSnapshots()10006 void HeapProfiler::DeleteAllHeapSnapshots() {
10007 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
10008 }
10009
10010
SetWrapperClassInfoProvider(uint16_t class_id,WrapperInfoCallback callback)10011 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
10012 WrapperInfoCallback callback) {
10013 reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
10014 callback);
10015 }
10016
SetGetRetainerInfosCallback(GetRetainerInfosCallback callback)10017 void HeapProfiler::SetGetRetainerInfosCallback(
10018 GetRetainerInfosCallback callback) {
10019 reinterpret_cast<i::HeapProfiler*>(this)->SetGetRetainerInfosCallback(
10020 callback);
10021 }
10022
GetProfilerMemorySize()10023 size_t HeapProfiler::GetProfilerMemorySize() {
10024 return reinterpret_cast<i::HeapProfiler*>(this)->
10025 GetMemorySizeUsedByProfiler();
10026 }
10027
10028
SetRetainedObjectInfo(UniqueId id,RetainedObjectInfo * info)10029 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
10030 RetainedObjectInfo* info) {
10031 reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
10032 }
10033
10034
10035 v8::Testing::StressType internal::Testing::stress_type_ =
10036 v8::Testing::kStressTypeOpt;
10037
10038
SetStressRunType(Testing::StressType type)10039 void Testing::SetStressRunType(Testing::StressType type) {
10040 internal::Testing::set_stress_type(type);
10041 }
10042
10043
GetStressRuns()10044 int Testing::GetStressRuns() {
10045 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
10046 #ifdef DEBUG
10047 // In debug mode the code runs much slower so stressing will only make two
10048 // runs.
10049 return 2;
10050 #else
10051 return 5;
10052 #endif
10053 }
10054
10055
SetFlagsFromString(const char * flags)10056 static void SetFlagsFromString(const char* flags) {
10057 V8::SetFlagsFromString(flags, i::StrLength(flags));
10058 }
10059
10060
PrepareStressRun(int run)10061 void Testing::PrepareStressRun(int run) {
10062 static const char* kLazyOptimizations =
10063 "--prepare-always-opt "
10064 "--max-inlined-source-size=999999 "
10065 "--max-inlined-nodes=999999 "
10066 "--max-inlined-nodes-cumulative=999999 "
10067 "--noalways-opt";
10068 static const char* kForcedOptimizations = "--always-opt";
10069
10070 // If deoptimization stressed turn on frequent deoptimization. If no value
10071 // is spefified through --deopt-every-n-times use a default default value.
10072 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
10073 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
10074 internal::FLAG_deopt_every_n_times == 0) {
10075 SetFlagsFromString(kDeoptEvery13Times);
10076 }
10077
10078 #ifdef DEBUG
10079 // As stressing in debug mode only make two runs skip the deopt stressing
10080 // here.
10081 if (run == GetStressRuns() - 1) {
10082 SetFlagsFromString(kForcedOptimizations);
10083 } else {
10084 SetFlagsFromString(kLazyOptimizations);
10085 }
10086 #else
10087 if (run == GetStressRuns() - 1) {
10088 SetFlagsFromString(kForcedOptimizations);
10089 } else if (run != GetStressRuns() - 2) {
10090 SetFlagsFromString(kLazyOptimizations);
10091 }
10092 #endif
10093 }
10094
10095
DeoptimizeAll(Isolate * isolate)10096 void Testing::DeoptimizeAll(Isolate* isolate) {
10097 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
10098 i::HandleScope scope(i_isolate);
10099 internal::Deoptimizer::DeoptimizeAll(i_isolate);
10100 }
10101
10102
10103 namespace internal {
10104
10105
FreeThreadResources()10106 void HandleScopeImplementer::FreeThreadResources() {
10107 Free();
10108 }
10109
10110
ArchiveThread(char * storage)10111 char* HandleScopeImplementer::ArchiveThread(char* storage) {
10112 HandleScopeData* current = isolate_->handle_scope_data();
10113 handle_scope_data_ = *current;
10114 MemCopy(storage, this, sizeof(*this));
10115
10116 ResetAfterArchive();
10117 current->Initialize();
10118
10119 return storage + ArchiveSpacePerThread();
10120 }
10121
10122
ArchiveSpacePerThread()10123 int HandleScopeImplementer::ArchiveSpacePerThread() {
10124 return sizeof(HandleScopeImplementer);
10125 }
10126
10127
RestoreThread(char * storage)10128 char* HandleScopeImplementer::RestoreThread(char* storage) {
10129 MemCopy(this, storage, sizeof(*this));
10130 *isolate_->handle_scope_data() = handle_scope_data_;
10131 return storage + ArchiveSpacePerThread();
10132 }
10133
10134
IterateThis(ObjectVisitor * v)10135 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
10136 #ifdef DEBUG
10137 bool found_block_before_deferred = false;
10138 #endif
10139 // Iterate over all handles in the blocks except for the last.
10140 for (int i = blocks()->length() - 2; i >= 0; --i) {
10141 Object** block = blocks()->at(i);
10142 if (last_handle_before_deferred_block_ != NULL &&
10143 (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
10144 (last_handle_before_deferred_block_ >= block)) {
10145 v->VisitPointers(block, last_handle_before_deferred_block_);
10146 DCHECK(!found_block_before_deferred);
10147 #ifdef DEBUG
10148 found_block_before_deferred = true;
10149 #endif
10150 } else {
10151 v->VisitPointers(block, &block[kHandleBlockSize]);
10152 }
10153 }
10154
10155 DCHECK(last_handle_before_deferred_block_ == NULL ||
10156 found_block_before_deferred);
10157
10158 // Iterate over live handles in the last block (if any).
10159 if (!blocks()->is_empty()) {
10160 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
10161 }
10162
10163 List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
10164 for (unsigned i = 0; i < arraysize(context_lists); i++) {
10165 if (context_lists[i]->is_empty()) continue;
10166 Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
10167 v->VisitPointers(start, start + context_lists[i]->length());
10168 }
10169 if (microtask_context_) {
10170 Object** start = reinterpret_cast<Object**>(µtask_context_);
10171 v->VisitPointers(start, start + 1);
10172 }
10173 }
10174
10175
Iterate(ObjectVisitor * v)10176 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
10177 HandleScopeData* current = isolate_->handle_scope_data();
10178 handle_scope_data_ = *current;
10179 IterateThis(v);
10180 }
10181
10182
Iterate(ObjectVisitor * v,char * storage)10183 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
10184 HandleScopeImplementer* scope_implementer =
10185 reinterpret_cast<HandleScopeImplementer*>(storage);
10186 scope_implementer->IterateThis(v);
10187 return storage + ArchiveSpacePerThread();
10188 }
10189
10190
Detach(Object ** prev_limit)10191 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
10192 DeferredHandles* deferred =
10193 new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
10194
10195 while (!blocks_.is_empty()) {
10196 Object** block_start = blocks_.last();
10197 Object** block_limit = &block_start[kHandleBlockSize];
10198 // We should not need to check for SealHandleScope here. Assert this.
10199 DCHECK(prev_limit == block_limit ||
10200 !(block_start <= prev_limit && prev_limit <= block_limit));
10201 if (prev_limit == block_limit) break;
10202 deferred->blocks_.Add(blocks_.last());
10203 blocks_.RemoveLast();
10204 }
10205
10206 // deferred->blocks_ now contains the blocks installed on the
10207 // HandleScope stack since BeginDeferredScope was called, but in
10208 // reverse order.
10209
10210 DCHECK(prev_limit == NULL || !blocks_.is_empty());
10211
10212 DCHECK(!blocks_.is_empty() && prev_limit != NULL);
10213 DCHECK(last_handle_before_deferred_block_ != NULL);
10214 last_handle_before_deferred_block_ = NULL;
10215 return deferred;
10216 }
10217
10218
BeginDeferredScope()10219 void HandleScopeImplementer::BeginDeferredScope() {
10220 DCHECK(last_handle_before_deferred_block_ == NULL);
10221 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
10222 }
10223
10224
~DeferredHandles()10225 DeferredHandles::~DeferredHandles() {
10226 isolate_->UnlinkDeferredHandles(this);
10227
10228 for (int i = 0; i < blocks_.length(); i++) {
10229 #ifdef ENABLE_HANDLE_ZAPPING
10230 HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
10231 #endif
10232 isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
10233 }
10234 }
10235
10236
Iterate(ObjectVisitor * v)10237 void DeferredHandles::Iterate(ObjectVisitor* v) {
10238 DCHECK(!blocks_.is_empty());
10239
10240 DCHECK((first_block_limit_ >= blocks_.first()) &&
10241 (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
10242
10243 v->VisitPointers(blocks_.first(), first_block_limit_);
10244
10245 for (int i = 1; i < blocks_.length(); i++) {
10246 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
10247 }
10248 }
10249
10250
InvokeAccessorGetterCallback(v8::Local<v8::Name> property,const v8::PropertyCallbackInfo<v8::Value> & info,v8::AccessorNameGetterCallback getter)10251 void InvokeAccessorGetterCallback(
10252 v8::Local<v8::Name> property,
10253 const v8::PropertyCallbackInfo<v8::Value>& info,
10254 v8::AccessorNameGetterCallback getter) {
10255 // Leaving JavaScript.
10256 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10257 RuntimeCallTimerScope timer(isolate,
10258 &RuntimeCallStats::AccessorGetterCallback);
10259 Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
10260 getter));
10261 VMState<EXTERNAL> state(isolate);
10262 ExternalCallbackScope call_scope(isolate, getter_address);
10263 getter(property, info);
10264 }
10265
10266
InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value> & info,v8::FunctionCallback callback)10267 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
10268 v8::FunctionCallback callback) {
10269 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
10270 RuntimeCallTimerScope timer(isolate,
10271 &RuntimeCallStats::InvokeFunctionCallback);
10272 Address callback_address =
10273 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
10274 VMState<EXTERNAL> state(isolate);
10275 ExternalCallbackScope call_scope(isolate, callback_address);
10276 callback(info);
10277 }
10278
10279
10280 } // namespace internal
10281 } // namespace v8
10282